5488-use_checkAccessAcl #1482

Merged
alexm merged 32 commits from 5488-use_checkAccessAcl into dev 2023-05-29 05:20:29 +00:00
39 changed files with 223 additions and 153 deletions

View File

@ -67,7 +67,7 @@ module.exports = Self => {
if (!image) return false; if (!image) return false;
const hasReadRole = models.ImageCollection.hasReadRole(ctx, collection); const hasReadRole = await models.ImageCollection.hasReadRole(ctx, collection);
Review

Aço dua 3 anys mal (sempre era true)

Aço dua 3 anys mal (sempre era true)
if (!hasReadRole) if (!hasReadRole)
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);

View File

@ -9,10 +9,11 @@ module.exports = Self => {
* @return {boolean} True for user with read privileges * @return {boolean} True for user with read privileges
*/ */
Self.hasReadRole = async(ctx, name, options) => { Self.hasReadRole = async(ctx, name, options) => {
const collection = await Self.findOne({where: {name}}, { const collection = await Self.findOne({
Review

Aço dua 3 anys mal, el objecte estava mal ficat i mai es fea la relacio

Aço dua 3 anys mal, el objecte estava mal ficat i mai es fea la relacio
include: { include: {
relation: 'readRole' relation: 'readRole'
} },
where: {name}
}, options); }, options);
return await hasRole(ctx, collection, options); return await hasRole(ctx, collection, options);

View File

@ -27,7 +27,6 @@ INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalTyp
('Client', 'summary', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'summary', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateAddress', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'updateAddress', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateFiscalData', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'updateFiscalData', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'updateUser', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'uploadFile', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'uploadFile', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'campaignMetricsPdf', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'campaignMetricsPdf', '*', 'ALLOW', 'ROLE', 'employee'),
('Client', 'campaignMetricsEmail', '*', 'ALLOW', 'ROLE', 'employee'), ('Client', 'campaignMetricsEmail', '*', 'ALLOW', 'ROLE', 'employee'),

View File

@ -0,0 +1,121 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Ticket', 'editDiscount', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Ticket', 'editDiscount', 'WRITE', 'ALLOW', 'ROLE', 'salesPerson'),
('Ticket', 'isRoleAdvanced', '*', 'ALLOW', 'ROLE', 'salesAssistant'),
('Ticket', 'isRoleAdvanced', '*', 'ALLOW', 'ROLE', 'deliveryBoss'),
('Ticket', 'isRoleAdvanced', '*', 'ALLOW', 'ROLE', 'buyer'),
('Ticket', 'isRoleAdvanced', '*', 'ALLOW', 'ROLE', 'claimManager'),
('Ticket', 'deleteTicketWithPartPrepared', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
('Ticket', 'editZone', 'WRITE', 'ALLOW', 'ROLE', 'deliveryBoss'),
('State', 'editableStates', 'READ', 'ALLOW', 'ROLE', 'employee'),
('State', 'seeEditableStates', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('State', 'seeEditableStates', 'READ', 'ALLOW', 'ROLE', 'production'),
('State', 'isSomeEditable', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('State', 'isAllEditable', 'READ', 'ALLOW', 'ROLE', 'production'),
('State', 'isAllEditable', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Agency', 'seeExpired', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Agency', 'seeExpired', 'READ', 'ALLOW', 'ROLE', 'productionBoss'),
('Claim', 'createAfterDeadline', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Client', 'editAddressLogifloraAllowed', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
('Client', 'editFiscalDataWithoutTaxDataCheck', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
('Client', 'editVerifiedDataWithoutTaxDataCheck', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
('Client', 'editCredit', 'WRITE', 'ALLOW', 'ROLE', 'financialBoss'),
('Client', 'isNotEditableCredit', 'WRITE', 'ALLOW', 'ROLE', 'financialBoss'),
('InvoiceOut', 'canCreatePdf', 'WRITE', 'ALLOW', 'ROLE', 'invoicing'),
('Supplier', 'editPayMethodCheck', 'WRITE', 'ALLOW', 'ROLE', 'financial'),
('Worker', 'isTeamBoss', 'WRITE', 'ALLOW', 'ROLE', 'teamBoss'),
('Worker', 'forceIsSubordinate', 'READ', 'ALLOW', 'ROLE', 'hr'),
('Claim', 'editState', 'WRITE', 'ALLOW', 'ROLE', 'claimManager');
DELETE FROM `salix`.`ACL`
WHERE
model = 'Claim'
AND property = '*'
AND accessType = '*';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Claim', 'find', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'findById', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'findOne', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'getSummary', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'updateClaim', 'WRITE', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'regularizeClaim', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Claim', 'updateClaimDestination', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Claim', 'downloadFile', 'READ', 'ALLOW', 'ROLE', 'claimManager'),
('Claim', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'claimManager'),
('Claim', 'filter', 'READ', 'ALLOW', 'ROLE', 'salesPerson'),
('Claim', 'logs', 'READ', 'ALLOW', 'ROLE', 'claimManager');
DELETE FROM `salix`.`ACL`
WHERE
model = 'Ticket'
AND property = '*'
AND accessType = '*';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Ticket', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'findById', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'findOne', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getVolume', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getTotalVolume', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'summary', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'priceDifference', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'componentUpdate', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'new', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'isEditable', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'setDeleted', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'restore', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getSales', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getSalesPersonMana', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'filter', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'makeInvoice', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'updateEditableTicket', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'updateDiscount', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'transferSales', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'sendSms', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'isLocked', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'freightCost', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'getComponentsSum', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Ticket', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'delivery'), -- Change Priority in Route tickets
('Ticket', 'deliveryNoteCsv', 'READ', 'ALLOW', 'ROLE', 'employee');
DELETE FROM `salix`.`ACL`
WHERE
model = 'State'
AND property = '*'
AND accessType = 'READ';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('State', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'),
('State', 'findById', 'READ', 'ALLOW', 'ROLE', 'employee'),
('State', 'findOne', 'READ', 'ALLOW', 'ROLE', 'employee');
DELETE FROM `salix`.`ACL`
WHERE
model = 'Worker'
AND property = '*'
AND accessType = 'READ';
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Worker', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'findById', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'findOne', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'filter', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'getWorkedHours', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'active', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'activeWithRole', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'uploadFile', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
('Worker', 'contracts', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'holidays', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'activeContract', 'READ', 'ALLOW', 'ROLE', 'employee'),
('Worker', 'activeWithInheritedRole', 'READ', 'ALLOW', 'ROLE', 'employee');
DELETE FROM `salix`.`ACL`
WHERE model = 'Client'
AND property = 'updateUser'
AND accessType = '*';

View File

@ -17,7 +17,7 @@ describe('Claim summary path', () => {
}); });
it('should navigate to the target claim summary section', async() => { it('should navigate to the target claim summary section', async() => {
await page.loginAndModule('employee', 'claim'); await page.loginAndModule('salesPerson', 'claim');
await page.accessToSearchResult(claimId); await page.accessToSearchResult(claimId);
await page.waitForState('claim.card.summary'); await page.waitForState('claim.card.summary');
}); });

View File

@ -16,7 +16,7 @@ describe('Claim descriptor path', () => {
}); });
it('should now navigate to the target claim summary section', async() => { it('should now navigate to the target claim summary section', async() => {
await page.loginAndModule('employee', 'claim'); await page.loginAndModule('salesPerson', 'claim');
await page.accessToSearchResult(claimId); await page.accessToSearchResult(claimId);
await page.waitForState('claim.card.summary'); await page.waitForState('claim.card.summary');
}); });

View File

@ -171,5 +171,6 @@
"Added observation": "Added observation", "Added observation": "Added observation",
"Comment added to client": "Comment added to client", "Comment added to client": "Comment added to client",
"This ticket is already a refund": "This ticket is already a refund", "This ticket is already a refund": "This ticket is already a refund",
"A claim with that sale already exists": "A claim with that sale already exists" "A claim with that sale already exists": "A claim with that sale already exists",
"ASSIGN_ZONE_FIRST": "Assign zone first"
} }

View File

@ -59,12 +59,14 @@ module.exports = Self => {
const landedPlusWeek = new Date(ticket.landed); const landedPlusWeek = new Date(ticket.landed);
landedPlusWeek.setDate(landedPlusWeek.getDate() + 7); landedPlusWeek.setDate(landedPlusWeek.getDate() + 7);
const hasClaimManagerRole = await models.VnUser.hasRole(userId, 'claimManager', myOptions);
const isClaimable = landedPlusWeek >= Date.vnNew(); const isClaimable = landedPlusWeek >= Date.vnNew();
const canCreateClaimAfterDeadline =
await models.ACL.checkAccessAcl(ctx, 'Claim', 'createAfterDeadline', 'WRITE');
if (ticket.isDeleted) if (ticket.isDeleted)
throw new UserError(`You can't create a claim for a removed ticket`); throw new UserError(`You can't create a claim for a removed ticket`);
if (!isClaimable && !hasClaimManagerRole) if (!isClaimable && !canCreateClaimAfterDeadline)
throw new UserError(`You can't create a claim from a ticket delivered more than seven days ago`); throw new UserError(`You can't create a claim from a ticket delivered more than seven days ago`);
const newClaim = await Self.create({ const newClaim = await Self.create({

View File

@ -46,7 +46,6 @@ module.exports = Self => {
Self.updateClaim = async(ctx, id, options) => { Self.updateClaim = async(ctx, id, options) => {
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const args = ctx.args; const args = ctx.args;
let tx; let tx;
const myOptions = {}; const myOptions = {};
@ -81,9 +80,9 @@ module.exports = Self => {
if (args.claimStateFk) { if (args.claimStateFk) {
const canEditOldState = await models.ClaimState.isEditable(ctx, claim.claimStateFk, myOptions); const canEditOldState = await models.ClaimState.isEditable(ctx, claim.claimStateFk, myOptions);
const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions); const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions);
const isClaimManager = await models.VnUser.hasRole(userId, 'claimManager', myOptions); const canEditState = await models.ACL.checkAccessAcl(ctx, 'Claim', 'editState', 'WRITE');
if (!canEditOldState || !canEditNewState || changedHasToPickUp && !isClaimManager) if (!canEditOldState || !canEditNewState || changedHasToPickUp && !canEditState)
throw new UserError(`You don't have enough privileges to change that field`); throw new UserError(`You don't have enough privileges to change that field`);
} }

View File

@ -87,15 +87,15 @@ module.exports = function(Self) {
Self.updateAddress = async(ctx, clientId, addressId, options) => { Self.updateAddress = async(ctx, clientId, addressId, options) => {
const models = Self.app.models; const models = Self.app.models;
const args = ctx.args; const args = ctx.args;
const userId = ctx.req.accessToken.userId;
const myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const isSalesAssistant = await models.VnUser.hasRole(userId, 'salesAssistant', myOptions); const canEditAddressLogifloraAllowed =
await models.ACL.checkAccessAcl(ctx, 'Client', 'editAddressLogifloraAllowed');
if (args.isLogifloraAllowed && !isSalesAssistant) if (args.isLogifloraAllowed && !canEditAddressLogifloraAllowed)
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);
const address = await models.Address.findOne({ const address = await models.Address.findOne({

View File

@ -131,9 +131,10 @@ module.exports = Self => {
myOptions.transaction = tx; myOptions.transaction = tx;
} }
try { try {
const isSalesAssistant = await models.VnUser.hasRole(userId, 'salesAssistant', myOptions); const canEditNotTaxDataChecked =
await models.ACL.checkAccessAcl(ctx, 'Client', 'editFiscalDataWithoutTaxDataCheck', 'WRITE');
Review

Igual es demasiado largo pero no sabia como ponerlo

Igual es demasiado largo pero no sabia como ponerlo
const client = await models.Client.findById(clientId, null, myOptions); const client = await models.Client.findById(clientId, null, myOptions);
if (!isSalesAssistant && client.isTaxDataChecked) if (!canEditNotTaxDataChecked && client.isTaxDataChecked)
throw new UserError(`Not enough privileges to edit a client with verified data`); throw new UserError(`Not enough privileges to edit a client with verified data`);
// Sage data validation // Sage data validation
const taxDataChecked = args.isTaxDataChecked; const taxDataChecked = args.isTaxDataChecked;

View File

@ -2,6 +2,7 @@ const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('updateUser', { Self.remoteMethodCtx('updateUser', {
description: 'Updates the user information', description: 'Updates the user information',
accessType: 'WRITE',
accepts: [ accepts: [
{ {
arg: 'id', arg: 'id',
@ -32,7 +33,6 @@ module.exports = Self => {
Self.updateUser = async function(ctx, id, options) { Self.updateUser = async function(ctx, id, options) {
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
let tx; let tx;
const myOptions = {}; const myOptions = {};
@ -45,9 +45,8 @@ module.exports = Self => {
} }
try { try {
const isSalesPerson = await models.VnUser.hasRole(userId, 'salesPerson', myOptions); const canEdit = await models.ACL.checkAccessAcl(ctx, 'Client', 'updateUser', 'WRITE');
alexm marked this conversation as resolved
Review

quitar codigo y crear directamente un acl

quitar codigo y crear directamente un acl
if (!canEdit)
if (!isSalesPerson)
throw new UserError(`Not enough privileges to edit a client`); throw new UserError(`Not enough privileges to edit a client`);
const isClient = await models.Client.findById(id, null, myOptions); const isClient = await models.Client.findById(id, null, myOptions);

View File

@ -218,9 +218,9 @@ module.exports = Self => {
const models = Self.app.models; const models = Self.app.models;
const loopBackContext = LoopBackContext.getCurrentContext(); const loopBackContext = LoopBackContext.getCurrentContext();
const userId = loopBackContext.active.accessToken.userId; const accessToken = {req: loopBackContext.active.accessToken};
const isSalesAssistant = await models.VnUser.hasRole(userId, 'salesAssistant', ctx.options); const editVerifiedDataWithoutTaxDataChecked = models.ACL.checkAccessAcl(accessToken, 'Client', 'editVerifiedDataWithoutTaxDataCheck', 'WRITE');
const hasChanges = orgData && changes; const hasChanges = orgData && changes;
const isTaxDataChecked = hasChanges && (changes.isTaxDataChecked || orgData.isTaxDataChecked); const isTaxDataChecked = hasChanges && (changes.isTaxDataChecked || orgData.isTaxDataChecked);
@ -232,8 +232,8 @@ module.exports = Self => {
const sageTransactionType = hasChanges && (changes.sageTransactionTypeFk || orgData.sageTransactionTypeFk); const sageTransactionType = hasChanges && (changes.sageTransactionTypeFk || orgData.sageTransactionTypeFk);
const sageTransactionTypeChanged = hasChanges && orgData.sageTransactionTypeFk != sageTransactionType; const sageTransactionTypeChanged = hasChanges && orgData.sageTransactionTypeFk != sageTransactionType;
const cantEditVerifiedData = isTaxDataCheckedChanged && !isSalesAssistant; const cantEditVerifiedData = isTaxDataCheckedChanged && !editVerifiedDataWithoutTaxDataChecked;
const cantChangeSageData = (sageTaxTypeChanged || sageTransactionTypeChanged) && !isSalesAssistant; const cantChangeSageData = (sageTaxTypeChanged || sageTransactionTypeChanged) && !editVerifiedDataWithoutTaxDataChecked;
if (cantEditVerifiedData || cantChangeSageData) if (cantEditVerifiedData || cantChangeSageData)
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);
@ -401,9 +401,10 @@ module.exports = Self => {
Self.changeCredit = async function changeCredit(ctx, finalState, changes) { Self.changeCredit = async function changeCredit(ctx, finalState, changes) {
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.options.accessToken.userId; const userId = ctx.options.accessToken.userId;
const accessToken = {req: {accessToken: ctx.options.accessToken} };
const isFinancialBoss = await models.VnUser.hasRole(userId, 'financialBoss', ctx.options); const canEditCredit = await models.ACL.checkAccessAcl(accessToken, 'Client', 'editCredit', 'WRITE');
if (!isFinancialBoss) { if (!canEditCredit) {
const lastCredit = await models.ClientCredit.findOne({ const lastCredit = await models.ClientCredit.findOne({
where: { where: {
clientFk: finalState.id clientFk: finalState.id
@ -412,10 +413,9 @@ module.exports = Self => {
}, ctx.options); }, ctx.options);
const lastAmount = lastCredit && lastCredit.amount; const lastAmount = lastCredit && lastCredit.amount;
const lastWorkerId = lastCredit && lastCredit.workerFk; const lastCreditIsNotEditable = !await models.ACL.checkAccessAcl(accessToken, 'Client', 'isNotEditableCredit', 'WRITE');
const lastWorkerIsFinancialBoss = await models.VnUser.hasRole(lastWorkerId, 'financialBoss', ctx.options);
if (lastAmount == 0 && lastWorkerIsFinancialBoss) if (lastAmount == 0 && lastCreditIsNotEditable)
throw new UserError(`You can't change the credit set to zero from a financialBoss`); throw new UserError(`You can't change the credit set to zero from a financialBoss`);
const creditLimits = await models.ClientCreditLimit.find({ const creditLimits = await models.ClientCreditLimit.find({

View File

@ -25,7 +25,6 @@ module.exports = Self => {
Self.createPdf = async function(ctx, id, options) { Self.createPdf = async function(ctx, id, options) {
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
if (process.env.NODE_ENV == 'test') if (process.env.NODE_ENV == 'test')
throw new UserError(`Action not allowed on the test environment`); throw new UserError(`Action not allowed on the test environment`);
@ -43,9 +42,9 @@ module.exports = Self => {
try { try {
const invoiceOut = await Self.findById(id, null, myOptions); const invoiceOut = await Self.findById(id, null, myOptions);
const hasInvoicing = await models.VnUser.hasRole(userId, 'invoicing', myOptions); const canCreatePdf = await models.ACL.checkAccessAcl(ctx, 'InvoiceOut', 'canCreatePdf', 'WRITE');
if (invoiceOut.hasPdf && !hasInvoicing) if (invoiceOut.hasPdf && !canCreatePdf)
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);
await invoiceOut.updateAttributes({ await invoiceOut.updateAttributes({

View File

@ -99,18 +99,20 @@ module.exports = Self => {
Self.observe('before save', async function(ctx) { Self.observe('before save', async function(ctx) {
if (ctx.isNewInstance) return; if (ctx.isNewInstance) return;
const loopbackContext = LoopBackContext.getCurrentContext();
const changes = ctx.data || ctx.instance; const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance; const orgData = ctx.currentInstance;
const userId = loopbackContext.active.accessToken.userId; const loopBackContext = LoopBackContext.getCurrentContext();
const accessToken = {req: loopBackContext.active.accessToken};
const editPayMethodCheck =
await Self.app.models.ACL.checkAccessAcl(accessToken, 'Supplier', 'editPayMethodCheck', 'WRITE');
const isNotFinancial = !await Self.app.models.VnUser.hasRole(userId, 'financial');
const isPayMethodChecked = changes.isPayMethodChecked || orgData.isPayMethodChecked; const isPayMethodChecked = changes.isPayMethodChecked || orgData.isPayMethodChecked;
const hasChanges = orgData && changes; const hasChanges = orgData && changes;
const isPayMethodCheckedChanged = hasChanges const isPayMethodCheckedChanged = hasChanges
&& orgData.isPayMethodChecked != isPayMethodChecked; && orgData.isPayMethodChecked != isPayMethodChecked;
if (isNotFinancial && isPayMethodCheckedChanged) if (!editPayMethodCheck && isPayMethodCheckedChanged)
throw new UserError('You can not modify is pay method checked'); throw new UserError('You can not modify is pay method checked');
}); });

View File

@ -64,7 +64,7 @@ describe('sale updateQuantity()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const isRoleAdvanced = await models.Ticket.isRoleAdvanced(ctx, options); const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*');
expect(isRoleAdvanced).toEqual(true); expect(isRoleAdvanced).toEqual(true);

View File

@ -64,7 +64,7 @@ module.exports = Self => {
const sale = await models.Sale.findById(id, filter, myOptions); const sale = await models.Sale.findById(id, filter, myOptions);
const isRoleAdvanced = await models.Ticket.isRoleAdvanced(ctx, myOptions); const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*');
if (newQuantity > sale.quantity && !isRoleAdvanced) 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');

View File

@ -19,13 +19,11 @@ module.exports = Self => {
Self.editableStates = async(ctx, filter, options) => { Self.editableStates = async(ctx, filter, options) => {
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const myOptions = {...(options || {})}; const myOptions = {...(options || {})};
const isProduction = await models.VnUser.hasRole(userId, 'production', myOptions); const seeEditableStates = await models.ACL.checkAccessAcl(ctx, 'State', 'seeEditableStates', 'READ');
const isAdministrative = await models.VnUser.hasRole(userId, 'administrative', myOptions);
if (!isProduction && !isAdministrative) if (!seeEditableStates)
filter = mergeFilters(filter, {where: {alertLevel: 0}}); filter = mergeFilters(filter, {where: {alertLevel: 0}});
const states = await models.State.find(filter, myOptions); const states = await models.State.find(filter, myOptions);

View File

@ -19,22 +19,23 @@ module.exports = Self => {
}); });
Self.isEditable = async(ctx, stateId, options) => { Self.isEditable = async(ctx, stateId, options) => {
const accessToken = ctx.req.accessToken;
const models = Self.app.models; const models = Self.app.models;
const userId = accessToken.userId;
const myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const isProduction = await models.VnUser.hasRole(userId, 'production', myOptions); const isAllEditable = await models.ACL.checkAccessAcl(ctx, 'State', 'isAllEditable', 'READ');
const isSalesPerson = await models.VnUser.hasRole(userId, 'salesPerson', myOptions);
const isAdministrative = await models.VnUser.hasRole(userId, 'administrative', myOptions);
const state = await models.State.findById(stateId, null, myOptions); const state = await models.State.findById(stateId, null, myOptions);
const isSomeEditable = (
await models.ACL.checkAccessAcl(ctx, 'State', 'isSomeEditable', 'READ')
&& (
state.code == 'PICKER_DESIGNED' || state.code == 'PRINTED'
)
);
const salesPersonAllowed = (isSalesPerson && (state.code == 'PICKER_DESIGNED' || state.code == 'PRINTED')); const isAllowed = isAllEditable || isSomeEditable || state.alertLevel == 0;
const isAllowed = isProduction || isAdministrative || salesPersonAllowed || state.alertLevel == 0;
return isAllowed; return isAllowed;
}; };
}; };

View File

@ -121,8 +121,8 @@ module.exports = Self => {
if (!isEditable) if (!isEditable)
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
const isDeliveryBoss = await models.VnUser.hasRole(userId, 'deliveryBoss', myOptions); const editZone = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'editZone', 'WRITE');
if (!isDeliveryBoss) { if (!editZone) {
const zoneShipped = await models.Agency.getShipped( const zoneShipped = await models.Agency.getShipped(
ctx, ctx,
args.landed, args.landed,

View File

@ -30,7 +30,7 @@ module.exports = Self => {
where: {ticketFk: id} where: {ticketFk: id}
}, myOptions); }, myOptions);
const isRoleAdvanced = await models.Ticket.isRoleAdvanced(ctx, myOptions); const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*');
const alertLevel = state ? state.alertLevel : null; const alertLevel = state ? state.alertLevel : null;
const ticket = await models.Ticket.findById(id, { const ticket = await models.Ticket.findById(id, {

View File

@ -1,32 +0,0 @@
module.exports = Self => {
Self.remoteMethodCtx('isRoleAdvanced', {
description: 'Check if a ticket is editable',
accessType: 'READ',
returns: {
type: 'boolean',
root: true
},
http: {
path: `/isRoleAdvanced`,
verb: 'GET'
}
});
Self.isRoleAdvanced = async(ctx, options) => {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const isSalesAssistant = await models.VnUser.hasRole(userId, 'salesAssistant', myOptions);
const isDeliveryBoss = await models.VnUser.hasRole(userId, 'deliveryBoss', myOptions);
const isBuyer = await models.VnUser.hasRole(userId, 'buyer', myOptions);
const isClaimManager = await models.VnUser.hasRole(userId, 'claimManager', myOptions);
const isRoleAdvanced = isSalesAssistant || isDeliveryBoss || isBuyer || isClaimManager;
return isRoleAdvanced;
};
};

View File

@ -60,7 +60,6 @@ module.exports = Self => {
Self.priceDifference = async(ctx, options) => { Self.priceDifference = async(ctx, options) => {
const args = ctx.args; const args = ctx.args;
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const myOptions = {}; const myOptions = {};
let tx; let tx;
@ -78,8 +77,8 @@ module.exports = Self => {
if (!isEditable) if (!isEditable)
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
const isDeliveryBoss = await models.VnUser.hasRole(userId, 'deliveryBoss', myOptions); const editZone = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'editZone', 'WRITE');
if (!isDeliveryBoss) { if (!editZone) {
const zoneShipped = await models.Agency.getShipped( const zoneShipped = await models.Agency.getShipped(
ctx, ctx,
args.landed, args.landed,

View File

@ -39,7 +39,6 @@ module.exports = Self => {
const ticketToDelete = await models.Ticket.findById(id, {fields: ['isDeleted']}, myOptions); const ticketToDelete = await models.Ticket.findById(id, {fields: ['isDeleted']}, myOptions);
if (ticketToDelete.isDeleted) return false; if (ticketToDelete.isDeleted) return false;
const userId = ctx.req.accessToken.userId;
const isEditable = await Self.isEditable(ctx, id, myOptions); const isEditable = await Self.isEditable(ctx, id, myOptions);
if (!isEditable) if (!isEditable)
@ -54,7 +53,8 @@ module.exports = Self => {
throw new UserError($t('Tickets with associated refunds', {id: ticketRefunds[0].id})); throw new UserError($t('Tickets with associated refunds', {id: ticketRefunds[0].id}));
// Check if has sales with shelving // Check if has sales with shelving
const isSalesAssistant = await models.VnUser.hasRole(userId, 'salesAssistant', myOptions); const canDeleteTicketWithPartPrepared =
await models.ACL.checkAccessAcl(ctx, 'Ticket', 'deleteTicketWithPartPrepared', 'WRITE');
const sales = await models.Sale.find({ const sales = await models.Sale.find({
include: {relation: 'itemShelvingSale'}, include: {relation: 'itemShelvingSale'},
where: {ticketFk: id} where: {ticketFk: id}
@ -63,7 +63,7 @@ module.exports = Self => {
return sale.itemShelvingSale(); return sale.itemShelvingSale();
}); });
if (hasItemShelvingSales && !isSalesAssistant) if (hasItemShelvingSales && !canDeleteTicketWithPartPrepared)
throw new UserError(`You cannot delete a ticket that part of it is being prepared`); throw new UserError(`You cannot delete a ticket that part of it is being prepared`);
// Check for existing claim // Check for existing claim

View File

@ -3,6 +3,7 @@ let UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('transferSales', { Self.remoteMethodCtx('transferSales', {
description: 'Transfer sales to a new or a given ticket', description: 'Transfer sales to a new or a given ticket',
accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'id', arg: 'id',
type: 'number', type: 'number',

View File

@ -85,17 +85,14 @@ module.exports = Self => {
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const isLocked = await models.Ticket.isLocked(id, myOptions); const isLocked = await models.Ticket.isLocked(id, myOptions);
const roles = await models.VnUser.getRoles(userId, myOptions); const canEditDiscount = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'editDiscount');
const hasAllowedRoles = roles.filter(role =>
role == 'salesPerson' || role == 'claimManager'
);
const state = await Self.app.models.TicketState.findOne({ const state = await Self.app.models.TicketState.findOne({
where: {ticketFk: id} where: {ticketFk: id}
}, myOptions); }, myOptions);
const alertLevel = state ? state.alertLevel : null; const alertLevel = state ? state.alertLevel : null;
if (isLocked || (!hasAllowedRoles && alertLevel > 0)) if (isLocked || (!canEditDiscount && alertLevel > 0))
throw new UserError(`The sales of this ticket can't be modified`); throw new UserError(`The sales of this ticket can't be modified`);
const usesMana = await models.Sale.usesMana(ctx, myOptions); const usesMana = await models.Sale.usesMana(ctx, myOptions);

View File

@ -36,7 +36,6 @@ module.exports = function(Self) {
require('../methods/ticket/getTicketsFuture')(Self); require('../methods/ticket/getTicketsFuture')(Self);
require('../methods/ticket/merge')(Self); require('../methods/ticket/merge')(Self);
require('../methods/ticket/getTicketsAdvance')(Self); require('../methods/ticket/getTicketsAdvance')(Self);
require('../methods/ticket/isRoleAdvanced')(Self);
require('../methods/ticket/collectionLabel')(Self); require('../methods/ticket/collectionLabel')(Self);
require('../methods/ticket/expeditionPalletLabel')(Self); require('../methods/ticket/expeditionPalletLabel')(Self);
require('../methods/ticket/saveSign')(Self); require('../methods/ticket/saveSign')(Self);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('worker-dms downloadFile()', () => { describe('worker-dms downloadFile()', () => {
let dmsId = 4; let dmsId = 4;
@ -6,7 +6,7 @@ describe('worker-dms downloadFile()', () => {
it('should return a response for an employee with text content-type', async() => { it('should return a response for an employee with text content-type', async() => {
let workerId = 1106; let workerId = 1106;
let ctx = {req: {accessToken: {userId: workerId}}}; let ctx = {req: {accessToken: {userId: workerId}}};
const result = await app.models.WorkerDms.downloadFile(ctx, dmsId); const result = await models.WorkerDms.downloadFile(ctx, dmsId);
expect(result[1]).toEqual('text/plain'); expect(result[1]).toEqual('text/plain');
}); });
@ -17,7 +17,7 @@ describe('worker-dms downloadFile()', () => {
let error; let error;
try { try {
await app.models.WorkerDms.downloadFile(ctx, dmsId); await models.WorkerDms.downloadFile(ctx, dmsId);
} catch (e) { } catch (e) {
error = e; error = e;
} }

View File

@ -40,10 +40,10 @@ module.exports = Self => {
Object.assign(myOptions, options); Object.assign(myOptions, options);
const isSubordinate = await models.Worker.isSubordinate(ctx, workerId, myOptions); const isSubordinate = await models.Worker.isSubordinate(ctx, workerId, myOptions);
const isTeamBoss = await models.VnUser.hasRole(currentUserId, 'teamBoss', myOptions); const isTeamBoss = await models.ACL.checkAccessAcl(ctx, 'Worker', 'isTeamBoss', 'WRITE');
const isHimself = currentUserId == workerId; const isHimself = currentUserId == workerId;
if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss)) if (!isSubordinate || (isSubordinate && isHimself && !isTeamBoss))
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);
query = `CALL vn.workerTimeControl_clockIn(?,?,?)`; query = `CALL vn.workerTimeControl_clockIn(?,?,?)`;

View File

@ -32,7 +32,7 @@ module.exports = Self => {
const targetTimeEntry = await Self.findById(id, null, myOptions); const targetTimeEntry = await Self.findById(id, null, myOptions);
const isSubordinate = await models.Worker.isSubordinate(ctx, targetTimeEntry.userFk, myOptions); const isSubordinate = await models.Worker.isSubordinate(ctx, targetTimeEntry.userFk, myOptions);
const isTeamBoss = await models.VnUser.hasRole(currentUserId, 'teamBoss', myOptions); const isTeamBoss = await models.ACL.checkAccessAcl(ctx, 'Worker', 'isTeamBoss', 'WRITE');
const isHimself = currentUserId == targetTimeEntry.userFk; const isHimself = currentUserId == targetTimeEntry.userFk;
if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss)) if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss))

View File

@ -38,7 +38,7 @@ module.exports = Self => {
const targetTimeEntry = await Self.findById(id, null, myOptions); const targetTimeEntry = await Self.findById(id, null, myOptions);
const isSubordinate = await models.Worker.isSubordinate(ctx, targetTimeEntry.userFk, myOptions); const isSubordinate = await models.Worker.isSubordinate(ctx, targetTimeEntry.userFk, myOptions);
const isTeamBoss = await models.VnUser.hasRole(currentUserId, 'teamBoss', myOptions); const isTeamBoss = await models.ACL.checkAccessAcl(ctx, 'Worker', 'isTeamBoss', 'WRITE');
const isHimself = currentUserId == targetTimeEntry.userFk; const isHimself = currentUserId == targetTimeEntry.userFk;
const notAllowed = isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss); const notAllowed = isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss);

View File

@ -53,7 +53,7 @@ module.exports = Self => {
try { try {
const isSubordinate = await models.Worker.isSubordinate(ctx, id, myOptions); const isSubordinate = await models.Worker.isSubordinate(ctx, id, myOptions);
const isTeamBoss = await models.VnUser.hasRole(userId, 'teamBoss', myOptions); const isTeamBoss = await models.ACL.checkAccessAcl(ctx, 'Worker', 'isTeamBoss', 'WRITE');
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss)) if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);

View File

@ -40,7 +40,7 @@ module.exports = Self => {
try { try {
const isSubordinate = await models.Worker.isSubordinate(ctx, id, myOptions); const isSubordinate = await models.Worker.isSubordinate(ctx, id, myOptions);
const isTeamBoss = await models.VnUser.hasRole(userId, 'teamBoss', myOptions); const isTeamBoss = await models.ACL.checkAccessAcl(ctx, 'Worker', 'isTeamBoss', 'WRITE');
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss)) if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);

View File

@ -25,22 +25,15 @@ module.exports = Self => {
Self.isSubordinate = async(ctx, id, options) => { Self.isSubordinate = async(ctx, id, options) => {
const models = Self.app.models; const models = Self.app.models;
const myUserId = ctx.req.accessToken.userId;
const myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const mySubordinates = await Self.mySubordinates(ctx, myOptions); const mySubordinates = await Self.mySubordinates(ctx, myOptions);
const isSubordinate = mySubordinates.find(subordinate => { const isSubordinate = mySubordinates.some(subordinate => subordinate.workerFk == id);
return subordinate.workerFk == id; const forceIsSubordinate = await models.ACL.checkAccessAcl(ctx, 'Worker', 'forceIsSubordinate', 'READ');
});
const isHr = await models.VnUser.hasRole(myUserId, 'hr', myOptions); return forceIsSubordinate || isSubordinate;
if (isHr || isSubordinate)
return true;
return false;
}; };
}; };

View File

@ -30,7 +30,7 @@ module.exports = Self => {
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const isSubordinate = await models.Worker.isSubordinate(ctx, id); const isSubordinate = await models.Worker.isSubordinate(ctx, id);
const isTeamBoss = await models.VnUser.hasRole(userId, 'teamBoss'); const isTeamBoss = await models.ACL.checkAccessAcl(ctx, 'Worker', 'isTeamBoss', 'WRITE');
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss)) if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
throw new UserError(`You don't have enough privileges`); throw new UserError(`You don't have enough privileges`);

View File

@ -35,19 +35,13 @@ module.exports = Self => {
}); });
Self.getLanded = async(ctx, shipped, addressFk, agencyModeFk, warehouseFk, options) => { Self.getLanded = async(ctx, shipped, addressFk, agencyModeFk, warehouseFk, options) => {
const models = Self.app.models;
const myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const userId = ctx.req.accessToken.userId; const canSeeExpired = await models.ACL.checkAccessAcl(ctx, 'Agency', 'seeExpired', 'READ');
const models = Self.app.models;
const roles = await models.VnUser.getRoles(userId);
const canSeeExpired = roles.filter(role =>
role == 'productionBoss' || role == 'administrative'
);
let showExpired = false;
if (canSeeExpired.length) showExpired = true;
const stmts = []; const stmts = [];
stmts.push(new ParameterizedSQL( stmts.push(new ParameterizedSQL(
@ -56,7 +50,7 @@ module.exports = Self => {
addressFk, addressFk,
agencyModeFk, agencyModeFk,
warehouseFk, warehouseFk,
showExpired canSeeExpired
] ]
)); ));

View File

@ -24,7 +24,6 @@ module.exports = Self => {
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
const userId = ctx.req.accessToken.userId;
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
const models = Self.app.models; const models = Self.app.models;
const where = filter.where; const where = filter.where;
@ -36,10 +35,7 @@ module.exports = Self => {
&& where.agencyModeFk && where.warehouseFk; && where.agencyModeFk && where.warehouseFk;
if (filterByAvailability) { if (filterByAvailability) {
const roles = await models.VnUser.getRoles(userId, myOptions); const canSeeExpired = await models.ACL.checkAccessAcl(ctx, 'Agency', 'seeExpired');
const canSeeExpired = roles.filter(role =>
role == 'productionBoss' || role == 'administrative'
);
let showExpired = false; let showExpired = false;
if (canSeeExpired.length) showExpired = true; if (canSeeExpired.length) showExpired = true;