changes to the encryption to the users and Items
This commit is contained in:
+418
-728
File diff suppressed because it is too large
Load Diff
+109
-232
@@ -110,13 +110,6 @@ def build_username_from_name(first_name, last_name=''):
|
|||||||
"""
|
"""
|
||||||
Build a deterministic username abbreviation from first and last name.
|
Build a deterministic username abbreviation from first and last name.
|
||||||
Uses 3 letters from each name and stores it lowercase.
|
Uses 3 letters from each name and stores it lowercase.
|
||||||
|
|
||||||
Args:
|
|
||||||
first_name (str): First name
|
|
||||||
last_name (str): Last name (optional)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: Generated username
|
|
||||||
"""
|
"""
|
||||||
alias = build_name_synonym(first_name, last_name)
|
alias = build_name_synonym(first_name, last_name)
|
||||||
return alias.lower()
|
return alias.lower()
|
||||||
@@ -325,7 +318,6 @@ def get_effective_permissions(username):
|
|||||||
return build_default_permission_payload('full_access')
|
return build_default_permission_payload('full_access')
|
||||||
|
|
||||||
preset_key = user.get('PermissionPreset')
|
preset_key = user.get('PermissionPreset')
|
||||||
print(preset_key)
|
|
||||||
payload = build_default_permission_payload(preset_key)
|
payload = build_default_permission_payload(preset_key)
|
||||||
payload['actions'] = _normalize_bool_map(user.get('ActionPermissions', {}), payload['actions'])
|
payload['actions'] = _normalize_bool_map(user.get('ActionPermissions', {}), payload['actions'])
|
||||||
payload['pages'] = _normalize_bool_map(user.get('PagePermissions', {}), payload['pages'])
|
payload['pages'] = _normalize_bool_map(user.get('PagePermissions', {}), payload['pages'])
|
||||||
@@ -353,10 +345,10 @@ def update_user_permissions(username, preset_key, action_permissions=None, page_
|
|||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
result = users.update_one({'Username': username}, {'$set': update_data})
|
result = users.update_one({'Username': dp.encrypt_text(username)}, {'$set': update_data})
|
||||||
|
|
||||||
if result.matched_count == 0:
|
if result.matched_count == 0:
|
||||||
result = users.update_one({'username': username}, {'$set': update_data})
|
result = users.update_one({'username': dp.encrypt_text(username)}, {'$set': update_data})
|
||||||
|
|
||||||
client.close()
|
client.close()
|
||||||
return result.matched_count > 0
|
return result.matched_count > 0
|
||||||
@@ -368,7 +360,7 @@ def get_favorites(username):
|
|||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
user = users.find_one({'Username': username}) or users.find_one({'username': username})
|
user = users.find_one({'Username': dp.encrypt_text(username)}) or users.find_one({'username': dp.encrypt_text(username)})
|
||||||
client.close()
|
client.close()
|
||||||
if not user:
|
if not user:
|
||||||
return []
|
return []
|
||||||
@@ -383,7 +375,7 @@ def add_favorite(username, item_id):
|
|||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
users.update_one(
|
users.update_one(
|
||||||
{'$or': [{'Username': username}, {'username': username}]},
|
{'$or': [{'Username': dp.encrypt_text(username)}, {'username': dp.encrypt_text(username)}]},
|
||||||
{'$addToSet': {'favorites': ObjectId(item_id)}}
|
{'$addToSet': {'favorites': ObjectId(item_id)}}
|
||||||
)
|
)
|
||||||
client.close()
|
client.close()
|
||||||
@@ -398,7 +390,7 @@ def remove_favorite(username, item_id):
|
|||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
users.update_one(
|
users.update_one(
|
||||||
{'$or': [{'Username': username}, {'username': username}]},
|
{'$or': [{'Username': dp.encrypt_text(username)}, {'username': dp.encrypt_text(username)}]},
|
||||||
{'$pull': {'favorites': ObjectId(item_id)}}
|
{'$pull': {'favorites': ObjectId(item_id)}}
|
||||||
)
|
)
|
||||||
client.close()
|
client.close()
|
||||||
@@ -407,16 +399,9 @@ def remove_favorite(username, item_id):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def check_password_strength(password):
|
def check_password_strength(password):
|
||||||
"""
|
"""
|
||||||
Check if a password meets minimum security requirements.
|
Check if a password meets minimum security requirements.
|
||||||
|
|
||||||
Args:
|
|
||||||
password (str): Password to check
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if password is strong enough, False otherwise
|
|
||||||
"""
|
"""
|
||||||
if password is None:
|
if password is None:
|
||||||
return False
|
return False
|
||||||
@@ -437,18 +422,14 @@ def check_password_strength(password):
|
|||||||
def hashing(password, salt=None):
|
def hashing(password, salt=None):
|
||||||
"""
|
"""
|
||||||
Hasht ein Passwort mit scrypt.
|
Hasht ein Passwort mit scrypt.
|
||||||
- Wenn kein Salt übergeben wird, wird ein sicherer, zufälliger Salt generiert (für neue Passwörter).
|
|
||||||
- Format für neue Hashes: v1$<salt_hex>$<hash_hex>
|
|
||||||
"""
|
"""
|
||||||
password_bytes = password.encode('utf-8') # Explizit UTF-8 für Plattformunabhängigkeit
|
password_bytes = password.encode('utf-8')
|
||||||
|
|
||||||
if salt is None:
|
if salt is None:
|
||||||
# Neuer Benutzer / Passwortänderung -> Dynamischer Salt
|
|
||||||
random_salt = os.urandom(16)
|
random_salt = os.urandom(16)
|
||||||
hashed = hashlib.scrypt(password_bytes, salt=random_salt, n=16384, r=8, p=1)
|
hashed = hashlib.scrypt(password_bytes, salt=random_salt, n=16384, r=8, p=1)
|
||||||
return f"v1${random_salt.hex()}${hashed.hex()}"
|
return f"v1${random_salt.hex()}${hashed.hex()}"
|
||||||
else:
|
else:
|
||||||
# Bestehender Benutzer (wird zur Verifizierung aufgerufen)
|
|
||||||
hashed = hashlib.scrypt(password_bytes, salt=salt, n=16384, r=8, p=1)
|
hashed = hashlib.scrypt(password_bytes, salt=salt, n=16384, r=8, p=1)
|
||||||
return hashed.hex()
|
return hashed.hex()
|
||||||
|
|
||||||
@@ -456,25 +437,20 @@ def hashing(password, salt=None):
|
|||||||
def verify_password(provided_password, stored_password_string):
|
def verify_password(provided_password, stored_password_string):
|
||||||
"""
|
"""
|
||||||
Verifiziert ein Passwort gegen einen gespeicherten Hash-String.
|
Verifiziert ein Passwort gegen einen gespeicherten Hash-String.
|
||||||
Unterstützt das alte Format (statischer Salt) und das neue Format (v1$...).
|
|
||||||
"""
|
"""
|
||||||
if not stored_password_string:
|
if not stored_password_string:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Überprüfung für das neue, sichere Format
|
|
||||||
if stored_password_string.startswith("v1$"):
|
if stored_password_string.startswith("v1$"):
|
||||||
try:
|
try:
|
||||||
_, salt_hex, hash_hex = stored_password_string.split("$")
|
_, salt_hex, hash_hex = stored_password_string.split("$")
|
||||||
salt_bytes = bytes.fromhex(salt_hex)
|
salt_bytes = bytes.fromhex(salt_hex)
|
||||||
# Berechne den Hash des eingegebenen Passworts mit dem extrahierten Salt
|
|
||||||
calculated_hash = hashing(provided_password, salt=salt_bytes)
|
calculated_hash = hashing(provided_password, salt=salt_bytes)
|
||||||
# Timing-Attack-sicherer Vergleich
|
|
||||||
return hmac.compare_digest(calculated_hash, hash_hex)
|
return hmac.compare_digest(calculated_hash, hash_hex)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
logger.error("Ungültiges Hash-Format in der Datenbank entdeckt.")
|
logger.error("Ungültiges Hash-Format in der Datenbank entdeckt.")
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
# Abwärtskompatibilität: Altes Format mit statischem Salt b'some_salt'
|
|
||||||
old_static_salt = b'some_salt'
|
old_static_salt = b'some_salt'
|
||||||
calculated_hash = hashing(provided_password, salt=old_static_salt)
|
calculated_hash = hashing(provided_password, salt=old_static_salt)
|
||||||
return hmac.compare_digest(calculated_hash, stored_password_string)
|
return hmac.compare_digest(calculated_hash, stored_password_string)
|
||||||
@@ -496,21 +472,20 @@ def check_nm_pwd(username, password):
|
|||||||
db = client[db_name]
|
db = client[db_name]
|
||||||
users = db['users']
|
users = db['users']
|
||||||
|
|
||||||
query = {'$or': [{'Username': username}, {'username': username}]}
|
query = {'$or': [{'Username': dp.encrypt_text(username)}, {'username': dp.encrypt_text(username)}]}
|
||||||
user_record = users.find_one(query)
|
user_record = users.find_one(query)
|
||||||
|
|
||||||
if user_record is None:
|
if user_record is None:
|
||||||
logger.warning("Kein Benutzer für %r in DB %r gefunden.", username, db_name)
|
logger.warning("Kein Benutzer für %r in DB %r gefunden.", dp.encrypt_text(username), db_name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
stored_password = user_record.get('Password') or user_record.get('password')
|
stored_password = user_record.get('Password') or user_record.get('password')
|
||||||
|
|
||||||
if not verify_password(password, stored_password):
|
if not verify_password(password, stored_password):
|
||||||
logger.warning("Falsches Passwort für Benutzer %r in DB %r.", username, db_name)
|
logger.warning("Falsches Passwort für Benutzer %r in DB %r.", dp.encrypt_text(username), db_name)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Automatische Migration alter Hashes auf das neue Format
|
if stored_password and not stored_password.startswith("v1$"):
|
||||||
if not stored_password.startswith("v1$"):
|
|
||||||
users.update_one({'_id': user_record['_id']}, {'$set': {'Password': hashing(password)}})
|
users.update_one({'_id': user_record['_id']}, {'$set': {'Password': hashing(password)}})
|
||||||
|
|
||||||
return user_record
|
return user_record
|
||||||
@@ -532,40 +507,35 @@ def add_user(
|
|||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Add a new user to the database.
|
Add a new user to the database.
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username for the new user
|
|
||||||
password (str): Password for the new user
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if user was added successfully, False if password was too weak
|
|
||||||
"""
|
"""
|
||||||
|
if not check_password_strength(password):
|
||||||
|
return False
|
||||||
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
try:
|
try:
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
if not check_password_strength(password):
|
|
||||||
return False
|
|
||||||
permission_defaults = build_default_permission_payload(permission_preset)
|
permission_defaults = build_default_permission_payload(permission_preset)
|
||||||
|
|
||||||
if isinstance(action_permissions, dict):
|
if isinstance(action_permissions, dict):
|
||||||
for key, value in action_permissions.items():
|
for key, value in action_permissions.items():
|
||||||
permission_defaults['actions'][str(key)] = bool(value)
|
permission_defaults['actions'][str(key)] = bool(value)
|
||||||
|
|
||||||
if isinstance(page_permissions, dict):
|
if isinstance(page_permissions, dict):
|
||||||
for key, value in page_permissions.items():
|
for key, value in page_permissions.items():
|
||||||
permission_defaults['pages'][str(key)] = bool(value)
|
permission_defaults['pages'][str(key)] = bool(value)
|
||||||
|
|
||||||
if permission_preset == "full_access":
|
safe_name = name.strip() if name else ''
|
||||||
can_admin_preset_based = True
|
safe_last_name = last_name.strip() if last_name else ''
|
||||||
else:
|
|
||||||
can_admin_preset_based = False
|
|
||||||
|
|
||||||
user_doc = {
|
user_doc = {
|
||||||
'Username': username,
|
'Username': dp.encrypt_text(username),
|
||||||
'Password': hashing(password),
|
'Password': hashing(password),
|
||||||
'Admin': can_admin_preset_based,
|
'Admin': (permission_preset == "full_access"),
|
||||||
'active_ausleihung': None,
|
'active_ausleihung': None,
|
||||||
'name': name.strip() if name else '',
|
'name': dp.encrypt_text(safe_name) if safe_name else '',
|
||||||
'last_name': last_name.strip() if last_name else '',
|
'last_name': dp.encrypt_text(safe_last_name) if safe_last_name else '',
|
||||||
'IsStudent': bool(is_student),
|
'IsStudent': bool(is_student),
|
||||||
'PermissionPreset': permission_defaults['preset'],
|
'PermissionPreset': permission_defaults['preset'],
|
||||||
'ActionPermissions': permission_defaults['actions'],
|
'ActionPermissions': permission_defaults['actions'],
|
||||||
@@ -602,7 +572,7 @@ def student_card_exists(student_card_id):
|
|||||||
|
|
||||||
|
|
||||||
def get_user_by_student_card(student_card_id):
|
def get_user_by_student_card(student_card_id):
|
||||||
"""Return user by student card id or None."""
|
"""Return user dict by student card id or None."""
|
||||||
normalized = normalize_student_card_id(student_card_id)
|
normalized = normalize_student_card_id(student_card_id)
|
||||||
if not normalized:
|
if not normalized:
|
||||||
return None
|
return None
|
||||||
@@ -611,65 +581,44 @@ def get_user_by_student_card(student_card_id):
|
|||||||
users = db['student_cards']
|
users = db['student_cards']
|
||||||
found_user = users.find_one({'SchülerName': normalized})
|
found_user = users.find_one({'SchülerName': normalized})
|
||||||
client.close()
|
client.close()
|
||||||
|
|
||||||
|
# Do not call dp.decrypt_text() here because found_user is a MongoDB dictionary.
|
||||||
return found_user
|
return found_user
|
||||||
|
|
||||||
|
|
||||||
def make_admin(username):
|
def make_admin(username):
|
||||||
"""
|
"""Grant administrator privileges to a user."""
|
||||||
Grant administrator privileges to a user.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username of the user to promote
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if user was promoted successfully
|
|
||||||
"""
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
result = users.update_one({'Username': username}, {'$set': {'Admin': True}})
|
result = users.update_one({'Username': dp.encrypt_text(username)}, {'$set': {'Admin': True}})
|
||||||
if result.matched_count == 0:
|
if result.matched_count == 0:
|
||||||
result = users.update_one({'username': username}, {'$set': {'Admin': True}})
|
result = users.update_one({'username': dp.encrypt_text(username)}, {'$set': {'Admin': True}})
|
||||||
client.close()
|
client.close()
|
||||||
return result.matched_count > 0
|
return result.matched_count > 0
|
||||||
|
|
||||||
|
|
||||||
def remove_admin(username):
|
def remove_admin(username):
|
||||||
"""
|
"""Remove administrator privileges from a user."""
|
||||||
Remove administrator privileges from a user.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username of the user to demote
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if user was demoted successfully
|
|
||||||
"""
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
result = users.update_one({'Username': username}, {'$set': {'Admin': False}})
|
result = users.update_one({'Username': dp.encrypt_text(username)}, {'$set': {'Admin': False}})
|
||||||
if result.matched_count == 0:
|
if result.matched_count == 0:
|
||||||
result = users.update_one({'username': username}, {'$set': {'Admin': False}})
|
result = users.update_one({'username': dp.encrypt_text(username)}, {'$set': {'Admin': False}})
|
||||||
client.close()
|
client.close()
|
||||||
return result.matched_count > 0
|
return result.matched_count > 0
|
||||||
|
|
||||||
|
|
||||||
def get_user(username):
|
def get_user(username):
|
||||||
"""
|
"""Retrieve a specific user by username."""
|
||||||
Retrieve a specific user by username.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username to search for
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: User document or None if not found
|
|
||||||
"""
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
try:
|
try:
|
||||||
def find_in_db(database_name):
|
def find_in_db(database_name):
|
||||||
db = client[database_name]
|
db = client[database_name]
|
||||||
users = db['users']
|
users = db['users']
|
||||||
return users.find_one({'Username': username}) or users.find_one({'username': username})
|
return users.find_one({'Username': dp.encrypt_text(username)}) or users.find_one({'username': dp.encrypt_text(username)})
|
||||||
|
|
||||||
# Try current tenant first when available
|
|
||||||
tenant_db, tenant_id = _resolve_request_tenant_db()
|
tenant_db, tenant_id = _resolve_request_tenant_db()
|
||||||
if tenant_db:
|
if tenant_db:
|
||||||
user = find_in_db(tenant_db)
|
user = find_in_db(tenant_db)
|
||||||
@@ -682,7 +631,6 @@ def get_user(username):
|
|||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Fallback to default configured database
|
|
||||||
user = find_in_db(cfg.MONGODB_DB)
|
user = find_in_db(cfg.MONGODB_DB)
|
||||||
if user:
|
if user:
|
||||||
return user
|
return user
|
||||||
@@ -693,146 +641,88 @@ def get_user(username):
|
|||||||
|
|
||||||
|
|
||||||
def check_admin(username):
|
def check_admin(username):
|
||||||
"""
|
"""Check if a user has administrator privileges."""
|
||||||
Check if a user has administrator privileges.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username to check
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if user is an administrator, False otherwise
|
|
||||||
"""
|
|
||||||
user = get_user(username)
|
user = get_user(username)
|
||||||
return bool(user and user.get('Admin', False))
|
return bool(user and user.get('Admin', False))
|
||||||
|
|
||||||
|
|
||||||
def update_active_ausleihung(username, id_item, ausleihung):
|
def update_active_ausleihung(username, id_item, ausleihung):
|
||||||
"""
|
"""Update a user's active borrowing record."""
|
||||||
Update a user's active borrowing record.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username of the user
|
|
||||||
id_item (str): ID of the borrowed item
|
|
||||||
ausleihung (str): ID of the borrowing record
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if successful
|
|
||||||
"""
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
users.update_one({'Username': username}, {'$set': {'active_ausleihung': {'Item': id_item, 'Ausleihung': ausleihung}}})
|
|
||||||
|
result = users.update_one(
|
||||||
|
{'Username': dp.encrypt_text(username)},
|
||||||
|
{'$set': {'active_ausleihung': {'Item': id_item, 'Ausleihung': ausleihung}}}
|
||||||
|
)
|
||||||
|
if result.matched_count == 0:
|
||||||
|
users.update_one(
|
||||||
|
{'username': dp.encrypt_text(username)},
|
||||||
|
{'$set': {'active_ausleihung': {'Item': id_item, 'Ausleihung': ausleihung}}}
|
||||||
|
)
|
||||||
client.close()
|
client.close()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def get_active_ausleihung(username):
|
def get_active_ausleihung(username):
|
||||||
"""
|
"""Get a user's active borrowing record."""
|
||||||
Get a user's active borrowing record.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username of the user
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: Active borrowing information or None
|
|
||||||
"""
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
user = users.find_one({'Username': username})
|
|
||||||
return user['active_ausleihung']
|
user = users.find_one({'Username': dp.encrypt_text(username)}) or users.find_one({'username': dp.encrypt_text(username)})
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
return None
|
||||||
|
return user.get('active_ausleihung')
|
||||||
|
|
||||||
|
|
||||||
def has_active_borrowing(username):
|
def has_active_borrowing(username):
|
||||||
"""
|
"""Check if a user currently has an active borrowing."""
|
||||||
Check if a user currently has an active borrowing.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username to check
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if user has an active borrowing, False otherwise
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
|
|
||||||
user = users.find_one({'username': username})
|
user = users.find_one({'username': dp.encrypt_text(username)}) or users.find_one({'Username': dp.encrypt_text(username)})
|
||||||
if not user:
|
client.close()
|
||||||
user = users.find_one({'Username': username})
|
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
client.close()
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
has_active = user.get('active_borrowing', False)
|
return user.get('active_borrowing', False)
|
||||||
|
|
||||||
client.close()
|
|
||||||
return has_active
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def delete_user(username):
|
def delete_user(username):
|
||||||
"""
|
"""Delete a user from the database."""
|
||||||
Delete a user from the database.
|
|
||||||
Administrative function for removing user accounts.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username of the account to delete
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if user was deleted successfully, False otherwise
|
|
||||||
"""
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
result = users.delete_one({'username': username})
|
|
||||||
client.close()
|
|
||||||
if result.deleted_count == 0:
|
|
||||||
# Try with different field name
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
|
||||||
db = _get_tenant_db(client)
|
|
||||||
users = db['users']
|
|
||||||
result = users.delete_one({'Username': username})
|
|
||||||
client.close()
|
|
||||||
|
|
||||||
|
result = users.delete_one({'username': dp.encrypt_text(username)})
|
||||||
|
if result.deleted_count == 0:
|
||||||
|
result = users.delete_one({'Username': dp.encrypt_text(username)})
|
||||||
|
|
||||||
|
client.close()
|
||||||
return result.deleted_count > 0
|
return result.deleted_count > 0
|
||||||
|
|
||||||
|
|
||||||
def update_active_borrowing(username, item_id, status):
|
def update_active_borrowing(username, item_id, status):
|
||||||
"""
|
"""Update a user's active borrowing status."""
|
||||||
Update a user's active borrowing status.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username of the user
|
|
||||||
item_id (str): ID of the borrowed item or None if returning
|
|
||||||
status (bool): True if borrowing, False if returning
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if successful, False on error
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
result = users.update_one(
|
|
||||||
{'username': username},
|
|
||||||
{'$set': {
|
|
||||||
'active_borrowing': status,
|
|
||||||
'borrowed_item': item_id if status else None
|
|
||||||
}}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
update_data = {'$set': {'active_borrowing': status, 'borrowed_item': item_id if status else None}}
|
||||||
|
|
||||||
|
result = users.update_one({'username': dp.encrypt_text(username)}, update_data)
|
||||||
if result.matched_count == 0:
|
if result.matched_count == 0:
|
||||||
result = users.update_one(
|
result = users.update_one({'Username': dp.encrypt_text(username)}, update_data)
|
||||||
{'Username': username},
|
|
||||||
{'$set': {
|
|
||||||
'active_borrowing': status,
|
|
||||||
'borrowed_item': item_id if status else None
|
|
||||||
}}
|
|
||||||
)
|
|
||||||
|
|
||||||
client.close()
|
client.close()
|
||||||
return result.modified_count > 0
|
return result.modified_count > 0
|
||||||
@@ -841,43 +731,37 @@ def update_active_borrowing(username, item_id, status):
|
|||||||
|
|
||||||
|
|
||||||
def get_name(username):
|
def get_name(username):
|
||||||
"""
|
"""Retrieve the name that is associated with the username."""
|
||||||
Retrieve the name that is assosiated with the username.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: String of name
|
|
||||||
"""
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
user = users.find_one({'Username': username})
|
|
||||||
name = user.get("name")
|
user = users.find_one({'Username': dp.encrypt_text(username)}) or users.find_one({'username': dp.encrypt_text(username)})
|
||||||
return name
|
client.close()
|
||||||
|
|
||||||
|
if not user or not user.get("name"):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return dp.decrypt_text(user.get("name"))
|
||||||
|
|
||||||
|
|
||||||
def get_last_name(username):
|
def get_last_name(username):
|
||||||
"""
|
"""Retrieve the last_name that is associated with the username."""
|
||||||
Retrieve the last_name that is assosiated with the username.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: String of last_name
|
|
||||||
"""
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
user = users.find_one({'Username': username})
|
|
||||||
name = user.get("last_name")
|
user = users.find_one({'Username': dp.encrypt_text(username)}) or users.find_one({'username': dp.encrypt_text(username)})
|
||||||
return name
|
client.close()
|
||||||
|
|
||||||
|
if not user or not user.get("last_name"):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return dp.decrypt_text(user.get("last_name"))
|
||||||
|
|
||||||
|
|
||||||
def get_all_users():
|
def get_all_users():
|
||||||
"""
|
"""Retrieve all users from the database."""
|
||||||
Retrieve all users from the database.
|
|
||||||
Administrative function for user management.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list: List of all user documents
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
@@ -888,17 +772,9 @@ def get_all_users():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def update_password(username, new_password):
|
def update_password(username, new_password):
|
||||||
"""
|
"""Update a user's password with a new one."""
|
||||||
Update a user's password with a new one.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username of the user
|
|
||||||
new_password (str): New password to set
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if password was updated successfully, False otherwise
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
if not check_password_strength(new_password):
|
if not check_password_strength(new_password):
|
||||||
return False
|
return False
|
||||||
@@ -907,14 +783,17 @@ def update_password(username, new_password):
|
|||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
|
|
||||||
# Hash the new password
|
|
||||||
hashed_password = hashing(new_password)
|
hashed_password = hashing(new_password)
|
||||||
|
|
||||||
# Update the user's password
|
|
||||||
result = users.update_one(
|
result = users.update_one(
|
||||||
{'Username': username},
|
{'Username': dp.encrypt_text(username)},
|
||||||
{'$set': {'Password': hashed_password}}
|
{'$set': {'Password': hashed_password}}
|
||||||
)
|
)
|
||||||
|
if result.matched_count == 0:
|
||||||
|
result = users.update_one(
|
||||||
|
{'username': dp.encrypt_text(username)},
|
||||||
|
{'$set': {'Password': hashed_password}}
|
||||||
|
)
|
||||||
|
|
||||||
client.close()
|
client.close()
|
||||||
return result.modified_count > 0
|
return result.modified_count > 0
|
||||||
@@ -922,28 +801,26 @@ def update_password(username, new_password):
|
|||||||
print(f"Error updating password: {e}")
|
print(f"Error updating password: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def update_user_name(username, name, last_name):
|
def update_user_name(username, name, last_name):
|
||||||
"""
|
"""Update a user's name and last name."""
|
||||||
Update a user's name and last name.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
username (str): Username of the user
|
|
||||||
name (str): New first name
|
|
||||||
last_name (str): New last name
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if updated successfully, False otherwise
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
name_alias = build_name_synonym(name, last_name)
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
|
|
||||||
|
safe_name = dp.encrypt_text(name.strip()) if name else ''
|
||||||
|
safe_last_name = dp.encrypt_text(last_name.strip()) if last_name else ''
|
||||||
|
|
||||||
result = users.update_one(
|
result = users.update_one(
|
||||||
{'Username': username},
|
{'Username': dp.encrypt_text(username)},
|
||||||
{'$set': {'name': name_alias, 'last_name': ''}}
|
{'$set': {'name': safe_name, 'last_name': safe_last_name}}
|
||||||
)
|
)
|
||||||
|
if result.matched_count == 0:
|
||||||
|
result = users.update_one(
|
||||||
|
{'username': dp.encrypt_text(username)},
|
||||||
|
{'$set': {'name': safe_name, 'last_name': safe_last_name}}
|
||||||
|
)
|
||||||
|
|
||||||
client.close()
|
client.close()
|
||||||
return True
|
return True
|
||||||
|
|||||||
Reference in New Issue
Block a user