Testys commited on
Commit
2e8a105
·
1 Parent(s): 1771391

Last push before leaving

Browse files
Files changed (2) hide show
  1. src/crud/__init__.py +9 -13
  2. 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 (optional, for explicit imports)
48
  __all__ = [
49
- # Utilities
 
 
 
 
 
 
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
- from src.crud import hash_password # Import from crud module instead of auth
 
 
 
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:int) -> models.User | None:
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) # Use the imported function
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
- db.query(models.PendingTagLink).filter(models.PendingTagLink.initiated_by_user_id == user_to_delete.id).delete()
 
 
 
 
 
 
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()