Files
Lazuli/src/lib/server/users.ts

87 lines
3.9 KiB
TypeScript
Raw Normal View History

2024-01-23 01:21:41 -05:00
import Database from 'better-sqlite3'
import { generateUUID } from '$lib/utils'
2024-02-01 18:10:15 -05:00
import { isValidURL } from '$lib/utils'
2024-01-23 01:21:41 -05:00
const db = new Database('./src/lib/server/users.db', { verbose: console.info })
db.pragma('foreign_keys = ON')
const initUsersTable = 'CREATE TABLE IF NOT EXISTS Users(id VARCHAR(36) PRIMARY KEY, username VARCHAR(30) UNIQUE NOT NULL, password VARCHAR(72) NOT NULL)'
const initConnectionsTable = 'CREATE TABLE IF NOT EXISTS Connections(id VARCHAR(36) PRIMARY KEY, userId VARCHAR(36) NOT NULL, service TEXT NOT NULL, tokens TEXT NOT NULL, FOREIGN KEY(userId) REFERENCES Users(id))'
2024-02-01 18:10:15 -05:00
db.exec(initUsersTable), db.exec(initConnectionsTable)
2024-01-23 01:21:41 -05:00
2024-01-25 03:05:13 -05:00
type UserQueryParams = {
includePassword?: boolean
}
2024-02-01 18:10:15 -05:00
interface ConnectionsTableSchema {
2024-01-24 14:16:24 -05:00
id: string
userId: string
2024-02-01 18:10:15 -05:00
service: string
tokens: string
2024-01-24 14:16:24 -05:00
}
2024-01-23 01:21:41 -05:00
export class Users {
2024-01-25 03:05:13 -05:00
static getUser = (id: string, params: UserQueryParams | null = null): User | undefined => {
const user = db.prepare('SELECT * FROM Users WHERE id = ?').get(id) as User | undefined
if (user && !params?.includePassword) delete user.password
return user
}
static getUsername = (username: string, params: UserQueryParams | null = null): User | undefined => {
const user = db.prepare('SELECT * FROM Users WHERE lower(username) = ?').get(username.toLowerCase()) as User | undefined
if (user && !params?.includePassword) delete user.password
return user
}
static allUsers = (includePassword: boolean = false): User[] => {
const users = db.prepare('SELECT * FROM Users').all() as User[]
if (!includePassword) users.forEach((user) => delete user.password)
return users
2024-01-24 14:16:24 -05:00
}
2024-01-23 01:21:41 -05:00
static addUser = (username: string, hashedPassword: string): User => {
const userId = generateUUID()
db.prepare('INSERT INTO Users(id, username, password) VALUES(?, ?, ?)').run(userId, username, hashedPassword)
2024-01-25 03:05:13 -05:00
return this.getUser(userId)!
}
static deleteUser = (id: string): void => {
const commandInfo = db.prepare('DELETE FROM Users WHERE id = ?').run(id)
if (commandInfo.changes === 0) throw new Error(`User with id ${id} does not exist`)
2024-01-23 01:21:41 -05:00
}
2024-01-24 14:16:24 -05:00
}
2024-01-23 01:21:41 -05:00
2024-01-23 12:05:33 -05:00
export class Connections {
2024-02-01 18:10:15 -05:00
static getConnection = (id: string): Connection => {
const { userId, service, tokens } = db.prepare('SELECT * FROM Connections WHERE id = ?').get(id) as ConnectionsTableSchema
2024-02-12 18:04:30 -05:00
const connection: Connection = { id, userId, service: JSON.parse(service), tokens: JSON.parse(tokens) }
2024-01-24 14:16:24 -05:00
return connection
}
2024-02-01 18:10:15 -05:00
static getUserConnections = (userId: string): Connection[] => {
const connectionRows = db.prepare('SELECT * FROM Connections WHERE userId = ?').all(userId) as ConnectionsTableSchema[]
const connections: Connection[] = []
for (const row of connectionRows) {
const { id, service, tokens } = row
2024-02-12 18:04:30 -05:00
connections.push({ id, userId, service: JSON.parse(service), tokens: JSON.parse(tokens) })
}
2024-01-25 03:05:13 -05:00
return connections
}
static addConnection = (userId: string, service: Service, tokens: Tokens): Connection => {
2024-01-24 14:16:24 -05:00
const connectionId = generateUUID()
2024-02-01 18:10:15 -05:00
if (!isValidURL(service.urlOrigin)) throw new Error('Service does not have valid url')
db.prepare('INSERT INTO Connections(id, userId, service, tokens) VALUES(?, ?, ?, ?)').run(connectionId, userId, JSON.stringify(service), JSON.stringify(tokens))
2024-01-24 14:16:24 -05:00
return this.getConnection(connectionId)
}
2024-01-25 03:05:13 -05:00
static deleteConnection = (id: string): void => {
const commandInfo = db.prepare('DELETE FROM Connections WHERE id = ?').run(id)
if (commandInfo.changes === 0) throw new Error(`Connection with id: ${id} does not exist`)
}
static updateTokens = (id: string, tokens: Tokens): void => {
const commandInfo = db.prepare('UPDATE Connections SET tokens = ? WHERE id = ?').run(JSON.stringify(tokens), id)
if (commandInfo.changes === 0) throw new Error('Failed to update tokens')
}
2024-01-23 12:05:33 -05:00
}