mirror of
https://github.com/fosrl/pangolin.git
synced 2025-07-31 16:14:46 +02:00
restore migrations and fix rate limit
This commit is contained in:
parent
d3383f0f1a
commit
0a97d91aed
7 changed files with 10 additions and 186 deletions
|
@ -1,45 +1,12 @@
|
||||||
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||||
import db from "./driver";
|
import db from "./driver";
|
||||||
import path from "path";
|
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 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 () => {
|
const runMigrations = async () => {
|
||||||
console.log("Running migrations...");
|
console.log("Running migrations...");
|
||||||
try {
|
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, {
|
migrate(db as any, {
|
||||||
migrationsFolder: migrationsFolder,
|
migrationsFolder: migrationsFolder,
|
||||||
});
|
});
|
||||||
|
|
|
@ -794,17 +794,17 @@ authRouter.get("/initial-setup-complete", auth.initialSetupComplete);
|
||||||
|
|
||||||
// Security Key routes
|
// Security Key routes
|
||||||
authRouter.post(
|
authRouter.post(
|
||||||
"/security-key/register/start",
|
"/security-key/register/start",
|
||||||
|
verifySessionUserMiddleware,
|
||||||
rateLimit({
|
rateLimit({
|
||||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||||
max: 5, // Allow 5 security key registrations per 15 minutes per IP
|
max: 5, // Allow 5 security key registrations per 15 minutes
|
||||||
keyGenerator: (req) => `securityKeyRegister:${req.ip}:${req.user?.userId}`,
|
keyGenerator: (req) => `securityKeyRegister:${req.user?.userId}`,
|
||||||
handler: (req, res, next) => {
|
handler: (req, res, next) => {
|
||||||
const message = `You can only register ${5} security keys every ${15} minutes. Please try again later.`;
|
const message = `You can only register ${5} security keys every ${15} minutes. Please try again later.`;
|
||||||
return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message));
|
return next(createHttpError(HttpCode.TOO_MANY_REQUESTS, message));
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
verifySessionUserMiddleware,
|
|
||||||
auth.startRegistration
|
auth.startRegistration
|
||||||
);
|
);
|
||||||
authRouter.post("/security-key/register/verify", verifySessionUserMiddleware, auth.verifyRegistration);
|
authRouter.post("/security-key/register/verify", verifySessionUserMiddleware, auth.verifyRegistration);
|
||||||
|
|
|
@ -22,8 +22,6 @@ import m18 from "./scriptsSqlite/1.2.0";
|
||||||
import m19 from "./scriptsSqlite/1.3.0";
|
import m19 from "./scriptsSqlite/1.3.0";
|
||||||
import m20 from "./scriptsSqlite/1.5.0";
|
import m20 from "./scriptsSqlite/1.5.0";
|
||||||
import m21 from "./scriptsSqlite/1.6.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
|
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
||||||
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
||||||
|
@ -45,9 +43,7 @@ const migrations = [
|
||||||
{ version: "1.2.0", run: m18 },
|
{ version: "1.2.0", run: m18 },
|
||||||
{ version: "1.3.0", run: m19 },
|
{ version: "1.3.0", run: m19 },
|
||||||
{ version: "1.5.0", run: m20 },
|
{ version: "1.5.0", run: m20 },
|
||||||
{ version: "1.6.0", run: m21 },
|
{ version: "1.6.0", run: m21 }
|
||||||
{ version: "1.7.0", run: m22 },
|
|
||||||
{ version: "1.8.0", run: m23 }
|
|
||||||
// Add new migrations here as they are created
|
// Add new migrations here as they are created
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
@ -83,21 +79,17 @@ export async function runMigrations() {
|
||||||
try {
|
try {
|
||||||
const appVersion = APP_VERSION;
|
const appVersion = APP_VERSION;
|
||||||
|
|
||||||
// Check if the database file exists and has tables
|
if (exists) {
|
||||||
const hasTables = await db.select().from(versionMigrations).limit(1).catch(() => false);
|
|
||||||
|
|
||||||
if (hasTables) {
|
|
||||||
await executeScripts();
|
await executeScripts();
|
||||||
} else {
|
} else {
|
||||||
console.log("Running initial migrations...");
|
console.log("Running migrations...");
|
||||||
try {
|
try {
|
||||||
migrate(db, {
|
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) {
|
} catch (error) {
|
||||||
console.error("Error running initial migrations:", error);
|
console.error("Error running migrations:", error);
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
|
|
|
@ -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`);
|
|
||||||
}
|
|
|
@ -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`);
|
|
||||||
}
|
|
|
@ -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`);
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue