maddy-admin/src/lib/db.ts
2024-01-17 20:21:08 +01:00

79 lines
2.3 KiB
TypeScript

import sqlite from "sqlite3";
import bcrypt from "bcryptjs";
import { PHASE_PRODUCTION_BUILD } from "next/dist/shared/lib/constants";
export const database = (type: 'credentials'|'aliases') => {
if (process.env.NEXT_PHASE != PHASE_PRODUCTION_BUILD) {
for (const v of ["CREDENTIALS_DB_PATH", "ALIASES_DB_PATH"]) {
if (!process.env[v]) {
throw `$${v} not provided; unable to connect to database`;
}
}
}
const dbPath = type == 'credentials'
? process.env["CREDENTIALS_DB_PATH"]
: process.env["ALIASES_DB_PATH"];
return new sqlite.Database(dbPath!, (err: any) => {
if (err && process.env.NEXT_PHASE != PHASE_PRODUCTION_BUILD) throw err;
});
};
export function validateCredentials(email: string, password: string) {
const db = database('credentials');
return new Promise<boolean>((resolve, reject) => {
db.get(
"SELECT key, value FROM passwords WHERE key = ?",
email,
async (err, row: any) => {
db.close(); // We don't need this anymore
if (err) return reject(err);
if (!row) return resolve(false);
try {
const hash: string = row.value.replace("bcrypt:", "");
const isValid = await bcrypt.compare(password, hash);
resolve(isValid);
} catch(e) {
reject(e);
}
}
);
});
}
export function setUserPassword(email: string, newPass: string) {
return new Promise<void>(async (resolve, reject) => {
const db = database('credentials');
const hash = 'bcrypt:' + await bcrypt.hash(newPass, 10);
db.run("UPDATE passwords SET value = $1 WHERE key = $2",
{ 1: hash, 2: email },
async (err: any, res: any) => {
db.close();
if (err) return reject(err);
console.log(res);
resolve();
});
});
}
export type AliasEntry = { id: number, address: string, alias: string, pending: boolean };
export function getUserAliases(email: string) {
return new Promise<AliasEntry[]>(async (resolve, reject) => {
const db = database('aliases');
db.all("SELECT id, address, alias, pending FROM aliases WHERE address = ?", email, (err, res: any[]) => {
db.close();
if (err) return reject(err);
resolve(res.map((data) => ({
...data,
pending: !!data.pending,
})));
});
});
}