refs #6085 trad, remove front, back test
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Carlos Satorres 2023-12-01 13:58:45 +01:00
parent 9a3efdd6fe
commit 6d486fbec9
15 changed files with 151 additions and 174 deletions

View File

@ -0,0 +1,73 @@
const models = require('vn-loopback/server/server').models;
fdescribe('loopback model MailAliasAccount', () => {
it('should fail to add a mail Alias if the worker doesnt have ACLs', async() => {
const tx = await models.MailAliasAccount.beginTransaction({});
let error;
try {
const options = {transaction: tx, accessToken: {userId: 1}};
await models.MailAliasAccount.create({mailAliasFk: 2, roleFk: 5}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual('The alias cant be modified');
});
it('should add a mail Alias', async() => {
const tx = await models.MailAliasAccount.beginTransaction({});
let error;
try {
const options = {transaction: tx, accessToken: {userId: 9}};
await models.MailAliasAccount.create({mailAliasFk: 2, roleFk: 5}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error).toBeUndefined();
});
it('should add a mail Alias of an inherit role', async() => {
const tx = await models.MailAliasAccount.beginTransaction({});
let error;
try {
const options = {transaction: tx, accessToken: {userId: 9}};
await models.MailAliasAccount.create({mailAliasFk: 3, roleFk: 5}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error).toBeUndefined();
});
it('should delete a mail Alias', async() => {
const tx = await models.MailAliasAccount.beginTransaction({});
let error;
try {
const options = {transaction: tx, accessToken: {userId: 1}};
const mailAclId = 2;
await models.MailAliasAccount.destroyAll({id: mailAclId}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error).toBeUndefined();
});
});

View File

@ -1,5 +1,6 @@
-- Definición de la tabla mailAliasACL -- Definición de la tabla mailAliasACL
CREATE TABLE `account`.`mailAliasACL` (
CREATE OR REPLACE TABLE `account`.`mailAliasAcl` (
`mailAliasFk` int(10) unsigned NOT NULL, `mailAliasFk` int(10) unsigned NOT NULL,
`roleFk` int(10) unsigned NOT NULL, `roleFk` int(10) unsigned NOT NULL,
FOREIGN KEY (`mailAliasFk`) REFERENCES `account`.`mailAlias` (`id`), FOREIGN KEY (`mailAliasFk`) REFERENCES `account`.`mailAlias` (`id`),

View File

@ -3002,3 +3002,10 @@ INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`)
(1, 'Error in VAT calculation'), (1, 'Error in VAT calculation'),
(2, 'Error in sales details'), (2, 'Error in sales details'),
(3, 'Error in customer data'); (3, 'Error in customer data');
INSERT INTO `account`.`mailAliasAcl` (`mailAliasFk`, `roleFk`)
VALUES
(1, 1),
(2, 9),
(3, 15);

View File

@ -68,3 +68,4 @@ Load more results: Cargar más resultados
Send cau: Enviar cau Send cau: Enviar cau
By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
ExplainReason: Explique el motivo por el que no deberia aparecer este fallo ExplainReason: Explique el motivo por el que no deberia aparecer este fallo
You already have the mailAlias: Ya tienes este mail

View File

@ -329,5 +329,7 @@
"The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima", "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima",
"quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima", "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima",
"Cannot past travels with entries": "No se pueden pasar envíos con entradas", "Cannot past travels with entries": "No se pueden pasar envíos con entradas",
"It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}" "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}",
"You already have the mailAlias": "You already have the mailAlias",
"The alias cant be modified": "The alias cant be modified"
} }

View File

@ -14,6 +14,9 @@
"MailAliasAccount": { "MailAliasAccount": {
"dataSource": "vn" "dataSource": "vn"
}, },
"MailAliasAcl": {
"dataSource": "vn"
},
"MailConfig": { "MailConfig": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -2,54 +2,54 @@
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
return new UserError(`You already have the mailAlias`);
return err;
});
Self.observe('before save', async ctx => { Self.observe('before save', async ctx => {
const changes = ctx.currentInstance || ctx.instance; const changes = ctx.currentInstance || ctx.instance;
await Self.hasGrant(ctx, changes.mailAlias); await checkModifyPermission(ctx, changes.mailAlias);
}); });
Self.observe('before delete', async ctx => { Self.observe('before delete', async ctx => {
const mailAliasAccount = await Self.findById(ctx.where.id); const mailAliasAccount = await Self.findById(ctx.where.id);
await Self.hasGrant(ctx, mailAliasAccount.mailAlias); await checkModifyPermission(ctx, mailAliasAccount.mailAlias);
}); });
/** async function checkModifyPermission(ctx, mailAliasFk) {
* Checks if current user has const userId = ctx.options.accessToken.userId;
* grant to add/remove alias const available = await Self.getAvailable(userId);
* if (!available.has(mailAliasFk))
* @param {Object} ctx - Request context throw new UserError('The alias cant be modified');
* @param {Interger} mailAlias - mailAlias id }
* @return {Boolean} True for user with grant
*/ Self.getAvailable = async function(userId, options) {
Self.hasGrant = async function(ctx, mailAlias) {
const models = Self.app.models; const models = Self.app.models;
const accessToken = {req: {accessToken: ctx.options.accessToken}};
const userId = accessToken.req.accessToken.userId;
const canEditAlias = await models.ACL.checkAccessAcl(accessToken, 'MailAliasAccount', 'canEditAlias', 'WRITE'); const myOptions = {};
if (canEditAlias) return true;
const user = await models.VnUser.findById(userId, {fields: ['hasGrant']}); if (typeof options == 'object')
if (!user.hasGrant) Object.assign(myOptions, options);
throw new UserError(`You don't have grant privilege`);
const account = await models.Account.findById(userId, { const roles = await models.RoleMapping.find({
fields: ['id'], fields: ['roleId'],
include: { where: {principalId: userId}
relation: 'aliases', }, myOptions);
scope: {
fields: ['mailAlias'] const availableMailAlias = await models.MailAliasAcl.find({
} fields: ['mailAliasFk'],
include: {relation: 'mailAlias'},
where: {
roleFk: {
inq: roles.map(role => role.roleId),
},
} }
}); }, myOptions);
const mailAliasArray = Array.from(availableMailAlias, alias => alias.mailAliasFk);
const aliases = account.aliases().map(alias => alias.mailAlias); return new Set(mailAliasArray);
const hasAlias = aliases.includes(mailAlias);
if (!hasAlias)
throw new UserError(`You cannot assign/remove an alias that you are not assigned to`);
return true;
}; };
}; };

View File

@ -1,43 +1,33 @@
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
require('../methods/notification/getList')(Self); Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
Self.observe('before save', async function(ctx) { return new UserError(`You already have the mailAlias`);
await checkModifyPermission(ctx); return err;
}); });
Self.observe('before delete', async function(ctx) { Self.observe('before save', async ctx => {
await checkModifyPermission(ctx); const changes = ctx.currentInstance || ctx.instance;
await checkModifyPermission(ctx, changes.mailAlias);
}); });
async function checkModifyPermission(ctx) { Self.observe('before delete', async ctx => {
const models = Self.app.models; const mailAliasAccount = await Self.findById(ctx.where.id);
const instance = ctx.instance;
await checkModifyPermission(ctx, mailAliasAccount.mailAlias);
});
async function checkModifyPermission(ctx, mailAliasFk) {
const userId = ctx.options.accessToken.userId; const userId = ctx.options.accessToken.userId;
const available = await Self.getAvailable(userId);
let mailAliasFk; if (!available.has(mailAliasFk))
let roleFk;
if (instance) {
mailAliasFk = instance.mailAliasFk;
roleFk = instance.roleFk;
} else {
const mailAliasAcl = await models.MailAlias.findById(ctx.where.id);
mailAliasFk = mailAliasAcl.id;
roleFk = mailAliasAcl.roleFk;
}
const role = await models.VnUser.findById(roleFk, {fields: ['id', 'role']});
const available = await Self.getAvailable(roleFk);
const hasAcl = available.has(mailAliasFk);
if (!hasAcl || (userId.role != role))
throw new UserError('The alias cant be modified'); throw new UserError('The alias cant be modified');
} }
Self.getAvailable = async function(userId, options) { Self.getAvailable = async function(userId, options) {
const availableMailAliasMap = new Map();
const models = Self.app.models; const models = Self.app.models;
const myOptions = {}; const myOptions = {};
@ -51,20 +41,15 @@ module.exports = Self => {
}, myOptions); }, myOptions);
const availableMailAlias = await models.MailAliasAcl.find({ const availableMailAlias = await models.MailAliasAcl.find({
fields: ['mailAliasFk', 'roleFk'], fields: ['mailAliasFk'],
include: {relation: 'roleFk'}, include: {relation: 'mailAlias'},
where: { where: {
roleFk: { roleFk: {
inq: roles.map(role => role.roleId), inq: roles.map(role => role.roleId),
}, },
} }
}, myOptions); }, myOptions);
const mailAliasArray = Array.from(availableMailAlias, alias => alias.mailAliasFk);
for (available of availableMailAlias) { return new Set(mailAliasArray);
availableMailAliasMap.set(available.mailAliasFk, {
mailAliasFk: available.mailAliasFk,
});
}
return availableMailAliasMap;
}; };
}; };

View File

@ -1,28 +1,30 @@
{ {
"name": "mailAliasACL", "name": "MailAliasAcl",
"base": "VnModel", "base": "VnModel",
"options": { "options": {
"mysql": { "mysql": {
"table": "account.mailAliasACL" "table": "account.mailAliasAcl"
} }
}, },
"properties": { "properties": {
"mailAliasFk": { "mailAliasFk": {
"id": true,
"type": "number" "type": "number"
}, },
"roleFk": { "roleFk": {
"id": true,
"type": "number" "type": "number"
} }
}, },
"relations": { "relations": {
"mailAlias": { "mailAlias": {
"type": "belongsTo", "type": "belongsTo",
"model": "VnUser", "model": "MailAlias",
"foreignKey": "mailAliasFk" "foreignKey": "mailAliasFk"
}, },
"role": { "role": {
"type": "belongsTo", "type": "belongsTo",
"model": "VnUser", "model": "Role",
"foreignKey": "roleFk" "foreignKey": "roleFk"
} }
} }

View File

@ -1,33 +0,0 @@
import ngModule from '../../../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
constructor(...args) {
super(...args);
this.accessTypes = [
{name: '*'},
{name: 'READ'},
{name: 'WRITE'}
];
this.permissions = [
{name: 'ALLOW'},
{name: 'DENY'}
];
this.models = [];
for (let model in window.validations)
this.models.push({name: model});
this.acl = {
property: '*',
principalType: 'ROLE',
accessType: 'READ',
permission: 'ALLOW'
};
}
}
ngModule.component('vnAclMailCreate', {
// template: require('./index.html'),
controller: Controller
});

View File

@ -1,4 +0,0 @@
import './main';
import './index/';
import './create';
import './search-panel';

View File

@ -1,15 +0,0 @@
import ngModule from '../../../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
onDelete(row) {
return this.$http.delete(`ACLs/${row.id}`)
.then(() => this.$.model.refresh())
.then(() => this.vnApp.showSuccess(this.$t('ACL removed')));
}
}
ngModule.component('vnAclMailIndex', {
// template: require('./index.html'),
controller: Controller
});

View File

@ -1,18 +0,0 @@
import ngModule from '../../../module';
import ModuleMain from 'salix/components/module-main';
export default class ACL extends ModuleMain {
exprBuilder(param, value) {
switch (param) {
case 'search':
return {model: {like: `%${value}%`}};
default:
return {[param]: value};
}
}
}
ngModule.vnComponent('vnAclMailComponent', {
controller: ACL
// template: require('./index.html')
});

View File

@ -1,26 +0,0 @@
import ngModule from '../../../module';
import SearchPanel from 'core/components/searchbar/search-panel';
export default class Controller extends SearchPanel {
constructor(...args) {
super(...args);
this.accessTypes = [
{name: '*'},
{name: 'READ'},
{name: 'WRITE'}
];
this.permissions = [
{name: 'ALLOW'},
{name: 'DENY'}
];
this.models = [];
for (let model in window.validations)
this.models.push({name: model});
}
}
ngModule.component('vnAclSearchPanel', {
// template: require('./index.html'),
controller: Controller
});

View File

@ -7,4 +7,3 @@ import './descriptor';
import './create'; import './create';
import './basic-data'; import './basic-data';
import './users'; import './users';
import './acl';