From 340bebd11d08a6a3df82cb4fe38018b6ed1ce090 Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Sun, 29 Oct 2017 12:58:46 +0100 Subject: [PATCH 01/15] stop auto-appending "owner" to the permissions list of each call to hasPermissions --- client/modules/core/main.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 31e21d60b90..c6eea9d197b 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -186,6 +186,8 @@ export default { // called out a userId is validated. // function roleCheck() { + // TODO: There're some outdated comments in this function. Clean them out. + // permissions can be either a string or an array // we'll force it into an array and use that if (checkPermissions === undefined) { @@ -193,14 +195,26 @@ export default { } else if (typeof checkPermissions === "string") { permissions = [checkPermissions]; } else { + /* TODO: Consult and add the code below if it is thought + of as useful. + if (!Array.isArray(checkPermissions)) { + return false; + } + if (checkPermissions.length === 0) { + return false; + } + */ permissions = checkPermissions; } // if the user has owner permissions we'll always check if those roles are enough // By adding the "owner" role to the permissions list, we are making hasPermission always return // true for "owners". This gives owners global access. // TODO: Review this way of granting global access for owners - permissions.push("owner"); - permissions = _.uniq(permissions); + + // TODO: Find out why were we ever joining "owner" to the permissions + // array in the first place. + // permissions.push("owner"); + // permissions = _.uniq(permissions); // // return if user has permissions in the group From 34b53cf33cff5ba8b90860caeb863b170d8f0eec Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Mon, 30 Oct 2017 15:10:52 +0100 Subject: [PATCH 02/15] remove unused code --- client/modules/core/main.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index c6eea9d197b..56877ae4d51 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -213,8 +213,6 @@ export default { // TODO: Find out why were we ever joining "owner" to the permissions // array in the first place. - // permissions.push("owner"); - // permissions = _.uniq(permissions); // // return if user has permissions in the group From 18ac96a140173753d12fbaf7b9d911a86503d31b Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Wed, 1 Nov 2017 00:17:09 +0100 Subject: [PATCH 03/15] remove a proposed parameter check --- client/modules/core/main.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 56877ae4d51..b4c8f1546e8 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -195,15 +195,6 @@ export default { } else if (typeof checkPermissions === "string") { permissions = [checkPermissions]; } else { - /* TODO: Consult and add the code below if it is thought - of as useful. - if (!Array.isArray(checkPermissions)) { - return false; - } - if (checkPermissions.length === 0) { - return false; - } - */ permissions = checkPermissions; } // if the user has owner permissions we'll always check if those roles are enough From 71402c6581b8fbb452ccbdaac0903e3ee2648f7d Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Thu, 2 Nov 2017 14:11:21 +0100 Subject: [PATCH 04/15] remove/update some comments --- client/modules/core/main.js | 60 +++++++------------------------------ 1 file changed, 11 insertions(+), 49 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index b4c8f1546e8..56f7b8d42b6 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -180,14 +180,10 @@ export default { let permissions = ["owner"]; let id = ""; const userId = checkUserId || Meteor.userId(); - // - // local roleCheck function - // is the bulk of the logic - // called out a userId is validated. - // - function roleCheck() { - // TODO: There're some outdated comments in this function. Clean them out. + // This is declared as a function for the sake of reuse. Note that it is + // only called after userId is validated. + function roleCheck() { // permissions can be either a string or an array // we'll force it into an array and use that if (checkPermissions === undefined) { @@ -197,46 +193,16 @@ export default { } else { permissions = checkPermissions; } - // if the user has owner permissions we'll always check if those roles are enough - // By adding the "owner" role to the permissions list, we are making hasPermission always return - // true for "owners". This gives owners global access. - // TODO: Review this way of granting global access for owners - - // TODO: Find out why were we ever joining "owner" to the permissions - // array in the first place. - // - // return if user has permissions in the group - // if (Roles.userIsInRole(userId, permissions, group)) { return true; } - // global roles check - // TODO: Review this commented out code - /* - - const sellerShopPermissions = Roles.getGroupsForUser(userId, "admin"); - // we're looking for seller permissions. - if (sellerShopPermissions) { - // loop through shops roles and check permissions - for (const key in sellerShopPermissions) { - if (key) { - const shop = sellerShopPermissions[key]; - if (Roles.userIsInRole(userId, permissions, shop)) { - return true; - } - } - } - }*/ - // no specific permissions found returning false return false; } - // - // check if a user id has been found - // in line 156 setTimeout - // + // If userId has been found, this calls roleCheck and then returns the + // result of that call. Returns false otherwise. function validateUserId() { if (Meteor.userId()) { Meteor.clearTimeout(id); @@ -246,21 +212,17 @@ export default { return false; } - // - // actual logic block to check permissions - // we'll bypass unecessary checks during - // a user logging, as we'll check again - // when everything is ready - // + /* + Checks for permissions. We'll skip performing some checks if the user is + currently logging in, as those will be done when log in is complete. + */ if (Meteor.loggingIn() === false) { - // // this userId check happens because when logout - // occurs it takes a few cycles for a new anonymous user + // occurs. It takes a few cycles for a new anonymous user // to get created and during this time the user has no // permission, not even guest permissions so we // need to wait and reload the routes. This - // mainly affects the logout from dashboard pages - // + // mainly affects the logout from dashboard pages. if (!userId) { id = Meteor.setTimeout(validateUserId, 5000); } else { From feb7a9c5f2d2bb1cd82db4370a7ef6263a88e63d Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Thu, 2 Nov 2017 20:32:55 +0100 Subject: [PATCH 05/15] permit owners to perform any action --- client/modules/core/main.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 56f7b8d42b6..f853eafc8a8 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -186,11 +186,20 @@ export default { function roleCheck() { // permissions can be either a string or an array // we'll force it into an array and use that + // TODO: Should we also cater for checkPermissions === "" and checkPermissions === []? if (checkPermissions === undefined) { permissions = ["owner"]; } else if (typeof checkPermissions === "string") { + if (checkPermissions === "owner") { + return Roles.userIsInRole(userId, "owner", group); + } + permissions = [checkPermissions]; } else { + if (checkPermissions.length === 1 && checkPermissions[0] === "owner") { + return Roles.userIsInRole(userId, checkPermissions, group); + } + permissions = checkPermissions; } From df09e4b830a4e6e72d913e7aa44269e23f5e95ee Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Fri, 3 Nov 2017 12:43:49 +0100 Subject: [PATCH 06/15] remove hard coding of 'owner' in hasPermission --- client/modules/core/main.js | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index f853eafc8a8..504927db336 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -177,33 +177,20 @@ export default { group = this.getShopId() || Roles.GLOBAL_GROUP; } - let permissions = ["owner"]; let id = ""; const userId = checkUserId || Meteor.userId(); // This is declared as a function for the sake of reuse. Note that it is // only called after userId is validated. function roleCheck() { - // permissions can be either a string or an array - // we'll force it into an array and use that - // TODO: Should we also cater for checkPermissions === "" and checkPermissions === []? - if (checkPermissions === undefined) { - permissions = ["owner"]; - } else if (typeof checkPermissions === "string") { - if (checkPermissions === "owner") { - return Roles.userIsInRole(userId, "owner", group); - } - - permissions = [checkPermissions]; - } else { - if (checkPermissions.length === 1 && checkPermissions[0] === "owner") { - return Roles.userIsInRole(userId, checkPermissions, group); - } - - permissions = checkPermissions; + if (!checkPermissions) { + return false; + } + if (typeof checkPermissions !== "string" && !Array.isArray(checkPermissions)) { + return false; } - if (Roles.userIsInRole(userId, permissions, group)) { + if (Roles.userIsInRole(userId, checkPermissions, group)) { return true; } From eed4b15f7b93b717625e3c7854eac27f52b67652 Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Fri, 3 Nov 2017 14:18:16 +0100 Subject: [PATCH 07/15] add jsdocs to some private functions --- client/modules/core/main.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 504927db336..84de60e85fe 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -180,8 +180,14 @@ export default { let id = ""; const userId = checkUserId || Meteor.userId(); - // This is declared as a function for the sake of reuse. Note that it is - // only called after userId is validated. + /** + * @method roleCheck + * @summary check whether or not a user is in a list of roles. + * @private + * @since 1.5.5 + * @return {Boolean} - returns true if a user is in one or more of the roles + * listed and false if not. + */ function roleCheck() { if (!checkPermissions) { return false; @@ -197,8 +203,15 @@ export default { return false; } - // If userId has been found, this calls roleCheck and then returns the - // result of that call. Returns false otherwise. + /** + * @method validateUserId + * @summary verifies that Meteor.userId() returns a value, after which + * it calls some functions, especially roleCheck. + * @private + * @since 1.5.5 + * @return {Boolean} - if userId has been found, this calls roleCheck and + * then returns the result of that call. Returns false otherwise. + */ function validateUserId() { if (Meteor.userId()) { Meteor.clearTimeout(id); From a88214561ed2b2c14aa6512c7780e542e8e4bf09 Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Fri, 3 Nov 2017 14:35:05 +0100 Subject: [PATCH 08/15] improve comments --- client/modules/core/main.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 84de60e85fe..5c5d1c9c1de 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -221,13 +221,14 @@ export default { return false; } - /* - Checks for permissions. We'll skip performing some checks if the user is - currently logging in, as those will be done when log in is complete. - */ + // Actual logic block to check permissions. + // We'll bypass unnecessary checks during + // a user's log in, as we'll check again + // when everything is ready. + // if (Meteor.loggingIn() === false) { // this userId check happens because when logout - // occurs. It takes a few cycles for a new anonymous user + // occurs, it takes a few cycles for a new anonymous user // to get created and during this time the user has no // permission, not even guest permissions so we // need to wait and reload the routes. This From c31f384e515950c9f62842947a0d3bf8022a1b9c Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Fri, 3 Nov 2017 14:59:05 +0100 Subject: [PATCH 09/15] make all calls to hasPermission explicitly list the permissions to check for --- client/modules/core/main.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 5c5d1c9c1de..23c8e76d5a6 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -192,9 +192,6 @@ export default { if (!checkPermissions) { return false; } - if (typeof checkPermissions !== "string" && !Array.isArray(checkPermissions)) { - return false; - } if (Roles.userIsInRole(userId, checkPermissions, group)) { return true; From d0728164f5a18a34827e12f720ba4ca027804b98 Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Tue, 14 Nov 2017 11:50:26 +0100 Subject: [PATCH 10/15] add tests for the server-side version of hasPermissions --- server/api/core/hasPermission.app-test.js | 63 +++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 server/api/core/hasPermission.app-test.js diff --git a/server/api/core/hasPermission.app-test.js b/server/api/core/hasPermission.app-test.js new file mode 100644 index 00000000000..0654d5d6440 --- /dev/null +++ b/server/api/core/hasPermission.app-test.js @@ -0,0 +1,63 @@ +import { Meteor } from "meteor/meteor"; +import { expect } from "meteor/practicalmeteor:chai"; +import { sinon } from "meteor/practicalmeteor:sinon"; +import { Factory } from "meteor/dburles:factory"; +import Core from "./core"; + +describe.only("hasPermission", function () { + let sandbox; + + beforeEach(function () { + sandbox = sinon.sandbox.create(); + }); + + afterEach(function () { + sandbox.restore(); + }); + + it.only("should return false when not passed any permissions", function () { + sandbox.stub(Meteor, "userId", () => "random-user-id"); + const hasPermissions = Core.hasPermission(); + expect(hasPermissions).to.be.false; + }); + + it.only("should return false when `permissions` is an empty string", function () { + sandbox.stub(Meteor, "userId", () => "random-user-id"); + const hasPermissions = Core.hasPermission(""); + expect(hasPermissions).to.be.false; + }); + + it.only("should return false when `permissions` is an empty array", function () { + sandbox.stub(Meteor, "userId", () => "random-user-id"); + const hasPermissions = Core.hasPermission([]); + expect(hasPermissions).to.be.false; + }); + + it.only("should return false for anonymous users when `permissions === [owner]`", function () { + const anonymousUser = Factory.create("anonymous"); + sandbox.stub(Meteor, "userId", () => anonymousUser._id); + const hasPermissions = Core.hasPermission(["owner"]); + expect(hasPermissions).to.be.false; + }); + + it.only("should return false for registered users when `permissions === [owner]`", function () { + const user = Factory.create("registeredUser"); + sandbox.stub(Meteor, "userId", () => user._id); + const hasPermissions = Core.hasPermission(["owner"]); + expect(hasPermissions).to.be.false; + }); + + it.only("should return true for anonymous users when `permissions === ['anonymous', 'guest']`", function () { + const user = Factory.create("anonymous"); + sandbox.stub(Meteor, "userId", () => user._id); + const hasPermissions = Core.hasPermission(["anonymous", "guest"]); + expect(hasPermissions).to.be.true; + }); + + it.only("should return true for registered users when `permissions === ['account/profile', 'guest']`", function () { + const user = Factory.create("registeredUser"); + sandbox.stub(Meteor, "userId", () => user._id); + const hasPermissions = Core.hasPermission(["account/profile", "guest"]); + expect(hasPermissions).to.be.true; + }); +}); From 827daab18dbf46dccf534dc1c7f8bb6421834bba Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Tue, 14 Nov 2017 11:52:42 +0100 Subject: [PATCH 11/15] remove code that auto-appends 'owner' to the permissions list supplied to hasPermissions --- server/api/core/core.js | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/server/api/core/core.js b/server/api/core/core.js index 915ef5f1c89..0b74d17697c 100644 --- a/server/api/core/core.js +++ b/server/api/core/core.js @@ -112,7 +112,6 @@ export default { hasPermission(checkPermissions, userId = Meteor.userId(), checkGroup = this.getShopId()) { // check(checkPermissions, Match.OneOf(String, Array)); check(userId, String); check(checkGroup, // Match.Optional(String)); - let permissions; // default group to the shop or global if shop isn't defined for some reason. let group; if (checkGroup !== undefined && typeof checkGroup === "string") { @@ -121,21 +120,12 @@ export default { group = this.getShopId() || Roles.GLOBAL_GROUP; } - // permissions can be either a string or an array we'll force it into an array and use that - if (checkPermissions === undefined) { - permissions = ["owner"]; - } else if (typeof checkPermissions === "string") { - permissions = [checkPermissions]; - } else { - permissions = checkPermissions; + if (!checkPermissions) { + return false; } - // if the user has admin, owner permissions we'll always check if those roles are enough - permissions.push("owner"); - permissions = _.uniq(permissions); - // return if user has permissions in the group - return Roles.userIsInRole(userId, permissions, group); + return Roles.userIsInRole(userId, checkPermissions, group); }, hasOwnerAccess() { From b7c5f647a645c4cfa30a2803d7b4518f9b6bbcf7 Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Wed, 15 Nov 2017 18:36:09 +0100 Subject: [PATCH 12/15] update the jsdocs of hasPermission on both the server and the client --- client/modules/core/main.js | 21 +++++++++++++-------- server/api/core/core.js | 18 +++++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 23c8e76d5a6..3ffbce78a1b 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -159,14 +159,19 @@ export default { }, /** - * hasPermission - client - * client permissions checks - * hasPermission exists on both the server and the client. - * - * @param {String | Array} checkPermissions -String or Array of permissions if empty, defaults to "admin, owner" - * @param {String} checkUserId - userId, defaults to Meteor.userId() - * @param {String} checkGroup group - default to shopId - * @return {Boolean} Boolean - true if has permission + * hasPermission - Performs client-side permission checks. Note that + * hasPermission exists on both the server and the client. So this is + * the client-side version. + * @param {String | Array} checkPermissions - permissions to check for. If + * empty/undefined, this function returns false. + * @param {String} checkUserId - user ID. If empty/undefined, this function uses + * the value returned by Meteor.userId(). + * @param {String} checkGroup - the group that the user being checked + * belongs to. If empty/undefined, this function uses the ID of the + * current shop or Roles.GLOBAL_GROUP. + * @since 0.14 + * @return {Boolean} - returns true if the said user has any of the permissions + * in checkPermissions, and false if s/he has none of them. */ hasPermission(checkPermissions, checkUserId, checkGroup) { let group; diff --git a/server/api/core/core.js b/server/api/core/core.js index 0b74d17697c..8dd310d78a4 100644 --- a/server/api/core/core.js +++ b/server/api/core/core.js @@ -101,13 +101,17 @@ export default { registerTemplate: registerTemplate, /** - * hasPermission - server - * server permissions checks - * hasPermission exists on both the server and the client. - * @param {String | Array} checkPermissions -String or Array of permissions if empty, defaults to "admin, owner" - * @param {String} userId - userId, defaults to Meteor.userId() - * @param {String} checkGroup group - default to shopId - * @return {Boolean} Boolean - true if has permission + * hasPermission - Performs server-side permission checks. Note that + * hasPermission exists on both the server and the client. This is + * the server-side version. + * @param {String | Array} checkPermissions - permissions to check for. If + * empty/undefined, this function returns false. + * @param {String} userId - user ID. Defaults to Meteor.userId(). + * @param {String} checkGroup - the group that the user being checked belongs + * to. Defaults to the ID of the current shop or Roles.GLOBAL_GROUP. + * @since 0.14 + * @return {Boolean} - returns true if the said user has any of the permissions + * in checkPermissions, and false if s/he has none of them. */ hasPermission(checkPermissions, userId = Meteor.userId(), checkGroup = this.getShopId()) { // check(checkPermissions, Match.OneOf(String, Array)); check(userId, String); check(checkGroup, From 64e04cc7aa26ad9cd458bf4eb807b06df3d29357 Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Wed, 15 Nov 2017 18:38:11 +0100 Subject: [PATCH 13/15] correct the release when some functions (in server-side hasPermission) were added --- client/modules/core/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/modules/core/main.js b/client/modules/core/main.js index 3ffbce78a1b..85115756ee0 100644 --- a/client/modules/core/main.js +++ b/client/modules/core/main.js @@ -189,7 +189,7 @@ export default { * @method roleCheck * @summary check whether or not a user is in a list of roles. * @private - * @since 1.5.5 + * @since 0.15.0 * @return {Boolean} - returns true if a user is in one or more of the roles * listed and false if not. */ @@ -210,7 +210,7 @@ export default { * @summary verifies that Meteor.userId() returns a value, after which * it calls some functions, especially roleCheck. * @private - * @since 1.5.5 + * @since 0.15.0 * @return {Boolean} - if userId has been found, this calls roleCheck and * then returns the result of that call. Returns false otherwise. */ From 4c017c01e11f7f87d0d537a8657ef1532a6285a3 Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Wed, 15 Nov 2017 19:20:00 +0100 Subject: [PATCH 14/15] improve the clarity of the description of some specs --- server/api/core/hasPermission.app-test.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/server/api/core/hasPermission.app-test.js b/server/api/core/hasPermission.app-test.js index 0654d5d6440..b4ea593f599 100644 --- a/server/api/core/hasPermission.app-test.js +++ b/server/api/core/hasPermission.app-test.js @@ -33,16 +33,9 @@ describe.only("hasPermission", function () { expect(hasPermissions).to.be.false; }); - it.only("should return false for anonymous users when `permissions === [owner]`", function () { - const anonymousUser = Factory.create("anonymous"); - sandbox.stub(Meteor, "userId", () => anonymousUser._id); - const hasPermissions = Core.hasPermission(["owner"]); - expect(hasPermissions).to.be.false; - }); - - it.only("should return false for registered users when `permissions === [owner]`", function () { - const user = Factory.create("registeredUser"); - sandbox.stub(Meteor, "userId", () => user._id); + it.only("should return false for users that don't have the `owner` permission", function () { + const registeredUser = Factory.create("registeredUser"); + sandbox.stub(Meteor, "userId", () => registeredUser._id); const hasPermissions = Core.hasPermission(["owner"]); expect(hasPermissions).to.be.false; }); From b97b0757d7465e17166aaf7142fc0a2e829829e2 Mon Sep 17 00:00:00 2001 From: Folusho Oladipo Date: Thu, 16 Nov 2017 14:02:16 +0100 Subject: [PATCH 15/15] fix failing tests --- server/api/core/hasPermission.app-test.js | 30 ++++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/server/api/core/hasPermission.app-test.js b/server/api/core/hasPermission.app-test.js index b4ea593f599..eaad13c9884 100644 --- a/server/api/core/hasPermission.app-test.js +++ b/server/api/core/hasPermission.app-test.js @@ -4,7 +4,7 @@ import { sinon } from "meteor/practicalmeteor:sinon"; import { Factory } from "meteor/dburles:factory"; import Core from "./core"; -describe.only("hasPermission", function () { +describe("hasPermission", function () { let sandbox; beforeEach(function () { @@ -15,42 +15,54 @@ describe.only("hasPermission", function () { sandbox.restore(); }); - it.only("should return false when not passed any permissions", function () { + it("should return false when not passed any permissions", function () { sandbox.stub(Meteor, "userId", () => "random-user-id"); const hasPermissions = Core.hasPermission(); expect(hasPermissions).to.be.false; }); - it.only("should return false when `permissions` is an empty string", function () { + it("should return false when `permissions` is an empty string", function () { sandbox.stub(Meteor, "userId", () => "random-user-id"); const hasPermissions = Core.hasPermission(""); expect(hasPermissions).to.be.false; }); - it.only("should return false when `permissions` is an empty array", function () { + it("should return false when `permissions` is an empty array", function () { sandbox.stub(Meteor, "userId", () => "random-user-id"); const hasPermissions = Core.hasPermission([]); expect(hasPermissions).to.be.false; }); - it.only("should return false for users that don't have the `owner` permission", function () { + it("should return false for users that don't have the `owner` permission", function () { const registeredUser = Factory.create("registeredUser"); sandbox.stub(Meteor, "userId", () => registeredUser._id); const hasPermissions = Core.hasPermission(["owner"]); expect(hasPermissions).to.be.false; }); - it.only("should return true for anonymous users when `permissions === ['anonymous', 'guest']`", function () { + it("should return true for anonymous users when `permissions === ['anonymous', 'guest']`", function () { const user = Factory.create("anonymous"); sandbox.stub(Meteor, "userId", () => user._id); - const hasPermissions = Core.hasPermission(["anonymous", "guest"]); + + // It is necessary to explicity supply shopId to the Core.hasPermission call + // below. If we don't, the said function defaults to using Core.getShopId + // which, when this test is run, will give a shop ID that will be different + // from the one used by Factory.create("anonymous"). + const shopId = Object.keys(user.roles)[0]; + const hasPermissions = Core.hasPermission(["anonymous", "guest"], user._id, shopId); expect(hasPermissions).to.be.true; }); - it.only("should return true for registered users when `permissions === ['account/profile', 'guest']`", function () { + it("should return true for registered users when `permissions === ['account/profile', 'guest']`", function () { const user = Factory.create("registeredUser"); sandbox.stub(Meteor, "userId", () => user._id); - const hasPermissions = Core.hasPermission(["account/profile", "guest"]); + + // It is necessary to explicity supply shopId to the Core.hasPermission call + // below. If we don't, the said function defaults to using Core.getShopId + // which, when this test is run, will give a shop ID that will be different + // from the one used by Factory.create("registeredUser"). + const shopId = Object.keys(user.roles)[0]; + const hasPermissions = Core.hasPermission(["account/profile", "guest"], user._id, shopId); expect(hasPermissions).to.be.true; }); });