Spaces:
Runtime error
Runtime error
File size: 4,883 Bytes
70dc852 9d8829a 5735639 a09ee49 9d8829a 93cf1dc 9d8829a 5735639 93cf1dc 5735639 9d8829a 93cf1dc 9d8829a 93cf1dc 73d94a0 93cf1dc 9d8829a 93cf1dc 9d8829a a09ee49 5735639 9d8829a 5d7f61c 5735639 9d8829a 5d7f61c 5735639 9d8829a 5735639 9d8829a 5735639 a09ee49 5735639 a09ee49 5735639 a09ee49 5735639 a09ee49 5735639 9d8829a 5735639 a09ee49 5735639 a09ee49 5735639 9d8829a 5735639 9d8829a 5735639 a09ee49 5735639 a09ee49 5735639 |
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from datetime import datetime
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
from contextlib import asynccontextmanager
import os
from fastapi import FastAPI
from sqlmodel import Session
from starlette.middleware.cors import CORSMiddleware
# Correctly import the database table creation function
from src.database import create_db_and_tables, engine
# Import all the necessary routers for the application
from src.routers import students, devices, clearance, token, users, admin
from src.crud import users as user_crud
from src.models import UserCreate, Role
@asynccontextmanager
async def lifespan(app: FastAPI):
# On startup
print("Starting up...")
create_db_and_tables()
# --- Create first superuser ---
# This runs only on startup. It checks if an admin exists and creates one if not.
# It's best practice to get credentials from environment variables for security.
with Session(engine) as session:
initial_username = os.getenv("INITIAL_ADMIN_USERNAME", "admin")
# Check if the user already exists
user = user_crud.get_user_by_username(session, username=initial_username)
if not user:
print("Initial admin user not found, creating one...")
initial_user = UserCreate(
username=initial_username,
email=os.getenv("INITIAL_ADMIN_EMAIL", "[email protected]"),
full_name="Initial Admin",
password=os.getenv("INITIAL_ADMIN_PASSWORD", "changethispassword"),
role=Role.ADMIN
)
user_crud.create_user(db=session, user=initial_user)
print("Initial admin user created successfully.")
else:
print("Initial admin user already exists.")
yield
# On shutdown
print("Shutting down...")
# Initialize the FastAPI application instance with metadata for documentation
app = FastAPI(
title="Undergraduate Clearance System API",
description="""
A comprehensive API for managing student clearance processes with RFID authentication.
## Features
* **RFID Authentication**: Students and staff use RFID tags for quick access.
* **Multi-Department Clearance**: Support for Library, Bursary, Alumni, and Departmental clearances.
* **Device Management**: Secure management of ESP32 RFID readers via API keys.
* **Role-Based Access Control**: Differentiated permissions for Students, Staff, and Administrators.
* **Real-Time Tracking**: Live updates on clearance status with comprehensive logging.
## Authentication Methods
* **JWT Tokens**: For web interfaces and administrative API access.
* **RFID Tags**: For quick, on-premise authentication of students and staff.
* **Device API Keys**: For secure communication with hardware like ESP32 RFID readers.
""",
version="2.0.1",
lifespan=lifespan,
docs_url="/docs",
redoc_url="/redoc",
openapi_url="/openapi.json",
)
# Configure CORS (Cross-Origin Resource Sharing) middleware
# This allows the frontend (like the Streamlit app) to communicate with the API
app.add_middleware(
CORSMiddleware,
allow_origins=['*'], # Allows all origins, consider restricting in production
allow_credentials=True,
allow_methods=["*"], # Allows all HTTP methods
allow_headers=["*"], # Allows all headers
)
# Include all the API routers into the main application
# Each router handles a specific domain of the application (e.g., students, devices)
print("Including API routers...")
app.include_router(admin.router)
app.include_router(clearance.router)
app.include_router(devices.router)
app.include_router(students.router)
app.include_router(token.router)
app.include_router(users.router)
print("All API routers included.")
# --- Default and System Endpoints ---
@app.get("/", summary="Root Endpoint", tags=["System"])
async def read_root():
"""
A simple root endpoint to confirm that the API is running and accessible.
"""
return {"message": "Welcome to the Undergraduate Clearance System API. See /docs for details."}
@app.get("/health", summary="Health Check", tags=["System"])
async def health_check():
"""
Provides a health status check for the API, useful for monitoring and uptime checks.
"""
health_status = {
"status": "healthy",
"timestamp": datetime.utcnow().isoformat(),
"version": app.version,
}
return JSONResponse(status_code=200, content=health_status)
# This block allows the script to be run directly using `python main.py`
# It will start the Uvicorn server, which is ideal for development.
if __name__ == "__main__":
print("Starting Uvicorn server for development...")
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
|