From bd535374d8bf197066a2a3949acbf5e3e6b5644a Mon Sep 17 00:00:00 2001 From: jorgep Date: Mon, 16 Oct 2023 15:58:25 +0200 Subject: [PATCH 1/3] ref #6138 setPasword created --- back/models/vn-user.json | 6 +- db/changes/234201/00-aclSetPassword.sql | 4 ++ .../worker/back/methods/worker/setPassword.js | 48 +++++++++++++++ .../methods/worker/specs/setPassword.spec.js | 61 +++++++++++++++++++ modules/worker/back/models/worker.js | 1 + modules/worker/front/card/index.js | 2 +- modules/worker/front/descriptor/index.html | 30 ++++++++- modules/worker/front/descriptor/index.js | 29 ++++++++- modules/worker/front/descriptor/index.spec.js | 20 ++++++ 9 files changed, 195 insertions(+), 6 deletions(-) create mode 100644 db/changes/234201/00-aclSetPassword.sql create mode 100644 modules/worker/back/methods/worker/setPassword.js create mode 100644 modules/worker/back/methods/worker/specs/setPassword.spec.js diff --git a/back/models/vn-user.json b/back/models/vn-user.json index 9e3f8df89..01d83e421 100644 --- a/back/models/vn-user.json +++ b/back/models/vn-user.json @@ -45,6 +45,9 @@ "email": { "type": "string" }, + "emailVerified": { + "type": "boolean" + }, "created": { "type": "date" }, @@ -144,7 +147,8 @@ "image", "hasGrant", "realm", - "email" + "email", + "emailVerified" ] } } diff --git a/db/changes/234201/00-aclSetPassword.sql b/db/changes/234201/00-aclSetPassword.sql new file mode 100644 index 000000000..44b3e9de0 --- /dev/null +++ b/db/changes/234201/00-aclSetPassword.sql @@ -0,0 +1,4 @@ +INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) + VALUES ('Worker','setPassword','*','ALLOW','ROLE','employee'); + + diff --git a/modules/worker/back/methods/worker/setPassword.js b/modules/worker/back/methods/worker/setPassword.js new file mode 100644 index 000000000..fcfb5e733 --- /dev/null +++ b/modules/worker/back/methods/worker/setPassword.js @@ -0,0 +1,48 @@ +const UserError = require('vn-loopback/util/user-error'); +module.exports = Self => { + Self.remoteMethodCtx('setPassword', { + description: 'Set a new password', + accepts: [ + { + arg: 'workerFk', + type: 'number', + required: true, + description: 'The worker id', + }, + { + arg: 'newPass', + type: 'String', + required: true, + description: 'The new worker password' + } + ], + http: { + path: `/:id/setPassword`, + verb: 'PATCH' + } + }); + Self.setPassword = async(ctx, options) => { + const models = Self.app.models; + const myOptions = {}; + const {args} = ctx; + let tx; + if (typeof options == 'object') + Object.assign(myOptions, options); + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + try { + const isSubordinate = await models.Worker.isSubordinate(ctx, args.workerFk, myOptions); + if (!isSubordinate) throw new UserError('You don\'t have enough privileges.'); + + await models.VnUser.setPassword(args.workerFk, args.newPass, myOptions); + await models.VnUser.updateAll({id: args.workerFk}, {emailVerified: 1}, myOptions); + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/worker/back/methods/worker/specs/setPassword.spec.js b/modules/worker/back/methods/worker/specs/setPassword.spec.js new file mode 100644 index 000000000..fbb403b24 --- /dev/null +++ b/modules/worker/back/methods/worker/specs/setPassword.spec.js @@ -0,0 +1,61 @@ +const UserError = require('vn-loopback/util/user-error'); + +const models = require('vn-loopback/server/server').models; + +describe('worker setPassword()', () => { + let ctx; + beforeAll(() => { + ctx = { + req: { + accessToken: {}, + headers: {origin: 'http://localhost'} + }, + args: {workerFk: 9} + }; + }); + + beforeEach(() => { + ctx.req.accessToken.userId = 20; + ctx.args.newPass = 'H3rn4d3z#'; + }); + + it('should change the password', async() => { + const tx = await models.Worker.beginTransaction({}); + + try { + const options = {transaction: tx}; + await models.Worker.setPassword(ctx, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should throw an error: Password does not meet requirements', async() => { + const tx = await models.Collection.beginTransaction({}); + ctx.args.newPass = 'Hi'; + try { + const options = {transaction: tx}; + await models.Worker.setPassword(ctx, options); + await tx.rollback(); + } catch (e) { + expect(e.sqlMessage).toEqual('Password does not meet requirements'); + await tx.rollback(); + } + }); + + it('should throw an error: You don\'t have enough privileges.', async() => { + ctx.req.accessToken.userId = 5; + const tx = await models.Collection.beginTransaction({}); + try { + const options = {transaction: tx}; + await models.Worker.setPassword(ctx, options); + await tx.rollback(); + } catch (e) { + expect(e).toEqual(new UserError(`You don't have enough privileges.`)); + await tx.rollback(); + } + }); +}); diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index ccae3a6e6..985d83e9f 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -18,6 +18,7 @@ module.exports = Self => { require('../methods/worker/allocatePDA')(Self); require('../methods/worker/search')(Self); require('../methods/worker/isAuthorized')(Self); + require('../methods/worker/setPassword')(Self); Self.validatesUniquenessOf('locker', { message: 'This locker has already been assigned' diff --git a/modules/worker/front/card/index.js b/modules/worker/front/card/index.js index b8b533c5d..9a40e31c2 100644 --- a/modules/worker/front/card/index.js +++ b/modules/worker/front/card/index.js @@ -8,7 +8,7 @@ class Controller extends ModuleCard { { relation: 'user', scope: { - fields: ['name'], + fields: ['name', 'emailVerified'], include: { relation: 'emailUser', scope: { diff --git a/modules/worker/front/descriptor/index.html b/modules/worker/front/descriptor/index.html index 758f639ff..aa6b80300 100644 --- a/modules/worker/front/descriptor/index.html +++ b/modules/worker/front/descriptor/index.html @@ -11,6 +11,9 @@ ? 'Click to allow the user to be disabled' : 'Click to exclude the user from getting disabled'}} + + Change password +
@@ -72,4 +75,29 @@ - + + + + + + + + + + + + diff --git a/modules/worker/front/descriptor/index.js b/modules/worker/front/descriptor/index.js index 07e16c0d6..fe337974c 100644 --- a/modules/worker/front/descriptor/index.js +++ b/modules/worker/front/descriptor/index.js @@ -1,5 +1,6 @@ import ngModule from '../module'; import Descriptor from 'salix/components/descriptor'; +const UserError = require('vn-loopback/util/user-error'); class Controller extends Descriptor { constructor($element, $, $rootScope) { super($element, $); @@ -12,9 +13,11 @@ class Controller extends Descriptor { set worker(value) { this.entity = value; - if (value) this.getIsExcluded(); + + if (this.entity && !this.entity.user.emailVerified) + this.getPassRequirements(); } getIsExcluded() { @@ -38,7 +41,7 @@ class Controller extends Descriptor { { relation: 'user', scope: { - fields: ['name'], + fields: ['name', 'emailVerified'], include: { relation: 'emailUser', scope: { @@ -66,10 +69,30 @@ class Controller extends Descriptor { } ] }; - + // Añadir filter para sacar user return this.getData(`Workers/${this.id}`, {filter}) .then(res => this.entity = res.data); } + + getPassRequirements() { + this.$http.get('UserPasswords/findOne') + .then(res => { + this.passRequirements = res.data; + }); + } + + setPassword() { + if (!this.newPassword) + throw new UserError(`You must enter a new password`); + if (this.newPassword != this.repeatPassword) + throw new UserError(`Passwords don't match`); + this.$http.patch( + `Workers/${this.entity.id}/setPassword`, + {workerFk: this.entity.id, newPass: this.newPassword} + ) .then(() => { + this.vnApp.showSuccess(this.$translate.instant('Password changed!')); + }); + } } Controller.$inject = ['$element', '$scope', '$rootScope']; diff --git a/modules/worker/front/descriptor/index.spec.js b/modules/worker/front/descriptor/index.spec.js index dfb800415..d158a9e8e 100644 --- a/modules/worker/front/descriptor/index.spec.js +++ b/modules/worker/front/descriptor/index.spec.js @@ -23,4 +23,24 @@ describe('vnWorkerDescriptor', () => { expect(controller.worker).toEqual(response); }); }); + + describe('setPassword()', () => { + it('should throw an error: You must enter a new password', () => { + try { + controller.setPassword(); + } catch (error) { + expect(error.message).toEqual('You must enter a new password'); + } + }); + + it('should throw an error: Passwords don\'t match', () => { + controller.newPassword = 'aaa'; + controller.repeatPassword = 'bbb'; + try { + controller.setPassword(); + } catch (error) { + expect(error.message).toEqual('Passwords don\'t match'); + } + }); + }); }); From 48003b5d03541ef7e19a8e703dc5609bbc3647b2 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 17 Oct 2023 08:28:15 +0200 Subject: [PATCH 2/3] ref #6138 --- modules/worker/front/descriptor/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/worker/front/descriptor/index.js b/modules/worker/front/descriptor/index.js index fe337974c..13ffa6f2f 100644 --- a/modules/worker/front/descriptor/index.js +++ b/modules/worker/front/descriptor/index.js @@ -69,7 +69,6 @@ class Controller extends Descriptor { } ] }; - // Añadir filter para sacar user return this.getData(`Workers/${this.id}`, {filter}) .then(res => this.entity = res.data); } From 52b14cf8b4fb8c4f0f19337c4ef56148b403c8c6 Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 19 Oct 2023 09:51:10 +0200 Subject: [PATCH 3/3] ref #6138 fix emailVerified --- modules/worker/back/methods/worker/setPassword.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/back/methods/worker/setPassword.js b/modules/worker/back/methods/worker/setPassword.js index fcfb5e733..43d3d946f 100644 --- a/modules/worker/back/methods/worker/setPassword.js +++ b/modules/worker/back/methods/worker/setPassword.js @@ -37,7 +37,7 @@ module.exports = Self => { if (!isSubordinate) throw new UserError('You don\'t have enough privileges.'); await models.VnUser.setPassword(args.workerFk, args.newPass, myOptions); - await models.VnUser.updateAll({id: args.workerFk}, {emailVerified: 1}, myOptions); + await models.VnUser.updateAll({id: args.workerFk}, {emailVerified: true}, myOptions); if (tx) await tx.commit(); } catch (e) {