Преглед изворни кода

Add support for Google Drive Shared Drives in Google Workspace integration

root пре 5 месеци
родитељ
комит
02ed49f17b
2 измењених фајлова са 136 додато и 16 уклоњено
  1. 42 4
      m22tc_google_workspace/models/crm_lead.py
  2. 94 12
      m22tc_google_workspace/models/res_company.py

+ 42 - 4
m22tc_google_workspace/models/crm_lead.py

@@ -2186,7 +2186,11 @@ class CrmLead(models.Model):
                 'Content-Type': 'application/json'
             }
             
-            # Test access to the specific folder
+            # Test access to the specific folder - try both regular Drive and Shared Drive endpoints
+            folder_found = False
+            folder_name = 'Unknown'
+            
+            # First, try the regular Drive API endpoint
             response = requests.get(
                 f'https://www.googleapis.com/drive/v3/files/{folder_id}?fields=id,name,mimeType',
                 headers=headers,
@@ -2197,13 +2201,42 @@ class CrmLead(models.Model):
                 folder_data = response.json()
                 if folder_data.get('mimeType') == 'application/vnd.google-apps.folder':
                     _logger.info(f"✅ Folder ID {folder_id} validated successfully in Google Drive")
-                    return True, folder_data.get('name', 'Unknown')
+                    folder_found = True
+                    folder_name = folder_data.get('name', 'Unknown')
                 else:
                     _logger.warning(f"❌ ID {folder_id} exists but is not a folder")
                     return False, "Not a folder"
             elif response.status_code == 404:
-                _logger.warning(f"❌ Folder ID {folder_id} not found in Google Drive")
-                return False, "Not found"
+                # If not found in regular Drive, try Shared Drive endpoint
+                shared_drive_response = requests.get(
+                    f'https://www.googleapis.com/drive/v3/drives/{folder_id}?fields=id,name',
+                    headers=headers,
+                    timeout=10
+                )
+                
+                if shared_drive_response.status_code == 200:
+                    shared_drive_data = shared_drive_response.json()
+                    folder_name = shared_drive_data.get('name', 'Unknown')
+                    folder_found = True
+                    
+                    # For shared drives, we also need to check if we can access files within it
+                    files_in_drive_url = f'https://www.googleapis.com/drive/v3/files?supportsAllDrives=true&includeItemsFromAllDrives=true&corpora=drive&driveId={folder_id}&pageSize=1'
+                    files_response = requests.get(files_in_drive_url, headers=headers, timeout=10)
+                    
+                    if files_response.status_code != 200:
+                        _logger.warning(f"❌ Access denied to Shared Drive {folder_id}")
+                        return False, "Access denied to Shared Drive"
+                    
+                    _logger.info(f"✅ Shared Drive ID {folder_id} validated successfully")
+                elif shared_drive_response.status_code == 403:
+                    _logger.warning(f"❌ Access denied to Shared Drive {folder_id}")
+                    return False, "Access denied to Shared Drive"
+                elif shared_drive_response.status_code == 404:
+                    _logger.warning(f"❌ Folder ID {folder_id} not found in Google Drive or Shared Drives")
+                    return False, "Not found"
+                else:
+                    _logger.warning(f"❌ Shared Drive API error: {shared_drive_response.status_code}")
+                    return False, f"Shared Drive API error: {shared_drive_response.status_code}"
             elif response.status_code == 403:
                 _logger.warning(f"❌ Access denied to folder ID {folder_id}")
                 return False, "Access denied"
@@ -2213,6 +2246,11 @@ class CrmLead(models.Model):
             else:
                 _logger.warning(f"❌ Google Drive API error: {response.status_code}")
                 return False, f"API error: {response.status_code}"
+            
+            if folder_found:
+                return True, folder_name
+            else:
+                return False, "Not found"
                 
         except requests.exceptions.Timeout:
             _logger.error(f"❌ Timeout validating folder ID {folder_id}")

+ 94 - 12
m22tc_google_workspace/models/res_company.py

@@ -81,13 +81,48 @@ class ResCompany(models.Model):
                 'Authorization': f'Bearer {access_token}',
             }
             
-            # Test access to the specific folder
+            # Test access to the specific folder - try both regular Drive and Shared Drive endpoints
+            folder_found = False
+            folder_name = 'Unknown'
+            
+            # First, try the regular Drive API endpoint
             drive_api_url = f"https://www.googleapis.com/drive/v3/files/{self.google_drive_crm_folder_id}"
             drive_response = requests.get(drive_api_url, headers=headers, timeout=10)
             
             if drive_response.status_code == 200:
                 folder_data = drive_response.json()
                 folder_name = folder_data.get('name', 'Unknown')
+                folder_found = True
+            elif drive_response.status_code == 404:
+                # If not found in regular Drive, try Shared Drive endpoint
+                shared_drive_api_url = f"https://www.googleapis.com/drive/v3/drives/{self.google_drive_crm_folder_id}"
+                shared_drive_response = requests.get(shared_drive_api_url, headers=headers, timeout=10)
+                
+                if shared_drive_response.status_code == 200:
+                    shared_drive_data = shared_drive_response.json()
+                    folder_name = shared_drive_data.get('name', 'Unknown')
+                    folder_found = True
+                    
+                    # For shared drives, we also need to check if we can access files within it
+                    files_in_drive_url = f"https://www.googleapis.com/drive/v3/files?supportsAllDrives=true&includeItemsFromAllDrives=true&corpora=drive&driveId={self.google_drive_crm_folder_id}&pageSize=1"
+                    files_response = requests.get(files_in_drive_url, headers=headers, timeout=10)
+                    
+                    if files_response.status_code != 200:
+                        raise UserError(_('Access denied to Shared Drive. Please check your permissions in the Shared Drive.'))
+                elif shared_drive_response.status_code == 403:
+                    raise UserError(_('Access denied to Shared Drive. Please check your permissions in the Shared Drive.'))
+                elif shared_drive_response.status_code == 404:
+                    raise UserError(_('Google Drive folder not found. Please verify the Folder ID is correct. This could be a regular folder or Shared Drive.'))
+                else:
+                    raise UserError(_('Shared Drive API test failed. Status: %s') % shared_drive_response.status_code)
+            elif drive_response.status_code == 403:
+                raise UserError(_('Access denied to Google Drive folder. Please check folder permissions.'))
+            elif drive_response.status_code == 401:
+                raise UserError(_('OAuth token expired or invalid. Please reconnect your Google account in Google API settings.'))
+            else:
+                raise UserError(_('Google Drive API test failed. Status: %s') % drive_response.status_code)
+            
+            if folder_found:
                 return {
                     'type': 'ir.actions.client',
                     'tag': 'display_notification',
@@ -98,14 +133,6 @@ class ResCompany(models.Model):
                         'sticky': False,
                     }
                 }
-            elif drive_response.status_code == 404:
-                raise UserError(_('Google Drive folder not found. Please verify the Folder ID is correct.'))
-            elif drive_response.status_code == 403:
-                raise UserError(_('Access denied to Google Drive folder. Please check folder permissions.'))
-            elif drive_response.status_code == 401:
-                raise UserError(_('OAuth token expired or invalid. Please reconnect your Google account in Google API settings.'))
-            else:
-                raise UserError(_('Google Drive API test failed. Status: %s') % drive_response.status_code)
             
         except requests.exceptions.Timeout:
             raise UserError(_('Connection timeout. Please check your internet connection.'))
@@ -121,7 +148,40 @@ class ResCompany(models.Model):
         if not self.google_drive_crm_folder_id:
             raise UserError(_('No Google Drive CRM folder configured'))
         
-        folder_url = f"https://drive.google.com/drive/folders/{self.google_drive_crm_folder_id}"
+        # For shared drives, the URL format is different
+        # Try to determine if it's a shared drive by checking the API
+        try:
+            import requests
+            
+            access_token = self.env['ir.config_parameter'].sudo().get_param('google_api.access_token')
+            if access_token:
+                headers = {'Authorization': f'Bearer {access_token}'}
+                
+                # First try regular folder
+                drive_api_url = f"https://www.googleapis.com/drive/v3/files/{self.google_drive_crm_folder_id}"
+                drive_response = requests.get(drive_api_url, headers=headers, timeout=5)
+                
+                if drive_response.status_code == 404:
+                    # Try shared drive
+                    shared_drive_api_url = f"https://www.googleapis.com/drive/v3/drives/{self.google_drive_crm_folder_id}"
+                    shared_drive_response = requests.get(shared_drive_api_url, headers=headers, timeout=5)
+                    
+                    if shared_drive_response.status_code == 200:
+                        # It's a shared drive
+                        folder_url = f"https://drive.google.com/drive/u/0/folders/{self.google_drive_crm_folder_id}"
+                    else:
+                        # Regular folder
+                        folder_url = f"https://drive.google.com/drive/folders/{self.google_drive_crm_folder_id}"
+                else:
+                    # Regular folder
+                    folder_url = f"https://drive.google.com/drive/folders/{self.google_drive_crm_folder_id}"
+            else:
+                # Fallback to regular folder URL
+                folder_url = f"https://drive.google.com/drive/folders/{self.google_drive_crm_folder_id}"
+                
+        except Exception:
+            # Fallback to regular folder URL
+            folder_url = f"https://drive.google.com/drive/folders/{self.google_drive_crm_folder_id}"
         
         return {
             'type': 'ir.actions.act_url',
@@ -162,6 +222,26 @@ class ResCompany(models.Model):
             if self.google_drive_crm_folder_id:
                 folder_metadata['parents'] = [self.google_drive_crm_folder_id]
             
+            # Create folder - check if parent is a shared drive and adjust accordingly
+            is_shared_drive = False
+            
+            # Check if the parent folder is a shared drive
+            if self.google_drive_crm_folder_id:
+                # Try to get parent folder info to determine if it's a shared drive
+                parent_check_url = f"https://www.googleapis.com/drive/v3/files/{self.google_drive_crm_folder_id}"
+                parent_response = requests.get(parent_check_url, headers=headers, timeout=10)
+                
+                if parent_response.status_code == 404:
+                    # Parent might be a shared drive, try shared drive endpoint
+                    shared_drive_check_url = f"https://www.googleapis.com/drive/v3/drives/{self.google_drive_crm_folder_id}"
+                    shared_drive_response = requests.get(shared_drive_check_url, headers=headers, timeout=10)
+                    
+                    if shared_drive_response.status_code == 200:
+                        is_shared_drive = True
+                        # For shared drives, we need to add specific parameters
+                        folder_metadata['supportsAllDrives'] = True
+                        folder_metadata['includeItemsFromAllDrives'] = True
+            
             # Create folder
             response = requests.post(
                 'https://www.googleapis.com/drive/v3/files',
@@ -209,11 +289,13 @@ class ResCompany(models.Model):
                 'Authorization': f'Bearer {access_token}',
             }
             
-            # List folders
+            # List folders - include both regular folders and shared drives
             params = {
                 'q': "mimeType='application/vnd.google-apps.folder' and trashed=false",
                 'fields': 'files(id,name,webViewLink)',
-                'pageSize': 10
+                'pageSize': 10,
+                'supportsAllDrives': 'true',
+                'includeItemsFromAllDrives': 'true'
             }
             
             response = requests.get(