Files
sure/app/models/mobile_device.rb
Juan José Mata bdfb0e64bc Add 'web' to valid device types
Flutter comes in as `web` when testing / using the Chrome profile

Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
2026-01-29 13:12:05 +01:00

63 lines
1.7 KiB
Ruby

class MobileDevice < ApplicationRecord
include Encryptable
# Encrypt device_id if ActiveRecord encryption is configured
if encryption_ready?
encrypts :device_id, deterministic: true
end
belongs_to :user
belongs_to :oauth_application, class_name: "Doorkeeper::Application", optional: true
validates :device_id, presence: true, uniqueness: { scope: :user_id }
validates :device_name, presence: true
validates :device_type, presence: true, inclusion: { in: %w[ios android web] }
before_validation :set_last_seen_at, on: :create
scope :active, -> { where("last_seen_at > ?", 90.days.ago) }
def active?
last_seen_at > 90.days.ago
end
def update_last_seen!
update_column(:last_seen_at, Time.current)
end
def create_oauth_application!
return oauth_application if oauth_application.present?
app = Doorkeeper::Application.create!(
name: "Mobile App - #{device_id}",
redirect_uri: "sureapp://oauth/callback", # Custom scheme for mobile
scopes: "read_write", # Use the configured scope
confidential: false # Public client for mobile
)
# Store the association
update!(oauth_application: app)
app
end
def active_tokens
return Doorkeeper::AccessToken.none unless oauth_application
Doorkeeper::AccessToken
.where(application: oauth_application)
.where(resource_owner_id: user_id)
.where(revoked_at: nil)
.where("expires_in IS NULL OR created_at + expires_in * interval '1 second' > ?", Time.current)
end
def revoke_all_tokens!
active_tokens.update_all(revoked_at: Time.current)
end
private
def set_last_seen_at
self.last_seen_at ||= Time.current
end
end