source: uc_users.py@ 527c097

main
Last change on this file since 527c097 was 527c097, checked in by teo <teodorbogoeski@…>, 3 months ago

Add connection pooling and transaction management

  • Property mode set to 100644
File size: 2.8 KB
RevLine 
[95cf703]1import getpass
2
3import bcrypt
4
[527c097]5from db import get_connection, get_transaction, pick_from_list
[95cf703]6
7
8def register_user():
9 """UC0009: Register a New User."""
10 print("\n=== Register a New User ===\n")
11
12 # Step 1: Show available roles
13 with get_connection() as conn:
14 with conn.cursor() as cur:
15 cur.execute("SELECT type_id, type_name, description FROM user_types ORDER BY type_id")
16 roles = cur.fetchall()
17
18 print(" Available roles:")
19 role_items = [f"{r[1]} - {r[2]}" for r in roles]
20 role_idx = pick_from_list(" Select role: ", role_items)
21 if role_idx is None:
22 return
23 type_id = roles[role_idx][0]
24 role_name = roles[role_idx][1]
25
26 # Step 2: Enter user details
27 first_name = input(" First name: ").strip()
28 if not first_name:
29 print(" First name is required.")
30 return
31
32 last_name = input(" Last name: ").strip()
33 if not last_name:
34 print(" Last name is required.")
35 return
36
37 email = input(" Email: ").strip()
38 if not email:
39 print(" Email is required.")
40 return
41
[527c097]42 # Step 3: Enter password
[95cf703]43 password = getpass.getpass(" Initial password: ").strip()
44 if not password:
45 print(" Password is required.")
46 return
47 password_confirm = getpass.getpass(" Confirm password: ").strip()
48 if password != password_confirm:
49 print(" Passwords do not match.")
50 return
51
[527c097]52 # Step 4: Hash password
[95cf703]53 hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
54
[527c097]55 # Step 5: Transaction — check email uniqueness + insert atomically
56 # This prevents a race condition where two users register with the
57 # same email simultaneously (one check passes, both insert).
[95cf703]58 try:
[527c097]59 with get_transaction() as conn:
60 with conn.cursor() as cur:
61 cur.execute("SELECT COUNT(*) FROM users WHERE email = %s", (email,))
62 if cur.fetchone()[0] > 0:
63 raise ValueError(f"A user with email '{email}' already exists.")
64
65 cur.execute(
66 """
67 INSERT INTO users (first_name, last_name, email, password, type_id)
68 VALUES (%s, %s, %s, %s, %s)
69 RETURNING user_id, first_name, last_name, email
70 """,
71 (first_name, last_name, email, hashed, type_id),
72 )
73 result = cur.fetchone()
[95cf703]74
[527c097]75 # Transaction committed automatically — Step 6: Confirmation
[95cf703]76 print(f"\n User created successfully!")
77 print(f" User ID: {result[0]}")
78 print(f" Name: {result[1]} {result[2]}")
79 print(f" Email: {result[3]}")
80 print(f" Role: {role_name}")
[527c097]81 except ValueError as e:
82 print(f"\n ERROR: {e}")
[95cf703]83 except Exception as e:
84 print(f"\n Error creating user: {e}")
Note: See TracBrowser for help on using the repository browser.