Ruby on rails 当Desive用户';你在我的默认范围之外吗?
我有一个Rails 4应用程序,它使用Desive 3.4进行身份验证,我已经定制了该应用程序,可以禁止用户(使用一个简单的布尔列Ruby on rails 当Desive用户';你在我的默认范围之外吗?,ruby-on-rails,activerecord,devise,warden,default-scope,Ruby On Rails,Activerecord,Devise,Warden,Default Scope,我有一个Rails 4应用程序,它使用Desive 3.4进行身份验证,我已经定制了该应用程序,可以禁止用户(使用一个简单的布尔列users.banked,默认为false)。User模型还有一个default\u作用域,它只返回非禁止用户 问题是——我仍然希望我的被禁止用户能够登录,即使他们在登录后不能做任何事情。(他们基本上只是看到一个页面,上面写着“你被禁止了”)。但似乎默认范围正在绊倒designe。当您登录或呼叫时,例如,authenticate\u user,designe尝试使用基
users.banked
,默认为false)。User
模型还有一个default\u作用域
,它只返回非禁止用户
问题是——我仍然希望我的被禁止用户能够登录,即使他们在登录后不能做任何事情。(他们基本上只是看到一个页面,上面写着“你被禁止了”)。但似乎默认范围
正在绊倒designe。当您登录或呼叫时,例如,authenticate\u user
,designe尝试使用基本的ActiveRecord方法之一(如find
或find\u by
)查找当前用户,但无法找到,因为它们位于默认范围之外。因此Desive得出结论,用户不存在,登录失败
如何使Deave忽略默认范围?在Deave和Warden源代码中花了很长的时间后,我终于找到了一个解决方案 简短答复: 将其添加到
用户
类:
def self.serialize_from_session(key, salt)
record = to_adapter.klass.unscoped.find(key[0])
record if record && record.authenticatable_salt == salt
end
(注意,我只对ActiveRecord进行了测试;如果您使用的是不同的ORM适配器,您可能需要更改该方法的第一行……但是我不确定其他ORM适配器是否有“default so”的概念
长答覆:
serialize\u from\u session
是从-混合到用户类中的。老实说,我不确定它实际上应该做什么,但它是一个公共方法,并且在Desive API中有文档记录(非常稀少),所以我认为它不太可能在没有警告的情况下从Desive中删除
以下是Desive 3.4.1的原始源代码:
def serialize_from_session(key, salt)
record = to_adapter.get(key)
record if record && record.authenticatable_salt == salt
end
问题在于to_adapter.get(key)
to_adapter
返回一个OrmAdapter::ActiveRecord
的实例,该实例围绕User
类,而to_adapter.get
与调用User.find
基本相同。(Deviate使用orm_适配器
gem使其保持灵活性;无论您使用的是ActiveRecord、Mongoid还是任何其他与OrmaAdapter兼容的orm,上述方法都不会修改。)
但是,当然,User.find
只在默认范围内搜索,这就是为什么它找不到我被禁止的用户。调用到适配器.klass
直接返回User
类,然后我可以调用unscoped.find
搜索所有被禁止的用户,并使被禁止的用户可见。所以工作路线是:
record = to_adapter.klass.unscoped.find(key[0])
请注意,我传递的是key[0]
而不是key
,因为key
是一个数组(在本例中是一个元素),将数组传递给find
将返回一个数组,这不是我们想要的
还要注意的是,在真正的Deavise源代码中调用klass
是个坏主意,因为这意味着你失去了或Adapter
的优势。但是在你自己的应用程序中,你可以肯定地知道你正在使用哪种ORM(Deavise不知道的东西),具体一点是安全的