develop #2

Merged
roberto merged 160 commits from develop into main 2026-06-12 15:27:23 +00:00
2 changed files with 33 additions and 3 deletions
Showing only changes of commit c510cbaae5 - Show all commits

View File

@@ -13,6 +13,7 @@ from __future__ import annotations
import hashlib import hashlib
import time import time
import urllib.parse
import uuid import uuid
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from typing import Literal from typing import Literal
@@ -20,6 +21,7 @@ from typing import Literal
import bcrypt import bcrypt
from cryptography.fernet import Fernet from cryptography.fernet import Fernet
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import RedirectResponse
from jose import jwt from jose import jwt
from pydantic import BaseModel from pydantic import BaseModel
from sqlalchemy import select from sqlalchemy import select
@@ -304,6 +306,31 @@ class _OAuthCallbackRequest(BaseModel):
# ── OAuth routes ────────────────────────────────────────────────────── # ── OAuth routes ──────────────────────────────────────────────────────
@router.get(
"/oauth/{provider}/web-callback",
summary="Web-facing OAuth redirect — bounces to the adiuvai:// deep link",
include_in_schema=False,
)
async def oauth_web_callback(
provider: Literal["google"],
code: str,
state: str,
) -> RedirectResponse:
"""Google redirects here after user consent.
This endpoint immediately redirects to the Electron deep-link URI so the
desktop app receives the authorization code. It is intentionally simple —
no state validation here (the Electron app + backend callback do that).
Registered in Google Cloud Console as:
http://localhost:8000/api/v1/auth/oauth/google/web-callback (dev)
https://api.adiuvai.com/api/v1/auth/oauth/google/web-callback (prod)
"""
params = urllib.parse.urlencode({"code": code, "state": state, "provider": provider})
deep_link = f"adiuvai://oauth/callback?{params}"
return RedirectResponse(url=deep_link, status_code=302)
@router.get( @router.get(
"/oauth/{provider}/authorize", "/oauth/{provider}/authorize",
response_model=_OAuthAuthorizeResponse, response_model=_OAuthAuthorizeResponse,

View File

@@ -45,9 +45,12 @@ class Settings(BaseSettings):
# Separate from GMAIL_CLIENT_ID/SECRET (which uses gmail.readonly scope). # Separate from GMAIL_CLIENT_ID/SECRET (which uses gmail.readonly scope).
GOOGLE_AUTH_CLIENT_ID: str = "" GOOGLE_AUTH_CLIENT_ID: str = ""
GOOGLE_AUTH_CLIENT_SECRET: str = "" GOOGLE_AUTH_CLIENT_SECRET: str = ""
# Deep-link URI registered in the Google Cloud Console for the desktop app. # The redirect URI registered in Google Cloud Console.
# Must match the protocol registered in forge.config.ts. # Google redirects here after consent; this backend route then bounces to
OAUTH_REDIRECT_URI: str = "adiuvai://oauth/callback" # the adiuvai:// deep link so the Electron app receives the code.
# Dev: http://localhost:8000/api/v1/auth/oauth/google/web-callback
# Prod: https://api.adiuvai.com/api/v1/auth/oauth/google/web-callback
OAUTH_REDIRECT_URI: str = "http://localhost:8000/api/v1/auth/oauth/google/web-callback"
# Fernet key (URL-safe base64, 32-byte key) for at-rest encryption of OAuth # Fernet key (URL-safe base64, 32-byte key) for at-rest encryption of OAuth
# tokens stored in cloud_agent_configs.oauth_token_encrypted. # tokens stored in cloud_agent_configs.oauth_token_encrypted.