feat: dynamic login providers + profiler auto-trigger + refresh endpoint
This commit is contained in:
parent
4bad893cb8
commit
3e3f84a00e
3 changed files with 68 additions and 3 deletions
|
|
@ -96,3 +96,27 @@ async def get_metric(
|
|||
return content
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error parsing metric: {e}")
|
||||
|
||||
|
||||
@router.post("/profile/{table_name}/refresh")
|
||||
async def refresh_profile(
|
||||
table_name: str,
|
||||
user: dict = Depends(get_current_user),
|
||||
conn: duckdb.DuckDBPyConnection = Depends(_get_db),
|
||||
):
|
||||
"""Re-generate profile for a table on demand."""
|
||||
from src.profiler import profile_table, TableInfo
|
||||
|
||||
data_dir = _get_data_dir()
|
||||
extracts_dir = data_dir / "extracts"
|
||||
candidates = list(extracts_dir.rglob(f"data/{table_name}.parquet"))
|
||||
if not candidates:
|
||||
raise HTTPException(status_code=404, detail=f"No parquet for '{table_name}'")
|
||||
|
||||
try:
|
||||
table_info = TableInfo(name=table_name, table_id=table_name)
|
||||
profile = profile_table(table_info, candidates[0], [], {}, {})
|
||||
ProfileRepository(conn).save(table_name, profile)
|
||||
return {"status": "ok", "table": table_name, "columns": len(profile.get("columns", {}))}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Profile failed: {e}")
|
||||
|
|
|
|||
|
|
@ -122,6 +122,36 @@ print(json.dumps(result))
|
|||
views = orch.rebuild()
|
||||
print(f"[SYNC] Orchestrator rebuild: {{{', '.join(f'{k}: {len(v)}' for k, v in views.items())}}}", file=_sys.stderr, flush=True)
|
||||
|
||||
# Auto-profile synced tables (best-effort, don't fail sync on profile error)
|
||||
try:
|
||||
from src.profiler import profile_table, TableInfo
|
||||
from src.repositories.profiles import ProfileRepository
|
||||
|
||||
data_dir = Path(os.environ.get("DATA_DIR", "./data"))
|
||||
extracts_dir = data_dir / "extracts"
|
||||
|
||||
sys_conn = get_system_db()
|
||||
try:
|
||||
profile_repo = ProfileRepository(sys_conn)
|
||||
profiled = 0
|
||||
for source_name, table_names in views.items():
|
||||
for table_name in table_names[:10]: # Limit per sync
|
||||
pq_path = extracts_dir / source_name / "data" / f"{table_name}.parquet"
|
||||
if not pq_path.exists():
|
||||
continue
|
||||
try:
|
||||
table_info = TableInfo(name=table_name, table_id=table_name)
|
||||
profile = profile_table(table_info, pq_path, [], {}, {})
|
||||
profile_repo.save(table_name, profile)
|
||||
profiled += 1
|
||||
except Exception as pe:
|
||||
print(f"[SYNC] Profile {table_name}: {pe}", file=_sys.stderr, flush=True)
|
||||
print(f"[SYNC] Profiled {profiled} tables", file=_sys.stderr, flush=True)
|
||||
finally:
|
||||
sys_conn.close()
|
||||
except Exception as e:
|
||||
print(f"[SYNC] Profiler skipped: {e}", file=_sys.stderr, flush=True)
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
print("[SYNC] Extractor timed out after 1800s", file=_sys.stderr, flush=True)
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -151,9 +151,20 @@ async def index(request: Request, user: Optional[dict] = Depends(get_optional_us
|
|||
|
||||
@router.get("/login", response_class=HTMLResponse)
|
||||
async def login_page(request: Request):
|
||||
providers = [
|
||||
{"name": "google", "display_name": "Google", "icon": "google"},
|
||||
]
|
||||
providers = []
|
||||
try:
|
||||
from app.auth.providers.google import is_available as google_available
|
||||
if google_available():
|
||||
providers.append({"name": "google", "display_name": "Google", "icon": "google"})
|
||||
except Exception:
|
||||
pass
|
||||
providers.append({"name": "password", "display_name": "Email & Password", "icon": "key"})
|
||||
try:
|
||||
from app.auth.providers.email import is_available as email_available
|
||||
if email_available():
|
||||
providers.append({"name": "email", "display_name": "Email Link", "icon": "mail"})
|
||||
except Exception:
|
||||
pass
|
||||
ctx = _build_context(request, providers=providers)
|
||||
return templates.TemplateResponse(request, "login.html", ctx)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue