Rails角色和权限 - 我该怎么做?

时间:2015-07-10 12:53:43

标签: ruby-on-rails ruby-on-rails-4 permissions authorization

我已经成功推出了自己的基于授权系统的角色和权限:

  • 角色和权限是数据库中与另一个表具有多对多关系的模型。
  • 用户通过该角色拥有角色和拥有权限
  • 管理员用户可以创建新角色并定义哪些权限与哪些角色配对。
  • 控制器和视图在执行或呈现某些内容之前检查当前用户是否具有特定权限。

这一切都很有效。这是代码的关键部分,它包含在application_controller,rb中:

def permitted_action (permission_names)
  # if the users permissions do not instersect with those given then redirect to root
  redirect_to(root_url) if (permission_names & current_user.permissions.map(&:name)).empty?
end

这是一个验证用户权限的控制器:

before_action only: [:new, :create] do
  permitted_action ['create_user'] 
end

我的问题是权限是具有唯一字符串名称的数据库行,我想在识别权限时使用这些名称。所以我使用我需要的所有权限为数据库播种,然后当View或Controller需要检查权限时,我需要在此时获得权限名称。如果我检查了许可" add_user"但在db中,权限名称是" add_users"它出错了。

然后在测试中我必须再次将所有权限作为固定装置,并再次获得所有名称。

当我添加需要更多权限的功能时,我必须在至少3个不同的位置使用相同的字符串添加这些权限。这对我来说似乎是错误的。

理想情况下,控制器会定义他们使用的权限,db / seeds.rb文件会接收这些权限并为数据库播种,测试设备也会接收它们,但我不是确定这是否可行。

我应该如何构建这个?

修改

我认为对我有帮助的是一个为db / seeds.rb文件提供信息的灯具解析器。从permissions.yml获取此类内容:

archive_tally:
  name: archive_tally
  description: Archive or make active any tally
  category: 3

吐出这样的东西:

archive_tally = Permission.find_or_initiate_by_name("archive_tally")
archive_tally.description = "Archive or make active any tally"
archive_tally.category = 3
archive_tally.save!

我不认为这种事情存在。

3 个答案:

答案 0 :(得分:1)

您可以通过添加is_adminis_general_user等字段将用户分组为权限组,从而将其简化为仅用户表(或角色也取决于有多少)。然后权限只是用户模型上的方法问题,例如:

def can_create_new_roles?
  self.is_admin
end

所以现在你可以做到

before_action only: [:create, :new] do
  redirect_to root_path unless current_user.can_create_new_roles?
end

哪个读得好多了。此外,由于这一切都发生在用户模型与其自己的数据库表上,因此可以更轻松地测试所有这些UserPermissions。

答案 1 :(得分:0)

这是我想出来的,它让我满意,虽然这不是我在问题中寻找的理想解决方案:

事实证明,我希望生产数据库能够使用灯具作为种子,这些灯具是我想要出现在测试数据库中的灯具的子集。

  1. 我制作了一个目录db/seed_fixtures,其中包含roles.ymlpermissions.yml等文件。在这些文件中,我放置了我想用生成数据库播种的装置。

  2. tests/fixtures/roles.yml中,我在文件顶部包含了此行的其他灯具: <%= ERB.new(IO.read(Rails.root.join "db/seed_fixtures/roles.yml")).result %> 同样处理权限.yml和其他适用的YAML文件。我在那个包含线的地方放置了任何仅测试的灯具。

  3. db/seeds.rb中,我从灯具生成种子代码,用于生产,如下所示:ActiveRecord::Fixtures.create_fixtures("#{Rails.root}/db/seed_fixtures", "roles")

  4. 现在我分别编写了所有的灯具,有些用作生产数据库中的种子,其他用于测试。要将种子加载到数据库中,我运行rake db:seed(我在生产服务器上执行)并加载我运行的数据库中的所有测试夹具rake db:fixtures:load

    <强>更新

    我刚开始使用Cucumber,我意识到我可以在Cucumber Step中使用上面步骤3中的代码将种子数据导入Cucumber的测试数据库:

    Given(/^seed data is loaded into the database$/) do
      ActiveRecord::FixtureSet.create_fixtures("#{Rails.root}/db/seed_fixtures", "roles")
      _(Role.count).wont_equal 0
    end
    

    Cucumber还告诉我,ActiveRecord::Fixtures已被弃用,转而使用ActiveRecord::FixtureSet

答案 2 :(得分:0)

我提出了一个完全不同的解决方案:我已经创建了一个夹具解析器。

我的第一个解决方案的大部分仍然适用(请参阅我的其他答案),但现在,我已经制作了一个解析器来读取我想用于种子的灯具,并将它们添加到数据库中,而不是该解决方案中的第3步。 ,检查他们是否已经在那里。我从db/seeds.rb

运行解析器

我已将code for the parser作为github上的要点