ruby-on-rails – 实现多个用户角色

我使用state_machine非常成功,并且通过几行代码爱上了动态创建的类方法.

但是,我不知道如何继续我创建的系统.我正在开发一个系统,用户有很多角色.所以这不是一个简单的,因为有一个用户的状态从未确认到确认,然后可能到管理员.

用户现在有许多角色,可以是潜在的,骑自行车的人,协调者,管理员,论坛管理员,商店管理员,超级管理员和筹款人.

所以层次结构如下所示:

superadmin

forum admin,store admin

cyclist,coordinator,manger,fundraiser

potential

但是,一个状态机在这里不会被切断,因为一个用户完全可以同时拥有所有上述角色.

我正在实现我自己的类方法,这样可以有点模仿状态机:

class User < ActiveModel::Base
    has_many :jobs
    has_many :roles,through: :jobs

    def role_array
        self.roles.pluck(:role)
    end

    def has_role?(role)
        role_array.include?(role)
    end

    # checking
    def is_superadmin?
        role_array.include?('superadmin')
    end


    # changing
    def add_role(role)
       self.update_attributes(accepted_at: Time.Now) if self.is_only_potential?
       self.user_roles.create(role_id: Role.find_by(role: role).id ) if !self.has_role?(role)
    end

    def remove_role(role)
        self.user_roles.find_by( role_id: Role.find_by(role: role).id ).destroy if self.has_role?(role)
    end

    def make_superadmin!
        add_role('superadmin')
    end

    def denounce_superadmin!
        remove_role('superadmin')
    end

end

这只是一个骗子.所以我的问题是:

我做错了吗?如何处理多角色的用户

2)即使我做的正确,我想创建一个state_machine类的DSL,所以当我需要创建一个新的角色,让我们说’跑步者’,我可以在我的模型中做这样的事情:

class User < ActiveModel::Base
    has_many :jobs
    has_many :roles,through: :jobs

    multiroles initial: :potential do
        roles [:superadmin,:forum_admin,:store_admin,:cyclist,:coordinator,:manager,:fundraiser,:potential]
         # dynamically creates the above methods for getting and setting for all roles
    end

我应该如何创建这个多卷方法?里面的lib?准备打包成为我的第一个宝石?

我不知道如何动态创建方法,但我想开始:)

只是一个想法,也许多轮方法可以通过Roles.all动态获取所有角色,并自动添加上述方法!也许甚至照顾has_many:jobs has_many:roles,通过::jobs

此外,我应该如何验证这些角色?我正在控制器中的前一个块中执行此操作:

def only_superadmins
    redirect_to root_url if !current_user.has_role?('superadmin')
end

我的应用程序控制器中也有一些这些方法,只有_superadmins,only_cyclists等等,我们通过before_method方法在各种子控制器中调用它们.

这样好吗我应该使用cancan还是什么东西?

如果我做的正确,我想知道我应该如何动态地创建这些方法与我的宝石.我在想这些事情:

class panel_controller < ApplicationController   
    allowed_roles [:super_admin,:store_admin]
end

而allowed_roles方法将创建这些方法

def allowed_roles(role_array)
    role_array.each do |role|
         define "only_#{role.to_s}s" do |arg|
            redirect_to root_url if !current_user.has_role?(arg.to_s)
         end
    end
end

这样可以编写这些方法

def only_super_admins
    redirect_to root_url if !current_user.has_role?('super_admin')
end

def only_forum_admins
    redirect_to root_url if !current_user.has_role?('forum_admin')
end


def only_store_admins
    redirect_to root_url if !current_user.has_role?('store_admin')
end

虽然我不明白为什么不起作用,但这并没有使我效率太高.

也许allowed_roles应该是这样的:

def allowed_roles(wanted_roles)
    redirect_to root_url unless (current_user.role_array & wanted_roles).empty? # it's ONLY empty when any of the current_user roles exists in the wanted_roles array
end

我只想要一些指针真的:)

如何创建一个gem以使allow_roles方法可用于用户模型可用的控制器和多重卷?

Cancan can can manage multiple roles like this?我应该用这个吗

解决方法

恢复回答:

为了处理模型的角色,一个很好的选择是使用gem rolify.通过它,您可以轻松地定义所需的角色,并将所需的角色与您的用户相关联.使用简单,只需按照官方文档here.

CanCan(或其附件CanCanCan)用于处理权限.您将定义每个角色(由rolify定义)的用户有权在文件app / models / ability.rb中执行的操作.然后,在控制器或视图中,您只需验证用户是否有权对资源执行操作.例如,在您的控制器中,您可以验证像@comment = Comment.new(params)这样的授权;授权! :创建@comment,并在您的视图中验证授权,如果可以的话? :创建,评论.请注意0​​7004的官方文档,了解如何设置和使用CanCan.

围绕这些您的具体问题:

宝石添加Rolify(宝石“rolify”)和CanCan(宝石“cancan”)宝石.

执行rails shell命令rails g rolify Role User创建一个名为Role的新类(或使用您喜欢的名称),并在现有类User中添加一些类方法.由于新的角色角色将向您的数据库添加表格角色,因此必须运行rake db:migrate(使用ActiveRecord时).

将资源添加用户将访问的任何类.例如:

class Forum < ActiveRecord::Base
  resourcify
end

完成这些步骤后,您的User类将配备add_role,remove_role和has_role方法,您可以使用它们添加任意数量的角色:

user.add_role :superadmin
user.add_role :fundraiser

user.has_role? :superadmin
# >> true
user.has_role? :fundraiser
# >> true

您甚至可以将角色定位到一个资源或实例:

user.add_role :cyclist,Forum
user.add_role :coordinator,Forum.first

user.has_role? :cyclist,Forum
# >> true
user.has_role? :cyclist,Store
# >> false
user.has_role? :coordinator,Forum.first
# >> true
user.has_role? :coordinator,Forum.second
# >> false

所以你可以这样写你的User类:

class User < ActiveModel::Base
  rolify
  has_many :jobs

  # checking
  def is_superadmin?
      self.has_role?('superadmin')
  end

  # changing
  def add_new_role(role)
     self.update_attributes(accepted_at: Time.Now) if self.is_only_potential?
     self.add_role(role)
  end

  def make_superadmin!
      add_new_role('superadmin')
  end

  def denounce_superadmin!
      remove_role('superadmin')
  end
end

要认证这些角色,您可以使用CanCan.执行rails shell命令rails g cancan:生成文件app / models / ability.rb的能力,您可以在其中定义角色的权限.

class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user

    if user.has_role? :superadmin
      can :manage,All  # can manage (Read,Create,Update,Destroy,...) everything
    elsif user.has_role? :forum_admin
      can :manage,Forum  # can manage (Read,...) any Forum
    elsif user.has_role? :store_admin
      can :manage,Store do |store|  # Can manage only its own store
        store.try(:user) == user
      end
    elsif user.has_role? :forum_member
      can :create,Post do |post|
        if post.forum.members.include? user
          true
        end
      end
      can :destroy,Post do |post|
        post.try(:user) == user
      end
      can :update,Post do |post|
        post.try(:user) == user
      end
    elsif ...

    else # Users without role
      can :read,All
    end
  end
end

在您的控制器中,您可以致电授权!方法.例如:

# app/controllers/posts_controller.rb
def create
  @post = Post.new(params[:post])
  @post.user = current_user
  authorize! :create,@post
  if @post.save
    redirect_to @post
  else
    render :action => 'new'
  end
end

或者,您可以在控制器的起始处包含这些信息,并在每个操作之前自动加载和授权资源(或不):

class PostController < ApplicationController
  load_and_authorize_resource :post

  ...

def create
  authorize! :create,@post
  if @post.save
    redirect_to @post
  else
    render :action => 'new'
  end
end

观看本教程RailsCast开始使用CanCan.

我希望这可以帮助您指导您解决问题.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...