-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] Fix Reaction.hasPermissions for anonymous users #3196
Changes from all commits
340bebd
34b53cf
18ac96a
71402c6
feb7a9c
df09e4b
eed4b15
a882145
c31f384
d072816
827daab
b7c5f64
64e04cc
4c017c0
b97b075
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
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("hasPermission", function () { | ||
let sandbox; | ||
|
||
beforeEach(function () { | ||
sandbox = sinon.sandbox.create(); | ||
}); | ||
|
||
afterEach(function () { | ||
sandbox.restore(); | ||
}); | ||
|
||
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("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("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("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("should return true for anonymous users when `permissions === ['anonymous', 'guest']`", function () { | ||
const user = Factory.create("anonymous"); | ||
sandbox.stub(Meteor, "userId", () => user._id); | ||
|
||
// 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]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doing [0] feels brittle because the value you're checking for could possibly be at index 1. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure it's possible for that index to be 1. I based my decision to use index 0 off of the declaration of So, I do think this is the best approach. Or do you have another approach in mind? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I meant that the fixture can change. A time will come when we make the fixtures multi-shop aware, then there will be more shopId keys (0,1 etc) there There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it will be better to wait till that change is made then. Coz until then, we can't know the structure of the new fixtures and the index of the right shopId to use above. |
||
const hasPermissions = Core.hasPermission(["anonymous", "guest"], user._id, shopId); | ||
expect(hasPermissions).to.be.true; | ||
}); | ||
|
||
it("should return true for registered users when `permissions === ['account/profile', 'guest']`", function () { | ||
const user = Factory.create("registeredUser"); | ||
sandbox.stub(Meteor, "userId", () => user._id); | ||
|
||
// 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; | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on this comment, do you think we should recommend that shopId be always passed to hasPermissions?
The value returned by getShopId() is based on the context it is called. I've seen this happen too when testing a cfs upload.
Also, considering that with v1.5.0+, there'll be more than one shop. It's important to be sure of the return value of getShopId().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zenweasel @spencern any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, being explicit with
shopId
too wouldn't hurt. The question is: is it necessary? And what are the scenarios that exist right now or may happen that will make it necessary?Consider this scenario: we have users X, Y and Z they are respectively the admins of shops X, Y and Z. If user X has shop X open, is there a button somewhere that s/he can use to delete a product in shop Z? Because then, even though s/he is logged into shop X, this app will need to check if s/he has the
deleteProduct
permissions in a different shop, shop Z.If scenarios similar to the above exist or can easily happen, then we definitely should require
shopId
to be explicitly passed tohasPermission
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about this again, I think it's fine as we have it currently. With default values for shopId (getShopId) and user (Meteor.user). The edge cases seem rare and each can be handled.
(so let's take this comment thread as resolved).