Kamilski81
Kamilski81

Reputation: 15107

How can I clean up my user permissions code in Ruby/Rails?

I am writing a system where every user can manage other users' permissions.

I have a business requirement where a logged_in_user can't demote someone higher than them in rankings. My positions are the following:

STAFF < MANAGER < ORGANIZATION_ADMIN

I am trying to display the permission buttons for the users and have the following (ugly) method that gets the job done, but feels like awful code.

# Iterate through all users and allow for their permissions to be modified
other_users.each do |other_user|
  buttons_to_show = get_buttons_to_show(logged_in_user, other_user)

  if buttons_to_show.include?(ORGANIZATION_ADMIN)
    puts "Make other_user #{ORGANIZATION_ADMIN}" # Will be a button on UI

  if buttons_to_show.include?(MANAGER)
    puts "Make other_user #{MANAGER}" # Will be a button on UI

  if buttons_to_show.include?(STAFF)
    puts "Make other_user #{STAFF}" # Will be a button on UI
end


def get_buttons_to_show(current_user, other_user)
  buttons_to_show = []

  if (current_user.at_least_staff? && other_user.role != MANAGER && other_user.role != ORGANIZATION_ADMIN) ||
      (current_user.at_least_manager? && other_user.role != ORGANIZATION_ADMIN) ||
      (current_user.at_least_organization_admin?)
    buttons_to_show << STAFF
  end

  if (current_user.at_least_manager? && other_user.role != ORGANIZATION_ADMIN) ||
      (current_user.at_least_organization_admin?)
    buttons_to_show << MANAGER
  end

  if current_user.at_least_organization_admin?
    buttons_to_show << ORGANIZATION_ADMIN
  end

  buttons_to_show
end                

Upvotes: 0

Views: 38

Answers (2)

Kamilski81
Kamilski81

Reputation: 15107

I decided to use Pundit and move all of those methods into my policies. Works like a charm and is much cleaner.

Upvotes: 0

ghstcode
ghstcode

Reputation: 2912

Have you looked at using something like https://github.com/CanCanCommunity/cancancan ?

I used it recently and you end up adding some code to the models like this:

if user.has_role? :uam_officer
  can :create, Segment
  cannot :approve, User
  cannot :reject, User
end

and then in views for instance:

<% if can?(:create, Segment) %>
   <%= link_to 'New', new_management_segment_path, { :class=>"btn btn-primary" } %>
<% end %>

it helps keep the authorization logic packaged neatly.

Upvotes: 1

Related Questions