feat(wip): ...

This commit is contained in:
Maieul BOYER 2025-08-13 19:15:27 +02:00 committed by Maix0
parent 70d72f4419
commit 33e893ec58
8 changed files with 49 additions and 29 deletions

View file

@ -13,6 +13,7 @@
"better-sqlite3": "^11.10.0", "better-sqlite3": "^11.10.0",
"fastify": "^5.0.0", "fastify": "^5.0.0",
"fastify-plugin": "^5.0.1", "fastify-plugin": "^5.0.1",
"joi": "^18.0.0",
"uuidv7": "^1.0.2" "uuidv7": "^1.0.2"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,5 +1,5 @@
import fp from 'fastify-plugin' import fp from 'fastify-plugin'
import { FastifyInstance } from 'fastify' import { FastifyInstance, FastifyPluginAsync } from 'fastify'
import { Base } from "./mixin/_base"; import { Base } from "./mixin/_base";
import { UserDb } from "./mixin/user"; import { UserDb } from "./mixin/user";
@ -18,16 +18,15 @@ declare module 'fastify' {
} }
} }
export type DatabaseOption = { export const useDatabase = fp<FastifyPluginAsync>(async function(
path: string;
};
export const useDatabase = fp<DatabaseOption>(async function(
f: FastifyInstance, f: FastifyInstance,
_options: DatabaseOption) { _options: {}) {
f.log.info("Database has been hooked up to fastify ?!");
f.log.warn("TODO: actually hook up database to fastify..."); let path = process.env.DATABASE_DIR;
f.decorate('db', new Database(_options.path)); if (path === null || path === undefined)
throw "env `DATABASE_DIR` not defined";
f.log.info(`Opening database with path: ${path}/database.db`)
f.decorate('db', new Database(`${path}/database.db`));
}); });
export default useDatabase; export default useDatabase;

View file

@ -35,7 +35,7 @@ Table auth {
Table session { Table session {
id integer [PK, not null, increment] id integer [PK, not null, increment]
cookie text [PK, unique, not null] cookie text [unique, not null]
userid integer [ref: > user.id, not null] userid integer [ref: > user.id, not null]
createAt text [not null] createAt text [not null]
userAgent text [not null] userAgent text [not null]

View file

@ -5,28 +5,18 @@ CREATE TABLE IF NOT EXISTS user (
); );
CREATE TABLE IF NOT EXISTS auth ( CREATE TABLE IF NOT EXISTS auth (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
provider INTEGER NOT NULL, provider TEXT NOT NULL,
user INTEGER NOT NULL, user INTEGER NOT NULL,
oauth2_user TEXT NOT NULL UNIQUE, oauth2_user TEXT NOT NULL UNIQUE,
FOREIGN KEY(provider) REFERENCES provider(id),
FOREIGN KEY(user) REFERENCES user(id) FOREIGN KEY(user) REFERENCES user(id)
); );
CREATE TABLE IF NOT EXISTS provider (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
name TEXT PRIMARY KEY NOT NULL,
displayName TEXT NOT NULL,
secret TEXT NOT NULL,
token_url TEXT NOT NULL,
auth_url TEXT NOT NULL,
me_url TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS session ( CREATE TABLE IF NOT EXISTS session (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
cookie TEXT PRIMARY KEY NOT NULL UNIQUE, cookie TEXT NOT NULL UNIQUE,
userid INTEGER NOT NULL, userid INTEGER NOT NULL,
createAt TEXT NOT NULL, createAt TEXT NOT NULL,
userAgent TEXT NOT NULL, userAgent TEXT NOT NULL,
reason INTEGER, reason INTEGER,
FOREIGN KEY(userid) REFERENCES user(id), FOREIGN KEY(userid) REFERENCES user(id)
FOREIGN KEY(reason) REFERENCES provider(id)
); );

View file

@ -10,6 +10,7 @@ export type MixinBase<T = {}> = new (...args: any[]) => {
db: sqlite.Database, db: sqlite.Database,
} & T; } & T;
export type SqliteReturn = object | undefined;
// Only way to use the database. Everything must be done through this. // Only way to use the database. Everything must be done through this.
// Prefer to use prepared statement `using this.db.prepare` // Prefer to use prepared statement `using this.db.prepare`

View file

@ -1,8 +1,16 @@
//import sqlite from "better-sqlite3" //import sqlite from "better-sqlite3"
import { MixinBase } from "./_base" import Joi from "joi"
import { MixinBase, SqliteReturn } from "./_base"
// never use this directly // never use this directly
const schema = Joi.object({
id: Joi.number(),
name: Joi.string(),
password: Joi.string().optional().allow(null),
salt: Joi.string().optional().allow(null),
})
export const UserDb = function <TBase extends MixinBase>(Base: TBase) { export const UserDb = function <TBase extends MixinBase>(Base: TBase) {
return class extends Base { return class extends Base {
@ -13,15 +21,29 @@ export const UserDb = function <TBase extends MixinBase>(Base: TBase) {
} }
private userFromRow(row: any): User { private userFromRow(row: any): User {
throw "TODO: User from Row" const v = Joi.attempt(row, schema);
return {
id: v.id as UserId,
name: v.name || null,
password: v.password || null,
salt: v.salt,
}
} }
public getUser(id: UserId): User | null { public getUser(id: UserId): User | null {
return null return this.getUserFromRawId(id);
} }
public getUserFromRawId(id: number): User | null {
let res = this.prepare('SELECT * FROM user WHERE id = ?').get(id) as SqliteReturn;
if (res === null || res === undefined) return null;
return this.userFromRow(res);
}
public setUser(id: UserId, partialUser: Partial<Omit<User, 'id'>>): User | null { public setUser(id: UserId, partialUser: Partial<Omit<User, 'id'>>): User | null {
return null return null
} }
} }
} }

View file

@ -14,6 +14,8 @@
}, },
"devDependencies": { "devDependencies": {
"rimraf": "^5.0.1" "rimraf": "^5.0.1"
},
"dependencies": {
"bindings": "^1.5.0"
} }
} }

View file

@ -2,3 +2,8 @@ packages:
- ./* - ./*
nodeLinker: hoisted nodeLinker: hoisted
onlyBuiltDependencies:
- better-sqlite3
- esbuild
- sharp