"""Invite page and form submit.""" import logging import re from urllib.parse import unquote from fastapi import APIRouter, Depends, Form, Request from fastapi.responses import HTMLResponse, JSONResponse from sqlmodel import Session, and_, select from app.core.db import get_session from app.managers.team import get_team_by_name, get_invite_link_for_team from app.models import LinkClicked, UserInvite router = APIRouter() logger = logging.getLogger(__name__) EMAIL_REGEX = re.compile(r"^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$") _REF_VALID = re.compile(r'^[A-Za-z0-9\-_/.]{1,200}$') def _validate_ref(ref: str) -> str: """Return ref if it only contains allowed chars, otherwise 'illegal'.""" return ref if _REF_VALID.match(ref) else "illegal" def _client_ip(request: Request) -> str: forwarded = request.headers.get("X-Forwarded-For") if forwarded: return forwarded.split(",")[0].strip() return request.client.host if request.client else "unknown" @router.get("/invite", response_class=HTMLResponse) def invite_get( request: Request, team: str = "tidb-community", ref: str = "direct", session: Session = Depends(get_session), ): ref = _validate_ref(ref) if ref == "illegal": logger.warning("Illegal referrer from IP %s ref=%r", _client_ip(request), request.query_params.get("ref", "")) team_obj = get_team_by_name(session, team) if not team_obj: return HTMLResponse(content=f"Team not found: {team}", status_code=503) invite_url = get_invite_link_for_team(session, team) try: session.add(LinkClicked(referrer=ref)) session.commit() except Exception: session.rollback() templates = request.app.state.templates return templates.TemplateResponse( request, "index.html", {"invite_url": invite_url, "team_domain": team_obj.team_domain}, ) from app.managers.slack import lookup_user_by_email @router.post("/invite", response_class=JSONResponse) def invite_post( request: Request, email: str = Form(...), channel: str = Form(...), team: str = Form(...), ref: str = Form("direct"), session: Session = Depends(get_session), ): email = unquote(email) ref = _validate_ref(ref) if ref == "illegal": logger.warning("Illegal referrer from IP %s ref=%r", _client_ip(request), request.query_params.get("ref", "")) team_obj = get_team_by_name(session, team) if not team_obj: return JSONResponse({"ok": False, "error": "team_not_found"}, status_code=503) in_workspace = False if team_obj.team_token: try: res = lookup_user_by_email(team_obj.team_token, email) if res.get("ok"): in_workspace = True except Exception: pass if EMAIL_REGEX.search(email): try: stmt = select(UserInvite).where( and_( UserInvite.email == email, UserInvite.channel == channel, UserInvite.team == team, ) ) existing = session.exec(stmt).first() if not existing: session.add( UserInvite( email=email, referrer=ref, channel=channel, team=team, ) ) session.commit() except Exception: session.rollback() return JSONResponse({"ok": True, "in_workspace": in_workspace})