2015-11-27 3 views
4

Я пытаюсь сделать приложение с Rails 4.Определение ролей с Rolify

Я смотрю на управление ролями и хотят использовать Rolify, поскольку он поддерживает экземпляр назначения роли уровня.

Для других пользователей, имеющих аналогичную проблему, есть 2 действительно хороших ответа ниже (я могу отметить только один, но я использовал оба). Проверьте lorefnon & ответы Cyb3rDud3 ниже). Я все еще понимаю это, но сделал миграцию с массивом (как показывает lorefnon) и функциями контроллера/маршрутов (как показывает Cyb3rDud3).

Что совершенно меня озадачивает, так это то, что все документы для драгоценного камня Rolify используют консоль для определения ролей.

Как определить роли в моем коде?

Другие на этой доске задавали вопросы, которые ссылаются на них, определяя роли в файле db: seed. Я не хочу этого делать, потому что я хочу контролировать, кто использует мой файл семян более плотно, чем кто может создавать роли.

Где вы?

Все примеры показывают, что это делается с консоли. Я хочу определить список ролей, а затем я хочу предоставить разрешения для ролей (я хочу использовать pundit для этой части).

У меня есть модель пользователя. Другой драгоценный камень, на который я смотрел, был примером для подражания. Он просит создать массив ролей в пользовательской модели. Это просто так очевидно, что вы должны сделать это в Rolify - что ни один из документов не дает вам этот шаг?

Где вы определяете роли?

ответ

5

Что совершенно меня озадачивает, так это то, что все документы для драгоценного камня Rolify используют консоль для определения ролей.

Документ Rolify не использует консоль для определения ролей - она ​​демонстрирует, как роли могут быть добавлены в чистый рубин. Это потрясающе мощно, потому что вы можете определить роли, в которых вы можете запустить рубин. Вы не ограничены статическим списком ролей, определенным в каком-либо файле конфигурации или в некоторой таблице базы данных.


Первый вопрос, который вам нужно задать, - это когда роли создаются?

Наиболее распространенные случаи использования делятся на две группы:

1. Роли статичны.

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

Наиболее распространенные случаи использования таких функций включает в себя моделирование обозначения людей в компании (разработчик, менеджер, поддержки и т.д.), или моделирование priorly известных обязанностей (редактор, администратор, зритель и т.д.)

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

1.1. Сам разработчик приложения - это человек, который должен добавлять/удалять/изменять роли. В таких случаях лучше полагаться на данные семенных данных или миграции Rails.

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

Такая миграция может выглядеть следующим образом:

дб/мигрируют/20151204083556_create_application_roles.rb

class CreateApplicationRoles < ActiveRecord::Migration 
    def up 
    ['admin', 'support', 'editor'].each do |role_name| 
     Role.create! name: role_name 
    end 
    end 
    def down 
    Role.where(name: ['admin', 'support', 'editor']).destroy_all 
    end 

end 

Некоторые люди rightly consider ему антипаттерн, чтобы изменения схемы и изменения данных и управляются миграции. data-migrate - это драгоценный камень, который позволяет отделять ориентированные на данные миграции от миграции вашей схемы.

В этом случае и во всех других случаях ниже фактического распределения ролей будет происходить на основе действий пользователя или событий приложений через add_role или remove_role методов, предоставляемых rolify.This будет происходить в течение всего жизненного цикла запущенного приложения, а не во время установка приложения.

1.2 Задача добавления/удаления/изменения ролей выполняется группой поддержки или техническими руководителями. В таких случаях потребуется создать административный интерфейс для управления ролями.

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

2. Роли динамичны

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

Этот случай похож на 1.2, поскольку вам приходится обрабатывать создание/удаление/обновление ролей через контроллеры рельсов.


Следующая часть состоит в том, как информация структурирована в ваших таблицах.

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

Rolify tables

+0

Привет, так как мне настроить набор ролей, которые могут быть назначены в моем приложении? Есть ли какой-нибудь справочник о том, как это сделать? Роли назначаются пользователям некоторыми другими приложениями (у которых есть права доступа к блогам для их назначения). Администраторы создают роли и делегируют полномочия назначения). Я пытаюсь понять, как создавать роли. Документация gem показывает, как это сделать в консоли, но я хочу, чтобы они были доступны в моем приложении. Я не могу понять, как это сделать. – Mel

+0

Используйте миграцию данных (data) для создания ролей. Эти миграции будут записаны в рубине и будут заполнять роли в базе данных. – lorefnon

+0

Вы хотите сделать таблицу в db для ролей и иметь роли в качестве логических атрибутов? – Mel

2

После прочтения документации и примеров на своих страницах проекта я решил не использовать драгоценный камень для управления ролями на моей странице, так как считал, что для настройки и использования потребуется много времени. Поэтому вместо этого я сделал следующее: (я считаю, что вы использовали программу для своей модели пользователя, хотя это необязательно):

Если вы хотите, чтобы определенные роли были определены и «статические» не изменялись, но были назначены с вашей страницы см ниже, если не перейти к следующей жирной линии

  1. Добавить поле, называемое role: integer к вашей User модели с миграцией.(Мы используем целое вызвать это значение будет связано с одной записью в перечислении мы определим в следующем шаге)
  2. В файле user.rb (модель), добавьте enum, как показано ниже:

    class User < ActiveRecord::Base 
        devise :registerable, #... 
    
        enum role: [:admin, :normal, :premium, :moreRolesHere ] 
        after_initialize :set_default_role, :if => :new_record? 
    
        def set_default_role 
        self.role ||= :normal 
        end 
    
    end 
    
  3. Тогда в любом контроллере или представлении или def вы просто должны получить текущий пользователь или любой пользователь, который вы хотите назначить роль и сделать так же просто, как линию ниже:

    #let's suppose we want to make premium the current user 
    current_user.premium! 
    
    #or someone else to be admin 
    user = User.first 
    user.admin! 
    
  4. Тогда вы можете сделать свой собственная валидация в любой странице или контроллере вы работаете, просто попросив роль пользователя:

    #see if the current user is admin 
    if current_user.role == "admin" 
        #do some admin stuff 
    end  
    

Если вы хотите добавлять, изменять и удалять роли в вашей странице, а также назначать их в там

Прежде всего, будьте осторожны при назначении ролей непосредственно со своей страницы. Проблема здесь в том, что каждый сможет присвоить себе свою собственную роль, выбранную в поле. Но если это то, что вам нужно, делать, как показано ниже:

  1. Создать модель под названием Role, с полем role: string
  2. Создайте контроллер, связанный с этой моделью, roles_controller.rb
  3. Создать точку нужно в чтобы отображать действия, связанные с управлением ролями (создавать, редактировать, удалять) быть осторожным, чтобы эти страницы были доступны только для подписчиков в пользователях. Выбор или добавление роли пользователю, которого вы будете управлять внутри своего пользовательского контроллера или любого другого контроллера, которого вы хотите.
  4. В любом другом представлении вы хотите задать вопрос о роли пользователя, которому необходимо будет получить доступ к таблице ролей и получить одно из них, соответствующее пользователю. Таблице пользователей будет нужен столбец role_ids: text (это текст, потому что вам нужно сохранить несколько ролей, все роли, завернутые в массив), который будет представлять его роли. В вашей user.rb модели вы могли бы иметь get_roles и другие def сек методы, чтобы иметь более чистый код в контроллерах и просмотров:

    class User < ActiveRecord::Base 
        devise :registerable, #... 
    
        serialize :role_ids 
    
        #will return you an array of roles-(strings) of the user 
        def get_roles 
        roles = [] 
        role_ids.each do |role_id| 
         roles << Role.find(role_id).role 
        end 
        return roles  
        end 
    
        #ask if this user has some role-(string) 
        def has_role(role) 
        roles = get_roles 
        return roles.include?(role) 
        end 
    
    end 
    
  5. И, наконец, вы, конечно, нужно будет реализовать контроллер для ролей, то создание, обновление и уничтожить и все def s, связанные с их представлениями.

Вы могли бы взглянуть на how to save arrays in database, serialize

Такой подход не используют каких-либо драгоценных камней, связанных с управлением ролей или разрешений, как те, в рынке: pundit, cancan, rolify. Оставьте вам некоторые ссылки, если вы скептически относитесь к моему подходу и хотите, чтобы ваши руки были грязными.

5

Я буквально только что прошел через тот же процесс, и как @ user2860931 все, что я смог найти несколько примеров о том, как назначать роли из консоли. То, что мне нужно, - это программно гибкий способ использования пользователем роли администратора или пользователя, говорящего, что роль pmo может назначить эти роли другим.

Немного экспериментируя, я решил это для себя. В этом примере я использую Devise для аутентификации и Rolify для ролей.

Предполагаю, что у вас уже установлено и работает Devise, поэтому у вас есть существующая модель пользователя. Установите Rolify в соответствии с инструкцией на странице gem. Я использовал предложенное имя Роль для модели ролей. Так что сделайте все, как указано здесь: https://github.com/RolifyCommunity/rolify. Установите GEM, сгенерируйте, используя роль Роль пользователя. И перенести миграцию базы данных.

Это эффективно предоставит вам новую таблицу Роли и отношения has_and_belongs_to_many с таблицей Users.

Что касается моей цели, я не нуждаюсь в обычном интерфейсе Create Read (show) Update Delete (CRUD) для ролей, я просто создал несколько через seeds.rb, как это.

#Seeding the Role table 
# 
p "Removing existing #{Role.all.count} roles" 
Role.destroy_all 
p "Creating 7 roles" 
[:user, :admin, :portfolio_manager, :programme_manager,  :project_manager, :coordinator, :pmo].each do |role| 
    Role.create(name: role) 
end 
p "Should have created 7 Roles, roles created: #{Role.all.count}" 

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

грабли БД: семян

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

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

users_controller.rb 

class UsersController < ApplicationController 
    before_action :set_user, only: [:show, :edit, :update] 

    def index 
    @users = User.all 
    end 

    def show 
    end 

    def edit 
    end 

    def update 
    respond_to do |format| 
     if @user.update(user_params) 
     # TODO: Move hardcode flash message into language file 
     format.html { redirect_to @user, notice: 'User was successfully updated.'} 
     format.json { render :show, status: :ok, location: @user } 
     else 
     format.html { render :edit } 
     format.json { render json: @user.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    private 

    def set_user 
    @user = User.find(params[:id]) 
    end 

    def user_params 
    params.require(:user).permit(:username, :email, {role_ids: []}) 
    end 
end 

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

routes.rb 

Rails.appliction.routes.draw do 
    devise_for :users 
    root 'pages#home' 
    resources :users #must be after devise 
end 

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

    Prefix Verb URI Pattern      Controller#Action 
     new_user_session GET /users/sign_in(.:format)  devise/sessions#new 
      user_session POST /users/sign_in(.:format)  devise/sessions#create 
    destroy_user_session DELETE /users/sign_out(.:format)  devise/sessions#destroy 
      user_password POST /users/password(.:format)  devise/passwords#create 
     new_user_password GET /users/password/new(.:format) devise/passwords#new 
     edit_user_password GET /users/password/edit(.:format) devise/passwords#edit 
         PATCH /users/password(.:format)  devise/passwords#update 
         PUT /users/password(.:format)  devise/passwords#update 
cancel_user_registration GET /users/cancel(.:format)  devise/registrations#cancel 
     user_registration POST /users(.:format)    devise/registrations#create 
    new_user_registration GET /users/sign_up(.:format)  devise/registrations#new 
    edit_user_registration GET /users/edit(.:format)   devise/registrations#edit 
         PATCH /users(.:format)    devise/registrations#update 
         PUT /users(.:format)    devise/registrations#update 
         DELETE /users(.:format)    devise/registrations#destroy 
      user_unlock POST /users/unlock(.:format)  devise/unlocks#create 
     new_user_unlock GET /users/unlock/new(.:format) devise/unlocks#new 
         GET /users/unlock(.:format)  devise/unlocks#show 
        root GET /       pages#home 
        about GET /about(.:format)    pages#about 
       contact GET /contact(.:format)    pages#about 
        users GET /users(.:format)    users#index 
         POST /users(.:format)    users#create 
       new_user GET /users/new(.:format)   users#new 
       edit_user GET /users/:id/edit(.:format)  users#edit 
        user GET /users/:id(.:format)   users#show 
         PATCH /users/:id(.:format)   users#update 
         PUT /users/:id(.:format)   users#update 
         DELETE /users/:id(.:format)   users#destroy 

Все, что осталось сделать, это построить пользовательский интерфейс, самая важная часть меня, и если я правильно понял, для вас. Чтобы быстро построить это, мой пример не очень хорошо представлен с полной магией css, но я уверен, что вы можете сделать это по своему вкусу.

Чтобы показать существующих пользователей и выбрать их список, создайте index.html.erb в папке/app/views/users. Создайте простой show.html.erb и отредактируйте, в котором вы можете назначать и удалять существующие роли. Как это.

index.html.erb 

<!-- TODO: Tidy up this file and make it look good --> 
<!-- TODO: Remove hard coded text to a locale file --> 
<% @users.each do |user| %> 
    <p> 
    <%= link_to "#{user.username}<#{user.email}>", user %> 
    <%= link_to "edit", edit_user_path(user) %> 
    </p> 
<% end %> 

show.html.erb 

<!-- TODO: Tidy up this file and make it look good --> 
<!-- TODO: Remove hard coded text to a locale file --> 
<p> 
    Username: <%= @user.username %> 
</p> 
<p> 
    Email address: <%= @user.email %> 
</p> 

<%= link_to "Back", users_path %> 

edit.html.erb 

<!-- TODO: Tidy up this file and make it look good --> 
<!-- TODO: Remove hard coded text to a locale file --> 
<p> 
Username: <%= @user.username %> 
</p> 
<p> 
Email address: <%= @user.email %> 
</p> 

<%= form_for @user do |f| %> 
    <% Role.all.each do |role| %> 
    <%= check_box_tag "user[role_ids][]", role.id, @user.role_ids.include?(role.id) %> 
    <%= role.name %></br> 
    <% end %> 
    <%= f.submit %> 
<% end %> 

<%= link_to "Back", users_path %> 

И там у вас есть, простой пользовательский интерфейс, в котором перечислены все доступные роли из базы данных и обеспечивает тикать коробки с записью пользователя, чтобы включить или отключить такую ​​роль. Как это:

Example of user record and role pick list

Это была маленькая голова скребок для меня, как хорошо, но, надеюсь, это будет разместить на вашем пути повышения логики и пользовательского опыта.

+0

Где вы определяете свои роли? Вы помещаете их в файл семян, но находятся ли они где-нибудь в вашем коде (например, таблица ролей с логическими атрибутами для YN о том, имеет ли пользователь роль?) – Mel

+0

Я только поместил их в файл семян, чтобы они могли легко быть и они определены. Как я описал в своем ответе, это обычный стол, вы можете даже подбросить его, если мы хотим добавить новые роли. В приведенном мной коде перечислены все роли в таблице ролей и вы можете назначить их с тиккетом для пользователя. Вы можете видеть это на скриншоте, который был прикреплен.Нет необходимости в других логических типах, потому что вы используете роллинг-камень, чтобы вы могли просто делать такие вещи, как user.has_role (: admin) then ... else – Cyb3rDud3

+0

Привет, теперь я действительно смущен. Как вы помещаете роли в таблицу, если вы не даете им тип атрибута? Я думаю, что в таблице ролей есть такие поля, как «student: boolean», а затем вы делаете это правдой, если пользователь является учеником. Где вы определяете вещи, которые идут в таблице, если этого не сделать? – Mel