add auth
This commit is contained in:
119
src/lib/users.ts
Normal file
119
src/lib/users.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
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,
|
||||
}))
|
||||
}
|
||||
Reference in New Issue
Block a user