-
Notifications
You must be signed in to change notification settings - Fork 59
/
token_issuer.rb
79 lines (65 loc) · 2.22 KB
/
token_issuer.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
79
require 'tiddle/model_name'
module Tiddle
class TokenIssuer
MAXIMUM_TOKENS_PER_USER = 20
def self.build
new(MAXIMUM_TOKENS_PER_USER)
end
def initialize(maximum_tokens_per_user)
self.maximum_tokens_per_user = maximum_tokens_per_user
end
def create_and_return_token(resource, request, expires_in: nil, metadata: {})
token_class = authentication_token_class(resource)
token, token_body = Devise.token_generator.generate(token_class, :body)
resource.authentication_tokens.create!(
token_attributes(
token_body: token_body,
request: request,
expires_in: expires_in,
metadata: metadata
)
)
token
end
def expire_token(resource, request)
find_token(resource, request.headers["X-#{ModelName.new.with_dashes(resource)}-TOKEN"])
.try(:destroy)
end
def find_token(resource, token_from_headers)
token_class = authentication_token_class(resource)
token_body = Devise.token_generator.digest(token_class, :body, token_from_headers)
# 'find_by' behaves differently in AR vs Mongoid, so using 'where' instead
resource.authentication_tokens.where(body: token_body).first
end
def purge_old_tokens(resource)
resource.authentication_tokens
.order(last_used_at: :desc)
.offset(maximum_tokens_per_user)
.destroy_all
end
private
attr_accessor :maximum_tokens_per_user
def authentication_token_class(resource)
if resource.respond_to?(:association) # ActiveRecord
resource.association(:authentication_tokens).klass
elsif resource.respond_to?(:relations) # Mongoid
resource.relations['authentication_tokens'].klass
else
raise 'Cannot determine authentication token class, unsupported ORM/ODM?'
end
end
def token_attributes(token_body:, request:, expires_in:, metadata: {})
attributes = {
body: token_body,
last_used_at: Time.current,
ip_address: request.remote_ip,
user_agent: request.user_agent
}.merge(metadata)
if expires_in
attributes.merge(expires_in: expires_in)
else
attributes
end
end
end
end