Add passkey and magic link authentication
This commit is contained in:
@@ -18,6 +18,18 @@ await mkdir(dirname(databasePath), { recursive: true });
|
||||
const database = await connect(databasePath);
|
||||
const schema = await readFile(schemaPath, 'utf8');
|
||||
|
||||
const usersTable = await (await database.prepare(
|
||||
"SELECT 1 FROM sqlite_master WHERE type='table' AND name='users'"
|
||||
)).get();
|
||||
if (usersTable) {
|
||||
const userColumns = await (await database.prepare("PRAGMA table_info('users')")).all();
|
||||
if (!userColumns.some((column) => column.name === 'login_username')) {
|
||||
console.log('Separating optional local login usernames from internal account identifiers.');
|
||||
await database.exec('ALTER TABLE users ADD COLUMN login_username TEXT');
|
||||
await database.exec('UPDATE users SET login_username=username WHERE password_hash IS NOT NULL');
|
||||
}
|
||||
}
|
||||
|
||||
// The project schema deliberately avoids semicolons inside string literals.
|
||||
const statements = schema
|
||||
.split(';')
|
||||
@@ -28,6 +40,25 @@ for (const statement of statements) {
|
||||
await database.exec(statement);
|
||||
}
|
||||
|
||||
const loginEventsDefinition = await (await database.prepare(
|
||||
"SELECT sql FROM sqlite_master WHERE type='table' AND name='login_events'"
|
||||
)).get();
|
||||
if (typeof loginEventsDefinition?.sql === 'string' && !loginEventsDefinition.sql.includes('magic_link')) {
|
||||
console.log('Expanding login event providers for passwordless authentication.');
|
||||
await database.exec('ALTER TABLE login_events RENAME TO login_events_legacy');
|
||||
await database.exec(`CREATE TABLE login_events (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
|
||||
provider TEXT NOT NULL CHECK(provider IN ('password', 'discord', 'magic_link', 'passkey')),
|
||||
succeeded INTEGER NOT NULL CHECK(succeeded IN (0, 1)),
|
||||
created_at TEXT NOT NULL
|
||||
)`);
|
||||
await database.exec(`INSERT INTO login_events(id,user_id,provider,succeeded,created_at)
|
||||
SELECT id,user_id,provider,succeeded,created_at FROM login_events_legacy`);
|
||||
await database.exec('DROP TABLE login_events_legacy');
|
||||
await database.exec('CREATE INDEX IF NOT EXISTS login_events_user_created_idx ON login_events(user_id, created_at DESC)');
|
||||
}
|
||||
|
||||
console.log(`Applied ${statements.length} schema statements to ${databasePath}`);
|
||||
|
||||
if (!databaseAlreadyExisted) {
|
||||
|
||||
Reference in New Issue
Block a user