【问题标题】:Rails Allow Admins to Make Other Users AdminsRails 允许管理员让其他用户成为管理员
【发布时间】:2017-07-16 04:49:54
【问题描述】:

我对它有点陌生,但我正在使用 Rails 构建一个新的网络应用程序。到目前为止,我所掌握的大部分内容都是基于 railstutorial.org。我只有几个可能的用户“角色”(基本用户、excom 和管理员),所以我只是使用用户模型中的几个布尔字段对其进行建模。

我希望我的管理员用户能够让其他用户成为管理员或 excom,而不必求助于一些成熟的用户角色建模系统。

我不希望管理员能够修改其他用户数据(如姓名、电子邮件等),或者当然允许用户使自己成为管理员,因此在 users_controller 更新方法中添加类似的内容似乎很麻烦且错误易于。但它也似乎是一个全新的控制器和路由是多余的。

我只想让管理员单击“使用户成为管理员”并让它工作的按钮,但我不确定实现它的“正确”方式。

编辑:

在这一点上,管理员唯一的暴露是在一些 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?

【问题讨论】:

  • 你能暴露你刚才所做的代码吗?

标签: ruby-on-rails authentication admin


【解决方案1】:

您可以使用自定义方法为管理员创建自定义路由

在 routes.rb 中,为 new 创建 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 %>

如果您想让某些用户成为管理员,请使用附加代码进行编辑

通常在 index.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

【讨论】:

  • 这是在正确的轨道上,但想法是让现有用户成为管理员,而不是创建新用户。
【解决方案2】:

这是我想出的解决方案,灵感来自@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

编辑:

这可能正在推动“良好/可维护”代码和“rails-way”的极限,这就是我问这个问题的原因。但是由于这很有效,并且比学习和建立一个完整的角色系统(如设计)花费的时间要少得多,所以我现在会坚持下去。如果我需要做出任何重大改变,那么我可能会转向设计。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多