设计CRUD +命名空间:专业级:)

设计CRUD +命名空间:专业级:)

问题描述:

  • Devise Admin & Devise User;
  • 我想使用命名空间;

我想达到的目标:设计CRUD +命名空间:专业级:)

  • 只设计管理员可以创建用户色器件用户
  • 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 

user_registration_controller:

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 

+我有用户的意见,因为他们将在一个正常的支架。

=>有了这个设置,任何人都可以创建一个用户

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

不要使用单独的用户类与设计,使用角色来代替。设计只是为了验证一个单一的课程,而你可以用两个课程搞得一团糟。你必须重写序列化/拒绝会话中用户的所有逻辑,以便devise知道它是否应该加载Admin或User类。

它也是一个坏的解决方案,因为你是一个授权问题下推入认证层。 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这是一个位掩码列来存储用户的角色。声明为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

+0

您描述的基于授权的方法非常好,但是我假设要使用不同的'Devise admin'&'Devise user',因为它们稍后将与其他模型有不同的关联('scaffold event title admin:references starts_at :日期','脚手架出席事件:引用用户:引用','脚手架约会管理员:引用用户:引用starts_at:日期'... – makerbreaker

+0

我真的不会建议,你可以设置单一用户关系很好如果你想调用关系'belongs_to::admin',你可以简单地提供'class_name'选项,我认为你低估了它会让你的授权系统变得糟糕,你基本上可以通过设计出来,而且,它不是真的推荐使用脚手架,除非在原型中使用脚手架。通过让人产生方式,你会很容易地摆脱困境y行为/视图等未正确锁定或测试的行为。 – max

+0

谢谢你的指导。我想我会以某种方式尝试2-devise-model +命名空间的方式,并且认证宝石+一个设计模型将成为下一个:) – makerbreaker