import { getDb } from './db' import { getLibraries } from './libraries' import type { Library } from '@/types' export interface User { id: string username: string role: 'admin' | 'user' createdAt: number } export interface UserWithHash extends User { passwordHash: string } export function getUserCount(): number { const db = getDb() const row = db.prepare('SELECT COUNT(*) as count FROM users').get() as { count: number } return row.count } export function getUserByUsername(username: string): UserWithHash | undefined { const db = getDb() const row = db .prepare('SELECT id, username, password_hash, role, created_at FROM users WHERE username = ?') .get(username) as { id: string; username: string; password_hash: string; role: string; created_at: number } | undefined if (!row) return undefined return { id: row.id, username: row.username, passwordHash: row.password_hash, role: row.role as 'admin' | 'user', createdAt: row.created_at, } } export function getUserById(id: string): User | undefined { const db = getDb() const row = db .prepare('SELECT id, username, role, created_at FROM users WHERE id = ?') .get(id) as { id: string; username: string; role: string; created_at: number } | undefined if (!row) return undefined return { id: row.id, username: row.username, role: row.role as 'admin' | 'user', createdAt: row.created_at, } } export function createUser(username: string, passwordHash: string, role: 'admin' | 'user'): User { const db = getDb() const id = crypto.randomUUID() const now = Math.floor(Date.now() / 1000) db.prepare( 'INSERT INTO users (id, username, password_hash, role, created_at) VALUES (?, ?, ?, ?, ?)' ).run(id, username, passwordHash, role, now) return { id, username, role, createdAt: now } } export function deleteUser(id: string): boolean { const db = getDb() const result = db.prepare('DELETE FROM users WHERE id = ?').run(id) return result.changes > 0 } export function listUsers(): User[] { const db = getDb() const rows = db .prepare('SELECT id, username, role, created_at FROM users ORDER BY created_at ASC') .all() as { id: string; username: string; role: string; created_at: number }[] return rows.map((r) => ({ id: r.id, username: r.username, role: r.role as 'admin' | 'user', createdAt: r.created_at, })) } export function getPermittedLibraryIds(userId: string): string[] { const db = getDb() const rows = db .prepare('SELECT library_id FROM library_permissions WHERE user_id = ?') .all(userId) as { library_id: string }[] return rows.map((r) => r.library_id) } export function setLibraryPermissions(userId: string, libraryIds: string[]): void { const db = getDb() const tx = db.transaction(() => { db.prepare('DELETE FROM library_permissions WHERE user_id = ?').run(userId) const insert = db.prepare('INSERT INTO library_permissions (user_id, library_id) VALUES (?, ?)') for (const libraryId of libraryIds) { insert.run(userId, libraryId) } }) tx() } export function getLibrariesForUser(userId: string, role: 'admin' | 'user'): Library[] { if (role === 'admin') return getLibraries() const db = getDb() const rows = db .prepare( `SELECT l.id, l.name, l.path, l.type, l.cover_ext FROM libraries l INNER JOIN library_permissions lp ON lp.library_id = l.id WHERE lp.user_id = ? ORDER BY l.name ASC` ) .all(userId) as { id: string; name: string; path: string; type: string; cover_ext: string | null }[] return rows.map((r) => ({ id: r.id, name: r.name, path: r.path, type: r.type as Library['type'], coverExt: r.cover_ext, })) }