Spaces:
Runtime error
Runtime error
| from fastapi import APIRouter, Depends, HTTPException, status, Query | |
| from sqlmodel import Session, SQLModel | |
| from typing import List, Optional, Dict | |
| from src.database import get_session | |
| from src.auth import get_current_active_user, get_api_key, require_super_admin | |
| from src.models import ( | |
| User, UserCreate, UserRead, UserUpdate, Role, | |
| Student, StudentCreate, StudentReadWithClearance, StudentUpdate, StudentRead, | |
| TagLink, RFIDTagRead, Device, DeviceCreate, DeviceRead, TagScan | |
| ) | |
| from src.crud import users as user_crud | |
| from src.crud import students as student_crud | |
| from src.crud import tag_linking as tag_crud | |
| from src.crud import devices as device_crud | |
| # Define the main administrative router | |
| router = APIRouter( | |
| prefix="/admin", | |
| tags=["Administration"], | |
| dependencies=[Depends(get_current_active_user(required_roles=[Role.ADMIN, Role.STAFF]))], | |
| ) | |
| # --- All other administrative endpoints remain the same --- | |
| # ... (Stuent Management, User Management, etc.) ... | |
| def create_student(student: StudentCreate, db: Session = Depends(get_session)): | |
| """(Admin & Staff) Creates a new student and initializes their clearance status.""" | |
| db_student = student_crud.get_student_by_matric_no(db, matric_no=student.matric_no) | |
| if db_student: | |
| raise HTTPException(status_code=400, detail="Matriculation number already registered") | |
| return student_crud.create_student(db=db, student_data=student) | |
| def read_all_students(skip: int = 0, limit: int = 100, db: Session = Depends(get_session)): | |
| """(Admin & Staff) Retrieves a list of all student records.""" | |
| return student_crud.get_all_students(db, skip=skip, limit=limit) | |
| def lookup_student( | |
| matric_no: Optional[str] = Query(None, description="Matriculation number of the student."), | |
| tag_id: Optional[str] = Query(None, description="RFID tag ID linked to the student."), | |
| db: Session = Depends(get_session) | |
| ): | |
| """(Admin & Staff) Looks up a single student by Matric Number OR Tag ID.""" | |
| if not matric_no and not tag_id: | |
| raise HTTPException(status_code=400, detail="A matric_no or tag_id must be provided.") | |
| if matric_no and tag_id: | |
| raise HTTPException(status_code=400, detail="Provide either matric_no or tag_id, not both.") | |
| db_student = None | |
| if matric_no: | |
| db_student = student_crud.get_student_by_matric_no(db, matric_no=matric_no) | |
| elif tag_id: | |
| db_student = student_crud.get_student_by_tag_id(db, tag_id=tag_id) | |
| if not db_student: | |
| raise HTTPException(status_code=404, detail="Student not found with the provided identifier.") | |
| return db_student | |
| def read_single_student(student_id: int, db: Session = Depends(get_session)): | |
| """(Admin & Staff) Retrieves a single student's complete record by their internal ID.""" | |
| db_student = student_crud.get_student_by_id(db, student_id=student_id) | |
| if not db_student: | |
| raise HTTPException(status_code=404, detail="Student not found") | |
| return db_student | |
| def update_student_details(student_id: int, student: StudentUpdate, db: Session = Depends(get_session)): | |
| """(Admin & Staff) Updates a student's information.""" | |
| updated_student = student_crud.update_student(db, student_id=student_id, student_update=student) | |
| if not updated_student: | |
| raise HTTPException(status_code=404, detail="Student not found") | |
| return updated_student | |
| # --- Tag Management (Admin + Staff) --- | |
| def link_rfid_tag(link_data: TagLink, db: Session = Depends(get_session)): | |
| """(Admin & Staff) Links an RFID tag to a student or user.""" | |
| new_tag = tag_crud.link_tag(db, link_data) | |
| if not new_tag: | |
| raise HTTPException( | |
| status_code=status.HTTP_409_CONFLICT, | |
| detail="Could not link tag. The tag may already be in use, or the user/student already has a tag." | |
| ) | |
| return new_tag | |
| def unlink_rfid_tag(tag_id: str, db: Session = Depends(get_session)): | |
| """(Admin & Staff) Unlinks an RFID tag, making it available again.""" | |
| deleted_tag = tag_crud.unlink_tag(db, tag_id) | |
| if not deleted_tag: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail="RFID Tag not found." | |
| ) | |
| return deleted_tag | |
| # --- Super Admin Only Functions --- | |
| def require_super_admin(current_user: User = Depends(get_current_active_user())): | |
| """Dependency to ensure a user has the ADMIN role.""" | |
| if current_user.role != Role.ADMIN: | |
| raise HTTPException( | |
| status_code=status.HTTP_403_FORBIDDEN, | |
| detail="This action requires Super Admin privileges." | |
| ) | |
| def create_user_as_admin(user: UserCreate, db: Session = Depends(get_session)): | |
| """(Super Admin Only) Creates a new user (admin or staff).""" | |
| if user_crud.get_user_by_username(db, username=user.username): | |
| raise HTTPException(status_code=400, detail="Username already registered.") | |
| if user_crud.get_user_by_email(db, email=user.email): | |
| raise HTTPException(status_code=400, detail="Email already registered.") | |
| return user_crud.create_user(db=db, user=user) | |
| def read_all_users(db: Session = Depends(get_session)): | |
| """(Super Admin Only) Retrieves a list of all users.""" | |
| return user_crud.get_all_users(db) | |
| def lookup_user( | |
| username: Optional[str] = Query(None, description="Username of the user."), | |
| tag_id: Optional[str] = Query(None, description="RFID tag ID linked to the user."), | |
| db: Session = Depends(get_session) | |
| ): | |
| """(Super Admin Only) Looks up a single user by Username OR Tag ID.""" | |
| if not username and not tag_id: | |
| raise HTTPException(status_code=400, detail="A username or tag_id must be provided.") | |
| if username and tag_id: | |
| raise HTTPException(status_code=400, detail="Provide either username or tag_id, not both.") | |
| db_user = None | |
| if username: | |
| db_user = user_crud.get_user_by_username(db, username=username) | |
| elif tag_id: | |
| db_user = user_crud.get_user_by_tag_id(db, tag_id=tag_id) | |
| if not db_user: | |
| raise HTTPException(status_code=404, detail="User not found with the provided identifier.") | |
| return db_user | |
| def update_user_details(user_id: int, user: UserUpdate, db: Session = Depends(get_session)): | |
| """(Super Admin Only) Updates a user's details (e.g., role).""" | |
| db_user = user_crud.get_user_by_id(db, user_id=user_id) | |
| if not db_user: | |
| raise HTTPException(status_code=404, detail="User not found") | |
| updated_user = user_crud.update_user(db, user=db_user, updates=user) | |
| if not updated_user: | |
| raise HTTPException(status_code=404, detail="User not found") | |
| return updated_user | |
| def delete_user_account(user_id: int, db: Session = Depends(get_session), current_user: User = Depends(get_current_active_user())): | |
| """(Super Admin Only) Deletes a user account.""" | |
| if current_user.id == user_id: | |
| raise HTTPException(status_code=400, detail="Cannot delete your own account.") | |
| deleted_user = user_crud.delete_user(db, user_id=user_id) | |
| if not deleted_user: | |
| raise HTTPException(status_code=404, detail="User not found") | |
| return deleted_user | |
| def delete_student_record(student_id: int, db: Session = Depends(get_session)): | |
| """(Super Admin Only) Deletes a student record and all associated data.""" | |
| deleted_student = student_crud.delete_student(db, student_id=student_id) | |
| if not deleted_student: | |
| raise HTTPException(status_code=404, detail="Student not found") | |
| return deleted_student | |
| def create_device(device: DeviceCreate, db: Session = Depends(get_session)): | |
| """(Super Admin Only) Registers a new RFID hardware device.""" | |
| db_device = device_crud.get_device_by_location(db, location=device.location) | |
| if db_device: | |
| raise HTTPException(status_code=400, detail=f"A device at location '{device.location}' already exists.") | |
| return device_crud.create_device(db=db, device=device) | |
| def read_all_devices(skip: int = 0, limit: int = 100, db: Session = Depends(get_session)): | |
| return device_crud.get_all_devices(db, skip=skip, limit=limit) | |
| def delete_device_registration(device_id: int, db: Session = Depends(get_session)): | |
| """(Super Admin Only) De-authorizes a hardware device.""" | |
| deleted_device = device_crud.delete_device(db, device_id=device_id) | |
| if not deleted_device: | |
| raise HTTPException(status_code=404, detail="Device not found") | |
| return deleted_device | |