-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.py
More file actions
153 lines (121 loc) · 4.82 KB
/
auth.py
File metadata and controls
153 lines (121 loc) · 4.82 KB
1
2
3
4
5
6
7
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""
Google API Authentication Module
Handles OAuth authentication for Google Docs and Drive APIs
"""
from pathlib import Path
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
# Scopes required for creating and managing documents
SCOPES = [
'https://www.googleapis.com/auth/documents',
'https://www.googleapis.com/auth/drive' # Full Drive access to find folders and create docs
]
CREDENTIALS_FILE = Path(__file__).parent / 'credentials.json'
TOKEN_FILE = Path(__file__).parent / 'token.json'
# Cached credentials (loaded/refreshed once, reused for all service builds)
_cached_credentials = None
def get_credentials():
"""
Load or create OAuth credentials with automatic refresh.
Credentials are cached after the first successful load so that
concurrent service builds reuse the same token without re-reading
disk or re-running the OAuth flow.
Returns:
google.oauth2.credentials.Credentials: Authenticated credentials
Raises:
FileNotFoundError: If credentials.json is not found
ValueError: If the credentials file is invalid
"""
global _cached_credentials
if _cached_credentials and _cached_credentials.valid:
return _cached_credentials
if not CREDENTIALS_FILE.exists():
raise FileNotFoundError(
f"OAuth credentials file not found: {CREDENTIALS_FILE}\n"
"Please download credentials.json from Google Cloud Console:\n"
"1. Go to APIs & Services > Credentials\n"
"2. Create OAuth Client ID (Desktop app)\n"
"3. Download JSON and save as credentials.json"
)
creds = None
# Load existing token if available
if TOKEN_FILE.exists():
try:
creds = Credentials.from_authorized_user_file(str(TOKEN_FILE), SCOPES)
except Exception as e:
print(f"Warning: Could not load token.json: {e}")
creds = None
# Refresh or create new credentials
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
# Refresh expired token
try:
creds.refresh(Request())
except Exception as e:
print(f"Token refresh failed: {e}. Re-authenticating...")
creds = None
if not creds:
# Run OAuth flow (opens browser)
try:
flow = InstalledAppFlow.from_client_secrets_file(
str(CREDENTIALS_FILE), SCOPES
)
creds = flow.run_local_server(port=0)
except Exception as e:
raise ValueError(f"OAuth authentication failed: {e}")
# Save credentials for future use
TOKEN_FILE.write_text(creds.to_json(), encoding='utf-8')
_cached_credentials = creds
return creds
def get_docs_service():
"""
Create an authenticated Google Docs API service client
Returns:
googleapiclient.discovery.Resource: Google Docs API service
"""
credentials = get_credentials()
return build('docs', 'v1', credentials=credentials)
def get_drive_service():
"""
Create an authenticated Google Drive API service client
Returns:
googleapiclient.discovery.Resource: Google Drive API service
"""
credentials = get_credentials()
return build('drive', 'v3', credentials=credentials)
def find_folder_id(folder_name='Resources', drive_service=None):
"""
Find the Google Drive folder ID by name
Args:
folder_name: Name of the folder to find (default: 'Resources')
drive_service: Optional pre-built Drive service (avoids recreating)
Returns:
str: The folder ID
Raises:
RuntimeError: If folder is not found or not accessible
"""
try:
if drive_service is None:
drive_service = get_drive_service()
# Search in user's Drive (no need for 'corpora' with OAuth - you own the files)
query = f"name='{folder_name}' and mimeType='application/vnd.google-apps.folder' and trashed=false"
results = drive_service.files().list(
q=query,
fields='files(id, name)',
pageSize=10
).execute()
files = results.get('files', [])
if not files:
raise RuntimeError(
f"Folder '{folder_name}' not found in your Google Drive.\n"
f"Please ensure the folder exists in your Drive."
)
if len(files) > 1:
print(f"Warning: Multiple folders named '{folder_name}' found. Using the first one.")
return files[0]['id']
except Exception as e:
if isinstance(e, RuntimeError):
raise
raise RuntimeError(f"Error accessing Google Drive: {e}")