Как лучше всего выполнять вход и выход с несколькими областями / ролями с помощью Rails / Devise? - PullRequest
1 голос
/ 17 октября 2011

Я искал в этом сайте в Google Devise RDocs ответы на мой вопрос, но не повезло.

Допустим, у меня есть четыре области / роли Devise, и у каждой есть своя собственная.атрибуты, страница входа и отдельные веб-потоки:

  • Студенты
  • Профессора
  • Деканы
  • Факультеты

Все они используют класс User и имеют следующие общие атрибуты:

  • Id
  • Имя
  • Электронная почта
  • Пароль
  • Роль

Вот пример маршрутов, которые я установил, чтобы установить это:

devise_for :students, :class_name => 'User'
devise_for :professors, :class_name => 'User'
devise_for :deans, :class_name => 'User'
devise_for :faculties, :class_name => 'User'
devise_for :users

Затем я сгенерировал видовые области обзора и поиграл с ними.

После этого мне пришлось добавить некоторый код в мой контроллер приложения, чтобы переопределить Devise :: RegistrationsController, который хотел перенаправить все в корневой путь:

def after_sign_in_path_for(resource)
 user_role = resource.role
 case user_role
   when "professor"
     professors_url
   when "faculty"
     faculties_url
   when "dean" 
     deans_url
   when "student"
     students_url
   else
     root_path       
  end 
end

def after_sign_out_path_for(resource)
  case resource
   when :faculty
     new_faculty_session_path
   when :professor
    new_professor_session_path
   when :dean 
     new_dean_session_path
   when :student
     new_student_session_path
   else
     root_path       
  end     
end

У меня есть доступ к отличным помощникам, таким как Sign_in? , который говорит мне, если какой-либо пользователь в какой-либо изВышеупомянутые области входят в систему. Отлично !!!Теперь мне нужен аналогичный функционал для current_user .

У меня есть доступ к следующим помощникам.

  • current_student
  • current_prof Professor
  • current_dean
  • current_faculty

Они работают отлично, но здесь у меня есть проблемы.Скажем, если у меня есть представление, которое разделяет все эти области.Теперь, если я попробую current_student в этом представлении, и я вошел в систему как профессор, это не сработает.

Например: у меня есть часть, которую я хочу включить на каждую страницу, чтобы позволить пользователям выходить из системы, если они вошли в систему. Так я поступил для студента.Работает просто отлично.

<% if student_signed_in? %>
 <div style="float: right;">Welcome <%= current_student.name %></div>
 <div>
    <%= link_to('Logout', destroy_student_session_path, :method => :delete) %>        
 </div>
<% end %>

То, что я хочу сделать, - это что-то вроде этого, которое обеспечит возможность выхода из системы всех моих областей / ресурсов независимо от того, вошел ли я в качестве студента, декана, профессора илифакультет:

<% if signed_in? %>
 <div style="float: right;">Welcome <%= current_resource.name %></div>
 <div>
    <%= link_to('Logout', destroy_resource_session_path, :method => :delete) %>        
 </div>
<% end %>

Моим следующим шагом было бы добавление моих собственных вспомогательных методов для определения области видимости следующим образом:

def current_resource
     current_professor unless current_professor.nil?
     current_student unless current_student.nil?
     current_dean unless current_dean.nil?
     current_faculty unless current_faculty.nil?
end

def destroy_resource_session_path
     destroy_professor_session_path unless current_professor.nil?
     destroy_student_session_path unless current_student.nil?
     destroy_dean_session_path unless current_dean.nil?
     destroy_faculty unless current_faculty.nil?
end

Если этот подход будет работать, я бы это сделал, но кажется крайне неэффективным и утомительным, если я решу добавить больше ролей или общих функций в будущем ...

Должен ли быть лучший способ?Это заставляет меня чувствовать, что я использую Devise неправильно, или просто что-то упускаю.

Ответы [ 3 ]

3 голосов
/ 20 октября 2011

После гораздо большего исследования я нашел драгоценный камень под названием CanTango, который делает именно то, что я искал. Он работает с Devise и обрабатывает несколько типов пользовательских моделей. Взгляни и посмотри.

https://github.com/kristianmandrup/cantango/wiki/Cantango-with-devise-accounts

Спасибо, что ответили на мои вопросы, ребята. Я многому научился из ваших ответов.

0 голосов
/ 17 октября 2011

Исходя из комментариев к ответу выше, альтернативой является использование нескольких приложений rails (по одному для каждой роли), и либо совместно использовать одну и ту же БД между ними (см. Этот вопрос в SO ), либо создайте другое приложение исключительно для аутентификации и авторизации и управляйте всеми входами через него.

Приведенные выше решения действительно являются запасным вариантом, если вы не хотите использовать одно приложение. Я бы порекомендовал просто продолжать делать то, что вы делаете прямо сейчас, определять области и создавать методы, которые могут иметь дело с каждым случаем.

Вы можете сделать это немного лучше с хорошо разработанными методами. Например, измените destroy_resource_session_path так, чтобы он принимал аргумент current_user, который присваивается любому из current_professor, ... current_faculty, не равному nil, и затем вызывает destroy_#{current_user}_session_path. Чтобы уточнить, как это сделать:

Вам не нужно точно определять четко определенные роли в вашем приложении, а просто направлять каждую роль на различные наборы моделей / представлений / контроллеров, поэтому лучший способ - создать отдельный контроллер, который определяет роль, и направляет запросы соответствующему контроллеру в зависимости от роли пользователя.

EDIT:

В общем, я думаю, что вы идете по этому пути правильно, но вы можете сделать это лучше, если скопируете методы, которые работают с разными пользователями (например, 2 у вас), в отдельный контроллер с такими действиями, как destroy_resource_session_path и current_resource. Аналогично, добавьте методы after_sign_in_path_for и after_sign_out_path_for к этому новому контроллеру

Дело в том, что новый контроллер должен учитывать различия между типами пользователей, поэтому добавление нового типа пользователя так же просто, как добавление нескольких строк только к этому контроллеру и изменение routes.rb.

Просто сохраните набор ролей, которые вы выполняете в этом контроллере. Затем вы можете изменить свои методы, чтобы использовать набор, чтобы выяснить, какие роли существуют, поэтому все, что вам нужно сделать, это добавить запись в набор и запись в routes.rb, чтобы добавить новую роль. Например, вы должны изменить after_sign_in_path_for(resource) на:

def after_sign_in_path_for(resource)
  user_role = resource.role
  if (set_of_roles.include?(user_role))
    return #{user_role}_url
  else
    return root_path
  end
end

Обратите внимание, что #{..} - это способ интерполяции строк в ruby, поэтому #{user_role}_url в ruby ​​эквивалентно user_role+"_url" в Java.

С помощью подобных методов единственное, что вам нужно сделать, чтобы добавить новую роль, - это создать новое представление для этой роли, определить маршрут с именем role_name в routes.rb и добавить роль к set_of_roles ,

Я бы порекомендовал изучить идею единого входа перед ее использованием - я не знаком с ней, но ответы на вопрос, с которым я связался в SO, говорят, что он усложняет вещи.

0 голосов
/ 17 октября 2011

Вы проверили CanCan от Райана Бейтса?Он позволяет вам использовать только пользовательскую модель Devise и определять способности в зависимости от роли в вашей пользовательской модели.Затем он дает вам доступ к вспомогательным методам can? и cannot? для дальнейшего определения ваших способностей.

РЕДАКТИРОВАТЬ:
Я бы переместил атрибуты в ссылочные модели и направилвеб-поток с CanCan.Примеры, которые вы видите в Интернете, не всегда показывают полные возможности, которые вам предоставит CanCan.Вы можете разместить ссылки на своей целевой странице, чтобы направить их на соответствующую страницу входа, каждая из которых имеет одинаковую форму входа в Devise.Сохраняйте логику для after_sign_in_path_for и блокируйте ограниченные действия с помощью CanCan.Это упрощает ваши маршруты и общую логику и дизайн приложения.Кроме того, устранение ошибок на 75% проще при использовании только одной модели.

...