Files
core/src/features/auth/db.js
T

125 lines
3.4 KiB
JavaScript

/**
* Auth Feature - Database
* Creates and drops zen_auth_* tables.
*/
import { query, tableExists } from '@zen/core/database';
import { done, warn } from '@zen/core/shared/logger';
import { createTables as createUserCoreTables, dropTables as dropUserCoreTables } from '../../core/users/db.js';
const AUTH_TABLES = [
{
name: 'zen_auth_users',
sql: `
CREATE TABLE zen_auth_users (
id text NOT NULL PRIMARY KEY,
name text NOT NULL,
email text NOT NULL UNIQUE,
email_verified boolean NOT NULL DEFAULT false,
image text,
created_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL,
role text DEFAULT 'user' CHECK (role IN ('admin', 'user'))
)
`
},
{
name: 'zen_auth_sessions',
sql: `
CREATE TABLE zen_auth_sessions (
id text NOT NULL PRIMARY KEY,
expires_at timestamptz NOT NULL,
token text NOT NULL UNIQUE,
created_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamptz NOT NULL,
ip_address text,
user_agent text,
user_id text NOT NULL REFERENCES zen_auth_users (id) ON DELETE CASCADE
)
`
},
{
name: 'zen_auth_accounts',
sql: `
CREATE TABLE zen_auth_accounts (
id text NOT NULL PRIMARY KEY,
account_id text NOT NULL,
provider_id text NOT NULL,
user_id text NOT NULL REFERENCES zen_auth_users (id) ON DELETE CASCADE,
access_token text,
refresh_token text,
id_token text,
access_token_expires_at timestamptz,
refresh_token_expires_at timestamptz,
scope text,
password text,
created_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamptz NOT NULL
)
`
},
{
name: 'zen_auth_verifications',
sql: `
CREATE TABLE zen_auth_verifications (
id text NOT NULL PRIMARY KEY,
identifier text NOT NULL,
value text NOT NULL,
token text NOT NULL,
expires_at timestamptz NOT NULL,
created_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at timestamptz DEFAULT CURRENT_TIMESTAMP NOT NULL
)
`
}
];
/**
* Create all authentication tables.
* @returns {Promise<{ created: string[], skipped: string[] }>}
*/
export async function createTables() {
const created = [];
const skipped = [];
for (const table of AUTH_TABLES) {
const exists = await tableExists(table.name);
if (!exists) {
await query(table.sql);
created.push(table.name);
done(`Created table: ${table.name}`);
} else {
skipped.push(table.name);
}
}
// Create role/permission tables and seed defaults
const coreResult = await createUserCoreTables();
created.push(...coreResult.created);
skipped.push(...coreResult.skipped);
return { created, skipped };
}
/**
* Drop all authentication tables in reverse dependency order.
* @returns {Promise<void>}
*/
export async function dropTables() {
const dropOrder = [...AUTH_TABLES].reverse().map(t => t.name);
warn('Dropping all Zen authentication tables...');
for (const tableName of dropOrder) {
const exists = await tableExists(tableName);
if (exists) {
await query(`DROP TABLE IF EXISTS "${tableName}" CASCADE`);
done(`Dropped table: ${tableName}`);
}
}
await dropUserCoreTables();
done('All authentication tables dropped');
}