web-dev-qa-db-ja.com

Rails 4ユーザーの役割と権限

Rails組織向けのアプリケーションを作成しています。すべてのユーザーが1つ以上の役割を持ち、それらの役割に応じて特定のコントローラーアクションにのみアクセスできます。

たとえば、Usersの特定のフィールドを作成、破棄、更新できるのはadminsだけです。また、それぞれにチームリーダーがあるTeamsがあり、チームリーダーのみがTeamに関する特定の情報を更新できます(メンバーリストなど)。ただし、Adminsチームリーダーを最初に割り当てる人です。

私のシナリオの具体的な詳細は重要ではありません。さまざまな役割と権限が存在する状況について説明したいと思います。

私の質問は、どのgemを使用するのですか?私の最初の考えはCanCanでしたが、最後のコミットはほぼ1年前であり、Rails 4互換性についての言及はありません。現在維持されている代替はありますか?

18
gdiazc

あなたの最初の推測は正しかった、 cancancan を使用して、あなたはそれでうまくいくでしょう。

編集2015年7月24日

私は長い間cancancanを使用してきました、そしてそれは常に素晴らしい働きをしていました。私は最近、承認に Pundit が使用されるプロジェクトに取り組み始めました。

すばらしい。リソースごとにポリシーを定義するように求められ、1つの肥大したAbilityクラスよりも自然に感じられます。

より大きなプロジェクトの場合は、Punditをお勧めします。

28
Andrey Deineko

アクションへのアクセスを制御するために私がお勧めするのは Action Access です。

class UsersController < ApplicationController
  let :admin, :all
  let :user, [:index, :show]

  # ...
end

これにより、コントローラーが自動的にロックされ、管理者はすべてのアクションにアクセスでき、ユーザーはユーザーの表示またはインデックス作成のみを行えます。他のユーザーは拒否され、アラートでリダイレクトされます。

さらに制御が必要な場合は、not_authorized!内部アクションを使用して、アクセスをチェックして拒否できます。

認証システムとは完全に独立であり、Userモデルや事前定義されたロールがなくても機能します。必要なのは、現在のリクエストのクリアランスレベルを設定することだけです。

class ApplicationController < ActionController::Base
  def current_clearance_level
    session[:role] || :guest
  end
end

ここでは、たとえばcurrent_user.roleのように、アプリで必要なものをすべて返すことができます。

必須ではありませんが、次のようなことができる便利なモデルの追加セットがバンドルされています。

<% if current_user.can? :edit, :team %>
  <%= link_to 'Edit team', edit_team_path(@team) %>
<% end %>

ここで:teamTeamsControllerを参照しているため、現在のユーザーがeditTeamsControllerアクションへのアクセスを許可されている場合にのみリンクが表示されます。 namespacesもサポートしています。

デフォルトでコントローラをロックしたり、リダイレクトパスやアラートメッセージをカスタマイズしたりできます。

それは非常に簡単で簡単です、あなたがそれが役に立つことを望みます。

5
404

現在使用していることが示唆されたのは petergate gemです。使いやすく、見た目もすっきりしているRails感触。

devise でうまく機能します。

Readmeの例をいくつか示します。

Deviseを使用している場合は運が良ければ、そうでない場合はプロジェクトに次のメソッドを追加する必要があります。

user_signed_in?
current_user
after_sign_in_path_for(current_user)
authenticate_user! 

これはUser.rbに含まれています。役割を追加するのは、配列に追加するのと同じくらい簡単です。

petergate(roles: [:admin, :editor], multiple: false)

インスタンスメソッド

user.role => :editor
user.roles => [:editor, :user]
user.roles=(v) #sets roles
user.available_roles => [:admin, :editor]
user.has_roles?(:admin, :editors) # returns true if user is any of roles passed in as params.

コントローラアクセス構文。

access all: [:show, :index], user: {except: [:destroy]}, company_admin: :all
2
Jake