Skip to content

Commit aff5d3c

Browse files
author
Rafael Teodoro
committed
Fix TUI: Service Account now accepts JSON file upload
Changed service account authentication to accept JSON file upload instead of just email, matching OAuth credentials flow. Changes: - 🔑 Service Account now requires JSON file (not just email) - 📂 Added 'Use Default SA Path' button (backend/service-account.json) - 📄 Shows examples and current directory - 🏠 Supports ~ expansion for home directory - ❌ Better error messages with full path Two authentication methods now available: 1. OAuth Credentials JSON (credentials.json) - Contains client_id, client_secret - For user-based OAuth flow 2. Service Account JSON (service-account.json) - Contains private_key, client_email - For service account authentication Both methods now have: - Default path buttons - Path examples - Full path error messages - Home directory expansion
1 parent 36d239d commit aff5d3c

File tree

1 file changed

+52
-4
lines changed

1 file changed

+52
-4
lines changed

tui.py

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,15 @@ def compose(self) -> ComposeResult:
218218
yield Button("Use Default Path", id="use-default-btn", variant="default")
219219

220220
with Vertical(classes="section"):
221-
yield Label("🔑 Or use Service Account:")
221+
yield Label("🔑 Or use Service Account JSON:")
222+
yield Label("Service account JSON file with private_key", classes="subtitle")
222223
yield Input(
223-
placeholder="Service account email...",
224-
id="service-account"
224+
placeholder="Path to service-account.json file...",
225+
id="service-account-path"
225226
)
226-
yield Button("Authenticate", id="auth-service-btn", variant="primary")
227+
with Horizontal():
228+
yield Button("Upload Service Account", id="auth-service-btn", variant="primary")
229+
yield Button("Use Default SA Path", id="use-default-sa-btn", variant="default")
227230

228231
yield Label("", id="auth-status")
229232
yield Button("Skip (for testing)", id="skip-btn", variant="default")
@@ -273,6 +276,51 @@ async def upload_json_credentials(self):
273276
except Exception as e:
274277
status.update(f"❌ Error: {str(e)}")
275278

279+
@on(Button.Pressed, "#use-default-sa-btn")
280+
def use_default_sa_path(self):
281+
"""Fill input with default service account path"""
282+
path_input = self.query_one("#service-account-path", Input)
283+
path_input.value = "backend/service-account.json"
284+
self.notify("Default SA path filled! Press 'Upload Service Account' to continue.")
285+
286+
@on(Button.Pressed, "#auth-service-btn")
287+
async def upload_service_account(self):
288+
"""Upload service account JSON file"""
289+
import os
290+
status = self.query_one("#auth-status", Label)
291+
path_input = self.query_one("#service-account-path", Input)
292+
293+
# Expand ~ to home directory
294+
path_str = os.path.expanduser(path_input.value.strip())
295+
path = Path(path_str)
296+
297+
if not path.exists():
298+
# Show helpful error with full path attempted
299+
abs_path = path.resolve()
300+
status.update(f"❌ File not found: {abs_path}")
301+
return
302+
303+
try:
304+
status.update("⏳ Uploading service account...")
305+
306+
with open(path, "rb") as f:
307+
files = {"file": (path.name, f, "application/json")}
308+
result = await self.app.api_client.post("/api/auth/service-account", files=files)
309+
310+
if result.get("success"):
311+
# Set auth token if provided
312+
if "token" in result:
313+
self.app.api_client.set_auth_token(result["token"])
314+
315+
status.update("✅ Service account authentication successful!")
316+
await asyncio.sleep(1)
317+
self.app.push_screen(MainMenuScreen())
318+
else:
319+
status.update(f"❌ {result.get('message', 'Authentication failed')}")
320+
321+
except Exception as e:
322+
status.update(f"❌ Error: {str(e)}")
323+
276324
@on(Button.Pressed, "#skip-btn")
277325
def skip_auth(self):
278326
"""Skip authentication for testing"""

0 commit comments

Comments
 (0)