-
-
Notifications
You must be signed in to change notification settings - Fork 86
/
session.rb
78 lines (62 loc) 路 1.6 KB
/
session.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# frozen_string_literal: true
module Passwordless
# The session responsible for holding the connection between the record
# trying to log in and the unique tokens.
class Session < ApplicationRecord
belongs_to(
:authenticatable,
polymorphic: true,
inverse_of: :passwordless_sessions
)
validates(
:authenticatable,
:timeout_at,
:expires_at,
:user_agent,
:remote_addr,
:token_digest,
presence: true
)
before_validation :set_defaults
# save the token in memory so we can put it in emails but only save the
# hashed version in the database
attr_accessor :token
scope(
:available,
lambda { where("expires_at > ?", Time.current) }
)
def self.valid
available
end
class << self
deprecate :valid, deprecator: SessionValidDeprecation
end
def expired?
expires_at <= Time.current
end
def timed_out?
timeout_at <= Time.current
end
def claim!
raise Errors::TokenAlreadyClaimedError if claimed?
touch(:claimed_at)
end
def claimed?
!!claimed_at
end
def available?
!expired?
end
private
def set_defaults
self.expires_at ||= Passwordless.expires_at.call
self.timeout_at ||= Passwordless.timeout_at.call
return if self.token || self.token_digest
self.token, self.token_digest = loop {
token = Passwordless.token_generator.call(self)
digest = Passwordless.digest(token)
break [token, digest] unless Session.find_by(token_digest: digest)
}
end
end
end