自定义Devise的authenticate和current_user方法以使用软删除/充当偏执狂

时间:2013-04-07 09:09:29

标签: ruby-on-rails devise ruby-on-rails-3.2 warden

我正在使用Devise作为rails 3.2 app的身份验证。我的用户模型叫做User,我一直在尝试实现软删除。我试图通过使用acts_as_paranoid来做到这一点,它会自动为你工作。事情按预期工作(其他人不能再看到“已删除”用户),除了我希望已停用的用户仍然能够登录并看到“已停用”屏幕,并让他们有机会重新激活他们的帐户。

问题是Devise(Warden?)不再能够找到已删除的用户。如果使用范围“with_deleted”,Acts_as_paranoid允许您访问软删除的记录。所以我能够通过以下方式获得部分:

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  where(conditions).with_deleted.first
end

我把它放到我的用户模型中,所以现在当我输入登录信息时,我将获得我已成功登录的flash消息,并且它将触及用户模型中的“updated_at”列并且增加sign_in_count等。但是,在认证方法返回false并且current_user帮助器方法返回nil的意义上,它并不真正进行身份验证。那么,让这些工作的最佳策略是什么?我可以以某种方式覆盖current_user方法,以便它使用with_deleted范围查询User模型吗?我是否必须对warden做一些事情,例如我使用find_first_by_auth_conditions方法添加的条件?我无法弄清楚如何做到这一点。任何帮助表示赞赏!

此外,在我确实运行之后,我想自动将所有软删除的用户发送到“已停用”的页面,其中唯一的选项是永久删除或重新激活。有没有办法通过“authenticated:user do {} end”进行路由,或者我必须在application_controller中放置一个before_filter并在每次请求时检查用户吗?

2 个答案:

答案 0 :(得分:0)

我可以回答你的最后一个问题,关于路由到"停用的页面"。您可以使用lambda来隔离不同类型的用户,如下所示:

authenticated :user, lambda {|u| u.deactivated? } do
  root :to => 'application#deactivated'
end
authenticated :user, lambda {|u| u.active? } do
  root :to => 'application#active'
end

答案 1 :(得分:0)

感谢Devise组提示,我发现我需要覆盖serialize_from_session方法,该方法位于可验证模块内,如下所示:

def serialize_from_session(key, salt)
  record = to_adapter.get(key)
  record if record && record.authenticatable_salt == salt
end

我一直在尝试使用初始化程序覆盖模块没有成功(我试图覆盖现有的策略,并尝试为warden编写一个新的策略);但我一直得到奇怪的名字错误。我还是没想出来。但是,通过提示,我继续并覆盖了我的User模型中的方法。由于我没有预见到使用其他资源,我不介意只是像这样编辑它。代码只是:

def self.serialize_from_session(key, salt)
  record = with_deleted.find(key).first
  record if record && record.authenticatable_salt == salt
end

这完全跳过了to_adapter.get方法(对任何感兴趣的人来说,都是在orm_adapter中,而不是设计;这需要我一段时间才能找到,因为我认为我需要覆盖它)。这可能不是最干净的方法,但对我来说效果还不错。即使我确实有不同的资源,这应该只覆盖User资源,所以我认为一切都会正常工作。

如果出现问题,我会在这里添加。如果没有,希望这会以某种方式帮助某人。当然花了我很长时间才到达底部!