環境
Ruby 2.5
Rails 5.2.4
実現したいこと
以下の3種類の役割があるとします。
RoleA → フル権限(GET,PUT,PATCH,DELETE)
RoleB → 全ページの閲覧とデータが更新ができる(GET,PATCH)
RoleC → データは更新できないが、全ページの閲覧が可能
この条件で各ページ、メソッド単位で各機能ごとに細かく権限管理したい。(仕様によりがっつりとrequestパラメーター使えない)
前提
UserはActiveRecordを使用しておらず、外部サービスで作られ、データも外部で保持されており必要に応じてRailsから参照しています。それに伴い私にはDeviseのGemが使えなかったためYmlを使用しようと思いました。
current_user[:role] # roleB
で現在のユーザーのroleを取得することはできます。
各ページごとのidを取得することができます。
params[:page_name] # page_a
この二軸で判定を行います
1. ymlを作成する
/config/previlege.ymlを自分で作成し権限とページの軸で記述していきます。
previlege.yml
1はフル権限(GET,PATCH,POST,DELETE)
2は参照と更新のみ(GET,PATCH)
3はアクセス権なし(記載がなければ自動的に3扱い)
roleA:
page_a: 1
page_b: 1
page_c: 1
page_d: 1
roleB:
page_a: 1
page_b: 1
page_c: 2
page_d: 2
roleC:
page_a: 2
page_b: 2
config/initializers/previlege.rb
file = File.read("#{Rails.root}/config/previlege.yml")
PREVILEGE = YAML.safe_load(file, [] , [], true)
ここまででymlを定義し定数として使えるようになりました。
以下のようにしてハッシュで取れます。
例
puts PREVILEGE[:roleB]
=> { page_a: 1
page_b: 1
page_c: 2
page_d: 2 }
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user # helperでcurrent_userが使える
private
def current_user
# 省略=> roleが返ってくる
end
def judge_previlege
if PREVIREGE[current_user[:role]][params[:page_name]] == 1
true
elsif PREVIREGE[current_user[:role]][params[:page_name]] == 2 && request.patch? || request.get?
true
else
return redirect_to root_path, flash[:error] = "権限がありません"
end
end
end
before_actionでメソッドを使う
app/controllers/posts_controller.rb
class PostsController < ApplicationControler
before_action :judge_previlege
def index
省略
end
def update
省略
end
end
こんな感じでコントローラーの制御はできます。
備忘録で大雑把に書いていますので、気に入っていただけたらあとは応用してもらうのが良いかと思います。
viewの出し分けは
app/helpers/application_helper.rb
module ApplicationHelper
def showrable?
if PREVIREGE[current_user[:role]][params[:page_name]] == 1 || PREVIREGE[current_user[:role]][params[:page_name]] == 2
true
else
false
end
end
def clickable?
if PREVIREGE[current_user[:role]][params[:page_name]] == 1
true
else
false
end
end
end
index.html.erb
表示するか
if showrable?
表示させる
end
クリックできるか
link_to_if(clickable?, "リンク",hoge_path)
以上になります
間違えている可能性ありますので(特にviewあたりは適当です....)、参考程度でお願いします...