目前,我的Users数据库有一个名为“admin”的列,其中包含一个布尔值,默认设置为false。我有一个管理员用户播种到数据库中。
如何编写我的应用程序,以便 管理员的用户可以创建新用户,但不的用户不能? (此外,用户应该由管理员仅创建)
似乎应该有一个简单的方法来设计,不涉及使用一些外部模块。到目前为止,我还没有找到一个满意的答案。
我更有可能选择仅设计的解决方案。 (一个只是标准的MVC / Rails解决方案加一个)然而,如果确实有一个更好的方法来做不涉及CanCan I 可能也接受它。
注意:
我一直在寻找一段时间,我发现了其他几个与此问题非常类似的stackoverflow问题,但要么没有完全回答问题,要么使用其他非设计模块。 (或两者兼而有之)
答案 0 :(得分:16)
要实施授权,请使用控制器上的方法
完全按照@ diego.greyrobot
的建议class UsersController < ApplicationController
before_filter :authorize_admin, only: :create
def create
# admins only
end
private
# This should probably be abstracted to ApplicationController
# as shown by diego.greyrobot
def authorize_admin
return unless !current_user.admin?
redirect_to root_path, alert: 'Admins only!'
end
end
要回避设计'已登录'问题,请定义新的创建用户路线。
我们将简单地定义一个新路由来处理用户的创建,然后将表单指向该位置。这样,表单提交不会通过设计控制器,因此您可以随意在正常的Rails方式中随意使用它。
# routes.rb
Rails.application.routes.draw do
devise_for :users
resources :users, except: :create
# Name it however you want
post 'create_user' => 'users#create', as: :create_user
end
# users/new.html.erb
# notice the url argument
<%= form_for User.new, url: create_user_path do |f| %>
# The form content
<% end %>
答案 1 :(得分:7)
问题是概念性的。 Devise只是一个身份验证库而不是授权库。您必须单独实现或使用CanCan。但是,不要担心,因为你只有一个角色,所以你很容易实现这一点。
使用之前的过滤器保护您的用户创建/更新/销毁操作:
class UsersController < ApplicationController
before_filter :authorize_admin, except [:index, :show]
def create
# user create code (can't get here if not admin)
end
end
class ApplicationController < ActionController::Base
def authorize_admin
redirect_to root_path, alert: 'Access Denied' unless current_user.admin?
end
end
通过这种简单的方法,您可以在任何可能影响用户记录的控制器操作上运行前置过滤器,方法是首先检查用户是否为管理员,如果他们不是,则将其踢出主页。
答案 2 :(得分:7)
这似乎是简单的方法。它只需要对设计控制器进行子类化。请参阅文档以了解如何执行此操作。
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_action :authenticate_user!, :redirect_unless_admin, only: [:new, :create]
skip_before_action :require_no_authentication
private
def redirect_unless_admin
unless current_user.try(:admin?)
flash[:error] = "Only admins can do that"
redirect_to root_path
end
end
def sign_up(resource_name, resource)
true
end
end
# config/routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :registrations => 'registrations'}
end
<强>阐释:强>
before_action
确保用户已登录,如果用户尝试注册,则会重定向,除非他们是管理员。 require_no_authentication
方法引起的,跳过它可以解决问题。 sign_up
帮助程序方法被覆盖,以防止自动注册。Welcome! You have signed up successfully.
文件来更改config/locales/devise.en.yml
注册Flash消息。答案 3 :(得分:1)
在处理 Rails 6 应用程序时遇到此问题。
我有一个admin
模型,我用它设计来创建管理员。
这是我修复的方式:
首先,我为Admin模型生成了一个Devise控制器,该控制器创建了以下文件:
app/controllers/admins/confirmations_controller.rb
app/controllers/admins/omniauth_callbacks_controller.rb
app/controllers/admins/passwords_controller.rb
app/controllers/admins/registrations_controller.rb
app/controllers/admins/sessions_controller.rb
app/controllers/admins/unlocks_controller.rb
接下来,我以这种方式修改了new
的{{1}}和create
操作以使用Devise将注册限制为管理员:
app/controllers/admins/registrations_controller.rb
此后,我以这种方式将class Admins::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
# GET /resource/sign_up
def new
if admin_signed_in?
super
else
redirect_to root_path
end
end
# POST /resource
def create
if admin_signed_in?
super
else
redirect_to root_path
end
end
.
.
.
end
操作添加到skip_before_action :require_no_authentication, only: [:new, :create]
中,以允许已存在的管理员在登录时创建新管理员:
app/controllers/admins/registrations_controller.rb
您可能还需要隐藏登录表单中的注册和忘记密码按钮,以仅由已登录的管理员登录:
class Admins::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
skip_before_action :require_no_authentication, only: [:new, :create]
.
.
.
end
(可选)在通过数据库迁移将# app/views/admins/sessions/new.html.erb
<% if admin_signed_in? %>
<%= render "admins/shared/links" %>
<% end %>
和first_name
参数添加到last_name
模型之后,我将app/controllers/admins/registrations_controller.rb
和admin
参数添加到class Admins::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
skip_before_action :require_no_authentication, only: [:new, :create]
.
.
.
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name,
:last_name])
end
# If you have extra params to permit, append them to the sanitizer.
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:first_name,
:last_name])
end
.
.
.
end
文件中允许的参数中: / p>
app/views/admin/registrations
注意:您将需要相应地修改index
视图以适应此情况
另外,您可能需要创建一个新的控制器,您可以在其中为admins
(例如app/controllers/admins/admins_controller.rb
)创建class Admins::AdminsController < ApplicationController
before_action :set_admin, only: [:show, :edit, :update, :destroy]
before_action :authenticate_admin!
# GET /admins
# GET /admins.json
def index
@admins = Admin.all
end
.
.
.
end
操作:
show
注意:如果您需要更多操作,例如通过从信息中心更新和删除其他管理员的信息来管理管理员,则可能需要添加其他操作,例如{{1 }},edit
,update
,destroy
和其他文件。
对于路线:
## config/routes.rb
# List of Admins
get 'admins', to: 'admins/admins#index'
namespace :admins do
resources :admins
end
然后在app/controllers/admins/registrations_controller.rb
中修改注册后使用的路径以重定向到admins_path
,这将向您显示所有管理员的列表< / strong>已创建:
class Admins::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
skip_before_action :require_no_authentication, only: [:new, :create]
.
.
.
# The path used after sign up.
def after_sign_up_path_for(resource)
admins_path
end
# The path used after sign up for inactive accounts.
def after_inactive_sign_up_path_for(resource)
admins_path
end
end
最后,您可能需要从以下位置更改在config/locales/devise.en.yml
文件中创建用户时Devise发出的通知:
Welcome, You have signed up successfully
说:
Account was created successfully.
仅此而已。
我希望这对您有帮助。