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 static initialized = false
|
||||||
|
|
||||||
private __db: Database
|
private static db: Database
|
||||||
|
|
||||||
// UGLY: should be more flexible
|
// UGLY: should be more flexible
|
||||||
constructor() {
|
public static init() {
|
||||||
this.__db = SSLSnifferApp.initDatabase()
|
|
||||||
|
if (SSLSnifferApp.initialized) {
|
||||||
|
throw new Error("SSLSniffer has already been initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLSnifferApp.db = SSLSnifferApp.initDatabase()
|
||||||
SSLSnifferApp.initialized = true
|
SSLSnifferApp.initialized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public get db() {
|
public static prepare(query: string) {
|
||||||
return this.__db
|
return SSLSnifferApp.db.prepare(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This needs to be static as it doesn't need the object
|
|
||||||
private static initDatabase() {
|
private static initDatabase() {
|
||||||
|
|
||||||
const db = new Database(
|
const db = new Database(
|
||||||
@ -35,14 +39,15 @@ export class SSLSnifferApp {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private closeDatabase(graceful?: boolean) {
|
private static closeDatabase(graceful?: boolean) {
|
||||||
|
|
||||||
if (!graceful) {
|
if (!graceful) {
|
||||||
graceful = true
|
graceful = true
|
||||||
}
|
}
|
||||||
// Change of variable to make it more readable
|
// Change of variable to make it more readable
|
||||||
const forceful = !graceful
|
const forceful = !graceful
|
||||||
|
|
||||||
this.db.close(forceful)
|
SSLSnifferApp.db.close(forceful)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user