对于rails查询的基于订阅的限制

时间:2015-10-16 23:00:10

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

我有一个相当复杂的问题,我可以提供一些帮助,因为我一直在尝试的所有实现都是有缺陷的(Rails 4.2.1)。

用户可以访问设备:

create_table "devices", force: :cascade do |t|
  t.string   "device_guid"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.integer  "user_ids"
end

并且设备有许多数据条目:

create_table "datas", force: :cascade do |t|
  t.string   "device_id"
  t.datetime "start_time"
  t.datetime "end_time"
end

我们希望根据订阅将所有查询限制为数据。

create_table "subscriptions", force: :cascade do |t|
  t.integer  "device_id"
  t.integer  "user_id"
  t.datetime "start_date"
  t.datetime "end_date"
end

如此有效,除非订阅允许,否则不应访问数据。

我希望在一个地方完成此限制(不是通过单独的方法来访问它),因此编写代码的其他人仍然处理订阅限制。我不想使用第三方gem,因为数据非常敏感。

我认为最明显的方法是在Data模型上设置default_scope,但我遇到了几个问题:
1)您无法从数据模型访问@user。我用一个丑陋的黑客来解决这个问题,从模型中访问User.current 2)我无法使用current_user,因为我们的管理员构成其他用户,并且需要按原样查看数据。使用与#1相同的解决方法 3)同一个用户和设备可能有多个具有不同日期的订阅。没有办法做一个我知道的ActiveRecord查询可以解释两个不同的日期范围(我通过使用arel_table解决了这个问题)。
4)当我在rails控制台(理论上通过API接口)时,这使得查询数据的所有方法都失败了。如果没有User.current,我忽略了默认范围,但是很明显这是一个安全问题。

这是我当前的实现(在psuedocode中):

query = []
Subscription.each do |s|
  if (User.current.id == s.user_id)
    temp = Data.all.where(data[:start_time] >= s.start_date).where(data[:end_time] <= s.end_date).where(data[:device_id] == Device.find_by(id: s.device_id).device_guid)
    end
  end
  query += temp
end
default_scope { query }

我将此代码直接放入模型中。我认为它不会起作用,但它确实......有时候。它行为奇怪,有时完全限制用户不应该,尽管它还没有(但)给某人访问他们不应该拥有的数据。

我正在寻求从头开始重新设计,并以最好的方式做到这一点。关于如何最好地接近它,我愿意接受任何建议(第三方除外,抱歉)。我不介意实施需要做很多工作,我宁愿这次做对。任何可扩展性帐户(例如,如果我们为远程查询实现了API)都将是一个很好的功能,尽管我们目前不需要它。

重申一下,我坚持认为这个限制对所有查询都是“自动的”,所以如果前编码器例如写道:

<%= @user.device.find(1).data.all.count %>

在视图中,它不会显示用户没有订阅的任何数据。

感谢您的任何建议。对于长篇文章感到抱歉,这是一个相当令人困惑的问题。

0 个答案:

没有答案
相关问题