Class: TimeOffRequests::GoogleAuthService

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

Overview

Service object: google auth service.

Class Method Summary collapse

Class Method Details

.authorize(employee) ⇒ Object



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

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)



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

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)
  if auth.google_auth_refresh_token.blank?
    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



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

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



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

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