How to authorize in multi-membership app? #840
-
In my app, I have # Events
can :manage, Event, created_by: member.id
can :read, Event, owned_by_group: member.group_id if member.has_permission?(:view, :events)
can [:update, :destroy, :activate, :cancel], Event, group: member.group if member.has_permission?(:edit, :events)
can :manage, Event, group: member.group if member.has_permission?(:create, :events) However, as users can acess app from email link, notification, calendar,..., I need to authorize if current user has any membership which permits them to access given resource, and if they have, switch current member to this membership (implemented via First part could be done by changing But I'm stuck on how to combine that with the second part - changing cookies based on that. I tried something like # app/controllers/application_controller.rb
def authorize_resource_and_set_member
memberships = [Current.member] + current_user.memberships.excluding(Current.member)
memberships.each do |member|
p member
begin
p "authorizing for #{member}"
authorize_resource
rescue CanCan::AccessDenied
p "denied for #{member}"
next
end
end
end which is not working (unsurprisingly). I'll be glad for any pointers and ideas. Update: |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Ok, so I probably solved this. I realized I can approach this bit different way, and only focus on switching member before trying to So, I came up with this: # app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
# ...
private
def switch_member_if_needed
memberships = [Current.member] + current_user.memberships.excluding(Current.member)
memberships.each do |membership|
@current_ability = Ability.new(membership)
object = instance_variable_get(:"@#{controller_name.singularize}")
next unless can? :show, object
Current.member = membership
set_current_member(Current.member)
return true
end
end
end used like # app/controllers/announcement_controller.rb
class AnnouncementsController < ApplicationController
before_action :set_announcement, only: %i[show edit update destroy]
before_action :switch_member_if_needed, only: %i[show]
authorize_resource
# ...
end This way, I load resource, find first member on current_user that can view that resource, switch to that, and authorize as I would normally do. It is bit unoptimized, as I'm running the permission check two times, but I don't need to deal with raising error and other things - I'm not really authorizing in my added method. |
Beta Was this translation helpful? Give feedback.
Ok, so I probably solved this.
I realized I can approach this bit different way, and only focus on switching member before trying to
authorize_resource
.So, I came up with this: