志愿
This commit is contained in:
@@ -32,6 +32,8 @@ export function createSqliteAdapter(context) {
|
||||
ensureColumns('users', [
|
||||
['admin_level', 'TEXT'], ['school_id', 'TEXT'], ['class_id', 'TEXT'], ['active', 'INTEGER NOT NULL DEFAULT 1'],
|
||||
['candidate_number', 'TEXT'], ['must_change_password', 'INTEGER NOT NULL DEFAULT 0'],
|
||||
['totp_enabled', 'INTEGER NOT NULL DEFAULT 0'], ['totp_secret_encrypted', 'TEXT'],
|
||||
['totp_recovery_codes', "TEXT NOT NULL DEFAULT '[]'"], ['totp_last_used_step', 'INTEGER'],
|
||||
['archived_at', 'TEXT'], ['archived_by', 'TEXT']
|
||||
]);
|
||||
ensureColumns('schema_metadata', [['self_registration_enabled', 'INTEGER NOT NULL DEFAULT 0']]);
|
||||
@@ -39,7 +41,8 @@ export function createSqliteAdapter(context) {
|
||||
['school_id', 'TEXT'], ['class_id', 'TEXT'], ['native_place', 'TEXT'], ['birth_date', 'TEXT'], ['ethnicity', 'TEXT'],
|
||||
['postal_code', 'TEXT'], ['guardian_name', 'TEXT'], ['guardian_phone', 'TEXT'], ['profile_completed', 'INTEGER NOT NULL DEFAULT 0'],
|
||||
['province_code', 'TEXT'], ['province_name', 'TEXT'], ['city_code', 'TEXT'], ['city_name', 'TEXT'],
|
||||
['district_code', 'TEXT'], ['district_name', 'TEXT']
|
||||
['district_code', 'TEXT'], ['district_name', 'TEXT'], ['specialty_types', "TEXT NOT NULL DEFAULT '[]'"],
|
||||
['specialty_certificate', 'TEXT'], ['policy_eligibility', 'TEXT']
|
||||
]);
|
||||
ensureColumns('registrations', [['registration_number', 'TEXT'], ['number_rule_id', 'TEXT']]);
|
||||
ensureColumns('exams', [
|
||||
@@ -68,6 +71,32 @@ export function createSqliteAdapter(context) {
|
||||
ensureColumns('admit_card_subjects', [
|
||||
['building', "TEXT NOT NULL DEFAULT ''"], ['floor', "TEXT NOT NULL DEFAULT ''"]
|
||||
]);
|
||||
if (tableExists('users')) {
|
||||
const usersSql = connection.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'users'").get()?.sql || '';
|
||||
if (!usersSql.includes('admission_school')) {
|
||||
connection.exec(`
|
||||
PRAGMA foreign_keys = OFF;
|
||||
BEGIN IMMEDIATE;
|
||||
CREATE TABLE users_v18 (
|
||||
id TEXT PRIMARY KEY, username TEXT NOT NULL UNIQUE, candidate_number TEXT UNIQUE, password_hash TEXT NOT NULL,
|
||||
role TEXT NOT NULL CHECK (role IN ('admin', 'candidate', 'admission_school')),
|
||||
admin_level TEXT CHECK (admin_level IN ('super', 'school', 'class')),
|
||||
school_id TEXT REFERENCES schools(id) ON DELETE SET NULL, class_id TEXT REFERENCES school_classes(id) ON DELETE SET NULL,
|
||||
active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0, 1)), must_change_password INTEGER NOT NULL DEFAULT 0 CHECK (must_change_password IN (0, 1)),
|
||||
totp_enabled INTEGER NOT NULL DEFAULT 0 CHECK (totp_enabled IN (0, 1)), totp_secret_encrypted TEXT,
|
||||
totp_recovery_codes TEXT NOT NULL DEFAULT '[]', totp_last_used_step INTEGER, archived_at TEXT,
|
||||
archived_by TEXT REFERENCES users_v18(id) ON DELETE RESTRICT, display_name TEXT NOT NULL, created_at TEXT NOT NULL
|
||||
) STRICT;
|
||||
INSERT INTO users_v18 SELECT id, username, candidate_number, password_hash, role, admin_level, school_id, class_id,
|
||||
active, must_change_password, COALESCE(totp_enabled, 0), totp_secret_encrypted, COALESCE(totp_recovery_codes, '[]'),
|
||||
totp_last_used_step, archived_at, archived_by, display_name, created_at FROM users;
|
||||
DROP TABLE users;
|
||||
ALTER TABLE users_v18 RENAME TO users;
|
||||
COMMIT;
|
||||
PRAGMA foreign_keys = ON;
|
||||
`);
|
||||
}
|
||||
}
|
||||
if (tableExists('workflow_definitions')) {
|
||||
const definitionSql = connection.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'workflow_definitions'").get()?.sql || '';
|
||||
if (!definitionSql.includes('candidate_account_batch')) {
|
||||
@@ -246,13 +275,10 @@ export function createSqliteAdapter(context) {
|
||||
connection.prepare('UPDATE schema_metadata SET schema_version = 16 WHERE id = 1').run();
|
||||
}
|
||||
if (existingSystem && Number(existingSystem.schema_version || 1) < 17) {
|
||||
connection.exec(`
|
||||
ALTER TABLE users ADD COLUMN totp_enabled INTEGER NOT NULL DEFAULT 0 CHECK (totp_enabled IN (0, 1));
|
||||
ALTER TABLE users ADD COLUMN totp_secret_encrypted TEXT;
|
||||
ALTER TABLE users ADD COLUMN totp_recovery_codes TEXT NOT NULL DEFAULT '[]';
|
||||
ALTER TABLE users ADD COLUMN totp_last_used_step INTEGER;
|
||||
UPDATE schema_metadata SET schema_version = 17 WHERE id = 1;
|
||||
`);
|
||||
connection.prepare('UPDATE schema_metadata SET schema_version = 17 WHERE id = 1').run();
|
||||
}
|
||||
if (existingSystem && Number(existingSystem.schema_version || 1) < 18) {
|
||||
connection.prepare('UPDATE schema_metadata SET schema_version = 18, app_version = 18 WHERE id = 1').run();
|
||||
}
|
||||
if (existingSystem && Number(existingSystem.app_version || 1) < 2) {
|
||||
const extension = seed();
|
||||
@@ -414,7 +440,7 @@ export function createSqliteAdapter(context) {
|
||||
try {
|
||||
connection.prepare(`
|
||||
INSERT INTO schema_metadata (id, schema_version, app_version, self_registration_enabled, created_at)
|
||||
VALUES (1, 17, ?, ?, ?)
|
||||
VALUES (1, 18, ?, ?, ?)
|
||||
`).run(Number(initialState.meta?.version || 1), initialState.settings?.selfRegistrationEnabled ? 1 : 0, initialState.meta?.createdAt || new Date().toISOString());
|
||||
for (const item of buildSeedOperations(initialState)) connection.prepare(item.sql).run(...item.params);
|
||||
connection.exec('COMMIT');
|
||||
|
||||
Reference in New Issue
Block a user