"use strict"; module.exports = { async up(queryInterface, Sequelize) { const userColumns = await queryInterface.describeTable("users"); await queryInterface.changeColumn("users", "accountType", { type: Sequelize.ENUM("superadmin", "admin", "manager", "business_customer", "rider", "customer", "support_agent"), allowNull: false, defaultValue: "customer", }); await queryInterface.changeColumn("users", "password", { type: Sequelize.STRING, allowNull: true }); if (!userColumns.passwordChangedAt) await queryInterface.addColumn("users", "passwordChangedAt", { type: Sequelize.DATE, allowNull: true }); await queryInterface.addColumn("users", "tokenVersion", { type: Sequelize.INTEGER, allowNull: false, defaultValue: 0 }); await queryInterface.addColumn("users", "lastLoginAt", { type: Sequelize.DATE, allowNull: true }); await queryInterface.createTable("auth_sessions", { id: { type: Sequelize.UUID, primaryKey: true }, user_id: { type: Sequelize.STRING, allowNull: false, references: { model: "users", key: "id" }, onDelete: "CASCADE" }, token_family_id: { type: Sequelize.UUID, allowNull: false }, refresh_token_hash: { type: Sequelize.STRING(64), allowNull: false }, device_name: Sequelize.STRING, user_agent: Sequelize.STRING(500), ip_address: Sequelize.STRING(64), remember_me: { type: Sequelize.BOOLEAN, allowNull: false, defaultValue: false }, token_version: { type: Sequelize.INTEGER, allowNull: false }, last_used_at: Sequelize.DATE, expires_at: { type: Sequelize.DATE, allowNull: false }, revoked_at: Sequelize.DATE, revoked_reason: Sequelize.STRING, replaced_by_session_id: Sequelize.UUID, createdAt: { type: Sequelize.DATE, allowNull: false }, updatedAt: { type: Sequelize.DATE, allowNull: false }, }); await queryInterface.addIndex("auth_sessions", ["user_id"]); await queryInterface.addIndex("auth_sessions", ["token_family_id"]); await queryInterface.addIndex("auth_sessions", ["expires_at"]); await queryInterface.createTable("user_identities", { id: { type: Sequelize.UUID, primaryKey: true }, user_id: { type: Sequelize.STRING, allowNull: false, references: { model: "users", key: "id" }, onDelete: "CASCADE" }, provider: { type: Sequelize.ENUM("google", "apple"), allowNull: false }, provider_subject: { type: Sequelize.STRING, allowNull: false }, provider_email: Sequelize.STRING, createdAt: { type: Sequelize.DATE, allowNull: false }, updatedAt: { type: Sequelize.DATE, allowNull: false }, }); await queryInterface.addIndex("user_identities", ["provider", "provider_subject"], { unique: true, name: "user_identity_provider_subject_unique" }); await queryInterface.addIndex("user_identities", ["user_id"]); await queryInterface.createTable("user_roles", { id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true }, user_id: { type: Sequelize.STRING, allowNull: false, references: { model: "users", key: "id" }, onDelete: "CASCADE" }, role_id: { type: Sequelize.STRING, allowNull: false, references: { model: "roles", key: "role_id" }, onDelete: "CASCADE" }, createdAt: { type: Sequelize.DATE, allowNull: false }, updatedAt: { type: Sequelize.DATE, allowNull: false }, }); await queryInterface.addIndex("user_roles", ["user_id", "role_id"], { unique: true, name: "user_role_unique" }); await queryInterface.addIndex("rolePermission", ["role_id", "permission_id"], { unique: true, name: "role_permission_unique" }); await queryInterface.addIndex("userPermission", ["user_id", "permission_id"], { unique: true, name: "user_permission_unique" }); await queryInterface.addIndex("roles", ["roleName"], { unique: true, name: "role_name_unique" }); }, async down(queryInterface, Sequelize) { await queryInterface.removeIndex("roles", "role_name_unique"); await queryInterface.removeIndex("userPermission", "user_permission_unique"); await queryInterface.removeIndex("rolePermission", "role_permission_unique"); await queryInterface.dropTable("user_roles"); await queryInterface.dropTable("user_identities"); await queryInterface.dropTable("auth_sessions"); await queryInterface.removeColumn("users", "lastLoginAt"); await queryInterface.removeColumn("users", "tokenVersion"); // passwordChangedAt may predate this migration, so down intentionally preserves it. await queryInterface.changeColumn("users", "password", { type: Sequelize.STRING, allowNull: false }); await queryInterface.changeColumn("users", "accountType", { type: Sequelize.ENUM("business_customer", "customer"), defaultValue: "customer" }); }, };