Source code for teuthology_api.routes.login

import logging
import os
from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import RedirectResponse
from dotenv import load_dotenv
import httpx

from teuthology_api.services.helpers import isAdmin

load_dotenv()

GH_CLIENT_ID = os.getenv("GH_CLIENT_ID")
GH_CLIENT_SECRET = os.getenv("GH_CLIENT_SECRET")
GH_AUTHORIZATION_BASE_URL = os.getenv("GH_AUTHORIZATION_BASE_URL")
GH_TOKEN_URL = os.getenv("GH_TOKEN_URL")
GH_FETCH_MEMBERSHIP_URL = os.getenv("GH_FETCH_MEMBERSHIP_URL")
PULPITO_URL = os.getenv("PULPITO_URL")

log = logging.getLogger(__name__)
router = APIRouter(
    prefix="/login",
    tags=["login"],
    responses={404: {"description": "Not found"}},
)


[docs] @router.get("/", status_code=200) async def github_login(): """ GET route for /login, (If first time) will redirect to github login page where you should authorize the app to gain access. """ if not GH_AUTHORIZATION_BASE_URL or not GH_CLIENT_ID: return HTTPException(status_code=500, detail="Environment secrets are missing.") scope = "read:org" return RedirectResponse( f"{GH_AUTHORIZATION_BASE_URL}?client_id={GH_CLIENT_ID}&scope={scope}", status_code=302, )
[docs] @router.get("/callback", status_code=200) async def handle_callback(code: str, request: Request): """ Call back route after user login & authorize the app for access. """ params = { "client_id": GH_CLIENT_ID, "client_secret": GH_CLIENT_SECRET, "code": code, } headers = {"Accept": "application/json"} async with httpx.AsyncClient() as client: response_token = await client.post( url=GH_TOKEN_URL, params=params, headers=headers ) log.info(response_token.json()) response_token_dic = dict(response_token.json()) token = response_token_dic.get("access_token") if response_token_dic.get("error") or not token: log.error("The code is incorrect or expired.") raise HTTPException( status_code=401, detail="The code is incorrect or expired." ) headers = {"Authorization": "token " + token} response_org = await client.get(url=GH_FETCH_MEMBERSHIP_URL, headers=headers) log.info(response_org.json()) if response_org.status_code == 404: log.error("User is not part of the Ceph Organization") raise HTTPException( status_code=404, detail="User is not part of the Ceph Organization, please contact <admin>", ) if response_org.status_code == 403: log.error("The application doesn't have permission to view github org") raise HTTPException( status_code=403, detail="The application doesn't have permission to view github org", ) response_org_dic = dict(response_org.json()) data = { "id": response_org_dic.get("user", {}).get("id"), "username": response_org_dic.get("user", {}).get("login"), "avatar_url": response_org_dic.get("user", {}).get("avatar_url"), "state": response_org_dic.get("state"), "role": response_org_dic.get("role"), "access_token": token, } request.session["user"] = data isUserAdmin = await isAdmin(data["username"], data["access_token"]) data["isUserAdmin"] = isUserAdmin cookie_data = { "username": data["username"], "avatar_url": response_org_dic.get("user", {}).get("avatar_url"), "isUserAdmin": isUserAdmin, } cookie = "; ".join( [f"{str(key)}={str(value)}" for key, value in cookie_data.items()] ) response = RedirectResponse(PULPITO_URL) response.set_cookie(key="GH_USER", value=cookie) return response