test(ticket): fix tests and add funcionalityAcl
gitea/salix/pipeline/head This commit is unstable Details

This commit is contained in:
Alex Moreno 2022-10-05 15:13:36 +02:00
parent 8b636497a4
commit 9d482f7dfd
11 changed files with 197 additions and 64 deletions

View File

@ -1,33 +0,0 @@
module.exports = Self => {
Self.remoteMethodCtx('aclFunc', {
description: 'Get the user information and permissions',
accepts: [
{
arg: 'property',
type: 'String',
description: 'The user name or email',
required: true
}
],
returns: {
type: 'Object',
root: true
},
http: {
path: `/aclFunc`,
verb: 'GET'
}
});
Self.aclFunc = async function(ctx, property) {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const [acl] = await Self.rawSql(
`SELECT a.principalId
FROM salix.ACL a
WHERE a.property = ?`, [property]);
return await models.Account.hasRole(userId, acl.principalId);
};
};

View File

@ -0,0 +1,40 @@
module.exports = Self => {
Self.remoteMethod('funcionalityAcl', {
description: 'Return if user has permissions',
accepts: [
{
arg: 'model',
type: 'String',
description: 'The model',
required: true
},
{
arg: 'property',
type: 'String',
description: 'The property',
required: true
}
],
returns: {
type: 'Object',
root: true
},
http: {
path: `/funcionalityAcl`,
verb: 'GET'
}
});
Self.funcionalityAcl = async function(ctx, model, property) {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const [acl] = await Self.rawSql(
`SELECT f.role
FROM salix.funcionalityAcl f
WHERE f.model = ?
AND f.property = ?`, [model, property]);
return await models.Account.hasRole(userId, acl.role);
};
};

View File

@ -0,0 +1,24 @@
{
"name": "FuncionalityAcl",
"base": "VnModel",
"options": {
"mysql": {
"table": "salix.funcionalityAcl"
}
},
"properties": {
"id": {
"type": "number",
"id": true
},
"model": {
"type": "string"
},
"property": {
"type": "string"
},
"role": {
"type": "string"
}
}
}

View File

@ -0,0 +1,7 @@
CREATE TABLE `funcionalityAcl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`model` varchar(255) COLLATE utf8mb3_unicode_ci DEFAULT NULL,
`property` varchar(255) COLLATE utf8mb3_unicode_ci DEFAULT NULL,
`role` varchar(45) COLLATE utf8mb3_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci

View File

@ -1149,7 +1149,8 @@ INSERT INTO `vn`.`saleTracking`(`saleFk`, `isChecked`, `created`, `originalQuant
(1, 0, util.VN_CURDATE(), 5, 55, 3, 1, 14), (1, 0, util.VN_CURDATE(), 5, 55, 3, 1, 14),
(1, 1, util.VN_CURDATE(), 5, 54, 3, 2, 8), (1, 1, util.VN_CURDATE(), 5, 54, 3, 2, 8),
(2, 1, util.VN_CURDATE(), 10, 40, 4, 3, 8), (2, 1, util.VN_CURDATE(), 10, 40, 4, 3, 8),
(3, 1, util.VN_CURDATE(), 2, 40, 4, 4, 8); (3, 1, util.VN_CURDATE(), 2, 40, 4, 4, 8),
(31, 1, util.VN_CURDATE(), -5, 40, 4, 5, 8);
INSERT INTO `vn`.`itemBarcode`(`id`, `itemFk`, `code`) INSERT INTO `vn`.`itemBarcode`(`id`, `itemFk`, `code`)
VALUES VALUES
@ -2664,8 +2665,11 @@ INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `created`, `lev
VALUES VALUES
(9, 3, util.VN_NOW(), NULL, 0, NULL, NULL, NULL, NULL); (9, 3, util.VN_NOW(), NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO salix.ACL INSERT INTO `salix`.`funcionalityAcl` (`model`, `property`, `role`)
(model, property, accessType, permission, principalType, principalId) VALUES
VALUES ('Sale', 'editTracked', 'production'),
('Sale', 'editTracked', 'WRITE', 'ALLOW', 'ROLE', 'production'), ('Sale', 'editCloned', 'production');
('Sale', 'editCloned', 'WRITE', 'ALLOW', 'ROLE', 'production');
INSERT INTO `vn`.`saleCloned` (`saleClonedFk`, `saleOriginalFk`)
VALUES
('26', '25');

View File

@ -37,8 +37,8 @@ module.exports = Self => {
const saleCloned = await models.SaleCloned.find({where: {saleClonedFk: {inq: sales}}}, myOptions); const saleCloned = await models.SaleCloned.find({where: {saleClonedFk: {inq: sales}}}, myOptions);
const hasSaleCloned = saleCloned.length; const hasSaleCloned = saleCloned.length;
const canEditTracked = await models.Account.aclFunc(ctx, 'editTracked'); const canEditTracked = await models.Account.funcionalityAcl(ctx, 'Sale', 'editTracked');
const canEditCloned = await models.Account.aclFunc(ctx, 'editCloned'); const canEditCloned = await models.Account.funcionalityAcl(ctx, 'Sale', 'editCloned');
const canEdit = (canEditTracked || !hasSaleTracking) && (canEditCloned || !hasSaleCloned); const canEdit = (canEditTracked || !hasSaleTracking) && (canEditCloned || !hasSaleCloned);

View File

@ -10,7 +10,7 @@ describe('sale canEdit()', () => {
const productionUserID = 49; const productionUserID = 49;
const ctx = {req: {accessToken: {userId: productionUserID}}}; const ctx = {req: {accessToken: {userId: productionUserID}}};
const sales = [3]; const sales = [25];
const result = await models.Sale.canEdit(ctx, sales, options); const result = await models.Sale.canEdit(ctx, sales, options);
@ -51,10 +51,10 @@ describe('sale canEdit()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const salesPersonUserID = 18; const buyerId = 35;
const ctx = {req: {accessToken: {userId: salesPersonUserID}}}; const ctx = {req: {accessToken: {userId: buyerId}}};
const sales = [3]; const sales = [31];
const result = await models.Sale.canEdit(ctx, sales, options); const result = await models.Sale.canEdit(ctx, sales, options);
@ -66,4 +66,48 @@ describe('sale canEdit()', () => {
throw e; throw e;
} }
}); });
it('should return false if any of the sales is cloned', async() => {
const tx = await models.Sale.beginTransaction({});
try {
const options = {transaction: tx};
const buyerId = 35;
const ctx = {req: {accessToken: {userId: buyerId}}};
const sales = [26];
const result = await models.Sale.canEdit(ctx, sales, options);
expect(result).toEqual(false);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return true if any of the sales is cloned and has the correct role', async() => {
const tx = await models.Sale.beginTransaction({});
// modify?
try {
const options = {transaction: tx};
const productionId = 49;
const ctx = {req: {accessToken: {userId: productionId}}};
const sales = [26];
const result = await models.Sale.canEdit(ctx, sales, options);
expect(result).toEqual(true);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
}); });

View File

@ -2,7 +2,7 @@ const models = require('vn-loopback/server/server').models;
describe('sale updateConcept()', () => { describe('sale updateConcept()', () => {
const ctx = {req: {accessToken: {userId: 9}}}; const ctx = {req: {accessToken: {userId: 9}}};
const saleId = 1; const saleId = 25;
it('should throw if ID was undefined', async() => { it('should throw if ID was undefined', async() => {
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});

View File

@ -28,13 +28,20 @@ describe('sale updateQuantity()', () => {
}); });
it('should throw an error if the quantity is greater than it should be', async() => { it('should throw an error if the quantity is greater than it should be', async() => {
const ctx = {
req: {
accessToken: {userId: 1},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});
let error; let error;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await models.Sale.updateQuantity(ctx, 1, 99, options); await models.Sale.updateQuantity(ctx, 17, 99, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -45,21 +52,60 @@ describe('sale updateQuantity()', () => {
expect(error).toEqual(new Error('The new quantity should be smaller than the old one')); expect(error).toEqual(new Error('The new quantity should be smaller than the old one'));
}); });
it('should update the quantity of a given sale current line', async() => { it('should add quantity if the quantity is greater than it should be and is role advanced', async() => {
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});
const saleId = 17;
const buyerId = 35;
const ctx = {
req: {
accessToken: {userId: buyerId},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const originalLine = await models.Sale.findOne({where: {id: 1}, fields: ['quantity']}, options); const isRoleAdvanced = await models.Ticket.isRoleAdvanced(ctx, options);
expect(originalLine.quantity).toEqual(5); expect(isRoleAdvanced).toEqual(true);
await models.Sale.updateQuantity(ctx, 1, 4, options); const originalLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
const modifiedLine = await models.Sale.findOne({where: {id: 1}, fields: ['quantity']}, options); expect(originalLine.quantity).toEqual(30);
expect(modifiedLine.quantity).toEqual(4); const newQuantity = originalLine.quantity + 1;
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
expect(modifiedLine.quantity).toEqual(newQuantity);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should update the quantity of a given sale current line', async() => {
const tx = await models.Sale.beginTransaction({});
const saleId = 25;
const newQuantity = 4;
try {
const options = {transaction: tx};
const originalLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
expect(originalLine.quantity).toEqual(20);
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
expect(modifiedLine.quantity).toEqual(newQuantity);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -41,14 +41,13 @@ module.exports = Self => {
} }
try { try {
const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions);
if (!canEditSale)
throw new UserError(`Sale(s) blocked, please contact production`);
if (isNaN(newQuantity)) if (isNaN(newQuantity))
throw new UserError(`The value should be a number`); throw new UserError(`The value should be a number`);
const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions);
if (!canEditSale)
throw new UserError(`Sale(s) blocked, please contact production`);
const filter = { const filter = {
include: { include: {
relation: 'ticket', relation: 'ticket',
@ -70,7 +69,8 @@ module.exports = Self => {
const sale = await models.Sale.findById(id, filter, myOptions); const sale = await models.Sale.findById(id, filter, myOptions);
if (newQuantity > sale.quantity) const isRoleAdvanced = await models.Ticket.isRoleAdvanced(ctx, myOptions);
if (newQuantity > sale.quantity && !isRoleAdvanced)
throw new UserError('The new quantity should be smaller than the old one'); throw new UserError('The new quantity should be smaller than the old one');
const oldQuantity = sale.quantity; const oldQuantity = sale.quantity;

View File

@ -33,4 +33,5 @@ module.exports = function(Self) {
require('../methods/ticket/closeByTicket')(Self); require('../methods/ticket/closeByTicket')(Self);
require('../methods/ticket/closeByAgency')(Self); require('../methods/ticket/closeByAgency')(Self);
require('../methods/ticket/closeByRoute')(Self); require('../methods/ticket/closeByRoute')(Self);
require('../methods/ticket/isRoleAdvanced')(Self);
}; };