controlpanel-old/backend/main.py

132 lines
3.4 KiB
Python

from typing import *
import os.path
import uuid
from fastapi import FastAPI, Request, Response, WebSocket, WebSocketDisconnect
from fastapi.responses import PlainTextResponse
from pydantic import BaseModel
from settings import settings
import auth
from state import StateManager
from proto import Computer, ComputerToken, ComputerType
app = FastAPI()
state_manager = StateManager()
@app.get("/api/{token}/validate", tags=["frontend"])
async def validate_token(token: str):
return {"success": auth.validate_frontend(token) is not None}
@app.websocket("/api/{token}/state")
async def state_updates_websocket(websocket: WebSocket, token: str):
if not auth.validate_frontend(token):
await websocket.close()
return
await websocket.accept()
await state_manager.on_connect(websocket)
try:
while True:
await websocket.receive_json()
except WebSocketDisconnect:
await state_manager.on_disconnect(websocket)
@app.get("/install", tags=["computer"], response_class=PlainTextResponse)
async def serve_install_script():
deploy_url = (
f'{"https" if settings.deploy_tls else "http"}://{settings.delpoy_path}'
)
return f"""
shell.run("wget {os.path.join(deploy_url, "lua/json.lua")}")
shell.run("wget {os.path.join(deploy_url, "lua/framebuffer.lua")}")
"""
class RegistrationRequest(BaseModel):
type: ComputerType
is_advanced: bool
label: Optional[str]
class RegistrationResponse(BaseModel):
token: str
@app.post("/computer/register", tags=["computer"], response_model=RegistrationResponse)
async def issue_new_token(data: RegistrationRequest):
computer = Computer(
uuid=uuid.uuid4(),
group="default",
**data.dict(),
)
await state_manager.on_computer_register(computer)
return {"token": auth.encode({"type": "computer", "uuid": str(computer.uuid)})}
@app.websocket("/computer/{token}/socket")
async def computer_websocket(websocket: WebSocket, token: str):
token = auth.validate_computer(token)
if not token:
await websocket.close()
return
await websocket.accept()
await state_manager.on_computer_connect(token.uuid)
try:
while True:
await websocket.receive_json()
except WebSocketDisconnect:
await state_manager.on_computer_disconnect(token.uuid)
if settings.dev_mode:
print("Starting in development mode.")
print(f"Proxying requests to npm server on localhost:{settings.dev_npm_port}")
import httpx
@app.get("/{path:path}", tags=["dev mode please ignore"])
async def dev_mode_proxy(path: str, response: Response):
async with httpx.AsyncClient() as proxy:
proxy_response = await proxy.get(
f"http://localhost:{settings.dev_npm_port}/{path}"
)
response.body = proxy_response.content
response.status_code = proxy_response.status_code
return response
else:
print("Starting in production mode")
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
@app.middleware("http")
async def index_catch_all(request: Request, call_next):
response = await call_next(request)
if response.status_code == 404:
return FileResponse(f"{settings.frontend_path}/index.html")
return response
app.mount("/", StaticFiles(directory=settings.frontend_path))