Skip to main content

How to prevent access to a group if user isn't a member?

Rails • Asked by Alan Reid
E1c4201cc974a033e860f7d7423a9b7f

Hi all,
I have user groups setup on my app using the code below...

class User < ActiveRecord::Base
  has_many :user_groups
  has_many :groups, through: :user_groups
end

class Group < ActiveRecord::Base
  has_many :user_groups
  has_many :users, through: :user_groups
end

class UserGroup < ActiveRecord::Base
  belongs_to :user
  belongs_to :group
end

All is working as expected, users are assigned to a group, and can access the data for that group. I have come accross an issue where any user, can access ANY group. Obvioulsy this is not good haha.

Can anyone recommend how i would go about preventing access to a group if a user is not a member of the group they are trying to access.

I was thinking of using a before_action and using it there and other controllers when needed.

FYI, i also have products assigned to groups so have a URL structure (below) which measn the ID variable for the group changes, not sure if i could just make that stay as :group_id maybe?

/groups/{:id}
/groups/{:group_id/products
/groups/{:group_id/products/{:id}

Any help would be much appreciated. Thanks in advance.
Alan


Dda4fed833fa3b14b5aaa24846f7debb

Hey Alan,

I think the before_methodis the way to go here if all you're needing to do is see if the current_user is part of the requested group.

  def authenticate_group_access
    unless current_user.groups.pluck(:id).include?(params[:group_id])
      redirect_back fallback_location: some_default_path, notice: "Silly bloke, you can't do that!"
    end
  end

There may be a cleaner way to handle the changing group_id param, but the few times this problem has popped up I break the rails convention (gasp!) and update my routes to use :group_id instead of :id since you have nested resources. Really I kind of prefer the more explicit convention of :model_id over the more ambigious :id for this very reason. It does require you to pay a bit more attention to your links and such.


E1c4201cc974a033e860f7d7423a9b7f

Had to convert the parm to an int using .to_i but otherwise that worked well. However, as I had set the route "slug" to group_id. and I then had the issues that my nested routes were given the param group_group_id dammit! haha

Any way, I stuck the nested resources inside a member do and a little tweaking of the paths, everything seems to be working as expected. Maybe not the cleanest solution, but sometimes I do feel the strictness of Rails can be a negative.


Dda4fed833fa3b14b5aaa24846f7debb

Haha, yeah it can be fun trying to figure out some of the little nuances...

For your routing, check out scopes which will let you do things like:

namespace :admins do
  scope module: :locations do
    scope ':location_id' do
      resources :discounts
    end
  end
end

Which would give routes like /admins/:location_id/discounts and /admins/:location_id/discounts/:id/edit


E1c4201cc974a033e860f7d7423a9b7f

As always so many ways to get stuff done. I will check out scopes later this evening.


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 18,000+ developers who get early access to new screencasts, articles, guides, updates, and more.

By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

More of a social being? We're also on Twitter and YouTube.