diff --git a/back/methods/vn-user/addAlias.js b/back/methods/vn-user/addAlias.js
new file mode 100644
index 000000000..9fe43e713
--- /dev/null
+++ b/back/methods/vn-user/addAlias.js
@@ -0,0 +1,68 @@
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+ Self.remoteMethod('addAlias', {
+ description: 'Add an alias if the user has the grant',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'ctx',
+ type: 'Object',
+ http: {source: 'context'}
+ },
+ {
+ arg: 'id',
+ type: 'number',
+ required: true,
+ description: 'The user id',
+ http: {source: 'path'}
+ },
+ {
+ arg: 'mailAlias',
+ type: 'number',
+ description: 'The new alias for user',
+ required: true
+ }
+ ],
+ http: {
+ path: `/:id/addAlias`,
+ verb: 'POST'
+ }
+ });
+
+ Self.addAlias = async function(ctx, id, mailAlias, options) {
+ const models = Self.app.models;
+ const userId = ctx.req.accessToken.userId;
+
+ const myOptions = {};
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ const user = await Self.findById(userId, {fields: ['hasGrant']}, myOptions);
+
+ if (!user.hasGrant)
+ throw new UserError(`You don't have grant privilege`);
+
+ const account = await models.Account.findById(userId, {
+ fields: ['id'],
+ include: {
+ relation: 'aliases',
+ scope: {
+ fields: ['mailAlias']
+ }
+ }
+ }, myOptions);
+
+ const aliases = account.aliases().map(alias => alias.mailAlias);
+
+ const hasAlias = aliases.includes(mailAlias);
+ if (!hasAlias)
+ throw new UserError(`You cannot assign an alias that you are not assigned to`);
+
+ return models.MailAliasAccount.create({
+ mailAlias: mailAlias,
+ account: id
+ }, myOptions);
+ };
+};
diff --git a/back/methods/vn-user/removeAlias.js b/back/methods/vn-user/removeAlias.js
new file mode 100644
index 000000000..0424c3e96
--- /dev/null
+++ b/back/methods/vn-user/removeAlias.js
@@ -0,0 +1,55 @@
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+ Self.remoteMethod('removeAlias', {
+ description: 'Remove alias if the user has the grant',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'ctx',
+ type: 'Object',
+ http: {source: 'context'}
+ },
+ {
+ arg: 'id',
+ type: 'number',
+ required: true,
+ description: 'The user id',
+ http: {source: 'path'}
+ },
+ {
+ arg: 'mailAlias',
+ type: 'number',
+ description: 'The alias to delete',
+ required: true
+ }
+ ],
+ http: {
+ path: `/:id/removeAlias`,
+ verb: 'POST'
+ }
+ });
+
+ Self.removeAlias = async function(ctx, id, mailAlias, options) {
+ const models = Self.app.models;
+ const userId = ctx.req.accessToken.userId;
+
+ const myOptions = {};
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ const canRemoveAlias = await models.ACL.checkAccessAcl(ctx, 'VnUser', 'canRemoveAlias', 'WRITE');
+
+ if (userId != id && !canRemoveAlias) throw new UserError(`You don't have grant privilege`);
+
+ const mailAliasAccount = await models.MailAliasAccount.findOne({
+ where: {
+ mailAlias: mailAlias,
+ account: id
+ }
+ }, myOptions);
+
+ await mailAliasAccount.destroy(myOptions);
+ };
+};
diff --git a/back/methods/vn-user/specs/addAlias.spec.js b/back/methods/vn-user/specs/addAlias.spec.js
new file mode 100644
index 000000000..ef657a3a8
--- /dev/null
+++ b/back/methods/vn-user/specs/addAlias.spec.js
@@ -0,0 +1,68 @@
+const {models} = require('vn-loopback/server/server');
+
+describe('VnUser addAlias()', () => {
+ const employeeId = 1;
+ const sysadminId = 66;
+ const developerId = 9;
+ const customerId = 2;
+ const mailAlias = 1;
+ it('should throw an error when user not has privileges', async() => {
+ const ctx = {req: {accessToken: {userId: employeeId}}};
+ const tx = await models.VnUser.beginTransaction({});
+
+ let error;
+ try {
+ const options = {transaction: tx};
+
+ await models.VnUser.addAlias(ctx, employeeId, mailAlias, options);
+
+ await tx.rollback();
+ } catch (e) {
+ error = e;
+ await tx.rollback();
+ }
+
+ expect(error.message).toContain(`You don't have grant privilege`);
+ });
+
+ it('should throw an error when user has privileges but not has the role from user', async() => {
+ const ctx = {req: {accessToken: {userId: sysadminId}}};
+ const tx = await models.VnUser.beginTransaction({});
+
+ let error;
+ try {
+ const options = {transaction: tx};
+
+ await models.VnUser.addAlias(ctx, employeeId, mailAlias, options);
+
+ await tx.rollback();
+ } catch (e) {
+ error = e;
+ await tx.rollback();
+ }
+
+ expect(error.message).toContain(`You cannot assign an alias that you are not assigned to`);
+ });
+
+ it('should add an alias', async() => {
+ const ctx = {req: {accessToken: {userId: developerId}}};
+ const tx = await models.VnUser.beginTransaction({});
+
+ let result;
+ try {
+ const options = {transaction: tx};
+
+ const user = await models.VnUser.findById(developerId, null, options);
+ await user.updateAttribute('hasGrant', true, options);
+
+ result = await models.VnUser.addAlias(ctx, customerId, mailAlias, options);
+
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ }
+
+ expect(result.mailAlias).toBe(mailAlias);
+ expect(result.account).toBe(customerId);
+ });
+});
diff --git a/back/models/vn-user.js b/back/models/vn-user.js
index b58395acc..12aab585c 100644
--- a/back/models/vn-user.js
+++ b/back/models/vn-user.js
@@ -11,6 +11,8 @@ module.exports = function(Self) {
require('../methods/vn-user/validate-token')(Self);
require('../methods/vn-user/privileges')(Self);
require('../methods/vn-user/renew-token')(Self);
+ require('../methods/vn-user/addAlias')(Self);
+ require('../methods/vn-user/removeAlias')(Self);
Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create');
diff --git a/db/changes/232601/00-aclAddAlias.sql b/db/changes/232601/00-aclAddAlias.sql
new file mode 100644
index 000000000..cc96f5ad8
--- /dev/null
+++ b/db/changes/232601/00-aclAddAlias.sql
@@ -0,0 +1,11 @@
+INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
+ VALUES
+ ('VnUser', 'addAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee');
+
+INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
+ VALUES
+ ('VnUser', 'removeAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee');
+
+INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
+ VALUES
+ ('VnUser', 'canRemoveAlias', 'WRITE', 'ALLOW', 'ROLE', 'itManagement');
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index 20a9557e9..809ed5874 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -296,7 +296,8 @@
"Fecha fuera de rango": "Fecha fuera de rango",
"Error while generating PDF": "Error al generar PDF",
"Error when sending mail to client": "Error al enviar el correo al cliente",
- "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico",
+ "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico",
"The renew period has not been exceeded": "El periodo de renovación no ha sido superado",
- "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}"
+ "Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}",
+ "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado"
}
diff --git a/modules/account/front/aliases/index.html b/modules/account/front/aliases/index.html
index 11d546afb..4a73ec873 100644
--- a/modules/account/front/aliases/index.html
+++ b/modules/account/front/aliases/index.html
@@ -17,9 +17,7 @@
+ ng-click="removeConfirm.show(row)">
@@ -32,9 +30,7 @@
translate-attr="{title: 'Add'}"
vn-bind="+"
ng-click="$ctrl.onAddClick()"
- fixed-bottom-right
- vn-acl="itManagement"
- vn-acl-action="remove">
+ fixed-bottom-right>
this.refresh())
.then(() => this.vnApp.showSuccess(
this.$t('Subscribed to alias!'))
@@ -34,11 +33,12 @@ export default class Controller extends Section {
}
onRemove(row) {
- return this.$http.delete(`MailAliasAccounts/${row.id}`)
- .then(() => {
- this.$.data.splice(this.$.data.indexOf(row), 1);
- this.vnApp.showSuccess(this.$t('Unsubscribed from alias!'));
- });
+ const params = {
+ mailAlias: row.mailAlias
+ };
+ return this.$http.post(`VnUsers/${this.$params.id}/removeAlias`, params)
+ .then(() => this.refresh())
+ .then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
}
}
diff --git a/modules/account/front/aliases/index.spec.js b/modules/account/front/aliases/index.spec.js
index 466f1e1e9..61f71949c 100644
--- a/modules/account/front/aliases/index.spec.js
+++ b/modules/account/front/aliases/index.spec.js
@@ -25,8 +25,9 @@ describe('component vnUserAliases', () => {
describe('onAddSave()', () => {
it('should add the new row', () => {
controller.addData = {account: 1};
+ controller.$params = {id: 1};
- $httpBackend.expectPOST('MailAliasAccounts').respond();
+ $httpBackend.expectPOST('VnUsers/1/addAlias').respond();
$httpBackend.expectGET('MailAliasAccounts').respond('foo');
controller.onAddSave();
$httpBackend.flush();
@@ -41,12 +42,14 @@ describe('component vnUserAliases', () => {
{id: 1, alias: 'foo'},
{id: 2, alias: 'bar'}
];
+ controller.$params = {id: 1};
- $httpBackend.expectDELETE('MailAliasAccounts/1').respond();
+ $httpBackend.expectPOST('VnUsers/1/removeAlias').respond();
+ $httpBackend.expectGET('MailAliasAccounts').respond(controller.$.data[1]);
controller.onRemove(controller.$.data[0]);
$httpBackend.flush();
- expect(controller.$.data).toEqual([{id: 2, alias: 'bar'}]);
+ expect(controller.$.data).toEqual({id: 2, alias: 'bar'});
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
});
});
diff --git a/modules/supplier/back/models/supplier.js b/modules/supplier/back/models/supplier.js
index 9c78e8590..e88fadc0b 100644
--- a/modules/supplier/back/models/supplier.js
+++ b/modules/supplier/back/models/supplier.js
@@ -103,7 +103,7 @@ module.exports = Self => {
const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance;
const loopBackContext = LoopBackContext.getCurrentContext();
- const accessToken = {req: loopBackContext.active.accessToken};
+ const accessToken = {req: loopBackContext.active};
const editPayMethodCheck =
await Self.app.models.ACL.checkAccessAcl(accessToken, 'Supplier', 'editPayMethodCheck', 'WRITE');