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
41 42 43 |
# File 'app/models/admin/device_authorization.rb', line 41 def self.digest(device_code) Digest::SHA256.hexdigest(device_code) end |
.generate_user_code ⇒ Object
45 46 47 |
# File 'app/models/admin/device_authorization.rb', line 45 def self.generate_user_code "#{SecureRandom.alphanumeric(4).upcase}-#{SecureRandom.alphanumeric(4).upcase}" end |
.issue!(requested_ip:, user_agent:) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'app/models/admin/device_authorization.rb', line 27 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
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'app/models/admin/device_authorization.rb', line 49 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 = .admin_user.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
109 110 111 |
# File 'app/models/admin/device_authorization.rb', line 109 def actionable? pending? && !expired? end |
#approve!(admin_user:) ⇒ Object
94 95 96 97 98 99 100 |
# File 'app/models/admin/device_authorization.rb', line 94 def approve!(admin_user:) update!( status: "approved", approved_at: Time.current, admin_user:, ) end |
#consume!(token_expires_in:) ⇒ Object
86 87 88 89 90 91 92 |
# File 'app/models/admin/device_authorization.rb', line 86 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
102 103 104 105 106 107 |
# File 'app/models/admin/device_authorization.rb', line 102 def deny!(admin_user:) update!( status: "denied", admin_user:, ) end |
#expired? ⇒ Boolean
71 72 73 |
# File 'app/models/admin/device_authorization.rb', line 71 def expired? request_expires_at <= Time.current end |
#issuable? ⇒ Boolean
75 76 77 |
# File 'app/models/admin/device_authorization.rb', line 75 def issuable? approved? && !expired? end |
#token_error ⇒ Object
79 80 81 82 83 84 |
# File 'app/models/admin/device_authorization.rb', line 79 def token_error return "authorization_pending" if pending? return "access_denied" if denied? "invalid_grant" if consumed? || expired? end |