diff --git a/back/models/vn-user.js b/back/models/vn-user.js index 39a0abd9e..b58395acc 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -12,6 +12,8 @@ module.exports = function(Self) { require('../methods/vn-user/privileges')(Self); require('../methods/vn-user/renew-token')(Self); + Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create'); + // Validations Self.validatesFormatOf('email', { diff --git a/back/models/vn-user.json b/back/models/vn-user.json index 8486e29b8..61e42f77a 100644 --- a/back/models/vn-user.json +++ b/back/models/vn-user.json @@ -118,5 +118,24 @@ "principalId": "$authenticated", "permission": "ALLOW" } - ] + ], + "scopes": { + "preview": { + "fields": [ + "id", + "name", + "username", + "roleFk", + "nickname", + "lang", + "active", + "created", + "updated", + "image", + "hasGrant", + "realm", + "email" + ] + } + } } diff --git a/db/changes/231801/00-userAcl.sql b/db/changes/231801/00-userAcl.sql index 64803bf18..9eb3ebf28 100644 --- a/db/changes/231801/00-userAcl.sql +++ b/db/changes/231801/00-userAcl.sql @@ -1,6 +1,5 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) VALUES - ('VnUser', '*', '*', 'ALLOW', 'ROLE', 'employee'), ('VnUser','acl','READ','ALLOW','ROLE','account'), ('VnUser','getCurrentUserData','READ','ALLOW','ROLE','account'), ('VnUser','changePassword', 'WRITE', 'ALLOW', 'ROLE', 'account'), diff --git a/db/changes/232601/00-aclAccount.sql b/db/changes/232601/00-aclAccount.sql new file mode 100644 index 000000000..bf8106b98 --- /dev/null +++ b/db/changes/232601/00-aclAccount.sql @@ -0,0 +1,8 @@ +DELETE + FROM `salix`.`ACL` + WHERE model='Account' AND property='*' AND accessType='*'; + +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('Account', '*', 'WRITE', 'ALLOW', 'ROLE', 'sysadmin'), + ('Account', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/232601/00-aclMailAliasAccount.sql b/db/changes/232601/00-aclMailAliasAccount.sql new file mode 100644 index 000000000..619e9bb6e --- /dev/null +++ b/db/changes/232601/00-aclMailAliasAccount.sql @@ -0,0 +1,5 @@ +DELETE FROM `salix`.`ACL` WHERE model = 'MailAliasAccount'; +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('MailAliasAccount', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('MailAliasAccount', '*', 'WRITE', 'ALLOW', 'ROLE', 'itManagement'); diff --git a/db/changes/232601/00-aclMailForward.sql b/db/changes/232601/00-aclMailForward.sql new file mode 100644 index 000000000..afe2acec8 --- /dev/null +++ b/db/changes/232601/00-aclMailForward.sql @@ -0,0 +1,5 @@ +DELETE FROM `salix`.`ACL` WHERE model = 'MailForward'; +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('MailForward', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('MailForward', '*', 'WRITE', 'ALLOW', 'ROLE', 'itManagement'); diff --git a/db/changes/232601/00-aclRole.sql b/db/changes/232601/00-aclRole.sql new file mode 100644 index 000000000..e16f052be --- /dev/null +++ b/db/changes/232601/00-aclRole.sql @@ -0,0 +1,5 @@ +DELETE FROM `salix`.`ACL` WHERE model = 'Role'; +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('Role', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Role', '*', 'WRITE', 'ALLOW', 'ROLE', 'it'); diff --git a/db/changes/232601/00-aclVnUser.sql b/db/changes/232601/00-aclVnUser.sql new file mode 100644 index 000000000..39fa2cb14 --- /dev/null +++ b/db/changes/232601/00-aclVnUser.sql @@ -0,0 +1,10 @@ +DELETE + FROM `salix`.`ACL` + WHERE model = 'VnUser' AND property = '*' AND principalId = 'employee'; + +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('VnUser', '*', '*', 'ALLOW', 'ROLE', 'itManagement'), + ('VnUser', '__get__preview', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('VnUser', 'preview', '*', 'ALLOW', 'ROLE', 'employee'), + ('VnUser', 'create', '*', 'ALLOW', 'ROLE', 'itManagement'); diff --git a/e2e/paths/03-worker/06_create.spec.js b/e2e/paths/03-worker/06_create.spec.js index 98e67edbf..11d36b3cf 100644 --- a/e2e/paths/03-worker/06_create.spec.js +++ b/e2e/paths/03-worker/06_create.spec.js @@ -53,7 +53,7 @@ describe('Worker create path', () => { expect(message.text).toContain('Data saved!'); // 'rollback' - await page.loginAndModule('sysadmin', 'account'); + await page.loginAndModule('itManagement', 'account'); await page.accessToSearchResult(newWorker); await page.waitToClick(selectors.accountDescriptor.menuButton); diff --git a/e2e/paths/14-account/01_create_and_basic_data.spec.js b/e2e/paths/14-account/01_create_and_basic_data.spec.js index 54e4d1f12..e38d1aeec 100644 --- a/e2e/paths/14-account/01_create_and_basic_data.spec.js +++ b/e2e/paths/14-account/01_create_and_basic_data.spec.js @@ -8,7 +8,7 @@ describe('Account create and basic data path', () => { beforeAll(async() => { browser = await getBrowser(); page = browser.page; - await page.loginAndModule('developer', 'account'); + await page.loginAndModule('itManagement', 'account'); }); afterAll(async() => { diff --git a/modules/account/front/aliases/index.html b/modules/account/front/aliases/index.html index 9f4ba857f..11d546afb 100644 --- a/modules/account/front/aliases/index.html +++ b/modules/account/front/aliases/index.html @@ -17,7 +17,9 @@ + ng-click="removeConfirm.show(row)" + vn-acl="itManagement" + vn-acl-action="remove"> @@ -30,9 +32,11 @@ translate-attr="{title: 'Add'}" vn-bind="+" ng-click="$ctrl.onAddClick()" - fixed-bottom-right> + fixed-bottom-right + vn-acl="itManagement" + vn-acl-action="remove"> - @@ -49,7 +53,7 @@ - this.user = res.data), + this.$http.get(`VnUsers/preview`, {filter}) + .then(res => { + const [user] = res.data; + this.user = user; + }), this.$http.get(`Accounts/${this.$params.id}/exists`) .then(res => this.hasAccount = res.data.exists) ]); diff --git a/modules/account/front/card/index.spec.js b/modules/account/front/card/index.spec.js index 204b897e4..712d3c1d8 100644 --- a/modules/account/front/card/index.spec.js +++ b/modules/account/front/card/index.spec.js @@ -15,12 +15,12 @@ describe('component vnUserCard', () => { it('should reload the controller data', () => { controller.$params.id = 1; - $httpBackend.expectGET('VnUsers/1').respond('foo'); + $httpBackend.expectGET('VnUsers/preview').respond('foo'); $httpBackend.expectGET('Accounts/1/exists').respond({exists: true}); controller.reload(); $httpBackend.flush(); - expect(controller.user).toBe('foo'); + expect(controller.user).toBe('f'); expect(controller.hasAccount).toBeTruthy(); }); }); diff --git a/modules/account/front/create/index.html b/modules/account/front/create/index.html index ee2de926a..acc07d346 100644 --- a/modules/account/front/create/index.html +++ b/modules/account/front/create/index.html @@ -12,18 +12,18 @@ @@ -39,7 +39,7 @@ type="password"> diff --git a/modules/account/front/create/index.js b/modules/account/front/create/index.js index 41fd718f6..01ba7905b 100644 --- a/modules/account/front/create/index.js +++ b/modules/account/front/create/index.js @@ -2,6 +2,11 @@ import ngModule from '../module'; import Section from 'salix/components/section'; export default class Controller extends Section { + constructor($element, $) { + super($element, $); + this.user = {active: true}; + } + onSubmit() { return this.$.watcher.submit().then(res => { this.$state.go('account.card.basicData', {id: res.data.id}); diff --git a/modules/account/front/descriptor/index.html b/modules/account/front/descriptor/index.html index 7a7ba43f3..381b2991c 100644 --- a/modules/account/front/descriptor/index.html +++ b/modules/account/front/descriptor/index.html @@ -6,7 +6,7 @@ Delete @@ -15,7 +15,7 @@ ng-if="::$root.user.id == $ctrl.id" ng-click="$ctrl.onChangePassClick(true)" name="changePassword" - vn-acl="hr" + vn-acl="sysadmin" vn-acl-action="remove" translate> Change password @@ -23,7 +23,7 @@ Set password @@ -32,7 +32,7 @@ ng-if="!$ctrl.hasAccount" ng-click="enableAccount.show()" name="enableAccount" - vn-acl="it" + vn-acl="sysadmin" vn-acl-action="remove" translate> Enable account @@ -41,7 +41,7 @@ ng-if="$ctrl.hasAccount" ng-click="disableAccount.show()" name="disableAccount" - vn-acl="it" + vn-acl="sysadmin" vn-acl-action="remove" translate> Disable account @@ -50,7 +50,7 @@ ng-if="!$ctrl.user.active" ng-click="activateUser.show()" name="activateUser" - vn-acl="hr" + vn-acl="itManagement" vn-acl-action="remove" translate> Activate user @@ -59,7 +59,7 @@ ng-if="$ctrl.user.active" ng-click="deactivateUser.show()" name="deactivateUser" - vn-acl="hr" + vn-acl="itManagement" vn-acl-action="remove" translate> Deactivate user diff --git a/modules/account/front/index/index.html b/modules/account/front/index/index.html index d067c8c37..7502c8b3d 100644 --- a/modules/account/front/index/index.html +++ b/modules/account/front/index/index.html @@ -14,11 +14,11 @@
{{::user.nickname}}
@@ -36,12 +36,12 @@ - - \ No newline at end of file + diff --git a/modules/account/front/mail-forwarding/index.html b/modules/account/front/mail-forwarding/index.html index 6c688f504..df5cd80bf 100644 --- a/modules/account/front/mail-forwarding/index.html +++ b/modules/account/front/mail-forwarding/index.html @@ -14,12 +14,12 @@ Todos los correos serán reenviados a la dirección especificada, no se mantendrá copia de los mismos en el buzón del usuario. +You don't have enough privileges: No tienes suficientes permisos diff --git a/modules/account/front/main/index.html b/modules/account/front/main/index.html index 5872a328d..36b493ec4 100644 --- a/modules/account/front/main/index.html +++ b/modules/account/front/main/index.html @@ -1,6 +1,6 @@ diff --git a/modules/account/front/privileges/index.html b/modules/account/front/privileges/index.html index 8e33b708e..61f2c534e 100644 --- a/modules/account/front/privileges/index.html +++ b/modules/account/front/privileges/index.html @@ -1,9 +1,7 @@ @@ -11,15 +9,16 @@ name="form" ng-submit="watcher.submit()" class="vn-w-md"> - + - + + + this.$.summary = res.data); + this.$http.get(`VnUsers/preview`, {filter}) + .then(res => { + const [summary] = res.data; + this.$.summary = summary; + }); } get isHr() { return this.aclService.hasAny(['hr']); diff --git a/modules/client/front/web-access/index.html b/modules/client/front/web-access/index.html index 15dc5ed58..74407ba5c 100644 --- a/modules/client/front/web-access/index.html +++ b/modules/client/front/web-access/index.html @@ -1,7 +1,5 @@ @@ -51,9 +49,9 @@ label="Save"> + ng-if="$ctrl.canChangePassword" + label="Change password" + vn-dialog="change-pass"> { + const [user] = res.data; + this.account = user; + }); + } + + get client() { + return this._client; + } + $onChanges() { if (this.client) { this.account = this.client.account; diff --git a/modules/client/front/web-access/index.spec.js b/modules/client/front/web-access/index.spec.js index c1bb47a8e..7325bf932 100644 --- a/modules/client/front/web-access/index.spec.js +++ b/modules/client/front/web-access/index.spec.js @@ -5,12 +5,14 @@ describe('Component VnClientWebAccess', () => { let $scope; let vnApp; let controller; + let $httpParamSerializer; beforeEach(ngModule('client')); - beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _vnApp_) => { + beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_, _vnApp_) => { $scope = $rootScope.$new(); $httpBackend = _$httpBackend_; + $httpParamSerializer = _$httpParamSerializer_; vnApp = _vnApp_; jest.spyOn(vnApp, 'showError'); const $element = angular.element(''); @@ -32,7 +34,10 @@ describe('Component VnClientWebAccess', () => { describe('isCustomer()', () => { it('should return true if the password can be modified', () => { controller.client = {id: '1234'}; + const filter = {where: {id: controller.client.id}}; + const serializedParams = $httpParamSerializer({filter}); + $httpBackend.expectGET(`VnUsers/preview?${serializedParams}`).respond('foo'); $httpBackend.expectGET(`Clients/${controller.client.id}/hasCustomerRole`).respond(true); controller.isCustomer(); $httpBackend.flush(); @@ -42,7 +47,10 @@ describe('Component VnClientWebAccess', () => { it(`should return a false if the password can't be modified`, () => { controller.client = {id: '1234'}; + const filter = {where: {id: controller.client.id}}; + const serializedParams = $httpParamSerializer({filter}); + $httpBackend.expectGET(`VnUsers/preview?${serializedParams}`).respond('foo'); $httpBackend.expectGET(`Clients/${controller.client.id}/hasCustomerRole`).respond(false); controller.isCustomer(); $httpBackend.flush(); @@ -54,9 +62,12 @@ describe('Component VnClientWebAccess', () => { describe('checkConditions()', () => { it('should perform a query to check if the client is valid', () => { controller.client = {id: '1234'}; + const filter = {where: {id: controller.client.id}}; + const serializedParams = $httpParamSerializer({filter}); expect(controller.canEnableCheckBox).toBeTruthy(); + $httpBackend.expectGET(`VnUsers/preview?${serializedParams}`).respond('foo'); $httpBackend.expectGET(`Clients/${controller.client.id}/isValidClient`).respond(false); controller.checkConditions(); $httpBackend.flush(); @@ -82,7 +93,10 @@ describe('Component VnClientWebAccess', () => { controller.newPassword = 'm24x8'; controller.repeatPassword = 'm24x8'; controller.canChangePassword = true; + const filter = {where: {id: controller.client.id}}; + const serializedParams = $httpParamSerializer({filter}); + $httpBackend.expectGET(`VnUsers/preview?${serializedParams}`).respond('foo'); const query = `Clients/${controller.client.id}/setPassword`; $httpBackend.expectPATCH(query, {newPassword: controller.newPassword}).respond('done'); controller.onPassChange(); diff --git a/modules/worker/back/methods/worker/isAuthorized.js b/modules/worker/back/methods/worker/isAuthorized.js new file mode 100644 index 000000000..519aab94f --- /dev/null +++ b/modules/worker/back/methods/worker/isAuthorized.js @@ -0,0 +1,44 @@ +module.exports = Self => { + Self.remoteMethod('isAuthorized', { + description: 'Return true if the current user is a superior of the worker that is passed by parameter', + accessType: 'READ', + accepts: [{ + arg: 'ctx', + type: 'Object', + http: {source: 'context'} + }, { + arg: 'id', + type: 'number', + required: true, + description: 'The worker id', + http: {source: 'path'} + }], + returns: { + type: 'boolean', + root: true + }, + http: { + path: `/:id/isAuthorized`, + verb: 'GET' + } + }); + + Self.isAuthorized = async(ctx, id, options) => { + const models = Self.app.models; + const currentUserId = ctx.req.accessToken.userId; + const isHimself = currentUserId == id; + + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const isSubordinate = await models.Worker.isSubordinate(ctx, id, myOptions); + const isTeamBoss = await models.VnUser.hasRole(currentUserId, 'teamBoss', myOptions); + + if (!isSubordinate || (isSubordinate && isHimself && !isTeamBoss)) + return false; + + return true; + }; +}; diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index fa17640a8..b44703a88 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -16,6 +16,7 @@ module.exports = Self => { require('../methods/worker/new')(Self); require('../methods/worker/deallocatePDA')(Self); require('../methods/worker/allocatePDA')(Self); + require('../methods/worker/isAuthorized')(Self); Self.validatesUniquenessOf('locker', { message: 'This locker has already been assigned' diff --git a/modules/worker/front/account/index.html b/modules/worker/front/account/index.html deleted file mode 100644 index 6f6be660c..000000000 --- a/modules/worker/front/account/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - -
- - - - - - - - - - - - - -
diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html index c9eacbd82..29540081e 100644 --- a/modules/worker/front/calendar/index.html +++ b/modules/worker/front/calendar/index.html @@ -63,6 +63,7 @@ ng-model="$ctrl.businessId" search-function="{businessFk: $search}" value-field="businessFk" + show-field="businessFk" order="businessFk DESC" limit="5"> diff --git a/modules/worker/front/calendar/index.js b/modules/worker/front/calendar/index.js index 4ca0fc929..a52ecd7da 100644 --- a/modules/worker/front/calendar/index.js +++ b/modules/worker/front/calendar/index.js @@ -71,10 +71,6 @@ class Controller extends Section { } } - get payedHolidays() { - return this._businessId; - } - buildYearFilter() { const now = Date.vnNew(); now.setFullYear(now.getFullYear() + 1); @@ -95,10 +91,10 @@ class Controller extends Section { } getActiveContract() { - this.$http.get(`Workers/${this.worker.id}/activeContract`).then(res => { - if (res.data) - this.businessId = res.data.businessFk; - }); + this.$http.get(`Workers/${this.worker.id}/activeContract`) + .then(res => { + if (res.data) this.businessId = res.data.businessFk; + }); } getContractHolidays() {