feat(canEdit): use checkAccess
gitea/salix/pipeline/head This commit is unstable
Details
gitea/salix/pipeline/head This commit is unstable
Details
This commit is contained in:
parent
36c0cc1a38
commit
b37c257885
|
@ -1,3 +1,5 @@
|
|||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES
|
||||
('Sale', 'editTracked', 'WRITE', 'ALLOW', 'ROLE', 'production');
|
||||
('Sale', 'editTracked', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||
('Sale', 'editFloramondo', 'WRITE', 'ALLOW', 'ROLE', 'salesAssistant'),
|
||||
('Ticket', 'editWeekly', 'WRITE', 'DENY', 'ROLE', '$authenticated');
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
module.exports = function(app) {
|
||||
app.models.ACL.checkAccess = async(ctx, modelId, property, accessType = '*') => {
|
||||
const models = app.models;
|
||||
const context = {
|
||||
accessToken: ctx.req.accessToken,
|
||||
model: models[modelId],
|
||||
property: property,
|
||||
modelId: modelId,
|
||||
accessType: accessType,
|
||||
sharedMethod: {
|
||||
name: property,
|
||||
aliases: [],
|
||||
sharedClass: true
|
||||
}
|
||||
};
|
||||
|
||||
const acl = await models.ACL.checkAccessForContext(context);
|
||||
|
||||
return acl.permission == 'ALLOW';
|
||||
};
|
||||
};
|
|
@ -1,5 +1,4 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const loopBackCtx = require('vn-loopback/server/server');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('canEdit', {
|
||||
|
@ -7,7 +6,7 @@ module.exports = Self => {
|
|||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'sales',
|
||||
type: ['object'],
|
||||
type: ['number'],
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
|
@ -16,7 +15,7 @@ module.exports = Self => {
|
|||
},
|
||||
http: {
|
||||
path: `/canEdit`,
|
||||
verb: 'get'
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -27,64 +26,39 @@ module.exports = Self => {
|
|||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
console.log(ctx.req.accessToken);
|
||||
const token = ctx.req.accessToken;
|
||||
let canEditTracked = await models.ACL.checkAccessForToken(token, models.Sale, null, 'refund');
|
||||
// const newCtx = ctx;
|
||||
// newCtx.property = 'refund';
|
||||
// newCtx.accessType = 'WRITE';
|
||||
// newCtx.methodNames = ['refund'];
|
||||
// newCtx.model = await models.Sale;
|
||||
const salesData = await models.Sale.find({
|
||||
fields: ['id', 'itemFk', 'ticketFk'],
|
||||
where: {id: {inq: sales}},
|
||||
include:
|
||||
{
|
||||
relation: 'item',
|
||||
scope: {
|
||||
fields: ['id', 'isFloramondo'],
|
||||
}
|
||||
}
|
||||
}, myOptions);
|
||||
|
||||
// let canEditTracked = await models.ACL.checkAccessForContext(newCtx);
|
||||
console.log(canEditTracked);
|
||||
const ticketId = salesData[0].ticketFk;
|
||||
|
||||
// let canEditTracked2 = await models.ACL.checkPermission('USER', 'developer', 'Sale', 'editTracked', 'READ');
|
||||
/* const array = ['editTracked'];
|
||||
const AccessContext = loopBackCtx.AccessContext;
|
||||
const toFind = {
|
||||
principals: [{
|
||||
type: 'ROLE',
|
||||
id: 'employee'
|
||||
}],
|
||||
model: 'Sale',
|
||||
property: 'editTracked',
|
||||
methodNames: ['editTracked'],
|
||||
accessType: 'WRITE'
|
||||
};
|
||||
const newContext = new AccessContext(toFind);
|
||||
newContext.methodNames = ['editTracked'];
|
||||
const isTicketEditable = await models.Ticket.isEditable(ctx, ticketId, myOptions);
|
||||
if (!isTicketEditable)
|
||||
throw new UserError(`The sales of this ticket can't be modified`);
|
||||
|
||||
let canEditTracked3 = await models.ACL.checkAccessForContext(newContext);
|
||||
const hasSaleTracking = await models.SaleTracking.findOne({where: {saleFk: {inq: sales}}}, myOptions);
|
||||
const hasSaleCloned = await models.SaleCloned.findOne({where: {saleClonedFk: {inq: sales}}}, myOptions);
|
||||
const isTicketWeekly = await models.TicketWeekly.findOne({where: {ticketFk: ticketId}}, myOptions);
|
||||
const hasSaleFloramondo = salesData.find(sale => sale.item().isFloramondo);
|
||||
|
||||
let canEditTracked4 = await models.ACL.checkAccessForContext({
|
||||
principals: [{
|
||||
type: 'ROLE',
|
||||
id: 'developer'
|
||||
}],
|
||||
model: 'Sale',
|
||||
property: 'editTracked',
|
||||
methodName: 'editTracked',
|
||||
methodNames: ['editTracked'],
|
||||
accessType: 'WRITE'
|
||||
});
|
||||
// console.log(canEditTracked);
|
||||
// canEditTracked = await models.ACL.resolvePermission(canEditTracked);
|
||||
// let canEditCloned = await models.ACL.checkPermission('ROLE', 'employee', 'Sale', 'editCloned', '*');
|
||||
// let canEditWeekly = await models.ACL.checkPermission('ROLE', 'employee', 'Ticket', 'editWeekly', '*');
|
||||
const canEditTracked = await models.ACL.checkAccess(ctx, 'Sale', 'editTracked');
|
||||
const canEditCloned = await models.ACL.checkAccess(ctx, 'Sale', 'editCloned');
|
||||
const canEditWeekly = await models.ACL.checkAccess(ctx, 'Ticket', 'editWeekly');
|
||||
const canEditFloramondo = await models.ACL.checkAccess(ctx, 'Sale', 'editFloramondo');
|
||||
|
||||
// console.log(canEditTracked, canEditTracked2);
|
||||
console.log('DENY: ', canEditTracked3.permission);
|
||||
console.log('ALLOW: ', canEditTracked4.permission);
|
||||
const shouldEditTracked = canEditTracked || !hasSaleTracking;
|
||||
const shouldEditCloned = canEditCloned || !hasSaleCloned;
|
||||
const shouldEditWeekly = canEditWeekly || !isTicketWeekly;
|
||||
const shouldEditFloramondo = canEditFloramondo || !hasSaleFloramondo;
|
||||
|
||||
const canEdit = shouldEditTracked && shouldEditCloned && shouldEditWeekly;
|
||||
|
||||
if (canEdit)
|
||||
return true;
|
||||
|
||||
return false;*/
|
||||
return shouldEditTracked && shouldEditCloned && shouldEditWeekly && shouldEditFloramondo;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,179 +1,253 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('sale canEdit()', () => {
|
||||
it('should return true if the role is production regardless of the saleTrackings', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const employeeId = 1;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
describe('sale editTracked', () => {
|
||||
it('should return true if the role is production regardless of the saleTrackings', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
const productionUserID = 49;
|
||||
const ctx = {req: {accessToken: {userId: productionUserID}}};
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const sales = [25];
|
||||
const productionUserID = 49;
|
||||
const ctx = {req: {accessToken: {userId: productionUserID}}};
|
||||
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
const sales = [25];
|
||||
|
||||
expect(result).toEqual(true);
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
expect(result).toEqual(true);
|
||||
|
||||
it('should return true if the role is not production and none of the sales has saleTracking', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const salesPersonUserID = 18;
|
||||
const ctx = {req: {accessToken: {userId: salesPersonUserID}}};
|
||||
|
||||
const sales = [10];
|
||||
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
|
||||
expect(result).toEqual(true);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return false if any of the sales has a saleTracking record', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const buyerId = 35;
|
||||
const ctx = {req: {accessToken: {userId: buyerId}}};
|
||||
|
||||
const sales = [31];
|
||||
|
||||
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 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 = [27];
|
||||
|
||||
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({});
|
||||
const roleEnabled = await models.ACL.findOne({
|
||||
where: {
|
||||
model: 'Sale',
|
||||
property: 'editCloned'
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
if (!roleEnabled || !roleEnabled.principalId) return;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
it('should return true if the role is not production and none of the sales has saleTracking', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
const roleId = await models.Role.findOne({
|
||||
where: {
|
||||
name: roleEnabled.principalId
|
||||
}
|
||||
});
|
||||
const ctx = {req: {accessToken: {userId: roleId}}};
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const sales = [27];
|
||||
const salesPersonUserID = 18;
|
||||
const ctx = {req: {accessToken: {userId: salesPersonUserID}}};
|
||||
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
const sales = [10];
|
||||
|
||||
expect(result).toEqual(true);
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
expect(result).toEqual(true);
|
||||
|
||||
it('should return false if any of the sales is of ticket weekly', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const employeeId = 1;
|
||||
const ctx = {req: {accessToken: {userId: employeeId}}};
|
||||
|
||||
const sales = [33];
|
||||
|
||||
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 of ticketWeekly and has the correct role', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const roleEnabled = await models.ACL.findOne({
|
||||
where: {
|
||||
model: 'Sale',
|
||||
property: 'editWeekly'
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
if (!roleEnabled || !roleEnabled.principalId) return;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
it('should return false if any of the sales has a saleTracking record', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
const roleId = await models.Role.findOne({
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const buyerId = 35;
|
||||
const ctx = {req: {accessToken: {userId: buyerId}}};
|
||||
|
||||
const sales = [31];
|
||||
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
|
||||
expect(result).toEqual(false);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('sale editCloned', () => {
|
||||
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 = [27];
|
||||
|
||||
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({});
|
||||
const roleEnabled = await models.ACL.findOne({
|
||||
where: {
|
||||
name: roleEnabled.principalId
|
||||
model: 'Sale',
|
||||
property: 'editCloned',
|
||||
permission: 'ALLOW'
|
||||
}
|
||||
});
|
||||
const ctx = {req: {accessToken: {userId: roleId}}};
|
||||
if (!roleEnabled || !roleEnabled.principalId) return await tx.rollback();
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const role = await models.Role.findOne({
|
||||
where: {
|
||||
name: roleEnabled.principalId
|
||||
}
|
||||
});
|
||||
const ctx = {req: {accessToken: {userId: role.id}}};
|
||||
|
||||
const sales = [27];
|
||||
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
|
||||
expect(result).toEqual(true);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('ticket editWeekly', () => {
|
||||
it('should return false if any of the sales is of ticket weekly', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const ctx = {req: {accessToken: {userId: employeeId}}};
|
||||
|
||||
const sales = [33];
|
||||
|
||||
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 of ticketWeekly and has the correct role', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const roleEnabled = await models.ACL.findOne({
|
||||
where: {
|
||||
model: 'Ticket',
|
||||
property: 'editWeekly',
|
||||
permission: 'ALLOW'
|
||||
}
|
||||
});
|
||||
|
||||
if (!roleEnabled || !roleEnabled.principalId) return await tx.rollback();
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const role = await models.Role.findOne({
|
||||
where: {
|
||||
name: roleEnabled.principalId
|
||||
}
|
||||
});
|
||||
const ctx = {req: {accessToken: {userId: role.id}}};
|
||||
|
||||
const sales = [33];
|
||||
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
|
||||
expect(result).toEqual(true);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('sale editFloramondo', () => {
|
||||
it('should return false if any of the sales isFloramondo', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const sales = [33];
|
||||
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
expect(result).toEqual(true);
|
||||
const ctx = {req: {accessToken: {userId: employeeId}}};
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
// For test
|
||||
const saleToEdit = await models.Sale.findById(sales[0], null, options);
|
||||
await saleToEdit.updateAttribute('itemFk', 9, options);
|
||||
|
||||
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 of isFloramondo and has the correct role', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const sales = [32];
|
||||
|
||||
const roleEnabled = await models.ACL.findOne({
|
||||
where: {
|
||||
model: 'Sale',
|
||||
property: 'editFloramondo',
|
||||
permission: 'ALLOW'
|
||||
}
|
||||
});
|
||||
|
||||
if (!roleEnabled || !roleEnabled.principalId) return await tx.rollback();
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const role = await models.Role.findOne({
|
||||
where: {
|
||||
name: roleEnabled.principalId
|
||||
}
|
||||
});
|
||||
const ctx = {req: {accessToken: {userId: role.id}}};
|
||||
|
||||
// For test
|
||||
const saleToEdit = await models.Sale.findById(sales[0], null, options);
|
||||
await saleToEdit.updateAttribute('itemFk', 9, options);
|
||||
|
||||
const result = await models.Sale.canEdit(ctx, sales, options);
|
||||
|
||||
expect(result).toEqual(true);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
fdescribe('sale reserve()', () => {
|
||||
describe('sale reserve()', () => {
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 1},
|
||||
|
@ -31,7 +31,7 @@ fdescribe('sale reserve()', () => {
|
|||
expect(error).toEqual(new Error(`The sales of this ticket can't be modified`));
|
||||
});
|
||||
|
||||
fit('should update the given sales of a ticket to reserved', async() => {
|
||||
it('should update the given sales of a ticket to reserved', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
try {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
const LoopBackContext = require('loopback-context');
|
||||
|
||||
describe('ticket componentUpdate()', () => {
|
||||
const userID = 1101;
|
||||
|
@ -175,10 +176,15 @@ describe('ticket componentUpdate()', () => {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||
active: ctx.req
|
||||
});
|
||||
const oldTicket = await models.Ticket.findById(ticketID, null, options);
|
||||
|
||||
await models.Ticket.componentUpdate(ctx, options);
|
||||
|
||||
const [newTicketID] = await models.Ticket.rawSql('SELECT MAX(id) as id FROM ticket', null, options);
|
||||
const oldTicket = await models.Ticket.findById(ticketID, null, options);
|
||||
const newTicket = await models.Ticket.findById(newTicketID.id, null, options);
|
||||
const newTicketSale = await models.Sale.findOne({where: {ticketFk: args.id}}, options);
|
||||
|
||||
|
|
Loading…
Reference in New Issue