Messenger/packages/backend/migrations/1720000000001_auth.cjs
Заид Омар Медхат | Zaid Omar Medhat 1fda5394c3 auth
2026-07-10 14:16:10 +05:00

49 lines
1.9 KiB
JavaScript

// Phase 1 — auth schema: users + refresh_tokens (sessions).
/** @param {import('node-pg-migrate').MigrationBuilder} pgm */
exports.up = (pgm) => {
// Case-insensitive text for the unique username (and non-unique email).
pgm.createExtension('citext', { ifNotExists: true });
pgm.createTable('users', {
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
username: { type: 'citext', notNull: true, unique: true },
display_name: { type: 'text', notNull: true },
// Email is optional and NOT unique (contact field only, not a login credential).
email: { type: 'citext' },
phone: { type: 'text' },
avatar_ref: { type: 'text' },
password_hash: { type: 'text', notNull: true },
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
updated_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
last_seen_at: { type: 'timestamptz' },
});
pgm.createTable('refresh_tokens', {
id: { type: 'uuid', primaryKey: true, default: pgm.func('gen_random_uuid()') },
user_id: {
type: 'uuid',
notNull: true,
references: 'users',
onDelete: 'CASCADE',
},
// Rotation lineage: reuse of any token in a family revokes the whole family.
family_id: { type: 'uuid', notNull: true },
token_hash: { type: 'text', notNull: true, unique: true },
user_agent: { type: 'text' },
ip: { type: 'text' },
created_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
last_used_at: { type: 'timestamptz', notNull: true, default: pgm.func('now()') },
expires_at: { type: 'timestamptz', notNull: true },
revoked_at: { type: 'timestamptz' },
});
pgm.createIndex('refresh_tokens', 'user_id');
pgm.createIndex('refresh_tokens', 'family_id');
};
/** @param {import('node-pg-migrate').MigrationBuilder} pgm */
exports.down = (pgm) => {
pgm.dropTable('refresh_tokens');
pgm.dropTable('users');
};