Created barebones for user database
This commit is contained in:
parent
925610161e
commit
3618af361b
79
src/lib/classes/users.ts
Normal file
79
src/lib/classes/users.ts
Normal file
@ -0,0 +1,79 @@
|
||||
export interface IUserBroker {
|
||||
|
||||
createTable(): void
|
||||
createUser(username: string, password: string): Promise<User>
|
||||
getUser(username: string, password: string): Promise<User|null>
|
||||
updatePassword(username: string, password: string, newPassword: string): Promise<void>
|
||||
getUserFromSession(session: string): User
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
export class User {
|
||||
|
||||
public userID: number
|
||||
public username: string
|
||||
|
||||
constructor(
|
||||
userID: number,
|
||||
username: string
|
||||
) {
|
||||
this.userID = userID
|
||||
this.username = username
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export class UserApp {
|
||||
|
||||
private static broker : IUserBroker
|
||||
private static initialized: boolean = false
|
||||
|
||||
|
||||
public static init(broker: IUserBroker) {
|
||||
|
||||
if (UserApp.initialized) {
|
||||
// UGLY: make this Error more specific
|
||||
throw Error("UserApp has already been initialized")
|
||||
}
|
||||
|
||||
UserApp.initialized = true
|
||||
UserApp.broker = broker
|
||||
UserApp.broker.createTable()
|
||||
|
||||
}
|
||||
|
||||
public static getUserFromSession(session: string): User {
|
||||
UserApp.assertInitialized()
|
||||
return UserApp.broker.getUserFromSession(session)
|
||||
}
|
||||
|
||||
public static createUser(username: string, password: string) {
|
||||
UserApp.assertInitialized()
|
||||
return UserApp.broker.createUser(username, password)
|
||||
}
|
||||
|
||||
public static getUser(username: string, password: string): User {
|
||||
UserApp.assertInitialized()
|
||||
return UserApp.broker.getUser(username, password)
|
||||
}
|
||||
|
||||
public static updatePassword(username: string, password: string, newPassword: string) {
|
||||
UserApp.assertInitialized()
|
||||
return UserApp.broker.updatePassword(username, password, newPassword)
|
||||
}
|
||||
|
||||
|
||||
private static assertInitialized() {
|
||||
|
||||
if (!UserApp.initialized) {
|
||||
// UGLY: make more specific
|
||||
throw Error("User app has't been Initialized yet!")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
17
src/lib/db-utils/SQL/Users.sql
Normal file
17
src/lib/db-utils/SQL/Users.sql
Normal file
@ -0,0 +1,17 @@
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
username TEXT UNIQUE NOT NULL ,
|
||||
password_hash TEXT NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO users (username, password_hash)
|
||||
VALUES (@username, @password);
|
||||
|
||||
SELECT user_id, username, password_hash
|
||||
FROM users
|
||||
WHERE username = @username;
|
||||
|
||||
UPDATE users
|
||||
SET password_hash = @newPassword
|
||||
WHERE username = @username;
|
||||
|
||||
@ -0,0 +1,183 @@
|
||||
import { User, type IUserBroker } from "$lib/classes/users";
|
||||
import { SSLSnifferApp } from "./sqlite";
|
||||
import * as argon2 from "argon2";
|
||||
|
||||
|
||||
class UserDB {
|
||||
|
||||
public user_id: number
|
||||
public username: string
|
||||
public password_hash: string
|
||||
|
||||
constructor(
|
||||
user_id: number,
|
||||
username: string,
|
||||
password_hash: string
|
||||
) {
|
||||
this.user_id = user_id
|
||||
this.username = username
|
||||
this.password_hash = password_hash
|
||||
}
|
||||
}
|
||||
export class UserDBBroker implements IUserBroker {
|
||||
|
||||
private static initialized = false
|
||||
|
||||
constructor() {
|
||||
if (UserDB.initialized) {
|
||||
// UGLY: make more specific
|
||||
throw Error("UserDB has been already initialized")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public createTable(): void {
|
||||
const stmt = SSLSnifferApp.prepare(
|
||||
`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
username TEXT UNIQUE NOT NULL ,
|
||||
password_hash TEXT NOT NULL
|
||||
);
|
||||
`
|
||||
)
|
||||
stmt.run()
|
||||
stmt.finalize()
|
||||
}
|
||||
|
||||
public async createUser(username: string, password: string): Promise<User> {
|
||||
|
||||
this.validateUniqueness(username)
|
||||
|
||||
const insertUser = SSLSnifferApp.prepare(
|
||||
`
|
||||
INSERT INTO users (username, password_hash)
|
||||
VALUES (@username, @password);
|
||||
`
|
||||
)
|
||||
|
||||
const passwordHash = await argon2.hash(password)
|
||||
|
||||
try {
|
||||
insertUser.run({
|
||||
username: username,
|
||||
password: passwordHash
|
||||
})
|
||||
} catch (error) {
|
||||
// UGLY: make this more specific
|
||||
console.error("Duplicate after check??")
|
||||
// UGLY: create a logger
|
||||
console.error(`Insert User ${Date.now()}:\n\t${error}\n\n`)
|
||||
throw new Error("You can't have duplicates")
|
||||
}
|
||||
|
||||
insertUser.finalize()
|
||||
|
||||
const user = await this.getUser(username, password)
|
||||
|
||||
if (!user) {
|
||||
// UGLY: make this more specific
|
||||
throw new Error("Something went wrong during the creation of the user")
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
public async getUser(username: string, password: string): Promise<User|null> {
|
||||
|
||||
const userToVerify = this.getUserByUsername(username)
|
||||
|
||||
if (!userToVerify) {
|
||||
// UGLY: make this more specific
|
||||
throw new Error("The specified user does not exist on the database")
|
||||
}
|
||||
|
||||
let match = false
|
||||
|
||||
try {
|
||||
match = await argon2.verify(userToVerify.password_hash, password)
|
||||
} catch(error) {
|
||||
// UGLY: make this more specific
|
||||
throw new Error("Argon2 had an error")
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
return null
|
||||
}
|
||||
|
||||
return new User(
|
||||
userToVerify.user_id,
|
||||
userToVerify.username
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
public async updatePassword(username: string, password: string, newPassword: string): Promise<void> {
|
||||
|
||||
const userToUpdate = await this.getUser(username, password)
|
||||
|
||||
if (!userToUpdate) {
|
||||
// UGLY: make this more specific
|
||||
throw new Error("Something went wrong while fetching the user")
|
||||
}
|
||||
const passwordHash = await argon2.hash(newPassword)
|
||||
|
||||
const stmt = SSLSnifferApp.prepare(
|
||||
`
|
||||
UPDATE users
|
||||
SET password_hash = @newPassword
|
||||
WHERE username = @username;
|
||||
`
|
||||
)
|
||||
|
||||
stmt.run({
|
||||
username: userToUpdate.username,
|
||||
newPassword: passwordHash
|
||||
})
|
||||
stmt.finalize()
|
||||
}
|
||||
|
||||
// TODO: implement this
|
||||
public getUserFromSession(session: string): User {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
private validateUniqueness(username: string) {
|
||||
|
||||
const user = this.getUserByUsername(username)
|
||||
|
||||
if (!user) {
|
||||
return
|
||||
}
|
||||
|
||||
throw new Error("User is already on the system")
|
||||
}
|
||||
|
||||
private getUserByUsername(username: string): UserDB | null {
|
||||
const stmt = SSLSnifferApp.prepare(
|
||||
`
|
||||
SELECT user_id, username, password_hash
|
||||
FROM users
|
||||
WHERE username = @username;
|
||||
`
|
||||
)
|
||||
|
||||
const user : any | null = stmt.get({
|
||||
username: username,
|
||||
})
|
||||
|
||||
stmt.finalize()
|
||||
|
||||
if (!user) {
|
||||
return null
|
||||
}
|
||||
|
||||
return new UserDB(
|
||||
user.user_id,
|
||||
user.username,
|
||||
user.password_hash
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,20 +5,24 @@ export class SSLSnifferApp {
|
||||
|
||||
private static initialized = false
|
||||
|
||||
private __db: Database
|
||||
private static db: Database
|
||||
|
||||
// UGLY: should be more flexible
|
||||
constructor() {
|
||||
this.__db = SSLSnifferApp.initDatabase()
|
||||
public static init() {
|
||||
|
||||
if (SSLSnifferApp.initialized) {
|
||||
throw new Error("SSLSniffer has already been initialized")
|
||||
}
|
||||
|
||||
SSLSnifferApp.db = SSLSnifferApp.initDatabase()
|
||||
SSLSnifferApp.initialized = true
|
||||
}
|
||||
|
||||
|
||||
public get db() {
|
||||
return this.__db
|
||||
public static prepare(query: string) {
|
||||
return SSLSnifferApp.db.prepare(query)
|
||||
}
|
||||
|
||||
// This needs to be static as it doesn't need the object
|
||||
private static initDatabase() {
|
||||
|
||||
const db = new Database(
|
||||
@ -35,14 +39,15 @@ export class SSLSnifferApp {
|
||||
|
||||
}
|
||||
|
||||
private closeDatabase(graceful?: boolean) {
|
||||
private static closeDatabase(graceful?: boolean) {
|
||||
|
||||
if (!graceful) {
|
||||
graceful = true
|
||||
graceful = true
|
||||
}
|
||||
// Change of variable to make it more readable
|
||||
const forceful = !graceful
|
||||
|
||||
this.db.close(forceful)
|
||||
SSLSnifferApp.db.close(forceful)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user