Ron M
Ron M

Reputation: 803

Restrict routes to certain users in Rails app

In my rails v4 app, users belong to a single group.

class User < ActiveRecord::Base
  belongs_to :group
  ...

Each group can have many projects,

class Group < ActiveRecord::Base
  has_many :projects
  has_many :users
  ...

Each project can have many experiments, in a one to many relationship.

In my routes, I have:

resources :projects do
    resources :experiments do
      ...
    end
  end

What I'd like to do is only allow users to access projects and experiments if the project has the same group_id as the user (i.e. if user enters a project id parameter in the projects#show route for a project outside of their group, it will not be displayed). Is there a clean way to implement this without having to do multiple checks in the view?

Upvotes: 0

Views: 1982

Answers (2)

kimrgrey
kimrgrey

Reputation: 562

This is authorization problem, so, as for me, it's better to define what users can and can not see using any auhtorization library, not using routes or something like that. Because you will, for example, definitely want to find out should you display link on given group in views, which groups is available for current user and so on.

Take a look on cancancan for example: https://github.com/CanCanCommunity/cancancan.

Upvotes: 1

Aegix
Aegix

Reputation: 649

Take a look at building a custom constraint based on Group membership:

http://guides.rubyonrails.org/routing.html#advanced-constraints

Extremely simple example (obviously, you'll need to match your project design):

class GroupConstraint
  def initialize
    @project = Project.find(params[:id])
    @user = current_user
  end
 
  def matches?(request)
    @user.groups.include?(@project.group)
  end
end

Then in your routes:

resources :projects, constraints: GroupConstraint.new do
  resources :experiments do
      ...
  end
end

Upvotes: 3

Related Questions