diff --git a/Web/app.py b/Web/app.py index f4f98f6..a3b5a95 100755 --- a/Web/app.py +++ b/Web/app.py @@ -7116,8 +7116,8 @@ def register(): name = (request.form.get('name') or '').strip() last_name = (request.form.get('last-name') or '').strip() - # Always generate username from abbreviation logic and auto-extend on collisions. - username = us.build_unique_username_from_name(name, last_name) + # Generate a truly anonymized username for new users. + username = us.build_anonymous_username() permission_preset = (request.form.get('permission_preset') or 'standard_user').strip() use_custom_permissions = request.form.get('use_custom_permissions') == 'on' diff --git a/Web/user.py b/Web/user.py index cc4b9ab..f40eca1 100755 --- a/Web/user.py +++ b/Web/user.py @@ -13,6 +13,8 @@ Provides methods for creating, validating, and retrieving user information. import hashlib import copy import re +import secrets +import string from bson.objectid import ObjectId import settings as cfg from settings import MongoClient @@ -57,6 +59,12 @@ def build_name_synonym(first_name, last_name=''): return combined[:6].title() +def _generate_anonymous_username(prefix='user', length=8): + """Generate a random anonymized username using lowercase letters and digits.""" + alphabet = string.ascii_lowercase + string.digits + return prefix + ''.join(secrets.choice(alphabet) for _ in range(length)) + + def build_username_from_name(first_name, last_name=''): """ Build a deterministic username abbreviation from first and last name. @@ -73,6 +81,22 @@ def build_username_from_name(first_name, last_name=''): return alias.lower() +def build_anonymous_username(): + """ + Build a truly anonymized username that is not derived from the user's + first name or last name. + """ + for _ in range(10): + candidate = _generate_anonymous_username() + if not get_user(candidate): + return candidate + + suffix = 2 + while get_user(f"user{suffix}"): + suffix += 1 + return f"user{suffix}" + + def build_unique_username_from_name(first_name, last_name=''): """ Build a unique username based on the abbreviation logic.