File size: 2,203 Bytes
a980424
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from __future__ import annotations

import time
from typing import List, Optional

from fastapi import APIRouter, HTTPException, Query

from app.models.schemas import GoogleScopeMapResponse
from app.services.google_scope_map import CATEGORY_ORDER, SCOPE_MAP

router = APIRouter()


@router.get(
    "/map",
    response_model=GoogleScopeMapResponse,
    summary="Friendly Google OAuth scope alias map (grouped by API category)",
)
async def get_scope_map(
    category: Optional[str] = Query(None, description="Return a single category only (e.g. gmail)"),
    search: Optional[str] = Query(None, description="Free-text search across aliases and scope URIs"),
) -> GoogleScopeMapResponse:
    """Return the friendly scope alias -> full URI mapping.

    Clients can read this map to pick short aliases (e.g. ``gmail_full``,
    ``sheets_readonly``) and then pass them as a list in
    ``POST /google/oauth/auth-url`` instead of pasting long scope URLs.
    """
    started = time.perf_counter()

    def _matches(alias: str, uri: str, needle: Optional[str]) -> bool:
        if not needle:
            return True
        needle_l = needle.lower()
        return needle_l in alias.lower() or needle_l in uri.lower()

    if category:
        if category not in SCOPE_MAP:
            valid = ", ".join(CATEGORY_ORDER)
            raise HTTPException(
                status_code=404,
                detail=f"Unknown category '{category}'. Valid categories: {valid}",
            )
        selected: dict = {category: SCOPE_MAP[category]}
    else:
        selected = dict(SCOPE_MAP)

    if search:
        selected = {
            cat: {
                alias: uri
                for alias, uri in entries.items()
                if _matches(alias, uri, search)
            }
            for cat, entries in selected.items()
            if any(_matches(a, u, search) for a, u in entries.items())
        }

    total_aliases = sum(len(entries) for entries in selected.values())
    return GoogleScopeMapResponse(
        success=True,
        time_ms=round((time.perf_counter() - started) * 1000, 3),
        count=total_aliases,
        categories=list(selected.keys()),
        map=selected,
    )