10

Tôi đang làm việc trên ứng dụng Rails 3.2 nơi tôi sử dụng Devise để xác thực. Tôi quyết định thử kế thừa bảng đơn để quản lý vai trò người dùng, nhưng tôi nhanh chóng gặp phải vấn đề. Tôi hiện có ba Mô hình người dùng, User < ActiveRecord, Admin < UserCollaborator < User. Quản trị viên và Cộng tác viên chia sẻ hầu hết các cột Người dùng nhưng chúng có các đặc điểm và đặc quyền hơi khác nhau. Mô hình của tôi hiện nay trông như thế này:Làm cách nào để xử lý xác thực bằng Devise khi sử dụng nhiều mô hình trong Rails 3.2 App

class User < ActiveRecord::Base 

    devise :database_authenticatable, :registerable, 
    :recoverable, :rememberable, :trackable, :validatable, :token_authenticatable 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :email, :name, :password, :password_confirmation, :remember_me 

    before_save :ensure_authentication_token 

    [...] 

end 

class Admin < User 
    has_one :account, dependent: :destroy 
    attr_accessible :account_attributes 
    accepts_nested_attributes_for :account 
end 


class Collaborator < User 
    has_one :account 
end 

class Account < ActiveRecord::Base 
    attr_accessible :name 
    validates_presence_of :name 
    has_many :projects, dependent: :destroy 
    has_many :users 
end 

Các aries vấn đề khi tôi cố gắng để xác thực Admins và cộng tác trong ProjectController của tôi (và các bộ điều khiển khác mà tôi cần chứng thực):

# Causes problem, no one can access anything. 
before_filter :authenticate_admin! 
before_filter :authenticate_collaborator! 

Một vấn đề tương tự như tôi đã với các phương thức trợ giúp của devise cho ví dụ. CURRENT_USER, bây giờ tôi đã current_admin và current_collaborator, tôi "giải quyết" đó bằng cách tạo một trước khi lọc và phương pháp:

def set_current_user 
    @current_user = current_admin || current_collaborator 
end 

Có một giải pháp tương tự hoặc đơn giản cho vấn đề xác thực của tôi với lập mưu, hoặc bạn muốn giới thiệu cách tiếp cận khác hơn Đơn Bảng Thừa kế, và đó sẽ là gì?

Mục tiêu của tôi là, 1. khi người dùng mới đăng ký, họ trở thành Quản trị viên, khi họ tạo tài khoản của họ, Mô hình tài khoản cũng được tạo. 2. Người dùng mới (Quản trị viên) có thể mời thêm người dùng vào Tài khoản, đó sẽ là Cộng tác viên. 3. Quản trị viên và Cộng tác viên phải có các đặc quyền khác nhau. Cộng tác viên sẽ không tạo "Tài khoản" mới khi họ đăng ký (công ty có thể là tên tốt hơn cho mô hình Tài khoản của tôi) nên Quản trị viên và Cộng tác viên sẽ cần các biểu mẫu hơi khác nhau để đăng ký và chỉnh sửa.

Cảm ơn.

Cập nhật

tôi kinda "giải quyết" nó bằng cách tạo ra một tương tự trước khi lọc:

def authenticate! 
    if @current_user == current_admin 
    :authenticate_admin! 
    elsif @current_user == current_collaborator 
    :authenticate_collaborator! 
    end 
end 

Gợi ý về các giải pháp có thể thêm thanh lịch vẫn sẽ được đánh giá.

+0

có được một cơ hội để kiểm tra câu trả lời của tôi không? – blnc

Trả lời

1

Bạn có thể tách tất cả logic chung thành mô-đun và chỉ sử dụng cùng một bảng.

module UserMethods 
    #... 
end 

class User < ActiveRecord::Base 
    include UserMethods 
    devise ... 

end 

class Admin < ActiveRecord::Base 
    include UserMethods 
    self.table_name = "users" 
    devise ... 
end 

Và định cấu hình tất cả mô hình phát triển riêng rẽ trong các tuyến đường, chế độ xem (nếu cần, xem Configuring Views). Trong trường hợp này, bạn có thể dễ dàng xử lý tất cả các logic khác nhau.

+0

Mm, cảm ơn. Có vẻ như điều đó sẽ hiệu quả. Tuy nhiên, giải pháp này tốt hơn giải pháp hiện tại của tôi như thế nào? Xin lỗi cho câu hỏi mới của tôi. Ở đây có một số khác. Tôi đang nghĩ đến việc thay đổi logic của mình một chút và cho phép Người dùng có nhiều Tài khoản, hoặc là Quản trị viên hoặc Cộng tác viên cho từng tài khoản, mối quan hệ nhiều-nhiều giữa Người dùng và Tài khoản, cách tôi có thể đạt được điều đó với giải pháp của bạn và vẫn có vai trò khác nhau? Cảm ơn! – Anders

+0

Thay vì bao gồm mô-đun, bạn có thể trích xuất tất cả logic sang mô hình chung, ví dụ, BaseUser, đặt ở đây tất cả các mối quan hệ. Nhưng tất cả các logic khác nhau, liên quan đến việc tạo ra hoặc các thuộc tính, bạn có thể đặt để tách riêng mô hình. I E. có vẻ như bạn và cách tiếp cận của tôi nên được kết hợp. Tôi không thích điều kiện 'if' trong các phương thức, vì nó không phải là kiểu OOP. – gayavat

3

Không chắc nếu điều này vẫn cần một giải pháp để này ...

Một cách thanh lịch hơn để có xác thực kép có thể làm như sau:

private 

def authenticate! 
    :authenticate_admin! || :authenticate_collaborator! 
    @current_user = admin_signed_in? ? current_admin : current_collaborator 
end 

Sau đó gọi before_filter: xác thực !

Nếu bạn không cần biến '@current_user' phổ biến, chỉ cần bỏ qua dòng thứ hai.

Hy vọng điều này sẽ hữu ích.

+0

Giải pháp này không hoạt động vì authenticate_admin sẽ chuyển hướng nếu không thành công ... bất kỳ ý tưởng nào? Tôi không thể làm cho nó hoạt động – Rafal

+0

bạn nói đúng, trong các phiên bản mới nhất này không còn hoạt động nữa. Tôi sẽ xem liệu tôi có thể tìm được một công việc hay không. – blnc

+0

Tôi đã thêm câu trả lời với giải pháp của mình – Rafal

5

Bạn có thể giải quyết việc này bằng cách sử dụng giải pháp sau

 
def authenticate! 
    if modelA_user_signed_in? 
     @current_user = current_modelA 
     true 
    else 
     authenticate_modelB! 
    end 

    end 
Các vấn đề liên quan