Class: TimeOffRequests::GoogleAuthService

Inherits:
Object
  • Object
show all
Defined in:
app/services/time_off_requests/google_auth_service.rb

Class Method Summary collapse

Class Method Details

.authorize(employee) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'app/services/time_off_requests/google_auth_service.rb', line 55

def self.authorize(employee)
  auth = employee.&.authentications&.google_auth&.first
  return unless auth

  client = Signet::OAuth2::Client.new(
    client_id: Heatwave::Configuration.fetch(:omniauth, :google_oauth2_id),
    client_secret: Heatwave::Configuration.fetch(:omniauth, :google_oauth2_secret),
    access_token: auth.google_auth_access_token,
    refresh_token: auth.google_auth_refresh_token,
    token_credential_uri: 'https://oauth2.googleapis.com/token'
  )

  # Refresh token if expired - return nil if refresh fails
  if client.expired?
    refreshed_client = refresh_token(employee, client)
    return nil unless refreshed_client
  end

  client
end

.check_status(employee, skip_api_check: false) ⇒ Object

Check if employee has valid Google Calendar authorization
Returns a hash with :connected (boolean) and :needs_reconnect (boolean)

Parameters:

  • employee (Employee)

    the employee to check

  • skip_api_check (Boolean) (defaults to: false)

    if true, only use cached status (fast but may be stale)



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
# File 'app/services/time_off_requests/google_auth_service.rb', line 8

def self.check_status(employee, skip_api_check: false)
  return { connected: false, needs_reconnect: false, message: 'No account linked' } unless employee&.

  auth = employee..authentications.google_auth&.first
  return { connected: false, needs_reconnect: false, message: 'Google account not connected' } unless auth

  # Check if we have refresh token (required for calendar access)
  unless auth.google_auth_refresh_token.present?
    update_cached_status(auth, 'needs_reconnect')
    return { connected: false, needs_reconnect: true, message: 'Google account needs to be reconnected' }
  end

  # If skip_api_check, use cached status if available and recent (within 24 hours)
  if skip_api_check && auth.respond_to?(:google_calendar_status) &&
     auth.google_calendar_status.present? && auth.google_calendar_status_checked_at&.>(24.hours.ago)
    case auth.google_calendar_status
    when 'connected'
      return { connected: true, needs_reconnect: false, message: 'Connected' }
    when 'needs_reconnect'
      return { connected: false, needs_reconnect: true, message: 'Google authorization expired - please reconnect' }
    end
  end

  # Actually try to refresh the token to verify it works
  # This is the only reliable way to know if the credentials are still valid
  refreshed_client = refresh_token(employee)
  if refreshed_client
    update_cached_status(auth, 'connected')
    { connected: true, needs_reconnect: false, message: 'Connected' }
  else
    update_cached_status(auth, 'needs_reconnect')
    { connected: false, needs_reconnect: true, message: 'Google authorization expired - please reconnect' }
  end
end

.refresh_token(employee, client = nil) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'app/services/time_off_requests/google_auth_service.rb', line 76

def self.refresh_token(employee, client = nil)
  auth = employee..authentications.google_auth&.first
  return unless auth

  client ||= Signet::OAuth2::Client.new(
    client_id: Heatwave::Configuration.fetch(:omniauth, :google_oauth2_id),
    client_secret: Heatwave::Configuration.fetch(:omniauth, :google_oauth2_secret),
    refresh_token: auth.google_auth_refresh_token,
    token_credential_uri: 'https://oauth2.googleapis.com/token'
  )

  begin
    client.refresh!
    auth.update!(google_auth_access_token: client.access_token)
    Rails.logger.info("Google OAuth token refreshed successfully for #{employee.email}")
    client
  rescue StandardError => e
    Rails.logger.error("Failed to refresh Google OAuth token: #{e.message}")
    nil
  end
end

.update_cached_status(auth, status) ⇒ Object

Update the cached Google Calendar status on the authentication record



44
45
46
47
48
49
50
51
52
53
# File 'app/services/time_off_requests/google_auth_service.rb', line 44

def self.update_cached_status(auth, status)
  return unless auth.respond_to?(:google_calendar_status)

  auth.update_columns(
    google_calendar_status: status,
    google_calendar_status_checked_at: Time.current
  )
rescue StandardError => e
  Rails.logger.error("Failed to update cached Google Calendar status: #{e.message}")
end