2014-10-11 55 views
0

我的Rails應用程序最多可以有一個管理員,但任意數量的用戶。如何確保最多一個管理員在軌道應用程序設計?

我正在使用設計寶石,並且正在使用用戶模型和布爾管理字段來確定用戶是否爲管理員。

我想確保在應用程序實例上至多存在一個管理員。更具體地說,我想確保如果網站上已存在管理員,則無法添加其他管理員。

我目前有一個弱的解決方案,覆蓋用戶/註冊/新設計視圖,只有在數據庫中沒有管理員(否則只有用戶可以註冊)的情況下允許用戶註冊爲管理員。

<!-- in /users/registrations/new.html.erb --> 
<% if admin_exists? %> 
    <h2>User Sign up</h2> 
<% else %> 
    <h2>Admin Sign up</h2> 
<% end %> 

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> 

    ... 

    <% unless admin_exists? %> 
     <%= f.hidden_field :admin, value: true%> 
    <% end %> 

    ... 

我需要比這更強的檢查,所以我認爲以下幾點:

  1. 驗證:我不希望使用ActiveRecord的驗證,因爲有驗證時跳過場景,允許多個管理員將是災難性的。

  2. before_action:基於this方法,它向控制器添加過濾器,我可以添加一個檢查,以防止在創建和更新期間添加管理員。

  3. 使用觸發器和存儲的特效(啊!)

更新1:

  • 非常類似於圖2,在ApplicationController中使用的檢查如下:

    class ApplicationController < ActionController::Base 
        before_action :check_at_most_one_admin_on_writes, if: :devise_controller?, 
        only: [:create, :update] 
    
        private 
        def check_at_most_one_admin_on_user_writes 
         if(admin_exists && params.has_key?(:admin) && params[:admin] == true) 
         flash[:alert] = "Site administrator already exists" 
         redirect_to :back 
         end 
        end 
    end 
    
  • 更新2: (4)不起作用。可能需要直接覆蓋RegistrationsController。

    我還不確定這些功能是否足夠強大,足以保證兩個管理員永遠不會無意中創建。在多達一個管理約束下執行此操作的好方法是什麼?

    更新3:(基於下面的評論)

    的應用程序是一個個人網站的框架,每個客戶下載,部署到主控器,然後立即配置自己作爲管理員。所以,我不能通過種子等預先創建管理員。

    +0

    你不應該允許任何提升權限的字段(比如'role'或者'admin')可以從表單訪問,使用種子創建你的admin用戶,並且不允許刪除它們,你可以防止刪除,或保存在模型中的回調(如果由於某種原因,你故意跳過驗證) – Pavling 2014-10-11 16:09:35

    +0

    @Pavling謝謝。rails應用程序是一個個人網站框架,每個客戶下載,部署到一個主機,然後立即配置爲一個自己因此,我不能通過種子等方式預先創建管理員 – Anand 2014-10-11 16:11:54

    +1

    您可以擁有一個生成管理員的rake任務...但是如果您堅持按照您的計劃方式執行此任務,請擁有一個單獨的控制器和路由用於創建管理員用戶(與正常Devise路線分開)。您仍然可以繼承Devise控制器,但在AdminsController中您可以設置admi n屬性並通過將塊傳遞給'super'來檢查衝突。 – Pavling 2014-10-12 08:28:44

    回答

    1

    假設你的布爾屬性映射到允許null的數據庫列,那麼你可以添加一個唯一的索引。然後,對於管理員用戶,該列設置爲1,並且該值只允許一行。然後您需要確保普通用戶將列設置爲未設置(保留爲空),因爲嘗試將多列設置爲0的列將由於唯一索引而失敗。這意味着數據庫本身將強制要求只有一個管理員用戶。它也避免了觸發器或存儲過程的需要。

    您通常不能依靠應用中的ruby代碼來通過驗證來強制實施約束,因爲它們不能提供完整性保證數據庫可以(例如具有多個線程/進程的情況)。

    相關問題