Created
January 27, 2025 01:03
-
-
Save KosayJabre/61cae43bab664f317fdf7ff43d31dc10 to your computer and use it in GitHub Desktop.
Basic username validation. Checks for profanity, emails, and other basic rules.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from better_profanity import profanity | |
from pydantic import BaseModel | |
from email_validator import validate_email, EmailNotValidError | |
MINIMUM_USERNAME_LENGTH = 3 | |
MAXIMUM_USERNAME_LENGTH = 24 | |
ALLOWED_CHARACTERS_REGEX = re.compile(r"^[\x20-\x7E]+$") # Only allow visible/printable ASCII characters | |
RESERVED_WORDS = ["admin", "administrator", "staff", "support", "root"] | |
class UsernameValidationResult(BaseModel): | |
is_valid: bool | |
reason: str | None = None | |
def validate_username(username: str) -> UsernameValidationResult: | |
if len(username) < MINIMUM_USERNAME_LENGTH: | |
return UsernameValidationResult(is_valid=False, reason=f"Username is too short. It must be at least {MINIMUM_USERNAME_LENGTH} characters.") | |
if len(username) > MAXIMUM_USERNAME_LENGTH: | |
return UsernameValidationResult(is_valid=False, reason=f"Username is too long. It must be at most {MAXIMUM_USERNAME_LENGTH} characters.") | |
if username.strip() != username: | |
return UsernameValidationResult(is_valid=False, reason=f"Username cannot start or end with whitespace.") | |
if not ALLOWED_CHARACTERS_REGEX.match(username): | |
return UsernameValidationResult( | |
is_valid=False, reason=f"Username contains invalid characters. Only alphanumeric characters, underscores, and hyphens are allowed." | |
) | |
if username.isdigit(): | |
return UsernameValidationResult(is_valid=False, reason=f"Username cannot be number-only.") | |
if username.lower() in RESERVED_WORDS: | |
return UsernameValidationResult(is_valid=False, reason=f"Username is reserved.") | |
if profanity.contains_profanity(username): | |
return UsernameValidationResult(is_valid=False, reason=f"Username might contain profanity.") | |
try: | |
validate_email(username, check_deliverability=False) # check_deliverability=False makes it not require internet | |
return UsernameValidationResult(is_valid=False, reason=f"Username cannot be an email address.") | |
except EmailNotValidError as e: | |
pass # Username is not an email address | |
return UsernameValidationResult(is_valid=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment