-
Notifications
You must be signed in to change notification settings - Fork 0
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
add allow_with_resource #8
Conversation
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.
All in all, I like this approach. Doesn't intervene with the existing logic and the code changes seem a lot safer. My suggestions are merely subjective and optional. With new tests for allow_with_resource
method, I think we should be good. Also, I would consider raising an error and force users to define role_resource
than building one for them. In the raised error, it might be helpful to mention that if you don't really care for resource for your roles, consider using allow
instead of allow_with_resource
.
@@ -90,8 +98,8 @@ def try_super(mname) | |||
end | |||
end | |||
|
|||
def build_gatekeeper(roles, actions) | |||
RoleGatekeeper.new(roles, actions).tap { |gatekeeper| | |||
def build_gatekeeper(roles, actions, require_resource) |
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.
You could make this false
by default and only pass true
when you need to. So, def build_gatekeeper(roles, actions, require_resource = false)
for definition and have the existing methods the same but call build_gatekeeper roles, nil, true
in allow_with_resource
method.
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.
Yeah, I couldn't decide if I should default it or not. My thinking it make more sense to explicitly say it's false or true. But I'm not sure if that really helps, so defaulting seems good.
@@ -31,22 +32,23 @@ def to_all | |||
self.all_actions = true | |||
end | |||
|
|||
def allow?(current_roles, action) | |||
def allow?(current_roles, action, role_resource) |
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.
You should name this differently if you intend to use the passed in param value in role?
. It could get confusing very easily when you have the same name in initializer that sets the self
attribute and the same name gets used in other parts of the class as local variable.
|
||
def match_roles(check_roles) | ||
def match_roles(check_roles, role_resource) | ||
check_roles = filter_roles_by_resource(check_roles, role_resource) if require_resouce |
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.
Since you call filter_roles_by_resource
only when require_resauce
is true, you should move the check in the method itself. You'll save yourself from repeated conditional and since
require_resauce
is already is an accessor, it's available across the class.
subject.to(:admin, :scorekeeper) | ||
end | ||
|
||
it_should_behave_like "allow should behave correctly" |
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.
lol wut!
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.
Right???
@vivekbisen could you take another look? I considered your idea of raising an error but we would have to raise it in the |
let(:admin_role) do | ||
admin = RoleObject.new(:admin) | ||
allow(admin).to receive(:resource?).and_return true | ||
admin |
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.
I wonder if you need the allow
here. Did you try moving the allow to your before-block. These let
blocks should only execute when called.
let(:scorekeeper_role) { RoleObject.new(:scorekeeper) } | ||
let(:current_user_roles) { [admin_role, scorekeeper_role] } | ||
let(:role_resource) { {resource: 123} } | ||
let(:check_access) { controller_instance.rolypoly_check_role_access! } |
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.
I like to append !
to my method names when they execute code that uses !
. So, check_access!
?
subject.publicize(:landing) | ||
allow(controller_instance).to receive(:current_user_roles).and_return(current_user_roles) | ||
allow(controller_instance).to receive(:action_name).and_return(action_name) | ||
allow(controller_instance).to receive(:role_resource).and_return(action_name) |
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.
👍
describe "#index" do | ||
let(:action_name) { "index" } | ||
|
||
it { expect(controller_instance).to_not be_public } |
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.
Is there a be_private
?
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.
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.
Rest of it looks good. Sorry, these things don't pop up all at once.
@@ -93,6 +93,46 @@ class ProfilesController < ApplicationController | |||
end | |||
``` | |||
|
|||
# Allow roles with a resource | |||
`allow_with_resource` acts similarly to `allow` but requires a resource check to access the endpoint. |
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.
So, as we discussed, it doesn't really require a resource check. It will check resources against an empty role_resource
.
@@ -17,6 +17,10 @@ def self.included(sub) | |||
unless sub.method_defined? :current_user_roles | |||
define_method(:current_user_roles) { [] } | |||
end | |||
|
|||
unless sub.method_defined? :role_resource | |||
define_method(:role_resource) { [] } |
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.
Also, you wanna change this to an empty hash.
@@ -4,102 +4,144 @@ module Rolypoly | |||
describe RoleGatekeeper do | |||
let(:roles) { %w[admin scorekeeper] } | |||
let(:actions) { %w[index show] } | |||
let(:resource) { [] } |
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.
And again, this resource would be a hash.
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.
👏 Let's get this moving.
|
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.
Description and Impact
Deploy Plan
Rollback Plan
git revert -m 1 MERGE_SHA
and perform another deploy.URLs
QA Plan