fix singletone

This commit is contained in:
monoid 2023-01-06 23:22:00 +09:00
parent 687c1ac5e8
commit b552553edb
6 changed files with 50 additions and 20 deletions

View File

@ -43,7 +43,6 @@ const CSSPlugin: Plugin = {
};
},
};
await prepareSecretKey();
async function startServer(manifest: Manifest, options: StartOptions = {}) {
const ctx = await ServerContext.fromManifest(manifest, options);
@ -86,7 +85,10 @@ if (import.meta.main) {
.option("--db-path <path:string>", "The path to the database file.", {
default: ":memory:",
})
.option("--id-password <idpassword:string>", "The password to use. (Not recommended). id:password format.")
.option(
"--id-password <idpassword:string>",
"The password to use. (Not recommended). id:password format.",
)
.arguments("[hostname:string]")
.action(async ({ debug, port, auth, dbPath, idPassword }, hostname) => {
hostname ??= "localhost";
@ -98,7 +100,7 @@ if (import.meta.main) {
}
if (idPassword) {
Deno.env.set("AUTH_REQUIRED", "true");
const db = connectDB();
const db = await connectDB();
const [username, password] = idPassword.split(":");
const new_user = await users.createUser(username, password);
await users.addUser(db, new_user);
@ -106,6 +108,7 @@ if (import.meta.main) {
if (debug) {
console.log("Debug mode enabled.");
}
await prepareSecretKey();
await prepareDocs();
await start({
port: port,

View File

@ -3,12 +3,11 @@ import { getCookies } from "http/cookie.ts";
import { verify } from "djwt";
import { prepareSecretKey } from "../util/secret.ts";
const secret_key = await prepareSecretKey();
export const handler = async (
req: Request,
ctx: MiddlewareHandlerContext<Record<string, unknown>>,
) => {
const secret_key = await prepareSecretKey();
const cookies = getCookies(req.headers);
const jwt = cookies["auth"];
try {

View File

@ -6,17 +6,16 @@ import { getUser, verifyUser } from "../../src/user/user.ts";
import { create as createJWT } from "djwt";
import { prepareSecretKey } from "../../util/secret.ts";
const SECRET_KEY = await prepareSecretKey();
async function POST(req: Request, ctx: HandlerContext): Promise<Response> {
async function POST(req: Request, _ctx: HandlerContext): Promise<Response> {
const url = new URL(req.url);
const form = await req.formData();
const username = form.get("username");
const password = form.get("password");
if (username && password) {
const DB = connectDB();
const DB = await connectDB();
const user = await getUser(DB, username.toString());
if (user) {
const SECRET_KEY = await prepareSecretKey();
if (await verifyUser(user, password.toString())) {
const headers = new Headers();
const jwt = await createJWT({ alg: "HS512", typ: "JWT" }, {

View File

@ -1,13 +1,31 @@
import { DB } from "sqlite";
import { createSchema } from "./user.ts";
export function connectDB(): DB {
let inmemoryDB: DB | undefined;
let previousPath = "";
let dbCache: DB | undefined;
export async function connectDB(): Promise<DB> {
let DB_path = Deno.env.get("DB_PATH");
if (DB_path === undefined) {
Deno.env.set("DB_PATH", "./db.sqlite");
DB_path = "./db.sqlite";
if (DB_path === ":memory:") {
if (inmemoryDB === undefined) {
inmemoryDB = new DB(":memory:");
await createSchema(inmemoryDB);
}
let db = new DB(DB_path);
createSchema(db);
return inmemoryDB;
} else if (DB_path === undefined) {
Deno.env.set("DB_PATH", "db.sqlite");
DB_path = "db.sqlite";
}
if (dbCache !== undefined && DB_path === previousPath) {
return dbCache;
} else {
dbCache?.close();
dbCache = undefined;
}
const db = new DB(DB_path);
previousPath = DB_path;
dbCache = db;
await createSchema(db);
return db;
}

View File

@ -24,7 +24,7 @@ export const user_command = new Command()
Deno.exit(1);
}
}
const db = connectDB();
const db = await connectDB();
const new_user = await users.createUser(username, password);
await users.addUser(db, new_user);
if (!quiet) {
@ -35,7 +35,7 @@ export const user_command = new Command()
.arguments("<username:string>")
.option("-q, --quiet", "Quiet output.")
.action(async ({ quiet }, username) => {
const db = connectDB();
const db = await connectDB();
await users.deleteUser(db, username);
if (!quiet) {
console.log(`Deleting user ${username}`);
@ -43,7 +43,7 @@ export const user_command = new Command()
})
.command("list", "list all users")
.action(async () => {
const db = connectDB();
const db = await connectDB();
const all_users = await users.getAllUsers(db);
for (const user of all_users) {
console.log(`${user.name}`);
@ -53,7 +53,7 @@ export const user_command = new Command()
.arguments("<username:string> <password:string>")
.option("-q, --quiet", "quiet output.")
.action(async ({ quiet }, [username, password]) => {
const db = connectDB();
const db = await connectDB();
const new_user = await users.createUser(username, password);
await users.updateUser(db, new_user);
if (!quiet) {

View File

@ -8,10 +8,17 @@ export async function generateSecretKey() {
return key;
}
let cacheKey: CryptoKey | undefined;
let previousKey = "invalid";
export async function prepareSecretKey() {
const key = Deno.env.get("SECRET_KEY");
if (key === previousKey) {
return cacheKey!;
}
if (key) {
const jwk = JSON.parse(key) as JsonWebKey;
previousKey = key;
{
const key = await crypto.subtle.importKey(
"jwk",
@ -20,12 +27,16 @@ export async function prepareSecretKey() {
true,
["sign", "verify"],
);
cacheKey = key;
return key;
}
} else {
const key = await generateSecretKey();
const out = await crypto.subtle.exportKey("jwk", key);
Deno.env.set("SECRET_KEY", JSON.stringify(out));
const outStr = JSON.stringify(out);
Deno.env.set("SECRET_KEY", outStr);
cacheKey = key;
previousKey = outStr;
return key;
}
}