Spaces:
Runtime error
Runtime error
Last push before leaving
Browse files- src/crud/__init__.py +9 -13
- src/crud/users.py +68 -4
src/crud/__init__.py
CHANGED
@@ -7,9 +7,6 @@ CRUD function directly from `src.crud` instead of the specific submodule,
|
|
7 |
keeping the router imports clean.
|
8 |
"""
|
9 |
|
10 |
-
# Import utility functions first
|
11 |
-
from .utils import hash_password, verify_password
|
12 |
-
|
13 |
from .students import (
|
14 |
create_student,
|
15 |
get_all_students,
|
@@ -25,6 +22,7 @@ from .users import (
|
|
25 |
update_user_tag_id,
|
26 |
get_user_by_id,
|
27 |
delete_user,
|
|
|
28 |
)
|
29 |
from .devices import (
|
30 |
get_device_by_id_str,
|
@@ -44,11 +42,16 @@ from .tag_linking import (
|
|
44 |
delete_pending_link,
|
45 |
)
|
46 |
|
47 |
-
# Export all functions
|
48 |
__all__ = [
|
49 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
'hash_password',
|
51 |
-
'verify_password',
|
52 |
# Students
|
53 |
'create_student',
|
54 |
'get_all_students',
|
@@ -56,13 +59,6 @@ __all__ = [
|
|
56 |
'get_student_by_tag_id',
|
57 |
'update_student_tag_id',
|
58 |
'delete_student',
|
59 |
-
# Users
|
60 |
-
'create_user',
|
61 |
-
'get_user_by_username',
|
62 |
-
'get_user_by_tag_id',
|
63 |
-
'update_user_tag_id',
|
64 |
-
'get_user_by_id',
|
65 |
-
'delete_user',
|
66 |
# Devices
|
67 |
'get_device_by_id_str',
|
68 |
'get_device_by_api_key',
|
|
|
7 |
keeping the router imports clean.
|
8 |
"""
|
9 |
|
|
|
|
|
|
|
10 |
from .students import (
|
11 |
create_student,
|
12 |
get_all_students,
|
|
|
22 |
update_user_tag_id,
|
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,
|
|
|
42 |
delete_pending_link,
|
43 |
)
|
44 |
|
45 |
+
# Export all functions
|
46 |
__all__ = [
|
47 |
+
# Users
|
48 |
+
'create_user',
|
49 |
+
'get_user_by_username',
|
50 |
+
'get_user_by_tag_id',
|
51 |
+
'update_user_tag_id',
|
52 |
+
'get_user_by_id',
|
53 |
+
'delete_user',
|
54 |
'hash_password',
|
|
|
55 |
# Students
|
56 |
'create_student',
|
57 |
'get_all_students',
|
|
|
59 |
'get_student_by_tag_id',
|
60 |
'update_student_tag_id',
|
61 |
'delete_student',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
# Devices
|
63 |
'get_device_by_id_str',
|
64 |
'get_device_by_api_key',
|
src/crud/users.py
CHANGED
@@ -3,9 +3,13 @@ CRUD operations for Users (Admins, Staff).
|
|
3 |
"""
|
4 |
from sqlalchemy.orm import Session
|
5 |
from fastapi import HTTPException, status
|
|
|
6 |
|
7 |
from src import models
|
8 |
-
|
|
|
|
|
|
|
9 |
|
10 |
def get_user_by_username(db: Session, username: str) -> models.User | None:
|
11 |
"""
|
@@ -25,12 +29,39 @@ def get_all_users(db: Session, skip: int = 0, limit: int = 100) -> list[models.U
|
|
25 |
"""
|
26 |
return db.query(models.User).offset(skip).limit(limit).all()
|
27 |
|
28 |
-
def get_user_by_tag_id(db:Session, tag_id:
|
29 |
"""
|
30 |
Retrieves a user by their TAG_ID.
|
31 |
"""
|
32 |
return db.query(models.User).filter(models.User.tag_id == tag_id).first()
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
def create_user(db: Session, user_data: models.UserCreate) -> models.User:
|
35 |
"""
|
36 |
Creates a new user account.
|
@@ -43,8 +74,17 @@ def create_user(db: Session, user_data: models.UserCreate) -> models.User:
|
|
43 |
detail=f"Username '{user_data.username}' is already registered."
|
44 |
)
|
45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
# Hash the password
|
47 |
-
hashed_password = hash_password(user_data.password)
|
48 |
|
49 |
# Create new user
|
50 |
db_user = models.User(
|
@@ -74,6 +114,24 @@ def update_user(db: Session, user_id: int, user_update: models.UserCreate) -> mo
|
|
74 |
detail=f"User with ID {user_id} not found."
|
75 |
)
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
# Update fields
|
78 |
db_user.username = user_update.username
|
79 |
db_user.name = user_update.name
|
@@ -117,7 +175,13 @@ def delete_user(db: Session, username_to_delete: str, current_admin: models.User
|
|
117 |
|
118 |
# Handle dependencies: set foreign keys to NULL where a user is referenced
|
119 |
db.query(models.ClearanceStatus).filter(models.ClearanceStatus.cleared_by == user_to_delete.id).update({"cleared_by": None})
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
db.delete(user_to_delete)
|
123 |
db.commit()
|
|
|
3 |
"""
|
4 |
from sqlalchemy.orm import Session
|
5 |
from fastapi import HTTPException, status
|
6 |
+
import bcrypt
|
7 |
|
8 |
from src import models
|
9 |
+
|
10 |
+
def hash_password(password: str) -> str:
|
11 |
+
"""Hashes a password using bcrypt."""
|
12 |
+
return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
|
13 |
|
14 |
def get_user_by_username(db: Session, username: str) -> models.User | None:
|
15 |
"""
|
|
|
29 |
"""
|
30 |
return db.query(models.User).offset(skip).limit(limit).all()
|
31 |
|
32 |
+
def get_user_by_tag_id(db: Session, tag_id: str) -> models.User | None:
|
33 |
"""
|
34 |
Retrieves a user by their TAG_ID.
|
35 |
"""
|
36 |
return db.query(models.User).filter(models.User.tag_id == tag_id).first()
|
37 |
|
38 |
+
def update_user_tag_id(db: Session, username: str, new_tag_id: str) -> models.User:
|
39 |
+
"""
|
40 |
+
Updates a user's tag_id.
|
41 |
+
"""
|
42 |
+
# Check if the new tag_id is already in use
|
43 |
+
existing_user_with_tag = get_user_by_tag_id(db, new_tag_id)
|
44 |
+
if existing_user_with_tag:
|
45 |
+
raise HTTPException(
|
46 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
47 |
+
detail=f"Tag ID '{new_tag_id}' is already assigned to another user."
|
48 |
+
)
|
49 |
+
|
50 |
+
# Get the user to update
|
51 |
+
user = get_user_by_username(db, username)
|
52 |
+
if not user:
|
53 |
+
raise HTTPException(
|
54 |
+
status_code=status.HTTP_404_NOT_FOUND,
|
55 |
+
detail=f"User '{username}' not found."
|
56 |
+
)
|
57 |
+
|
58 |
+
# Update the tag_id
|
59 |
+
user.tag_id = new_tag_id
|
60 |
+
db.commit()
|
61 |
+
db.refresh(user)
|
62 |
+
|
63 |
+
return user
|
64 |
+
|
65 |
def create_user(db: Session, user_data: models.UserCreate) -> models.User:
|
66 |
"""
|
67 |
Creates a new user account.
|
|
|
74 |
detail=f"Username '{user_data.username}' is already registered."
|
75 |
)
|
76 |
|
77 |
+
# Check if tag_id is already in use (if provided)
|
78 |
+
if user_data.tag_id:
|
79 |
+
existing_tag_user = get_user_by_tag_id(db, user_data.tag_id)
|
80 |
+
if existing_tag_user:
|
81 |
+
raise HTTPException(
|
82 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
83 |
+
detail=f"Tag ID '{user_data.tag_id}' is already assigned to another user."
|
84 |
+
)
|
85 |
+
|
86 |
# Hash the password
|
87 |
+
hashed_password = hash_password(user_data.password)
|
88 |
|
89 |
# Create new user
|
90 |
db_user = models.User(
|
|
|
114 |
detail=f"User with ID {user_id} not found."
|
115 |
)
|
116 |
|
117 |
+
# Check if new username is already taken (if changed)
|
118 |
+
if user_update.username != db_user.username:
|
119 |
+
existing_user = get_user_by_username(db, user_update.username)
|
120 |
+
if existing_user:
|
121 |
+
raise HTTPException(
|
122 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
123 |
+
detail=f"Username '{user_update.username}' is already taken."
|
124 |
+
)
|
125 |
+
|
126 |
+
# Check if new tag_id is already in use (if changed and provided)
|
127 |
+
if user_update.tag_id and user_update.tag_id != db_user.tag_id:
|
128 |
+
existing_tag_user = get_user_by_tag_id(db, user_update.tag_id)
|
129 |
+
if existing_tag_user:
|
130 |
+
raise HTTPException(
|
131 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
132 |
+
detail=f"Tag ID '{user_update.tag_id}' is already assigned to another user."
|
133 |
+
)
|
134 |
+
|
135 |
# Update fields
|
136 |
db_user.username = user_update.username
|
137 |
db_user.name = user_update.name
|
|
|
175 |
|
176 |
# Handle dependencies: set foreign keys to NULL where a user is referenced
|
177 |
db.query(models.ClearanceStatus).filter(models.ClearanceStatus.cleared_by == user_to_delete.id).update({"cleared_by": None})
|
178 |
+
|
179 |
+
# Check if PendingTagLink model exists before trying to delete
|
180 |
+
try:
|
181 |
+
db.query(models.PendingTagLink).filter(models.PendingTagLink.initiated_by_user_id == user_to_delete.id).delete()
|
182 |
+
except AttributeError:
|
183 |
+
# PendingTagLink model doesn't exist, skip this cleanup
|
184 |
+
pass
|
185 |
|
186 |
db.delete(user_to_delete)
|
187 |
db.commit()
|