108 lines
3.4 KiB
JavaScript
108 lines
3.4 KiB
JavaScript
"use strict";
|
|
|
|
/** @type {import('sequelize-cli').Migration} */
|
|
module.exports = {
|
|
async up(queryInterface, Sequelize) {
|
|
// Add TOTP configuration fields
|
|
await queryInterface.addColumn("Users", "twoFactorEnabled", {
|
|
type: Sequelize.BOOLEAN,
|
|
defaultValue: false,
|
|
allowNull: false,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "twoFactorMethod", {
|
|
type: Sequelize.ENUM("totp", "email"),
|
|
allowNull: true,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "totpSecret", {
|
|
type: Sequelize.STRING,
|
|
allowNull: true,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "totpSecretIv", {
|
|
type: Sequelize.STRING,
|
|
allowNull: true,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "twoFactorEnabledAt", {
|
|
type: Sequelize.DATE,
|
|
allowNull: true,
|
|
});
|
|
|
|
// Add Email OTP fields (backup method)
|
|
await queryInterface.addColumn("Users", "emailOtpCode", {
|
|
type: Sequelize.STRING,
|
|
allowNull: true,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "emailOtpExpiry", {
|
|
type: Sequelize.DATE,
|
|
allowNull: true,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "emailOtpAttempts", {
|
|
type: Sequelize.INTEGER,
|
|
defaultValue: 0,
|
|
allowNull: false,
|
|
});
|
|
|
|
// Add Recovery Codes fields
|
|
await queryInterface.addColumn("Users", "recoveryCodesHash", {
|
|
type: Sequelize.TEXT,
|
|
allowNull: true,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "recoveryCodesGeneratedAt", {
|
|
type: Sequelize.DATE,
|
|
allowNull: true,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "recoveryCodesUsedCount", {
|
|
type: Sequelize.INTEGER,
|
|
defaultValue: 0,
|
|
allowNull: false,
|
|
});
|
|
|
|
// Add Step-up session tracking
|
|
await queryInterface.addColumn("Users", "twoFactorVerifiedAt", {
|
|
type: Sequelize.DATE,
|
|
allowNull: true,
|
|
});
|
|
|
|
// Add temporary secret storage during setup
|
|
await queryInterface.addColumn("Users", "twoFactorSetupPendingSecret", {
|
|
type: Sequelize.STRING,
|
|
allowNull: true,
|
|
});
|
|
|
|
await queryInterface.addColumn("Users", "twoFactorSetupPendingSecretIv", {
|
|
type: Sequelize.STRING,
|
|
allowNull: true,
|
|
});
|
|
},
|
|
|
|
async down(queryInterface, Sequelize) {
|
|
// Remove all 2FA fields in reverse order
|
|
await queryInterface.removeColumn("Users", "twoFactorSetupPendingSecretIv");
|
|
await queryInterface.removeColumn("Users", "twoFactorSetupPendingSecret");
|
|
await queryInterface.removeColumn("Users", "twoFactorVerifiedAt");
|
|
await queryInterface.removeColumn("Users", "recoveryCodesUsedCount");
|
|
await queryInterface.removeColumn("Users", "recoveryCodesGeneratedAt");
|
|
await queryInterface.removeColumn("Users", "recoveryCodesHash");
|
|
await queryInterface.removeColumn("Users", "emailOtpAttempts");
|
|
await queryInterface.removeColumn("Users", "emailOtpExpiry");
|
|
await queryInterface.removeColumn("Users", "emailOtpCode");
|
|
await queryInterface.removeColumn("Users", "twoFactorEnabledAt");
|
|
await queryInterface.removeColumn("Users", "totpSecretIv");
|
|
await queryInterface.removeColumn("Users", "totpSecret");
|
|
await queryInterface.removeColumn("Users", "twoFactorMethod");
|
|
await queryInterface.removeColumn("Users", "twoFactorEnabled");
|
|
|
|
// Remove the ENUM type
|
|
await queryInterface.sequelize.query(
|
|
'DROP TYPE IF EXISTS "enum_Users_twoFactorMethod";'
|
|
);
|
|
},
|
|
};
|