發新話題
打印

Rails的管理權限設計手法2

本主題由 lovingcatz 於 2010-2-24 07:38 移動

Rails的管理權限設計手法2

上篇的啟發,這篇是實作的部份,只講概念,因為實際的code與系統架構差異甚大,所以請自行設計內容物

大概是這樣的,先在model內增加like
複製內容到剪貼板
代碼:
class User < ActiveRecord::Base
  def is_admin? ; end
  def is_editor? ; end
end
class Organization < ActiveRecord::Base
  def is_admin?(user) ; end
  def is_editor?(user) ; end
  def is_member?(user) ; end
end
因為這個check很常用,所以直接上application controller(各只寫一個當demo|||)
複製內容到剪貼板
代碼:
class ApplicationController < ActionController::Base
  def site_editor_check
    unless logged_in? && current_user.is_editor?
      warning_stickie("您進入到了全站編輯者專用的區域,但您並未擁有編輯者的身分,已儲存IP位址相關資訊,君子請自重")
      redirect_back_or_default('/')
      return false
    end
    return true
  end
  def org_admin_check
    unless logged_in? && @organization && @organization.is_admin?(current_user)
      warning_stickie("您進入到了公司管理員專用的區域,但您並未擁有管理員的身分,已儲存IP位址相關資訊,君子請自重")
      redirect_back_or_default('/')
      return false
    end
    return true
  end
end
裡面有個重點在於@organization的產生,如果都是使用paramd[:id] or params[:org]之類的方式來指定,可以獨立寫出一個action來做filter,來產生@organization即可(或是你高興也可以在check內直接判定),當然不是凡事都那麼美好,所以就會有兩種指定check的方式
複製內容到剪貼板
代碼:
class UsersController < ActionController::Base
  before_filter :site_admin_check
  before_filter :org_admin_check, :only => [ :edit, :update ]
  skip_before_filter :site_member_check
end
最後一個skip是用在如果已經繼承之後的情況下,例如application controller有before_filter,但繼承的users controller又不想用那個filter時使用,而only是用在指定action的情況下,或是用except來做排除指定的action,這是全域的宣告,而如果想用在action內,也就是前述所提的@organization產生後的情況,請在action內指定為
複製內容到剪貼板
代碼:
class UsersController < ActionController::Base
  def index #需Org最高權限管理員身分
    @organization = Organization.first
    return unless org_admin_check
    ....
  end
end
要用return中斷的原因在於任何一個action內只能有一個render或redirect_to,而filter算是預先執行的action,和本身的action分離,但在action內呼叫的話就算是同一個action,所以需要return來做brake的動作,&系統做大後,也建議在每個action後面加註解,包括所需要的身分與用途之類的,不然才不會看到眼花X"D

以上的code尚未測試,but照理可行,實作後有錯誤再另補上,以上
(Plurk) 人因夢想而偉大,如果沒有信仰,則將一無所有,持續往殉道的路邁進,獻祭著自己的靈魂,走著最極端的路;而那迷霧的後面,會是地獄,也是天堂
self.attributes #=> [惡搞之魂,貓化身,怪咖吸鐵石,邪道程式設計師,動漫宅,蘿莉控,惡趣味,Geek,H=F^3]
[82,117,98,121,32,79,110,32,82,97,105,108,115,32,105,115,32,77,121,32,76,105,102,101].map{|l|l.chr}.to_s

TOP

判斷身分Check的程式碼最好寫在Action一開始的地方
複製內容到剪貼板
代碼:
class UsersController < ActionController::Base
  def index #需Org最高權限管理員身分
    return unless org_admin_check # 這樣可以少掉撈資料庫的動作
    @organization = Organization.first
    ....
  end
end
Think Different
[code]
[73, 32, 108, 111, 118, 101, 32, 121, 111, 117, 32, 115, 111, 32, 109, 117, 99, 104, 33].map{|c| c.chr}.join
[/code]

TOP

CFC,我那樣寫基本上是沒有錯的,因為身分check需要org & current_user,所以要先把org select出來丟進method內或是成為global var才能判斷,而不是把condition丟到判斷式內,那要會select兩次,也就是先init的方式,除非你想用該check method一起來做global var的init
(Plurk) 人因夢想而偉大,如果沒有信仰,則將一無所有,持續往殉道的路邁進,獻祭著自己的靈魂,走著最極端的路;而那迷霧的後面,會是地獄,也是天堂
self.attributes #=> [惡搞之魂,貓化身,怪咖吸鐵石,邪道程式設計師,動漫宅,蘿莉控,惡趣味,Geek,H=F^3]
[82,117,98,121,32,79,110,32,82,97,105,108,115,32,105,115,32,77,121,32,76,105,102,101].map{|l|l.chr}.to_s

TOP

喔,我看懂了
我以為Organization是其他資料
Think Different
[code]
[73, 32, 108, 111, 118, 101, 32, 121, 111, 117, 32, 115, 111, 32, 109, 117, 99, 104, 33].map{|c| c.chr}.join
[/code]

TOP

發新話題