res_config_settings.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. # -*- coding: utf-8 -*-
  2. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  3. import requests
  4. import json
  5. from odoo import fields, models, api, _
  6. from odoo.exceptions import UserError
  7. class ResConfigSettings(models.TransientModel):
  8. _inherit = 'res.config.settings'
  9. # Google API Configuration
  10. google_api_enabled = fields.Boolean(
  11. string='Google API Integration',
  12. config_parameter='google_api.enabled',
  13. help='Enable integration with Google Drive and Google Calendar'
  14. )
  15. # Google API Credentials (shared for all services)
  16. google_api_client_id = fields.Char(
  17. string='Google API Client ID',
  18. config_parameter='google_api.client_id',
  19. help='Client ID for Google APIs (Drive, Calendar, etc.)'
  20. )
  21. google_api_client_secret = fields.Char(
  22. string='Google API Client Secret',
  23. config_parameter='google_api.client_secret',
  24. help='Client Secret for Google APIs (Drive, Calendar, etc.)'
  25. )
  26. def action_test_google_api_connection(self):
  27. """Test Google API connection by checking if credentials are valid"""
  28. self.ensure_one()
  29. if not self.google_api_enabled:
  30. raise UserError(_('Google API Integration is not enabled'))
  31. if not self.google_api_client_id or not self.google_api_client_secret:
  32. raise UserError(_('Please provide both Client ID and Client Secret'))
  33. try:
  34. # Test 1: Verify credentials format
  35. if len(self.google_api_client_id) < 10:
  36. raise UserError(_('Client ID appears to be invalid (too short)'))
  37. if len(self.google_api_client_secret) < 10:
  38. raise UserError(_('Client Secret appears to be invalid (too short)'))
  39. # Test 2: Try to reach Google APIs (basic connectivity test)
  40. google_api_url = "https://www.googleapis.com"
  41. response = requests.get(google_api_url, timeout=10)
  42. if response.status_code not in [200, 404]: # 404 is expected for root URL
  43. raise UserError(_('Cannot reach Google APIs. Please check your internet connection.'))
  44. # Test 3: Check if Drive API is available
  45. drive_api_url = "https://www.googleapis.com/drive/v3/about"
  46. drive_response = requests.get(drive_api_url, timeout=10)
  47. # Drive API requires authentication, so 401 is expected
  48. if drive_response.status_code not in [401, 403]:
  49. raise UserError(_('Google Drive API is not accessible'))
  50. # Test 4: Check if Calendar API is available
  51. calendar_api_url = "https://www.googleapis.com/calendar/v3/users/me/calendarList"
  52. calendar_response = requests.get(calendar_api_url, timeout=10)
  53. # Calendar API requires authentication, so 401 is expected
  54. if calendar_response.status_code not in [401, 403]:
  55. raise UserError(_('Google Calendar API is not accessible'))
  56. # Test 5: Validate OAuth2 endpoints
  57. oauth_auth_url = "https://accounts.google.com/o/oauth2/auth"
  58. oauth_response = requests.get(oauth_auth_url, timeout=10)
  59. if oauth_response.status_code not in [200, 405]: # 405 Method Not Allowed is expected for GET
  60. raise UserError(_('Google OAuth2 endpoints are not accessible'))
  61. # All tests passed
  62. return {
  63. 'type': 'ir.actions.client',
  64. 'tag': 'display_notification',
  65. 'params': {
  66. 'title': _('Success'),
  67. 'message': _('Google API connection test successful! All APIs are accessible.'),
  68. 'type': 'success',
  69. 'sticky': False,
  70. }
  71. }
  72. except requests.exceptions.Timeout:
  73. raise UserError(_('Connection timeout. Please check your internet connection.'))
  74. except requests.exceptions.ConnectionError:
  75. raise UserError(_('Connection error. Please check your internet connection.'))
  76. except Exception as e:
  77. raise UserError(_('Connection test failed: %s') % str(e))
  78. def action_validate_credentials(self):
  79. """Validate that the credentials are properly formatted"""
  80. self.ensure_one()
  81. if not self.google_api_client_id:
  82. raise UserError(_('Client ID is required'))
  83. if not self.google_api_client_secret:
  84. raise UserError(_('Client Secret is required'))
  85. # Basic format validation
  86. if not self.google_api_client_id.endswith('.apps.googleusercontent.com'):
  87. raise UserError(_('Client ID should end with .apps.googleusercontent.com'))
  88. if len(self.google_api_client_secret) < 20:
  89. raise UserError(_('Client Secret appears to be too short'))
  90. return {
  91. 'type': 'ir.actions.client',
  92. 'tag': 'display_notification',
  93. 'params': {
  94. 'title': _('Success'),
  95. 'message': _('Credentials format is valid!'),
  96. 'type': 'success',
  97. 'sticky': False,
  98. }
  99. }
  100. def action_show_oauth_redirect_uris(self):
  101. """Show the redirect URIs that need to be configured in Google Cloud Console"""
  102. self.ensure_one()
  103. base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
  104. redirect_uri = f"{base_url}/web/google_oauth_callback"
  105. return {
  106. 'type': 'ir.actions.client',
  107. 'tag': 'display_notification',
  108. 'params': {
  109. 'title': _('OAuth Redirect URI'),
  110. 'message': _('Configure this redirect URI in Google Cloud Console:\n\n%s\n\nCopy this URL and add it to your OAuth 2.0 client configuration.') % redirect_uri,
  111. 'type': 'info',
  112. 'sticky': True,
  113. }
  114. }
  115. @api.model
  116. def set_values(self):
  117. super().set_values()
  118. IrConfigParameter = self.env['ir.config_parameter'].sudo()
  119. # Set our custom parameters
  120. IrConfigParameter.set_param('google_api.client_id', self.google_api_client_id or '')
  121. IrConfigParameter.set_param('google_api.client_secret', self.google_api_client_secret or '')
  122. IrConfigParameter.set_param('google_api.enabled', self.google_api_enabled)
  123. # Also set the parameters expected by google.service for compatibility
  124. if self.google_api_client_id:
  125. IrConfigParameter.set_param('google_drive_client_id', self.google_api_client_id)
  126. if self.google_api_client_secret:
  127. IrConfigParameter.set_param('google_drive_client_secret', self.google_api_client_secret)