How to prevent access to a group if user isn't a member?
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
Hey Alan,
I think the before_method
is 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.
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.
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