import bcrypt from 'bcryptjs'; import { db, now } from '../db.js'; import { publicUser } from '../auth.js'; import { config } from '../config.js'; function fullUser(userId) { return db.prepare('SELECT * FROM users WHERE id = ?').get(userId); } export function updateProfile(userId, payload) { const current = fullUser(userId); if (!current) throw new Error('User not found'); const nextEmail = current.auth_provider === 'local' ? (payload.email || current.email).toLowerCase() : current.email; const duplicate = db.prepare('SELECT id FROM users WHERE email = ? AND id <> ?').get(nextEmail, userId); if (duplicate) throw new Error('Email address is already in use'); db.prepare(` UPDATE users SET email = ?, display_name = ?, job_title = ?, phone = ?, timezone = ?, avatar_url = ?, updated_at = ? WHERE id = ? `).run( nextEmail, payload.displayName, payload.jobTitle || '', payload.phone || '', payload.timezone || '', payload.avatarUrl || '', now(), userId ); return publicUser(fullUser(userId)); } export function updateTheme(userId, theme) { db.prepare('UPDATE users SET theme = ?, updated_at = ? WHERE id = ?').run(theme, now(), userId); return publicUser(fullUser(userId)); } export function changePassword(userId, payload) { const current = fullUser(userId); if (!current) throw new Error('User not found'); if (current.auth_provider !== 'local') { return { external: true, provider: current.auth_provider || 'entra', redirectUrl: config.entra.passwordChangeUrl }; } if (!current.password_hash || !bcrypt.compareSync(payload.currentPassword || '', current.password_hash)) { throw new Error('Current password is incorrect'); } if (!payload.newPassword || payload.newPassword.length < 8) { throw new Error('New password must be at least 8 characters'); } db.prepare('UPDATE users SET password_hash = ?, updated_at = ? WHERE id = ?').run( bcrypt.hashSync(payload.newPassword, 12), now(), userId ); return { changed: true }; }