Rails 允许管理员将其他用户设为管理员
Rails Allow Admins to Make Other Users Admins
我对它有点陌生,但我正在使用 rails 构建一个新的网络应用程序。到目前为止,我得到的大部分内容都是基于 railstutorial.org。我只有几个可能的用户 "roles"(基本用户、excom 和管理员),所以我只是在用户模型中使用几个布尔字段对其进行建模。
我希望我的管理员用户能够让其他用户成为管理员或 excom,而不必求助于一些成熟的用户角色建模系统。
我不希望管理员能够修改其他用户数据(如姓名、电子邮件等)或者当然允许用户将自己设置为管理员,因此将类似的内容添加到 users_controller update 方法看起来很麻烦而且容易出错。但它也似乎是一个全新的控制器和路由是矫枉过正。
我只想要一个按钮供管理员单击 "Make user admin" 并使其正常工作,但我不确定 "right" 的实现方式。
编辑:
此时管理员唯一的曝光是在某些 before_action 中检查用户是否是管理员。即
def admin_user
redirect_to(root_url) unless current_user.admin?
end
或
def correct_user_or_excom_or_admin
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user) || current_user.admin? || current_user.excom?
end
我想我想要的是如何定义一个路由,这样我就可以在 users_controller 中编写以下方法并将其包含在 admin_user before_action.
def make_admin
@user = User.find(params[:id])
@user.admin = true
@user.save
flash[:success] = "#{@user.name} is now an Admin"
end
然后能够在适当的视图中包含以下内容
<%= link_to "Make Admin", user_admin_path(user), method: :post,
data: { confirm: "You sure?" } %>
我认为@widjajayd 的回答是正确的。以这种方式创建自定义路由是否在参数中包含用户 ID?
您可以使用自定义方法为管理员创建自定义路由
在 routes.rb 中,为新用户创建 2 条路由,为管理员创建 2 条路由
resources users do
collection {
get :new_admin
put :create_admin
}
end
在 user_controllers.rb 中,创建 2 个方法
def new_admin
@user = User.new
# this depending with what system you use devise/bcryt/others
end
def create_admin
@user = User.new(user_params)
@user.role = "Admin"
# this depending with what system you use devise/bcryt/others
end
在 app/users/new_admin.html.erb
中创建视图文件
<%= form_for @user, url: create_admin_users_path, do |f| %>
# your fields name, password, etc
<% end %>
仅管理员用户可用的按钮
<% if user.role == admin %>
<%= link_to 'Make User Admin', new_admin_users_path, :class => 'form-control btn btn-info' %>
<% end %>
如果您想让某些用户成为管理员,请使用附加代码进行编辑
下面通常你在索引中列出用户。html.erb
<% if @users.any? %>
<table id="table-user" class="table table-striped">
<thead>
<tr>
<th>email</th>
<th>name</th>
<th>Role</th>
<th class="edit"></th>
<th class="destroy"></th>
</tr>
</thead>
<tbody>
<tr>
<% @user.each do |user| %>
<td><%= user.email %></td>
<td><%= user.username %></td>
<td><%= user.role %></td>
<td><%= link_to "Make Admin", create_admin_users_path(user_id: user.id), method: :post,
data: { confirm: "You sure?" } %> </td>
<% end %>
</tbody>
</table>
<% end %>
从表单中传递带有散列的参数 user_id(它可以是您想要的任何名称)然后在创建控制器中您将获得下面示例中的参数
def create_admin
@user = User.find(params[:user_id])
@user.admin = true
@user.save
flash[:success] = "#{@user.name} is now an Admin"
end
这是我想出的解决方案,灵感来自@widjalayd。
创建以下自定义路由。
post '/users/:id/make_admin', to: 'users#make_admin', as: :make_admin
delete '/users/:id/remove_admin', to: 'users#remove_admin', as: :remove_admin
post '/users/:id/make_excom', to: 'users#make_excom', as: :make_excom
delete '/users/:id/remove_excom', to: 'users#remove_excom', as: :remove_excom
在 users_controller 中创建相应的方法,确保它们在 admin_user before_action
中
def make_admin
@user = User.find(params[:id])
@user.admin = true
@user.save
flash[:success] = "#{@user.name} is now an Admin"
redirect_to users_url
end
def remove_admin
@user = User.find(params[:id])
@user.admin = false
@user.save
flash[:success] = "#{@user.name} is no longer an Admin"
redirect_to users_url
end
def make_excom
@user = User.find(params[:id])
@user.excom = true
@user.save
flash[:success] = "#{@user.name} is now an Executive Committee Member"
redirect_to users_url
end
def remove_excom
@user = User.find(params[:id])
@user.excom = false
@user.save
flash[:success] = "#{@user.name} is no longer an Executive Committee Member"
redirect_to users_url
end
然后在索引页上显示用户的部分是
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
|
<%= link_to "Delete", user, method: :delete,
data: { confirm: "You sure?" } %>
|
<% if user.admin? %>
<%= link_to "Remove Admin", remove_admin_path(user), method: :delete,
data: { confirm: "You sure?" } %>
<% else %>
<%= link_to "Make Admin", make_admin_path(user), method: :post,
data: { confirm: "You sure?" } %>
<% end %>
|
<% if user.excom? %>
<%= link_to "Remove Excom", remove_excom_path(user), method: :delete,
data: { confirm: "You sure?" } %>
<% else %>
<%= link_to "Make Excom", make_excom_path(user), method: :post,
data: { confirm: "You sure?" } %>
<% end %>
<% end %>
</li>
然后写一些测试来确定。
test "admins should be able to make and remove new admins" do
log_in_as(@user)
post make_admin_path(@other_user)
assert @other_user.reload.admin?
delete remove_admin_path(@other_user)
assert_not @other_user.reload.admin?
end
test "non admins can't make or remove admins" do
log_in_as(@other_user)
delete remove_admin_path(@user)
assert @user.reload.admin?
post make_admin_path(@another_user)
assert_not @another_user.reload.admin?
end
test "admins should be able to make and remove executive committee" do
log_in_as(@user)
post make_excom_path(@another_user)
assert @another_user.reload.excom?
delete remove_excom_path(@another_user)
assert_not @another_user.reload.excom?
end
test "non admins can't make or remove executive committee" do
log_in_as(@another_user)
post make_excom_path(@user)
assert_not @user.reload.excom?
delete remove_excom_path(@other_user)
assert @other_user.reload.excom?
end
编辑:
这可能正在推动 "good/maintainable" 代码和 "rails-way" 的极限,这就是我问这个问题的原因。但由于这有效,并且比学习和设置像设计这样的完整角色系统花费的时间少得多,所以我现在会坚持使用它。如果我需要进行任何重大更改,那么我可能会转而设计。
我对它有点陌生,但我正在使用 rails 构建一个新的网络应用程序。到目前为止,我得到的大部分内容都是基于 railstutorial.org。我只有几个可能的用户 "roles"(基本用户、excom 和管理员),所以我只是在用户模型中使用几个布尔字段对其进行建模。
我希望我的管理员用户能够让其他用户成为管理员或 excom,而不必求助于一些成熟的用户角色建模系统。
我不希望管理员能够修改其他用户数据(如姓名、电子邮件等)或者当然允许用户将自己设置为管理员,因此将类似的内容添加到 users_controller update 方法看起来很麻烦而且容易出错。但它也似乎是一个全新的控制器和路由是矫枉过正。
我只想要一个按钮供管理员单击 "Make user admin" 并使其正常工作,但我不确定 "right" 的实现方式。
编辑:
此时管理员唯一的曝光是在某些 before_action 中检查用户是否是管理员。即
def admin_user
redirect_to(root_url) unless current_user.admin?
end
或
def correct_user_or_excom_or_admin
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user) || current_user.admin? || current_user.excom?
end
我想我想要的是如何定义一个路由,这样我就可以在 users_controller 中编写以下方法并将其包含在 admin_user before_action.
def make_admin
@user = User.find(params[:id])
@user.admin = true
@user.save
flash[:success] = "#{@user.name} is now an Admin"
end
然后能够在适当的视图中包含以下内容
<%= link_to "Make Admin", user_admin_path(user), method: :post,
data: { confirm: "You sure?" } %>
我认为@widjajayd 的回答是正确的。以这种方式创建自定义路由是否在参数中包含用户 ID?
您可以使用自定义方法为管理员创建自定义路由
在 routes.rb 中,为新用户创建 2 条路由,为管理员创建 2 条路由
resources users do
collection {
get :new_admin
put :create_admin
}
end
在 user_controllers.rb 中,创建 2 个方法
def new_admin
@user = User.new
# this depending with what system you use devise/bcryt/others
end
def create_admin
@user = User.new(user_params)
@user.role = "Admin"
# this depending with what system you use devise/bcryt/others
end
在 app/users/new_admin.html.erb
中创建视图文件<%= form_for @user, url: create_admin_users_path, do |f| %>
# your fields name, password, etc
<% end %>
仅管理员用户可用的按钮
<% if user.role == admin %>
<%= link_to 'Make User Admin', new_admin_users_path, :class => 'form-control btn btn-info' %>
<% end %>
如果您想让某些用户成为管理员,请使用附加代码进行编辑
下面通常你在索引中列出用户。html.erb
<% if @users.any? %>
<table id="table-user" class="table table-striped">
<thead>
<tr>
<th>email</th>
<th>name</th>
<th>Role</th>
<th class="edit"></th>
<th class="destroy"></th>
</tr>
</thead>
<tbody>
<tr>
<% @user.each do |user| %>
<td><%= user.email %></td>
<td><%= user.username %></td>
<td><%= user.role %></td>
<td><%= link_to "Make Admin", create_admin_users_path(user_id: user.id), method: :post,
data: { confirm: "You sure?" } %> </td>
<% end %>
</tbody>
</table>
<% end %>
从表单中传递带有散列的参数 user_id(它可以是您想要的任何名称)然后在创建控制器中您将获得下面示例中的参数
def create_admin
@user = User.find(params[:user_id])
@user.admin = true
@user.save
flash[:success] = "#{@user.name} is now an Admin"
end
这是我想出的解决方案,灵感来自@widjalayd。
创建以下自定义路由。
post '/users/:id/make_admin', to: 'users#make_admin', as: :make_admin
delete '/users/:id/remove_admin', to: 'users#remove_admin', as: :remove_admin
post '/users/:id/make_excom', to: 'users#make_excom', as: :make_excom
delete '/users/:id/remove_excom', to: 'users#remove_excom', as: :remove_excom
在 users_controller 中创建相应的方法,确保它们在 admin_user before_action
中def make_admin
@user = User.find(params[:id])
@user.admin = true
@user.save
flash[:success] = "#{@user.name} is now an Admin"
redirect_to users_url
end
def remove_admin
@user = User.find(params[:id])
@user.admin = false
@user.save
flash[:success] = "#{@user.name} is no longer an Admin"
redirect_to users_url
end
def make_excom
@user = User.find(params[:id])
@user.excom = true
@user.save
flash[:success] = "#{@user.name} is now an Executive Committee Member"
redirect_to users_url
end
def remove_excom
@user = User.find(params[:id])
@user.excom = false
@user.save
flash[:success] = "#{@user.name} is no longer an Executive Committee Member"
redirect_to users_url
end
然后在索引页上显示用户的部分是
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.name, user %>
<% if current_user.admin? && !current_user?(user) %>
|
<%= link_to "Delete", user, method: :delete,
data: { confirm: "You sure?" } %>
|
<% if user.admin? %>
<%= link_to "Remove Admin", remove_admin_path(user), method: :delete,
data: { confirm: "You sure?" } %>
<% else %>
<%= link_to "Make Admin", make_admin_path(user), method: :post,
data: { confirm: "You sure?" } %>
<% end %>
|
<% if user.excom? %>
<%= link_to "Remove Excom", remove_excom_path(user), method: :delete,
data: { confirm: "You sure?" } %>
<% else %>
<%= link_to "Make Excom", make_excom_path(user), method: :post,
data: { confirm: "You sure?" } %>
<% end %>
<% end %>
</li>
然后写一些测试来确定。
test "admins should be able to make and remove new admins" do
log_in_as(@user)
post make_admin_path(@other_user)
assert @other_user.reload.admin?
delete remove_admin_path(@other_user)
assert_not @other_user.reload.admin?
end
test "non admins can't make or remove admins" do
log_in_as(@other_user)
delete remove_admin_path(@user)
assert @user.reload.admin?
post make_admin_path(@another_user)
assert_not @another_user.reload.admin?
end
test "admins should be able to make and remove executive committee" do
log_in_as(@user)
post make_excom_path(@another_user)
assert @another_user.reload.excom?
delete remove_excom_path(@another_user)
assert_not @another_user.reload.excom?
end
test "non admins can't make or remove executive committee" do
log_in_as(@another_user)
post make_excom_path(@user)
assert_not @user.reload.excom?
delete remove_excom_path(@other_user)
assert @other_user.reload.excom?
end
编辑:
这可能正在推动 "good/maintainable" 代码和 "rails-way" 的极限,这就是我问这个问题的原因。但由于这有效,并且比学习和设置像设计这样的完整角色系统花费的时间少得多,所以我现在会坚持使用它。如果我需要进行任何重大更改,那么我可能会转而设计。