【问题标题】:Devise crud + namespaces: Pro level :)设计 crud + 命名空间:专业级:)
【发布时间】:2016-06-16 17:02:59
【问题描述】:
  • 我有Devise Admin & Devise User;
  • 我想使用命名空间;

我想要达到的目标:

  • 只有设计管理员可以创建设计用户
  • registerable 用户没有被删除,所以他只能编辑页面
  • 用户只能看到 current_user/显示页面

我有什么

路线:

Rails.application.routes.draw do root :to => 'dashboard#index'
  devise_for :users, controllers: { registrations: 'user_registrations' }
  devise_for :admins, controllers: { registrations: 'admin_registrations' }
  get 'dashboard/index'
  namespace :admin do
    root 'dashboard#index'
    resources :users
  end

用户注册控制器:

class UserRegistrationsController < Devise::RegistrationsController
end

users_controller:

class UsersController < ApplicationController

  def index
    @users = User.all
  end
  def show
    @user =  User.find(params[:id])
  end
  def new
    @user = User.new
  end
  def edit
  end
  def create
    @user = User.new(user_params)
    respond_to do |format|
      if @guest.save
        format.html { redirect_to users_path }
      else
        format.html { render :new }
      end
    end
  end
  def update
    respond_to do |format|
      if @user.update(user_params)
        format.html { redirect_to @user }
      else
        format.html { render :edit }
      end
    end
  end
  def destroy
    user = User.find(params[:id])
    user.destroy
    redirect_to users_path
  end

  private
    def set_user
      @user = User.find(params[:id])
    end
    def user_params
      params.require(:user).permit(:email, :password, :password_confirmation)
    end
end

+ 我有用户视图,就像在普通脚手架中一样。

=> 使用此设置,任何人都可以创建用户

任何想法如何解决上面的问题?..

【问题讨论】:

    标签: ruby-on-rails devise namespaces


    【解决方案1】:

    不要在 Devise 中使用单独的用户类,而是使用角色。 Devise 仅用于验证单个类,而您可以将其破解为使用两个类,这很混乱。您必须重写会话中序列化/反序列化用户的所有逻辑,以便设计知道它是否应该加载 Admin 或 User 类。

    这也是一个糟糕的解决方案,因为您将 authorization 问题下推到 authentication 层。 Devise 的工作是验证用户是她/他声称的那个人,这是一个不小的壮举。 授权,另一方面是关于用户可以做什么的规则。 “只有管理员才能创建用户”是明确的授权规则。

    最简单的基于角色的授权可能是这样的:

    class AddRoleToUser < ActiveRecord::Migration
      def change
        add_column :users, :role, :integer, default: 0
        add_index :users, :role
      end
    end
    
    class User
      # ...
      enum role: [:visitor, :admin]
    end 
    

    我们使用enum,它是一个位掩码列来存储用户角色。将其声明为枚举列也为我们提供了一些免费的方法:

    user.visitor?
    user.admin?
    user.admin!
    

    让我们创建一个基本的授权检查:

    def create
      unless current_user.admin?
        redirect_to root_path, status: 401, error: 'You are not authorized to perform this action' and return
      end 
    
      # ...
    end
    

    但我们不想在每次要授权时都重复,所以让我们清理一下:

    class AuthorizationError < StandardError; end
    
    class ApplicationController
    
      rescue_from AuthorizationError, with: :deny_access!
    
      private
    
        def authorize_admin!
          raise AuthorizationError, unless current_user.admin?
        end
    
        def deny_access!
          redirect_to root_path, 
               status: 401, 
               error: 'You are not authorized to perform this action'
        end
    end
    

    那么我们可以在控制器执行操作之前设置一个过滤器来检查授权:

    class UsersController < ApplicationController
      before_action :authorize_admin!, except: [:show]
    
      # ... 
    end
    

    但是,您可能不想重新发明轮子,而是想看看PunditCanCanCan,它们是拥有强大社区的可靠授权库。您可能还想查看Rolify

    【讨论】:

    • 您描述的基于授权的方法很棒,但是我假设使用不同的Devise adminDevise user,因为它们稍后会与其他模型有不同的关联(scaffold event title admin:references starts_at:date,@ 987654333@, scaffold appointment admin:references user:references starts_at:date...
    • 我真的不建议这样做,您可以使用单个用户类很好地设置关系。如果您想调用关系belongs_to: :admin,您可以简单地提供class_name 选项。我认为您低估了它会破坏您的授权系统的严重程度,如果您沿着这条路线走,您基本上可以通过设计。此外,除了在尖峰中进行原型制作外,实际上不建议使用脚手架。通过生成许多未正确锁定或测试的操作/视图等,您将轻松超越自己。
    • 感谢您的指导。我想我会以某种方式尝试 2-devise-model + 命名空间的方式,然后 auth gems + 一个设计模型将是下一个:)..
    猜你喜欢
    • 2014-01-29
    • 2014-10-08
    • 2011-03-04
    • 2011-05-28
    • 2021-10-10
    • 1970-01-01
    • 2016-12-03
    相关资源
    最近更新 更多