Testys commited on
Commit
2ea4a10
·
1 Parent(s): 60dc045

Fixed issue push

Browse files
src/crud/__init__.py CHANGED
@@ -23,6 +23,7 @@ from .users import (
23
  get_user_by_id,
24
  delete_user,
25
  hash_password, # Import hash_password from users module
 
26
  )
27
  from .devices import (
28
  get_device_by_id_str,
@@ -35,11 +36,14 @@ from .clearance import (
35
  get_clearance_statuses_by_student_id,
36
  update_clearance_status,
37
  delete_clearance_status,
 
 
38
  )
39
  from .tag_linking import (
40
  create_pending_tag_link,
41
- get_pending_link_by_device,
42
- delete_pending_link,
 
43
  )
44
 
45
  # Export all functions
@@ -52,6 +56,7 @@ __all__ = [
52
  'get_user_by_id',
53
  'delete_user',
54
  'hash_password',
 
55
  # Students
56
  'create_student',
57
  'get_all_students',
@@ -71,6 +76,8 @@ __all__ = [
71
  'delete_clearance_status',
72
  # Tag Linking
73
  'create_pending_tag_link',
74
- 'get_pending_link_by_device',
75
- 'delete_pending_link',
 
 
76
  ]
 
23
  get_user_by_id,
24
  delete_user,
25
  hash_password, # Import hash_password from users module
26
+ get_all_users
27
  )
28
  from .devices import (
29
  get_device_by_id_str,
 
36
  get_clearance_statuses_by_student_id,
37
  update_clearance_status,
38
  delete_clearance_status,
39
+ get_all_clearance_status,
40
+ get_student_clearance_status
41
  )
42
  from .tag_linking import (
43
  create_pending_tag_link,
44
+ get_pending_link_by_id,
45
+ delete_pending_link_by_device_id,
46
+ get_pending_links,
47
  )
48
 
49
  # Export all functions
 
56
  'get_user_by_id',
57
  'delete_user',
58
  'hash_password',
59
+ 'get_all_users',
60
  # Students
61
  'create_student',
62
  'get_all_students',
 
76
  'delete_clearance_status',
77
  # Tag Linking
78
  'create_pending_tag_link',
79
+ 'get_pending_link_by_device_id',
80
+ 'get_pending_link_by_token',
81
+ 'delete_pending_link_by_id',
82
+ 'get_all_pending_links',
83
  ]
src/crud/clearance.py CHANGED
@@ -75,3 +75,28 @@ def delete_clearance_status(
75
  db.commit()
76
 
77
  return status_to_delete
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  db.commit()
76
 
77
  return status_to_delete
78
+
79
+
80
+ def get_all_clearance_status(db: Session) -> list[models.ClearanceStatus]:
81
+ """
82
+ Retrieves all clearance statuses from the database.
83
+
84
+ This function is useful for administrative purposes, allowing staff to view
85
+ all clearance records across all students and departments.
86
+ """
87
+ return db.query(models.ClearanceStatus).all()
88
+
89
+ def get_student_clearance_status(
90
+ db: Session,
91
+ student_id: str,
92
+ department: models.ClearanceDepartment
93
+ ) -> models.ClearanceStatus | None:
94
+ """
95
+ Retrieves the clearance status for a specific student in a specific department.
96
+
97
+ Returns None if no status exists for that student and department.
98
+ """
99
+ return db.query(models.ClearanceStatus).filter(
100
+ models.ClearanceStatus.student_id == student_id,
101
+ models.ClearanceStatus.department == department
102
+ ).first()
src/crud/tag_linking.py CHANGED
@@ -26,16 +26,19 @@ def create_pending_tag_link(db: Session, link_details: models.PrepareTagLinkRequ
26
  db.refresh(new_link)
27
  return new_link
28
 
29
- def get_pending_link_by_device(db: Session, device_id: int) -> models.PendingTagLink | None:
30
  """
31
  Fetches the active (non-expired) pending tag link for a specific device.
32
  """
33
- return db.query(models.PendingTagLink).filter(
34
- models.PendingTagLink.device_id_fk == device_id,
35
- models.PendingTagLink.expires_at > datetime.utcnow()
36
- ).first()
37
 
38
- def delete_pending_link(db: Session, link_id: int):
 
 
 
 
 
 
39
  """Deletes a pending link, typically after it has been used."""
40
  link_to_delete = db.query(models.PendingTagLink).filter(models.PendingTagLink.id == link_id).first()
41
  if link_to_delete:
 
26
  db.refresh(new_link)
27
  return new_link
28
 
29
+ def get_pending_links(db: Session, device_id: int) -> models.PendingTagLink | None:
30
  """
31
  Fetches the active (non-expired) pending tag link for a specific device.
32
  """
33
+ return db.query(models.PendingTagLink).offset(0).limit(limit=1000).all()
 
 
 
34
 
35
+ def get_pending_link_by_id(db: Session, link_id: int) -> models.PendingTagLink | None:
36
+ """
37
+ Fetches a pending tag link by its ID.
38
+ """
39
+ return db.query(models.PendingTagLink).filter(models.PendingTagLink.id == link_id).first()
40
+
41
+ def delete_pending_link_by_device_id(db: Session, link_id: int):
42
  """Deletes a pending link, typically after it has been used."""
43
  link_to_delete = db.query(models.PendingTagLink).filter(models.PendingTagLink.id == link_id).first()
44
  if link_to_delete:
src/routers/token.py CHANGED
@@ -3,6 +3,7 @@ Router for handling user authentication and issuing JWT tokens.
3
  """
4
  from fastapi import APIRouter, Depends, HTTPException, status
5
  from fastapi.security import OAuth2PasswordRequestForm
 
6
  from sqlalchemy.orm import Session
7
  from datetime import timedelta
8
 
@@ -13,7 +14,7 @@ from src.config import settings
13
 
14
  router = APIRouter(
15
  prefix="/api",
16
- tags=["Authentication"]
17
  )
18
 
19
  @router.post("/token", response_model=models.Token)
@@ -27,7 +28,9 @@ async def login_for_access_token(
27
  This is the primary login endpoint. It takes a username and password
28
  and returns an access token if the credentials are valid.
29
  """
30
- user = await authenticate_user(db, form_data.username, form_data.password)
 
 
31
  if not user:
32
  raise HTTPException(
33
  status_code=status.HTTP_401_UNAUTHORIZED,
 
3
  """
4
  from fastapi import APIRouter, Depends, HTTPException, status
5
  from fastapi.security import OAuth2PasswordRequestForm
6
+ from fastapi.concurrency import run_in_threadpool
7
  from sqlalchemy.orm import Session
8
  from datetime import timedelta
9
 
 
14
 
15
  router = APIRouter(
16
  prefix="/api",
17
+ tags=["Authentication Token"]
18
  )
19
 
20
  @router.post("/token", response_model=models.Token)
 
28
  This is the primary login endpoint. It takes a username and password
29
  and returns an access token if the credentials are valid.
30
  """
31
+ user = await run_in_threadpool(
32
+ authenticate_user, db, form_data.username, form_data.password
33
+ )
34
  if not user:
35
  raise HTTPException(
36
  status_code=status.HTTP_401_UNAUTHORIZED,
src/routers/users.py CHANGED
@@ -2,6 +2,7 @@
2
  Router for managing users (staff, admins).
3
  """
4
  from fastapi import APIRouter, Depends, HTTPException, status
 
5
  from sqlalchemy.orm import Session
6
  from typing import List
7
 
@@ -19,10 +20,10 @@ async def create_new_user(user: models.UserCreate, db: Session = Depends(get_db)
19
  """
20
  Admin: Create a new user (staff or admin).
21
  """
22
- try:
23
- return await crud.create_user(db=db, user=user)
24
- except HTTPException as e:
25
- raise e
26
 
27
  @router.get("/", response_model=List[models.UserResponse], dependencies=[Depends(get_current_active_admin_user_from_token)])
28
  async def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
@@ -32,9 +33,18 @@ async def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_
32
  users = await crud.get_all_users(db, skip=skip, limit=limit) # Assumes get_all_users exists in crud.users
33
  return users
34
 
 
 
 
 
 
 
 
 
35
  @router.get("/me", response_model=models.UserResponse)
36
  async def read_users_me(current_user: models.User = Depends(get_current_active_user)):
37
  """
38
  Get profile information for the currently authenticated user.
39
  """
40
  return current_user
 
 
2
  Router for managing users (staff, admins).
3
  """
4
  from fastapi import APIRouter, Depends, HTTPException, status
5
+ from fastapi.concurrency import run_in_threadpool
6
  from sqlalchemy.orm import Session
7
  from typing import List
8
 
 
20
  """
21
  Admin: Create a new user (staff or admin).
22
  """
23
+ db_user = await run_in_threadpool(crud.get_user_by_username, db, user.username)
24
+ if db_user:
25
+ raise HTTPException(status_code=400, detail="Username already registered")
26
+ return await run_in_threadpool(crud.create_user, db, user)
27
 
28
  @router.get("/", response_model=List[models.UserResponse], dependencies=[Depends(get_current_active_admin_user_from_token)])
29
  async def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
 
33
  users = await crud.get_all_users(db, skip=skip, limit=limit) # Assumes get_all_users exists in crud.users
34
  return users
35
 
36
+ @router.get("/all", response_model=list[models.UserResponse], dependencies=[Depends(get_current_active_admin_user_from_token)])
37
+ async def get_all_users(db: Session = Depends(get_db)):
38
+ """
39
+ Admin: Get a list of all users.
40
+ """
41
+ users = await run_in_threadpool(crud.get_all_users, db)
42
+ return users
43
+
44
  @router.get("/me", response_model=models.UserResponse)
45
  async def read_users_me(current_user: models.User = Depends(get_current_active_user)):
46
  """
47
  Get profile information for the currently authenticated user.
48
  """
49
  return current_user
50
+