CLI scripts for extracting and decrypting attachments from the FaceKom PostgreSQL database.

Scripts Created

bin/crypto/extract-room-attachments

Node.js script that queries PostgreSQL, decrypts attachments using AttachmentCryptoService (AES-256-GCM), and packages them into a zip file.

Usage:

# Extract attachments for a specific room
cd /workspace/vuer_oss && node bin/crypto/extract-room-attachments -r <ROOM_ID> -o output.zip
 
# Extract ALL attachments from the database
cd /workspace/vuer_oss && node bin/crypto/extract-room-attachments --all -o output.zip

Key details:

  • Shared bootstrap via bin/crypto/helpers/setup.js — resolves paths relative to __dirname
  • Decrypts via AttachmentCryptoService.decrypt() using the Encryption table metadata
  • Output is a zip file with files named {timestamp}_{label}_{attachmentId}.{ext}
  • Room mode: uses getRoomAttachmentIds(roomId) from helpers/room.js — picks up attachment, videochat:presentation:open activities AND Document table entries
  • All mode: queries Attachment table directly
  • Lazy-loads BLOB data per attachment (excludes file column in list query)

bin/crypto/find-room-with-attachments

Helper script to find the most recent room that has attachment activities. Outputs just the room ID to stdout.

cd /workspace/vuer_oss && node bin/crypto/find-room-with-attachments

bin/crypto/extract-room-attachments-remote.sh

Shell script that automates the full remote extraction workflow:

  1. Uploads scripts + helpers to $VUER_PATH/bin/crypto/ on the server (not /tmp/, so relative requires work)
  2. Finds a room with attachments
  3. Runs extraction and decryption
  4. Downloads the resulting zip
bin/crypto/extract-room-attachments-remote.sh [HOST] [VUER_PATH] [OUTPUT_DIR]

Defaults: HOST=Facekom, VUER_PATH=/workspace/vuer_oss, OUTPUT_DIR=~/Downloads

SSH Auth

Requires ssh-add to be run first for key-based auth through the ProxyJump.

Architecture Notes

  • Attachments are stored as encrypted BLOBs in the attachment table
  • Encryption metadata (algorithm, key, AAD) is in the encryption table, linked via encryptionId
  • Attachments link to rooms through activity records (type: 'attachment', content.attachmentId)
  • Some attachments may have null roomId/selfServiceRoomId on the activity — use --all flag for those
  • The Attachment model has no direct roomId foreign key

Refactoring (2026-04-08)

  • Replaced inline Activity query in findAttachments() with getRoomAttachmentIds(roomId) from bin/crypto/helpers/room.js
  • Had to export getRoomAttachmentIds from room.js (was previously internal-only)
  • Removed --self-service flag and category wrapper; uses attachment.name as filename label
  • Remote script now deploys to $VUER_PATH/bin/crypto/ instead of /tmp/ so relative requires resolve

Tested

  • 2026-03-31: Extracted and decrypted a 44KB PNG (1920x1080) from Facekom dev server
  • 2026-04-08: Re-tested after refactor — same results (3 found, 1 decrypted, 2 skipped no file data)