In my app I have 3 different models in a linear fashion:
M1, M2, and M3. M1 has many M2 which has many M3.
M1 has 2 properties: private and completed. If it's private then only
the person who created M1 can do anything with it (all the rest
actions), and if it's completed then more M2 and M3 cannot be added.
For M2, only the M1 creator and the M2 creater (the M2 creator is most
likely a different person) can do anything with it (rest actions), and
the same goes for M3 except the people who can do anything with M3 are
the owners of M1, M2, and M3.
It seems these permissions are really complex and I'm not sure how I
should go about this. Before I just had protected methods in each of
the controllers of these models, but theres a lot of repeated code and
its just not pretty to look at. Should I abstract some of this into
the ApplicationController, or create a module/helper for this?
Look at CanCan or Aegis as gems that deal with authorization. Your matrix isn’t all that complicated as a model of permissions
I'm using CanCan right now but I don't see any options for it to help
me with these kinds of permissions. Or can it? I read through the
little readme on github and didn't see anything.
Ah. Well, I favour Aegis (mainly as I discovered it before CanCan) and
it certainly does support custom permissions, and complex conditionals
when required in a permissions evaluation.
Regular controller authorization in my Permissions.rb file such as:
resources :environments do
action :index do
# everyone can access the index page
action :show do
# users can only see environments they're allocated to
allow :user do
# admins can see environments they're allocated to, or that
allow :admin do
user.environments.include?(object) || user.administering?(object)
...which lets me do "current_user.may_show_environment?(environment)"
in a controller, view, wherever.
Or a custom permission:
action :view_all_evidence_for_control do
# flatly only allow admins
# (or have big case statement that evaluates true or false
depending on future criteria)
...gives me "current_user.may_view_all_evidence_for_control?(control)"
Unfortunately, I can't tell you how to do the same with CanCan... just
that I *thought* it was almost equivalent.