refactor(vnUser): refs #7792 use twoFactorFk and add foreignKey
gitea/salix/pipeline/pr-dev Build queued... Details

This commit is contained in:
Alex Moreno 2024-09-09 09:58:20 +02:00
parent 05b75c1f0d
commit 71eb44d083
14 changed files with 83 additions and 23 deletions

View File

@ -33,7 +33,7 @@ module.exports = Self => {
const where = Self.userUses(user);
const vnUser = await Self.findOne({
fields: ['id', 'name', 'password', 'active', 'email', 'passExpired', 'twoFactor'],
fields: ['id', 'name', 'password', 'active', 'email', 'passExpired', 'twoFactorFk'],
where
}, myOptions);
@ -46,7 +46,7 @@ module.exports = Self => {
await Self.sendTwoFactor(ctx, vnUser, myOptions);
await Self.passExpired(vnUser, myOptions);
if (vnUser.twoFactor)
if (vnUser.twoFactorFk)
throw new ForbiddenError(null, 'REQUIRES_2FA');
}
return Self.validateLogin(user, password, ctx);
@ -58,13 +58,13 @@ module.exports = Self => {
if (vnUser.passExpired && vnUser.passExpired.getTime() <= today.getTime()) {
const err = new UserError('Pass expired', 'passExpired');
err.details = {userId: vnUser.id, twoFactor: vnUser.twoFactor ? true : false};
err.details = {userId: vnUser.id, twoFactorFk: vnUser.twoFactorFk ? true : false};
throw err;
}
};
Self.sendTwoFactor = async(ctx, vnUser, myOptions) => {
if (vnUser.twoFactor === 'email') {
if (vnUser.twoFactorFk === 'email') {
const $ = Self.app.models;
const min = 100000;

View File

@ -70,7 +70,7 @@ describe('VnUser Sign-in()', () => {
let error;
try {
const options = {transaction: tx};
await employee.updateAttribute('twoFactor', 'email', options);
await employee.updateAttribute('twoFactorFk', 'email', options);
await VnUser.signIn(unAuthCtx, 'employee', 'nightmare', options);
await tx.rollback();

View File

@ -25,8 +25,8 @@ module.exports = Self => {
type: 'string',
description: 'The user lang'
}, {
arg: 'twoFactor',
type: 'string',
arg: 'twoFactorFk',
type: 'any',
description: 'The user twoFactor'
}
],
@ -36,8 +36,8 @@ module.exports = Self => {
}
});
Self.updateUser = async(ctx, id, name, nickname, email, lang, twoFactor) => {
Self.updateUser = async(ctx, id, name, nickname, email, lang, twoFactorFk) => {
await Self.userSecurity(ctx, id);
await Self.upsertWithWhere({id}, {name, nickname, email, lang, twoFactor});
await Self.upsertWithWhere({id}, {name, nickname, email, lang, twoFactorFk});
};
};

View File

@ -55,7 +55,7 @@ module.exports = Self => {
throw new UserError('Invalid or expired verification code');
const user = await Self.findById(authCode.userFk, {
fields: ['name', 'twoFactor']
fields: ['name', 'twoFactorFk']
}, myOptions);
if (user.name.toLowerCase() !== username.toLowerCase())

View File

@ -58,9 +58,6 @@
},
"passExpired": {
"type": "date"
},
"twoFactor": {
"type": "string"
}
},
"relations": {
@ -89,6 +86,11 @@
"type": "hasOne",
"model": "UserConfig",
"foreignKey": "userFk"
},
"twoFactor": {
"type": "belongsTo",
"model": "TwoFactorType",
"foreignKey": "twoFactorFk"
}
},
"acls": [
@ -165,7 +167,8 @@
"hasGrant",
"realm",
"email",
"emailVerified"
"emailVerified",
"twoFactorFk"
]
}
}

View File

@ -9,7 +9,7 @@
},
"vn": {
"view": {
"expeditionPallet_Print": "ced2b84a114fcb99fce05f0c34f4fc03f3fa387bef92621be1bc306608a84345"
"expeditionPallet_Print": "99f75145ac2e7b612a6d71e74b6e55f194a465780fd9875a15eb01e6596b447e"
}
}
}

View File

@ -7,10 +7,10 @@ BEGIN
UPDATE vn.department_recalc SET isChanged = TRUE;
END IF;
IF !(OLD.twoFactor <=> NEW.twoFactor) THEN
IF !(OLD.twoFactorFk <=> NEW.twoFactorFk) THEN
UPDATE account.user u
JOIN vn.workerDepartment wd ON wd.workerFk = u.id
SET u.twoFactor = NEW.twoFactor
SET u.twoFactorFk = NEW.twoFactorFk
WHERE wd.departmentFk = NEW.id;
END IF;
END$$

View File

@ -0,0 +1,27 @@
CREATE OR REPLACE TABLE account.twoFactorType (
`code` varchar(20) NOT NULL,
`description` varchar(255) NOT NULL,
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
ALTER TABLE account.user ADD twoFactorFk varchar(20) NULL;
ALTER TABLE account.user ADD CONSTRAINT user_twoFactor_fk FOREIGN KEY (twoFactorFk) REFERENCES account.twoFactorType(code) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE vn.department ADD twoFactorFk varchar(20) NULL;
ALTER TABLE vn.department ADD CONSTRAINT department_twoFactor_fk FOREIGN KEY (twoFactorFk) REFERENCES account.twoFactorType(code) ON DELETE CASCADE ON UPDATE CASCADE;
INSERT INTO account.twoFactorType (code, description)
VALUES('email', 'Envia un código por email');
UPDATE account.`user` u
JOIN account.`user` u2 ON u.id = u2.id
SET u.twoFactorFk = u.twoFactor
WHERE u2.twoFactor IS NOT NULL;
UPDATE vn.`department` d
JOIN vn.`department` d2 ON d.id = d2.id
SET d.twoFactorFk = d.twoFactor
WHERE d2.twoFactor IS NOT NULL;
ALTER TABLE account.user CHANGE twoFactor twoFactor__ enum('email') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL NULL COMMENT 'Deprecated 2024-09-09';
ALTER TABLE vn.department CHANGE twoFactor twoFactor__ enum('email') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL NULL COMMENT 'Deprecated 2024-09-09';

View File

@ -22,7 +22,7 @@
autocomplete="false">
</vn-textfield>
<vn-textfield
ng-if="$ctrl.$state.params.twoFactor == 'true'"
ng-if="$ctrl.$state.params.twoFactorFk == 'true'"
label="Verification code"
ng-model="$ctrl.code"
vn-name="code"

View File

@ -37,13 +37,13 @@ module.exports = Self => {
Object.assign(myOptions, options);
const {VnUser} = Self.app.models;
const user = await VnUser.findById(userId, {fields: ['name', 'twoFactor']}, myOptions);
const user = await VnUser.findById(userId, {fields: ['name', 'twoFactorFk']}, myOptions);
await user.hasPassword(oldPassword);
if (oldPassword == newPassword)
throw new UserError(`You can not use the same password`);
if (user.twoFactor)
if (user.twoFactorFk)
await VnUser.validateCode(user.name, code, myOptions);
await VnUser.changePassword(userId, oldPassword, newPassword, myOptions);

View File

@ -75,7 +75,7 @@ describe('account changePassword()', () => {
await models.VnUser.updateAll(
{id: 70},
{
twoFactor: 'email',
twoFactorFk: 'email',
passExpired: yesterday
}
, options);

View File

@ -1,4 +1,7 @@
{
"Account": {
"dataSource": "vn"
},
"AccountConfig": {
"dataSource": "vn"
},
@ -47,7 +50,7 @@
"SipConfig": {
"dataSource": "vn"
},
"Account": {
"TwoFactorType": {
"dataSource": "vn"
},
"UserLog": {

View File

@ -0,0 +1,26 @@
{
"name": "TwoFactorType",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.twoFactorType"
}
},
"properties": {
"code": {
"type": "string",
"id": true
},
"description": {
"type": "string"
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

@ -38,6 +38,7 @@ fixtures:
- userPassword
- accountConfig
- mailConfig
- twoFactorType
salix:
- ACL
- fieldAcl