实现ActiveRecord方法的授权

时间:2016-04-12 10:52:11

标签: mysql ruby-on-rails ruby activerecord authorization

我一直在尝试在ActiveRecord之上实现授权层。让我解释一下它应该如何运作。

数据库

考虑具有以下字段的数据库表Invoices

  • InvoiceId
  • 客户ID
  • ......其他领域

将有一个带有字段

的辅助表InvoicePrivileges
  • ObjectId(指发票ID)
  • SubjectId(在这种情况下指客户ID)
  • 主题类型(处理多种用户 - 客户,管理员,运营商等)
  • 读(布尔)
  • 写(布尔)

授权检查

为了能够阅读发票,尝试read行或行集的实体必须在InvoicePrivileges表中有一组条目(其中InvoicePrivileges.object_id指的是InvoiceIdInvoicePrivileges.read = true。{/ p>

示例,用于从数据库中获取大量发票的查询

SELECT invoice.*
FROM Invoices invoice
LEFT JOIN InvoicePrivileges privilege 
    ON invoice.invoice_id = privilege.object_id
    AND privilege.subject_id = <user_id>
    AND privilege.subject_type = <user_type>
WHERE privilege.read = TRUE;

尝试update发票时,相同的条件适用,但上一个WHERE条件变为WHERE privilege.write = true

实施

我可以使用Arel library轻松创建这些约束。但是,我在哪里以所有ActiveRecord保存和更新操作都包含这些约束的方式实现这些方法?

我不介意编写一些代码来启用它。我正在寻找关于如何最好地解决它的指针。

1 个答案:

答案 0 :(得分:0)

创建一个gem并在ActiveRecord gem之后需要它。在你的gem中打开ActiveRecord类并覆盖感兴趣的方法。

module ActiveRecord
  class Base

    def save(*)
      if(authorised?)
        super
      else
        raise NotAuthorisedError.new("Your meaningful message!")
      end
    end

  end
end

Rails源代码的原始代码位于Persistence class。所有持久性方法通常在内部使用create_or_update方法。因此,您可以考虑改为覆盖该方法。但是,您需要查看代码并查看这是否是个好主意。