Rails5、Rolify——角色分配策略
Rails 5, Rolify - Role Assignment Strategy
我不太擅长学习如何编码。我已经尝试了 4 年,但仍在努力弄清楚基本概念。
我还没有找到正确的起点,所以我一直在填补可能是基础但我还不知道的东西。
我有一个 Rails 5 应用程序。它有用户、角色、app_roles 和 assign_roles.
模型
协会是:
用户
rolify strict: true # strict means you get true only on a role that you manually add
attr_accessor :current_role
belongs_to :organisation
角色
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource,
:polymorphic => true,
:optional => true
AppRole
[无关联]
注意:这是我用来定义角色的 CRUD 资源,应用程序可以使用这些角色为用户分配角色。
分配角色
[无关联]
注意:这是我用来允许某些用户将角色分配给其他用户的资源。
组织
has_many :users
我正在使用 rolify gem。
我的用户模型有:
class User < ApplicationRecord
rolify strict: true # strict means you get true only on a role that you manually add
attr_accessor :current_role
我的角色 table 有:
class Role < ApplicationRecord
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource,
:polymorphic => true,
:optional => true
validates :resource_type,
:inclusion => { :in => Rolify.resource_types },
:allow_nil => true
scopify
end
在我的 assign_roles 控制器中,我有:
class Users::AssignRolesController < ApplicationController
before_action :authenticate_user!
def index
# if @current_user.is_admin?
@app_roles = AppRole.all
# else
# @app_roles = AppRole.where(category: relevant_category)
# end
# if @current_user.is_admin?
@users = User.all
# else
# @users = current_user.organisation.users.select { |u| u.id != current_user.organisation.owner_id }
# end
end
def create
user = User.find(params[:users])
role = AppRole.find(params[:roles])
# organisation = Organisation.first
# @organisation = Organisation.find(@current_user.organisation)
# byebug
user.add_role role.display_name, @current_user.organisation
flash[:notice] = "Successfully created"
redirect_to action: :index
end
def show
# @users = User.joins(:profiles).where('profiles.organisation_id = ?' @current_user.organisation.id)
# @users = User.all
@current_user.organisation.users
end
def update
end
def destroy
user = User.find(params[:users])
# role = AppRole.find(params[:roles])
assigned_role = user.roles
# user_roles = user.roles
# organisation = Organisation.first
# byebug
user.remove_role assigned_role.name, @current_user.organisation
flash[:notice] = "Successfully created"
redirect_to action: :index
end
end
在我的路线文件中,我有:
resources :users, shallow: true do
scope module: :users do
resources :assign_roles
resources :identities
end
end
在我的 views/users/assign_roles/index 文件中,我有:
<%= form_tag(url: '/assign_roles', method: :post ) do |f| %>
<div class="row" style="margin-top:50px; margin-bottom: 150px">
<div class="col-md-3 col-md-offset-1">
<%= select_tag "users", options_from_collection_for_select(@users, "id", "full_name"), { class: "chosen-select form-control" } %>
</div>
<!-- # roles -->
<div class="col-md-3 col-md-offset-1">
<%= select_tag "roles", options_from_collection_for_select(@app_roles, "id", "display_name"), :class => 'chosen-select form-control' %>
</div>
<div class="col-md-3 col-md-offset-1">
<div class="form-actions">
<%= submit_tag(value = "Submit") %>
</div>
</div>
</div>
<% end %>
到目前为止,一切看起来都还不错。我卡在下一部分了。
在我的views/users/assign_roles/show.html.er
我试图在视图中显示每个用户的角色。我希望分配任何现有角色的用户能够删除它们。
我有:
<% @users.each do |user| %>
<td><%= user.roles.count %></td>
<% user.roles.each do |role| %>
<td><%= role.name.titleize %></td>
<td><%= link_to 'Destroy', role, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
<% end %>
我的 assign_roles 控制器保存在 app/controllers/users 文件夹中。我用于分配角色的视图文件夹保存在 app/views/users/assign_roles
中
当我尝试使用 app/users/4/assign_roles 表单时,我得到了要呈现的表单以及可分配的 AppRoles 列表。我没有收到任何错误消息。相反,我收到了成功创建的通知。但是,当我尝试检查用户是否具有角色时,我得到了 false。
我可以看到服务器日志如下:
Started POST "/users/4/assign_roles?method=post&url=%2Fassign_roles" for ::1 at 2016-10-23 11:50:11 +1100
Processing by Users::AssignRolesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"U80gMQd01SaTcHHnnSFxvRc2u9JvJMFB+5smS9SaN8ZRixQvJRTMbutG0KkoqXL+oMU1aOxX8AURBtuy2Rm5yA==", "users"=>"4", "roles"=>"3", "commit"=>"Submit", "method"=>"post", "url"=>"/assign_roles", "user_id"=>"4"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = ORDER BY "users"."id" ASC LIMIT [["id", 4], ["LIMIT", 1]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = LIMIT [["id", 4], ["LIMIT", 1]]
AppRole Load (0.2ms) SELECT "app_roles".* FROM "app_roles" WHERE "app_roles"."id" = LIMIT [["id", 3], ["LIMIT", 1]]
Organisation Load (0.4ms) SELECT "organisations".* FROM "organisations" ORDER BY "organisations"."id" ASC LIMIT [["LIMIT", 1]]
Role Load (1.1ms) SELECT "roles".* FROM "roles" WHERE "roles"."name" = AND "roles"."resource_type" = AND "roles"."resource_id" = ORDER BY "roles"."id" ASC LIMIT [["name", "sdfddd"], ["resource_type", "Organisation"], ["resource_id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
(0.1ms) ROLLBACK
HABTM_Roles Load (0.4ms) SELECT "users_roles".* FROM "users_roles" WHERE "users_roles"."user_id" = [["user_id", 4]]
Role Load (0.3ms) SELECT "roles".* FROM "roles" WHERE "roles"."id" = LIMIT [["id", 1], ["LIMIT", 1]]
(0.5ms) SELECT "roles".id FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = [["user_id", 4]]
Role Load (0.3ms) SELECT "roles".* FROM "roles" WHERE "roles"."id" = 1
Role Load (0.4ms) SELECT "roles".* FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = [["user_id", 4]]
Redirected to http://localhost:3000/users/4/assign_roles
Completed 302 Found in 33ms (ActiveRecord: 6.5ms)
我不知道 ROLLBACK 行是什么意思,但我认为当一切正常时,这些日志消息通常不会出现。
任何人都可以看到我需要做什么才能使角色分配正常工作吗?
组织模式
class Organisation < ApplicationRecord
include LogoUploader[:logo]
include BannerUploader[:banner]
# --------------- associations
has_many :users
# --------------- scopes
# --------------- validations
# --------------- class methods
enum org_type: {
University: 1,
Publicly_Funded_Research_Organisation: 2,
Industry: 3,
Grantor: 4,
Investor: 5,
Policy: 6,
}
# --------------- callbacks
# --------------- instance methods
# --------------- private methods
end
将 resourcify
添加到您的组织模型,然后尝试。
我们没有开发自己的 RBAC(基于角色的访问控制),rails 社区中已经有一些开源 gem 可用。我们可以利用它。
不错gem
还有许多其他 gem 可用
如果以上 gem 中的 none 满足您的需求,那么至少您可以将其用作开发的示例模型。
我不太擅长学习如何编码。我已经尝试了 4 年,但仍在努力弄清楚基本概念。
我还没有找到正确的起点,所以我一直在填补可能是基础但我还不知道的东西。
我有一个 Rails 5 应用程序。它有用户、角色、app_roles 和 assign_roles.
模型协会是:
用户
rolify strict: true # strict means you get true only on a role that you manually add
attr_accessor :current_role
belongs_to :organisation
角色
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource,
:polymorphic => true,
:optional => true
AppRole
[无关联] 注意:这是我用来定义角色的 CRUD 资源,应用程序可以使用这些角色为用户分配角色。
分配角色
[无关联] 注意:这是我用来允许某些用户将角色分配给其他用户的资源。
组织
has_many :users
我正在使用 rolify gem。
我的用户模型有:
class User < ApplicationRecord
rolify strict: true # strict means you get true only on a role that you manually add
attr_accessor :current_role
我的角色 table 有:
class Role < ApplicationRecord
has_and_belongs_to_many :users, :join_table => :users_roles
belongs_to :resource,
:polymorphic => true,
:optional => true
validates :resource_type,
:inclusion => { :in => Rolify.resource_types },
:allow_nil => true
scopify
end
在我的 assign_roles 控制器中,我有:
class Users::AssignRolesController < ApplicationController
before_action :authenticate_user!
def index
# if @current_user.is_admin?
@app_roles = AppRole.all
# else
# @app_roles = AppRole.where(category: relevant_category)
# end
# if @current_user.is_admin?
@users = User.all
# else
# @users = current_user.organisation.users.select { |u| u.id != current_user.organisation.owner_id }
# end
end
def create
user = User.find(params[:users])
role = AppRole.find(params[:roles])
# organisation = Organisation.first
# @organisation = Organisation.find(@current_user.organisation)
# byebug
user.add_role role.display_name, @current_user.organisation
flash[:notice] = "Successfully created"
redirect_to action: :index
end
def show
# @users = User.joins(:profiles).where('profiles.organisation_id = ?' @current_user.organisation.id)
# @users = User.all
@current_user.organisation.users
end
def update
end
def destroy
user = User.find(params[:users])
# role = AppRole.find(params[:roles])
assigned_role = user.roles
# user_roles = user.roles
# organisation = Organisation.first
# byebug
user.remove_role assigned_role.name, @current_user.organisation
flash[:notice] = "Successfully created"
redirect_to action: :index
end
end
在我的路线文件中,我有:
resources :users, shallow: true do
scope module: :users do
resources :assign_roles
resources :identities
end
end
在我的 views/users/assign_roles/index 文件中,我有:
<%= form_tag(url: '/assign_roles', method: :post ) do |f| %>
<div class="row" style="margin-top:50px; margin-bottom: 150px">
<div class="col-md-3 col-md-offset-1">
<%= select_tag "users", options_from_collection_for_select(@users, "id", "full_name"), { class: "chosen-select form-control" } %>
</div>
<!-- # roles -->
<div class="col-md-3 col-md-offset-1">
<%= select_tag "roles", options_from_collection_for_select(@app_roles, "id", "display_name"), :class => 'chosen-select form-control' %>
</div>
<div class="col-md-3 col-md-offset-1">
<div class="form-actions">
<%= submit_tag(value = "Submit") %>
</div>
</div>
</div>
<% end %>
到目前为止,一切看起来都还不错。我卡在下一部分了。
在我的views/users/assign_roles/show.html.er
我试图在视图中显示每个用户的角色。我希望分配任何现有角色的用户能够删除它们。
我有:
<% @users.each do |user| %>
<td><%= user.roles.count %></td>
<% user.roles.each do |role| %>
<td><%= role.name.titleize %></td>
<td><%= link_to 'Destroy', role, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<% end %>
<% end %>
我的 assign_roles 控制器保存在 app/controllers/users 文件夹中。我用于分配角色的视图文件夹保存在 app/views/users/assign_roles
中当我尝试使用 app/users/4/assign_roles 表单时,我得到了要呈现的表单以及可分配的 AppRoles 列表。我没有收到任何错误消息。相反,我收到了成功创建的通知。但是,当我尝试检查用户是否具有角色时,我得到了 false。
我可以看到服务器日志如下:
Started POST "/users/4/assign_roles?method=post&url=%2Fassign_roles" for ::1 at 2016-10-23 11:50:11 +1100
Processing by Users::AssignRolesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"U80gMQd01SaTcHHnnSFxvRc2u9JvJMFB+5smS9SaN8ZRixQvJRTMbutG0KkoqXL+oMU1aOxX8AURBtuy2Rm5yA==", "users"=>"4", "roles"=>"3", "commit"=>"Submit", "method"=>"post", "url"=>"/assign_roles", "user_id"=>"4"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = ORDER BY "users"."id" ASC LIMIT [["id", 4], ["LIMIT", 1]]
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = LIMIT [["id", 4], ["LIMIT", 1]]
AppRole Load (0.2ms) SELECT "app_roles".* FROM "app_roles" WHERE "app_roles"."id" = LIMIT [["id", 3], ["LIMIT", 1]]
Organisation Load (0.4ms) SELECT "organisations".* FROM "organisations" ORDER BY "organisations"."id" ASC LIMIT [["LIMIT", 1]]
Role Load (1.1ms) SELECT "roles".* FROM "roles" WHERE "roles"."name" = AND "roles"."resource_type" = AND "roles"."resource_id" = ORDER BY "roles"."id" ASC LIMIT [["name", "sdfddd"], ["resource_type", "Organisation"], ["resource_id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
(0.1ms) ROLLBACK
HABTM_Roles Load (0.4ms) SELECT "users_roles".* FROM "users_roles" WHERE "users_roles"."user_id" = [["user_id", 4]]
Role Load (0.3ms) SELECT "roles".* FROM "roles" WHERE "roles"."id" = LIMIT [["id", 1], ["LIMIT", 1]]
(0.5ms) SELECT "roles".id FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = [["user_id", 4]]
Role Load (0.3ms) SELECT "roles".* FROM "roles" WHERE "roles"."id" = 1
Role Load (0.4ms) SELECT "roles".* FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = [["user_id", 4]]
Redirected to http://localhost:3000/users/4/assign_roles
Completed 302 Found in 33ms (ActiveRecord: 6.5ms)
我不知道 ROLLBACK 行是什么意思,但我认为当一切正常时,这些日志消息通常不会出现。
任何人都可以看到我需要做什么才能使角色分配正常工作吗?
组织模式
class Organisation < ApplicationRecord
include LogoUploader[:logo]
include BannerUploader[:banner]
# --------------- associations
has_many :users
# --------------- scopes
# --------------- validations
# --------------- class methods
enum org_type: {
University: 1,
Publicly_Funded_Research_Organisation: 2,
Industry: 3,
Grantor: 4,
Investor: 5,
Policy: 6,
}
# --------------- callbacks
# --------------- instance methods
# --------------- private methods
end
将 resourcify
添加到您的组织模型,然后尝试。
我们没有开发自己的 RBAC(基于角色的访问控制),rails 社区中已经有一些开源 gem 可用。我们可以利用它。
不错gem
还有许多其他 gem 可用
如果以上 gem 中的 none 满足您的需求,那么至少您可以将其用作开发的示例模型。