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

Ask A Question

Notifications

You’re not receiving notifications from this thread.

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

Alan Reid asked in Rails

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_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.

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

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

Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 37,629+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

    © 2020 GoRails, LLC. All rights reserved.