55 lines
1.7 KiB
JavaScript
55 lines
1.7 KiB
JavaScript
/**
|
|
* Physician users (OTP login), OTP codes, and link applications to users.
|
|
* Leaves admin_users unchanged.
|
|
* @param {import('knex').Knex} knex
|
|
*/
|
|
export async function up(knex) {
|
|
await knex.schema.createTable('users', (table) => {
|
|
table.charset('utf8mb4');
|
|
table.collate('utf8mb4_unicode_ci');
|
|
table.increments('id').primary();
|
|
table.string('email', 255).notNullable().unique();
|
|
table.string('name', 255).nullable();
|
|
table.boolean('is_active').notNullable().defaultTo(true);
|
|
table.datetime('last_login_at').nullable();
|
|
table.timestamps(true, true);
|
|
});
|
|
|
|
await knex.schema.createTable('login_otps', (table) => {
|
|
table.charset('utf8mb4');
|
|
table.collate('utf8mb4_unicode_ci');
|
|
table.increments('id').primary();
|
|
table.string('email', 255).notNullable().index();
|
|
table.string('code_hash', 128).notNullable();
|
|
table.datetime('expires_at').notNullable();
|
|
table.integer('attempts').unsigned().notNullable().defaultTo(0);
|
|
table.datetime('used_at').nullable();
|
|
table.datetime('created_at').notNullable().defaultTo(knex.fn.now());
|
|
});
|
|
|
|
await knex.schema.alterTable('applications', (table) => {
|
|
table
|
|
.integer('user_id')
|
|
.unsigned()
|
|
.nullable()
|
|
.unique()
|
|
.references('id')
|
|
.inTable('users')
|
|
.onDelete('SET NULL');
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {import('knex').Knex} knex
|
|
*/
|
|
export async function down(knex) {
|
|
await knex.schema.alterTable('applications', (table) => {
|
|
table.dropForeign(['user_id']);
|
|
table.dropUnique(['user_id']);
|
|
table.dropColumn('user_id');
|
|
});
|
|
|
|
await knex.schema.dropTableIfExists('login_otps');
|
|
await knex.schema.dropTableIfExists('users');
|
|
}
|