Changeset 527c097 for uc_users.py


Ignore:
Timestamp:
04/05/26 20:02:04 (3 months ago)
Author:
teo <teodorbogoeski@…>
Branches:
main
Parents:
95cf703
Message:

Add connection pooling and transaction management

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uc_users.py

    r95cf703 r527c097  
    33import bcrypt
    44
    5 from db import get_connection, pick_from_list
     5from db import get_connection, get_transaction, pick_from_list
    66
    77
     
    4040        return
    4141
    42     # Step 3: Check email uniqueness
    43     with get_connection() as conn:
    44         with conn.cursor() as cur:
    45             cur.execute("SELECT COUNT(*) FROM users WHERE email = %s", (email,))
    46             exists = cur.fetchone()[0]
    47     if exists > 0:
    48         print(f"\n  ERROR: A user with email '{email}' already exists.")
    49         return
    50 
    51     # Step 4: Enter password
     42    # Step 3: Enter password
    5243    password = getpass.getpass("  Initial password: ").strip()
    5344    if not password:
     
    5950        return
    6051
    61     # Step 5: Hash and insert
     52    # Step 4: Hash password
    6253    hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
    6354
    64     conn = get_connection()
     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).
    6558    try:
    66         with conn.cursor() as cur:
    67             cur.execute(
    68                 """
    69                 INSERT INTO users (first_name, last_name, email, password, type_id)
    70                 VALUES (%s, %s, %s, %s, %s)
    71                 RETURNING user_id, first_name, last_name, email
    72                 """,
    73                 (first_name, last_name, email, hashed, type_id),
    74             )
    75             result = cur.fetchone()
    76         conn.commit()
     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.")
    7764
    78         # Step 6: Confirmation
     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()
     74
     75        # Transaction committed automatically — Step 6: Confirmation
    7976        print(f"\n  User created successfully!")
    8077        print(f"  User ID:  {result[0]}")
     
    8279        print(f"  Email:    {result[3]}")
    8380        print(f"  Role:     {role_name}")
     81    except ValueError as e:
     82        print(f"\n  ERROR: {e}")
    8483    except Exception as e:
    85         conn.rollback()
    8684        print(f"\n  Error creating user: {e}")
    87     finally:
    88         conn.close()
Note: See TracChangeset for help on using the changeset viewer.