Repository navigation
Expand file tree
/
Copy pathmain.py
More file actions
96 lines (74 loc) · 2.87 KB
/
Copy pathmain.py
File metadata and controls
96 lines (74 loc) · 2.87 KB
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import os
from typing import Optional, Annotated
import string
import random
import uvicorn
from dotenv import load_dotenv
from fastapi import FastAPI, Cookie
from fastapi.responses import RedirectResponse
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from scalekit import ScalekitClient
from scalekit import AuthorizationUrlOptions, CodeAuthenticationOptions
from starlette.exceptions import HTTPException
from starlette.responses import JSONResponse
load_dotenv()
app = FastAPI()
url = os.environ['SCALEKIT_ENV_URL']
client_id = os.environ['SCALEKIT_CLIENT_ID']
client_secret = os.environ['SCALEKIT_CLIENT_SECRET']
redirect_uri = os.environ['AUTH_REDIRECT_URI']
host = os.environ['HOST']
scale = ScalekitClient(url, client_id, client_secret)
users = {}
class WebFiles(StaticFiles):
async def get_response(self, path: str, scope):
try:
response = await super().get_response(path, scope)
return response
except HTTPException as exp:
if exp.status_code == 404:
response = await super().get_response('.', scope)
return response
raise exp
class Login(BaseModel):
connectionId: Optional[str] = None
organizationId: Optional[str] = None
email: Optional[str] = None
@app.get("/auth/me")
def auth_me(uid: Annotated[str | None, Cookie()] = None):
if not uid:
return JSONResponse(status_code=401, content={"message": "User data not found"})
user = users[uid]
if not user:
return JSONResponse(status_code=401, content={"message": "User not found"})
return user
@app.post("/auth/login")
async def auth_login(login: Login):
options = AuthorizationUrlOptions()
options.connection_id = login.connectionId
options.organization_id = login.organizationId
options.login_hint = login.email
options.state = ''.join(random.choices(string.ascii_letters, k=15)).lower()
auth_url = scale.get_authorization_url(redirect_uri=redirect_uri, options=options)
return {'url': auth_url}
@app.get("/auth/callback")
async def auth_callback(code, error_description: Optional[str] = None):
if error_description:
return JSONResponse(status_code=400, content=error_description)
options = CodeAuthenticationOptions()
result = scale.authenticate_with_code(code, redirect_uri, options=options)
user = result['user']
uid = user['id']
users[uid] = user
response = RedirectResponse(url='/profile', status_code=303)
response.set_cookie(key='uid', value=uid, httponly=False)
return response
@app.post("/auth/logout")
async def auth_logout():
response = JSONResponse(status_code=200, content='')
response.delete_cookie(key='uid', httponly=False)
return response
app.mount("/", WebFiles(directory="web/build", html=True), name="web/build")
if __name__ == "__main__":
uvicorn.run(app, host=host, port=8080)