ben

OMÜ , Bilgisayar Mühendisliği, 13'

21 Ağustos 2015 Cuma

rails-devise-pundit


   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?