Skip to content
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

Policy actions for model association managed through nested resource controller #51

Closed
leehericks opened this issue Dec 20, 2018 · 1 comment

Comments

@leehericks
Copy link

I have a NewsPost model which has a HABTM association to Users as :readers.
The purpose is basically to mark posts read to know who and how many have read it.

This is an API so I have the follow request:
GET /api/v1/news/:news_post_id/readers # Get list of users who read
POST /api/v1/news/:news_post_id/readers # Add the current user to readers
GET /api/v1/news/:news_post_id/readers/count # Just get the latest readers count

This maps to a NewsPostReadersController with index, create, count actions.
A before_action sets the news post for all these actions and calls authorize!

So here is the conundrum. Do I...

  1. Create a NewsPostReaderPolicy just for this "virtual resource"?
  2. Use the NewsPostPolicy but map associated actions?

1 didn't feel right because I was authorizing a NewsPost, so I went with 2:

def set_news_post
  @news_post = NewsPost.find(params[:news_post_id])
  policy_action = :"#{action_name}_readers?"
  authorize! @news_post, to: policy_action
  ...
end

This means index_readers?, create_readers? and count_readers?

What surprised me was that without defining those in my policy, they all passed. I think this was because I defined manage?? Is that correct?

Is there a better way to handle this situation with action_policy or should there be some api in the policy to define actions done on associations?

Thanks for your time! Saw your AnyCable presentation at Ruby Kaigi in Sendai and thought it was one of the best presentations. ;)

@palkan
Copy link
Owner

palkan commented Dec 21, 2018

Saw your AnyCable presentation at Ruby Kaigi in Sendai and thought it was one of the best presentations. ;)

Thanks! Glad you liked it)

I think this was because I defined manage?

Yep. manage? is the default rule for ActionPolicy::Base. You can change this behaviour either by not using ActionPolicy::Base as your root policy (see https://actionpolicy.evilmartians.io/#/custom_policy) or by setting default_rule nil.

This means index_readers?, create_readers? and count_readers?

Do these three actions require different permissions?

Usually, when dealing with associations I use some basic rule for the parent model instead of defining custom, e.g.: if I can see the post, I can see the readers and count them => call authorize! post, to: :show? in #index_readers and #count_readers.

That would also provide a meaningful failure reason (if you use i18n integration), e.g. "You don't have enough permissions to see this post".

There is no generic solution though, it highly depends on the business logic of your authorization model.

@palkan palkan closed this as completed Mar 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants