v0.9.1 encrypt database and bug fixes

This commit is contained in:
2026-03-13 15:22:40 -04:00
parent 9f7266bc6a
commit e02cf69745
11 changed files with 185 additions and 12 deletions

View File

@@ -1,9 +1,10 @@
const Database = require('better-sqlite3');
const Database = require('better-sqlite3-sqlcipher');
const path = require('path');
const fs = require('fs');
const bcrypt = require('bcryptjs');
const DB_PATH = process.env.DB_PATH || '/app/data/jama.db';
const DB_KEY = process.env.DB_KEY || '';
let db;
@@ -16,6 +17,13 @@ function getDb() {
console.log(`[DB] Created data directory: ${dir}`);
}
db = new Database(DB_PATH);
if (DB_KEY) {
// Apply encryption key — must be the very first pragma before any other DB access
db.pragma(`key = '${DB_KEY.replace(/'/g, "''")}'`);
console.log('[DB] Encryption key applied');
} else {
console.warn('[DB] WARNING: DB_KEY not set — database is unencrypted');
}
db.pragma('journal_mode = WAL');
db.pragma('foreign_keys = ON');
console.log(`[DB] Opened database at ${DB_PATH}`);

View File

@@ -99,11 +99,29 @@ router.post('/support', (req, res) => {
${message.trim()}`;
db.prepare(`
const msgResult = db.prepare(`
INSERT INTO messages (group_id, user_id, content, type)
VALUES (?, ?, ?, 'text')
`).run(groupId, admin.id, content);
// Emit socket event so online admins see the message immediately
const newMsg = db.prepare(`
SELECT m.*, u.name as user_name, u.display_name as user_display_name, u.avatar as user_avatar
FROM messages m JOIN users u ON m.user_id = u.id
WHERE m.id = ?
`).get(msgResult.lastInsertRowid);
if (newMsg) {
newMsg.reactions = [];
io.to(`group:${groupId}`).emit('message:new', newMsg);
}
// Notify each admin via their user channel so they can reload groups if needed
const admins = db.prepare("SELECT id FROM users WHERE role = 'admin' AND status = 'active'").all();
for (const a of admins) {
io.to(`user:${a.id}`).emit('notification:new', { type: 'support', groupId });
}
console.log(`[Support] Message from ${email} posted to Support group`);
res.json({ success: true });
});

View File

@@ -53,11 +53,11 @@ router.get('/', authMiddleware, (req, res) => {
(SELECT COUNT(*) FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0) as message_count,
(SELECT m.content FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message,
(SELECT m.created_at FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_at,
(SELECT m.user_id FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_user_id,
(SELECT m.user_id FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_user_id
FROM groups g
WHERE g.type = 'public'
ORDER BY g.is_default DESC, g.name ASC
`).all(userId);
`).all();
// For direct messages, replace name with opposite user's display name
const privateGroupsRaw = db.prepare(`
@@ -66,7 +66,7 @@ router.get('/', authMiddleware, (req, res) => {
(SELECT COUNT(*) FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0) as message_count,
(SELECT m.content FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message,
(SELECT m.created_at FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_at,
(SELECT m.user_id FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_user_id,
(SELECT m.user_id FROM messages m WHERE m.group_id = g.id AND m.is_deleted = 0 ORDER BY m.created_at DESC LIMIT 1) as last_message_user_id
FROM groups g
JOIN group_members gm ON g.id = gm.group_id AND gm.user_id = ?
LEFT JOIN users u ON g.owner_id = u.id