我让用户最初登录时没有确认他们的电子邮件地址 - 但是在7天之后,如果他们还没有确认 - 我会阻止访问,直到他们确认他们的地址。
(注意 - 这是通过在Devise初始化程序中设置config.allow_unconfirmed_access_for = 7.days
来实现的)
如果他们达到'宽限'限制(例如他们没有确认并且7天通过)那么我想:
做#2我需要访问用户才能获得电子邮件地址。
设计显然'知道'用户是谁 - 这就是它知道他们已经通过确认到期的方式。
如果用户刚刚尝试登录,那么我可以通过查看参数来获取此信息。 但是,如果用户已经在他们的会话中有一个实时登录令牌,那么当他们通过神奇的一周 - 他们将突然开始被设计拒绝。在这种情况下如何访问用户?
#based on
#https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated
#https://stackoverflow.com/questions/9223555/devise-with-confirmable-redirect-user-to-a-custom-page-when-users-tries-to-sig
class CustomFailure < Devise::FailureApp
def redirect_url
if warden_message == :unconfirmed
user = User.find_by_email(params.dig(:user,:email))
user&.send_confirmation_instructions
if user.nil?
#if the user had a valid login session when they passed the grace period, they will end up here
!! how do I get the user in this scenario !!
end
confirmation_required_info_path(params: {found: !user.nil?})
elsif warden_message == :invalid
new_user_session_path(user:{email: params.dig(:user,:email)})
else
super
end
end
# You need to override respond to eliminate recall
def respond
if http_auth?
http_auth
else
redirect
end
end
end
这实现了目标#1,但如果失败是新注册的结果,它只能达到目标#2
有没有直接的方式来访问用户有实时会话,但已经过了有效期?
(current_user不可用,env ['warden'] .user is nil)
谢谢
Rails 5.0.6 设计4.2
编辑:更新以澄清我需要帮助的示例方案:
第0天:用户使用电子邮件/密码注册。我告诉他们没有确认他们的电子邮件。他们有7天的宽限期来确认他们的电子邮件。
第2天:他们退出
第7天(上午):他们再次登录
第7天(当天晚些时候):他们采取了一些行动。他们的登录令牌仍然有效 - 设计识别它,找到他们的用户记录并检查他们是否已确认他们的电子邮件地址。他们没有 - 所以设计拒绝授权行动,给出错误:未经证实
在这种情况下 - 他们来到失败应用程序。我会将它们重定向到一个页面,上面写着“您已经过了7天的宽限期,现在确实需要确认您的电子邮件地址”。
在失败的应用程序中,我想知道他们的电子邮件地址是什么,以便我可以自动重新发送确认电子邮件。 我如何得到这个?
注意 - 在这种情况下,设计已拒绝授权。 current_user是零。然而,Devise清楚地“知道”用户是谁 - 因为它能够在数据库中查找他们的记录,并检查他们是否已经超过了未经证实的电子邮件地址的宽限期。我如何访问相同的“知识”
答案 0 :(得分:1)
我认为有更好的方法可以在不创建Devise::FailureApp
的情况下实现相同的结果:
这可以通过覆盖confirmed?
module中存在的Devise资源扩展程序中的Confirmable
方法来实现。
一个简单的例子是:
delayed_confirmation_expiry_date
日期时间字段添加到您的模型表中。当用户首次注册到您的应用程序时,此字段将用于存储到期日期时间。您必须覆盖SessionsController#create
方法,因此可以调用资源上的#delay_confirmation!
方法。
User
等效模型中添加:# Will update the field you have added with the new temporary expiration access datetime
def delay_confirmation!(expiry_datetime=7.days.from_now)
self.delayed_confirmation_expiry_date = expiry_datetime
self.save
end
# Override that will make sure that, once the user is confirmed, the delayed confirmation information is cleared
def confirm(args={})
clear_delay_confirmation!
super
end
# Self-explanatory
def clear_delay_confirmation!
self.delayed_confirmation_expiry_date = nil
self.save
end
# Used on your controllers to show messages to the user warning him about the presence of the confirmation delay
def confirmation_is_delayed?
self.confirmed? && !self.confirmed_at.present?
end
# Overrides the default implementation to allow temporary access for users who haven't confirmed their accounts within the time limit
def confirmed?
if !self.confirmation_is_delayed?
super
else
self.delayed_confirmation_expiry_date >= DateTime.now.in_time_zone
end
end