refs #6085 aclMail back #1869

Merged
carlossa merged 16 commits from 6085-ACLsMail into dev 2024-01-03 07:56:11 +00:00
15 changed files with 151 additions and 174 deletions
Showing only changes of commit 6d486fbec9 - Show all commits

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
carlossa marked this conversation as resolved Outdated
Outdated
Review

Cambiar a nueva versión

Cambiar a nueva versión
CREATE TABLE `account`.`mailAliasACL` (
carlossa marked this conversation as resolved Outdated
Outdated
Review

CREATE OR REPLACE

CREATE OR REPLACE
CREATE OR REPLACE TABLE `account`.`mailAliasAcl` (
`mailAliasFk` int(10) unsigned NOT NULL,
`roleFk` int(10) unsigned NOT NULL,
FOREIGN KEY (`mailAliasFk`) REFERENCES `account`.`mailAlias` (`id`),

View File

@ -3002,3 +3002,10 @@ INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`)
(1, 'Error in VAT calculation'),
(2, 'Error in sales details'),
(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
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
You already have the mailAlias: Ya tienes este mail
carlossa marked this conversation as resolved Outdated
Outdated
Review

este alias de correo

este alias de correo

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",
"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",
"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",
carlossa marked this conversation as resolved Outdated
Outdated
Review

Habria que traducirlo aqui

Habria que traducirlo aqui
"The alias cant be modified": "The alias cant be modified"
}

View File

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

View File

@ -2,54 +2,54 @@
const UserError = require('vn-loopback/util/user-error');
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 => {
const changes = ctx.currentInstance || ctx.instance;
await Self.hasGrant(ctx, changes.mailAlias);
await checkModifyPermission(ctx, changes.mailAlias);
});
Self.observe('before delete', async ctx => {
const mailAliasAccount = await Self.findById(ctx.where.id);
await Self.hasGrant(ctx, mailAliasAccount.mailAlias);
await checkModifyPermission(ctx, mailAliasAccount.mailAlias);
});
/**
* Checks if current user has
* grant to add/remove alias
*
* @param {Object} ctx - Request context
* @param {Interger} mailAlias - mailAlias id
* @return {Boolean} True for user with grant
*/
Self.hasGrant = async function(ctx, mailAlias) {
async function checkModifyPermission(ctx, mailAliasFk) {
const userId = ctx.options.accessToken.userId;
const available = await Self.getAvailable(userId);
if (!available.has(mailAliasFk))
throw new UserError('The alias cant be modified');
carlossa marked this conversation as resolved
Review

myOptions no tiene utilidad

myOptions no tiene utilidad
}
carlossa marked this conversation as resolved Outdated
Outdated
Review

options no esta definida en ningún sitio

options no esta definida en ningún sitio
Self.getAvailable = async function(userId, options) {
const models = Self.app.models;
const accessToken = {req: {accessToken: ctx.options.accessToken}};
const userId = accessToken.req.accessToken.userId;
carlossa marked this conversation as resolved Outdated
Outdated
Review

Un findOne sería mes adequat. I faría la inversa, primer traure els registres de MailAliasAcl i despres comprobar si el usuari te algún dells en findOne

Un `findOne` sería mes adequat. I faría la inversa, primer traure els registres de MailAliasAcl i despres comprobar si el usuari te algún dells en findOne
const canEditAlias = await models.ACL.checkAccessAcl(accessToken, 'MailAliasAccount', 'canEditAlias', 'WRITE');
if (canEditAlias) return true;
const myOptions = {};
const user = await models.VnUser.findById(userId, {fields: ['hasGrant']});
if (!user.hasGrant)
throw new UserError(`You don't have grant privilege`);
if (typeof options == 'object')
Object.assign(myOptions, options);
const account = await models.Account.findById(userId, {
fields: ['id'],
include: {
relation: 'aliases',
scope: {
fields: ['mailAlias']
const roles = await models.RoleMapping.find({
fields: ['roleId'],
where: {principalId: userId}
}, myOptions);
const availableMailAlias = await models.MailAliasAcl.find({
fields: ['mailAliasFk'],
include: {relation: 'mailAlias'},
where: {
roleFk: {
inq: roles.map(role => role.roleId),
carlossa marked this conversation as resolved Outdated
Outdated
Review

Se ha quedado un console log

Se ha quedado un console log
},
}
carlossa marked this conversation as resolved Outdated
Outdated
Review

Estic dubtant de si igual valdria la pena possar tb mailAliasFk: mailAliasFk
Aixina despres no cal buscarlo concretament.

Este enfoque se pareix al de notificactions (que es com te vaig dir) pero igual en este cas com no es crida des de altre lloc per a demanar el llistat igual no val la pena fer-ho igual

Estic dubtant de si igual valdria la pena possar tb mailAliasFk: mailAliasFk Aixina despres no cal buscarlo concretament. Este enfoque se pareix al de notificactions (que es com te vaig dir) pero igual en este cas com no es crida des de altre lloc per a demanar el llistat igual no val la pena fer-ho igual
}
});
const aliases = account.aliases().map(alias => alias.mailAlias);
const hasAlias = aliases.includes(mailAlias);
if (!hasAlias)
throw new UserError(`You cannot assign/remove an alias that you are not assigned to`);
return true;
}, myOptions);
const mailAliasArray = Array.from(availableMailAlias, alias => alias.mailAliasFk);
return new Set(mailAliasArray);
};
};

View File

@ -1,43 +1,33 @@
const UserError = require('vn-loopback/util/user-error');
carlossa marked this conversation as resolved Outdated
Outdated
Review

Pq el codi esta duplicat en modules/account/back/models/mail-alias-acl.js i modules/account/back/models/mail-alias-account.js ?

Pq el codi esta duplicat en modules/account/back/models/mail-alias-acl.js i modules/account/back/models/mail-alias-account.js ?
module.exports = Self => {
carlossa marked this conversation as resolved Outdated
Outdated
Review

mmmm

mmmm
require('../methods/notification/getList')(Self);
Self.observe('before save', async function(ctx) {
await checkModifyPermission(ctx);
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
return new UserError(`You already have the mailAlias`);
return err;
});
Self.observe('before delete', async function(ctx) {
await checkModifyPermission(ctx);
Self.observe('before save', async ctx => {
const changes = ctx.currentInstance || ctx.instance;
await checkModifyPermission(ctx, changes.mailAlias);
carlossa marked this conversation as resolved Outdated
Outdated
Review

Esta part mirala be pq soles has de comprovar el userId del que esta fent el canvi const userId = ctx.options.accessToken.userId;

Esta part mirala be pq soles has de comprovar el userId del que esta fent el canvi const userId = ctx.options.accessToken.userId;

No se usa ese fichero, se usa account, solucionado

No se usa ese fichero, se usa account, solucionado
});
async function checkModifyPermission(ctx) {
const models = Self.app.models;
const instance = ctx.instance;
Self.observe('before delete', async ctx => {
const mailAliasAccount = await Self.findById(ctx.where.id);
await checkModifyPermission(ctx, mailAliasAccount.mailAlias);
});
async function checkModifyPermission(ctx, mailAliasFk) {
const userId = ctx.options.accessToken.userId;
let 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))
const available = await Self.getAvailable(userId);
if (!available.has(mailAliasFk))
throw new UserError('The alias cant be modified');
}
Self.getAvailable = async function(userId, options) {
const availableMailAliasMap = new Map();
const models = Self.app.models;
const myOptions = {};
@ -51,20 +41,15 @@ module.exports = Self => {
}, myOptions);
const availableMailAlias = await models.MailAliasAcl.find({
fields: ['mailAliasFk', 'roleFk'],
include: {relation: 'roleFk'},
fields: ['mailAliasFk'],
include: {relation: 'mailAlias'},
where: {
roleFk: {
inq: roles.map(role => role.roleId),
},
}
}, myOptions);
for (available of availableMailAlias) {
availableMailAliasMap.set(available.mailAliasFk, {
mailAliasFk: available.mailAliasFk,
});
}
return availableMailAliasMap;
const mailAliasArray = Array.from(availableMailAlias, alias => alias.mailAliasFk);
return new Set(mailAliasArray);
};
};

View File

@ -1,28 +1,30 @@
{
"name": "mailAliasACL",
"name": "MailAliasAcl",
"base": "VnModel",
"options": {
"mysql": {
"table": "account.mailAliasACL"
"table": "account.mailAliasAcl"
}
},
"properties": {
"mailAliasFk": {
"id": true,
"type": "number"
},
"roleFk": {
"id": true,
"type": "number"
}
},
"relations": {
"mailAlias": {
"type": "belongsTo",
"model": "VnUser",
"model": "MailAlias",
"foreignKey": "mailAliasFk"
},
"role": {
"type": "belongsTo",
"model": "VnUser",
"model": "Role",
"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 './basic-data';
import './users';
import './acl';