diff --git a/server/db/sqlite/migrate.ts b/server/db/sqlite/migrate.ts index 55399ea6..20b9043f 100644 --- a/server/db/sqlite/migrate.ts +++ b/server/db/sqlite/migrate.ts @@ -1,45 +1,12 @@ import { migrate } from "drizzle-orm/better-sqlite3/migrator"; import db from "./driver"; import path from "path"; -import { location } from "./driver"; -import Database from "better-sqlite3"; -import type { Database as BetterSqlite3Database } from "better-sqlite3"; const migrationsFolder = path.join("server/migrations"); -const dropAllTables = (sqlite: BetterSqlite3Database) => { - console.log("Dropping all existing tables..."); - - // Disable foreign key checks - sqlite.pragma('foreign_keys = OFF'); - - // Get all tables - const tables = sqlite.prepare(` - SELECT name FROM sqlite_master - WHERE type='table' - AND name NOT LIKE 'sqlite_%' - `).all() as { name: string }[]; - - // Drop each table - for (const table of tables) { - console.log(`Dropping table: ${table.name}`); - sqlite.prepare(`DROP TABLE IF EXISTS "${table.name}"`).run(); - } - - // Re-enable foreign key checks - sqlite.pragma('foreign_keys = ON'); -}; - const runMigrations = async () => { console.log("Running migrations..."); try { - // Initialize the database file with a valid SQLite header - const sqlite = new Database(location) as BetterSqlite3Database; - - // Drop all existing tables first - dropAllTables(sqlite); - - // Run the migrations migrate(db as any, { migrationsFolder: migrationsFolder, }); diff --git a/server/routers/external.ts b/server/routers/external.ts index 1e39aa11..1ebf0cfe 100644 --- a/server/routers/external.ts +++ b/server/routers/external.ts @@ -794,17 +794,17 @@ authRouter.get("/initial-setup-complete", auth.initialSetupComplete); // Security Key routes authRouter.post( - "/security-key/register/start", + "/security-key/register/start", + verifySessionUserMiddleware, rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes - max: 5, // Allow 5 security key registrations per 15 minutes per IP - keyGenerator: (req) => `securityKeyRegister:${req.ip}:${req.user?.userId}`, + max: 5, // Allow 5 security key registrations per 15 minutes + keyGenerator: (req) => `securityKeyRegister:${req.user?.userId}`, handler: (req, res, next) => { const message = `You can only register ${5} security keys every ${15} minutes. Please try again later.`; return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message)); } }), - verifySessionUserMiddleware, auth.startRegistration ); authRouter.post("/security-key/register/verify", verifySessionUserMiddleware, auth.verifyRegistration); diff --git a/server/setup/migrationsSqlite.ts b/server/setup/migrationsSqlite.ts index aa6649ea..1e279bae 100644 --- a/server/setup/migrationsSqlite.ts +++ b/server/setup/migrationsSqlite.ts @@ -22,8 +22,6 @@ import m18 from "./scriptsSqlite/1.2.0"; import m19 from "./scriptsSqlite/1.3.0"; import m20 from "./scriptsSqlite/1.5.0"; import m21 from "./scriptsSqlite/1.6.0"; -import m22 from "./scriptsSqlite/1.7.0"; -import m23 from "./scriptsSqlite/1.8.0"; // THIS CANNOT IMPORT ANYTHING FROM THE SERVER // EXCEPT FOR THE DATABASE AND THE SCHEMA @@ -45,9 +43,7 @@ const migrations = [ { version: "1.2.0", run: m18 }, { version: "1.3.0", run: m19 }, { version: "1.5.0", run: m20 }, - { version: "1.6.0", run: m21 }, - { version: "1.7.0", run: m22 }, - { version: "1.8.0", run: m23 } + { version: "1.6.0", run: m21 } // Add new migrations here as they are created ] as const; @@ -83,21 +79,17 @@ export async function runMigrations() { try { const appVersion = APP_VERSION; - // Check if the database file exists and has tables - const hasTables = await db.select().from(versionMigrations).limit(1).catch(() => false); - - if (hasTables) { + if (exists) { await executeScripts(); } else { - console.log("Running initial migrations..."); + console.log("Running migrations..."); try { migrate(db, { - migrationsFolder: path.join(APP_PATH, "server", "migrations") + migrationsFolder: path.join(__DIRNAME, "init") // put here during the docker build }); - console.log("Initial migrations completed successfully."); + console.log("Migrations completed successfully."); } catch (error) { - console.error("Error running initial migrations:", error); - throw error; + console.error("Error running migrations:", error); } await db diff --git a/server/setup/scriptsSqlite/1.4.0.ts b/server/setup/scriptsSqlite/1.4.0.ts deleted file mode 100644 index 3885b4bf..00000000 --- a/server/setup/scriptsSqlite/1.4.0.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { db } from "../../db/sqlite"; -import { sql } from "drizzle-orm"; - -const version = "1.4.0"; - -export default async function migration() { - console.log(`Running setup script ${version}...`); - - try { - db.transaction((trx) => { - trx.run(sql`CREATE TABLE 'securityKey' ( - 'credentialId' text PRIMARY KEY NOT NULL, - 'userId' text NOT NULL, - 'publicKey' text NOT NULL, - 'signCount' integer NOT NULL, - 'transports' text, - 'name' text, - 'lastUsed' text NOT NULL, - 'dateCreated' text NOT NULL, - FOREIGN KEY ('userId') REFERENCES 'user'('id') ON DELETE CASCADE - );`); - }); - - console.log(`Migrated database schema`); - } catch (e) { - console.log("Unable to migrate database schema"); - throw e; - } - - console.log(`${version} migration complete`); -} \ No newline at end of file diff --git a/server/setup/scriptsSqlite/1.7.0.ts b/server/setup/scriptsSqlite/1.7.0.ts deleted file mode 100644 index 59166827..00000000 --- a/server/setup/scriptsSqlite/1.7.0.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { APP_PATH } from "@server/lib/consts"; -import Database from "better-sqlite3"; -import path from "path"; - -const version = "1.7.0"; - -export default async function migration() { - console.log(`Running setup script ${version}...`); - - const location = path.join(APP_PATH, "db", "db.sqlite"); - const db = new Database(location); - - try { - db.pragma("foreign_keys = OFF"); - db.transaction(() => { - db.exec(` - CREATE TABLE IF NOT EXISTS securityKey ( - credentialId TEXT PRIMARY KEY, - userId TEXT NOT NULL, - publicKey TEXT NOT NULL, - signCount INTEGER NOT NULL, - transports TEXT, - name TEXT, - lastUsed TEXT NOT NULL, - dateCreated TEXT NOT NULL, - FOREIGN KEY (userId) REFERENCES user(id) ON DELETE CASCADE - ); - `); - })(); // executes the transaction immediately - db.pragma("foreign_keys = ON"); - console.log(`Created securityKey table`); - } catch (e) { - console.error("Unable to create securityKey table"); - console.error(e); - throw e; - } - - console.log(`${version} migration complete`); -} \ No newline at end of file diff --git a/server/setup/scriptsSqlite/1.8.0.ts b/server/setup/scriptsSqlite/1.8.0.ts deleted file mode 100644 index 7777d50e..00000000 --- a/server/setup/scriptsSqlite/1.8.0.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { APP_PATH } from "@server/lib/consts"; -import Database from "better-sqlite3"; -import path from "path"; - -const version = "1.8.0"; - -export default async function migration() { - console.log(`Running setup script ${version}...`); - - const location = path.join(APP_PATH, "db", "db.sqlite"); - const db = new Database(location); - - try { - db.pragma("foreign_keys = OFF"); - db.transaction(() => { - db.exec(` - CREATE TABLE IF NOT EXISTS securityKeyChallenge ( - sessionId TEXT PRIMARY KEY, - challenge TEXT NOT NULL, - securityKeyName TEXT, - userId TEXT, - expiresAt INTEGER NOT NULL, - FOREIGN KEY (userId) REFERENCES user(id) ON DELETE CASCADE - ); - - CREATE INDEX IF NOT EXISTS idx_securityKeyChallenge_expiresAt ON securityKeyChallenge(expiresAt); - `); - })(); // executes the transaction immediately - db.pragma("foreign_keys = ON"); - console.log(`Created securityKeyChallenge table`); - } catch (e) { - console.error("Unable to create securityKeyChallenge table"); - console.error(e); - throw e; - } - - console.log(`${version} migration complete`); -} \ No newline at end of file diff --git a/server/setup/scriptsSqlite/1.8.1.ts b/server/setup/scriptsSqlite/1.8.1.ts deleted file mode 100644 index 560b314a..00000000 --- a/server/setup/scriptsSqlite/1.8.1.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { db } from "@server/db"; - -export default async function migrate() { - try { - console.log("Starting table rename migration..."); - - // Rename the table - await db.run(` - ALTER TABLE securityKeyChallenge RENAME TO webauthnChallenge; - `); - console.log("Successfully renamed table"); - - // Rename the index - await db.run(` - DROP INDEX IF EXISTS idx_securityKeyChallenge_expiresAt; - CREATE INDEX IF NOT EXISTS idx_webauthnChallenge_expiresAt ON webauthnChallenge(expiresAt); - `); - console.log("Successfully updated index"); - - console.log(`Renamed securityKeyChallenge table to webauthnChallenge`); - return true; - } catch (error: any) { - console.error("Unable to rename securityKeyChallenge table:", error); - console.error("Error details:", error.message); - return false; - } -} \ No newline at end of file