Pundit ,sisteme giren kullanıcıların yetkilerini sınırlandıran gemdir. Daha önce devise ile olusturduğumuz projeye devam olarak yazalım
Benim eklemek istediğim rol yapısı , bir kişi bırden fazla rolu olabilir. Admin olan kulanıcı aynı zamanda teacher olabilir. Ve Bir rolde birden fazla kullanıcıda olabilir. Bu yapıya göre bir model olusturup bu modeli User modelimizle ÇokaÇok ilişki kurmamızdır.
$ rails g model Role role:string
$ rails generate migration CreateJoinTableUserRole user role
user.rb=> has_and_belong_to_many: roles
role.rb=> has_and_belong_to_many: users
Role Tablosuna rol ekleyelim
seed.rb dosyasına superAdminKullanıcısı ekleyelim. SuperAdmin sistem le ilgili işlemler yapabilir. Bu yuzden sisteme kayıt olan kullanıcılar Super Admin Yetkisinde kayıt olamazlar.
$ rails c
Role.create(role: "SuperAdmin")
Role.create(role: "Admin")
Role.create(role: "Teacher")
iki kullanıcı kaydı olusturalım Admin ve Teacher kullanıcısı
Admin Post Kayıtlarını düzenleyebilir, Teacher ise görüntüleyebilir.
app/views/devise/registrations/new.html.erb
<% for role in Role.all %>
<div>
<% if role.role!="SuperAdmin"%>
<%= radio_button_tag "user[role_ids][]", role.id, @user.roles.include?(role) %>
<%= role.role %>
<%end%>
</div>
<% end %>
Devise Geminin kullandığı controlları customize etmemiz gerek. Burdan sayfayı projemize ekleyebiliriz
confg.routes
devise_for :users, :controllers => { :registrations => "registrations" }
app/Controller/registrations_controller.rb
create alanına:
build_resource(sign_up_params)
a=params['user']
self.resource.roles<<Role.find(a['role_ids'])
resource.save
Rol modelimizi olusturup kullanıcı kaydettiğimize göre gelelim Pundit ile yetkilendirmeye, Gerekli gem;
gemfile
gem "pundit"
controller/application.rb
include Pundit
protect_from_forgery
$ rails g pundit:install
$ rails g pundit:policy post
post_policy.rb
attr_reader :user, :post
def initialize(user, post)
@user = user
@post = post
end
def edit?
user.roles.where(role: 'Admin').exists?
end
def show?
user.roles.where(role: 'Teacher').exists?
end
Not:
burda eğer bir kullanıcının bir yetkisi user tablosuna column olarak eklersek , örneğin bool turunde user tablosuna isAdmin, isTeacher olarak eklersek burdaki sorgu ;
user.isAdmin?
Ayrı bir tabloda(Role) bire-bir ılşkili olursa;
user.has_roles?("Admin")
--------
controller/post_controller.rb
edit ve show kısımlara
authorize @post
Admin yetkisi olan esra@gmail ile sisteme girelim.
edit sayfasına izin verildi.
Show sayfasına izin hatası verdi
Bu hatayı public/403.html hata sayfasına yönlendirebiliriz. 403 sayfası yoksa yeni olusuturalım. varsa düzenleyebiliriz.
application_controller.rb
include Pundit
protect_from_forgery with: :exception
rescue_from Pundit::NotAuthorizedError, with: :permission_denied
def permission_denied
render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)
end
public/403.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<img src="https://0.s3.envato.com/files/31735931/12_403error.png" width="1200", height="600">
</body>
</html>
Arayüzde engellemek için ;
view/post/index.html
-if current_user.roles.where(role: 'Teacher').exists?
td = link_to 'Show', post
-if current_user.roles.where(role: 'Admin').exists?
td= link_to 'Edit', edit_post_path(post)
teacher yetkisiyle giriş yapalım. Edit alanı gizlendi.
Birden fazla role izin vermek için;
if current_user.roles.where(role: 'Teacher'||role: 'student').exists?