Class: Admin::DeviceAuthorization
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Admin::DeviceAuthorization
- Defined in:
- app/models/admin/device_authorization.rb
Defined Under Namespace
Classes: TokenError
Constant Summary collapse
- EXPIRES_IN =
10.minutes
Class Method Summary collapse
- .digest(device_code) ⇒ Object
- .generate_user_code ⇒ Object
- .issue!(requested_ip:, user_agent:) ⇒ Object
- .issue_access_token!(device_code:, token_expires_in: 12.hours) ⇒ Object
Instance Method Summary collapse
- #actionable? ⇒ Boolean
- #approve!(admin_user:) ⇒ Object
- #consume!(token_expires_in:) ⇒ Object
- #deny!(admin_user:) ⇒ Object
- #expired? ⇒ Boolean
- #issuable? ⇒ Boolean
- #token_error ⇒ Object
Class Method Details
.digest(device_code) ⇒ Object
47 48 49 |
# File 'app/models/admin/device_authorization.rb', line 47 def self.digest(device_code) Digest::SHA256.hexdigest(device_code) end |
.generate_user_code ⇒ Object
51 52 53 |
# File 'app/models/admin/device_authorization.rb', line 51 def self.generate_user_code "#{SecureRandom.alphanumeric(4).upcase}-#{SecureRandom.alphanumeric(4).upcase}" end |
.issue!(requested_ip:, user_agent:) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'app/models/admin/device_authorization.rb', line 33 def self.issue!(requested_ip:, user_agent:) device_code = SecureRandom.urlsafe_base64(32) = create!( device_code_digest: digest(device_code), user_code: generate_user_code, request_expires_at: EXPIRES_IN.from_now, requested_ip:, user_agent:, ) [, device_code] end |
.issue_access_token!(device_code:, token_expires_in: 12.hours) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'app/models/admin/device_authorization.rb', line 55 def self.issue_access_token!(device_code:, token_expires_in: 12.hours) = find_by(device_code_digest: digest(device_code.to_s)) raise TokenError.new("invalid_grant") unless .with_lock do .reload if (error = .token_error) raise TokenError.new(error) end access_token = .generate_token_for(:api_access) .consume!(token_expires_in:) { access_token:, token_type: "Bearer", expires_in: token_expires_in.to_i, } end end |
Instance Method Details
#actionable? ⇒ Boolean
115 116 117 |
# File 'app/models/admin/device_authorization.rb', line 115 def actionable? pending? && !expired? end |
#approve!(admin_user:) ⇒ Object
100 101 102 103 104 105 106 |
# File 'app/models/admin/device_authorization.rb', line 100 def approve!(admin_user:) update!( status: "approved", approved_at: Time.current, admin_user:, ) end |
#consume!(token_expires_in:) ⇒ Object
92 93 94 95 96 97 98 |
# File 'app/models/admin/device_authorization.rb', line 92 def consume!(token_expires_in:) update!( status: "consumed", consumed_at: Time.current, token_expires_at: token_expires_in.from_now, ) end |
#deny!(admin_user:) ⇒ Object
108 109 110 111 112 113 |
# File 'app/models/admin/device_authorization.rb', line 108 def deny!(admin_user:) update!( status: "denied", admin_user:, ) end |
#expired? ⇒ Boolean
77 78 79 |
# File 'app/models/admin/device_authorization.rb', line 77 def expired? request_expires_at <= Time.current end |
#issuable? ⇒ Boolean
81 82 83 |
# File 'app/models/admin/device_authorization.rb', line 81 def issuable? approved? && !expired? end |
#token_error ⇒ Object
85 86 87 88 89 90 |
# File 'app/models/admin/device_authorization.rb', line 85 def token_error return "authorization_pending" if pending? return "access_denied" if denied? "invalid_grant" if consumed? || expired? end |