Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ jobs:
run: |
cd src
python manage.py migrate
python manage.py test

python manage.py test tests/

build_docker:
needs: [ lint ]
Expand Down
3 changes: 3 additions & 0 deletions api-collection/environments/development.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
vars {
baseUrl: https://dev-api.unitystation.org
}
7 changes: 5 additions & 2 deletions src/accounts/validators.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from django.contrib.auth.validators import ASCIIUsernameValidator
from django.utils.deconstruct import deconstructible

IDENTIFIER_REGEX = r"^[a-zA-Z0-9_\-\.]{3,}$"
USERNAME_REGEX = r"^[a-zA-Z0-9\.\-_](?!.* {2})[ \w.-]{1,}[a-zA-Z0-9\.\-_]$"


@deconstructible()
class AccountNameValidator(ASCIIUsernameValidator):
# match account identifier that only has letters, numbers, dash, underscore
# and at least 3 characters
regex = r"^[a-zA-Z0-9_\-]{3,}$"
regex = IDENTIFIER_REGEX
message = (
"Enter a valid account identifier. This value may contain only English letters, numbers, and -/_ characters."
)
Expand All @@ -16,7 +19,7 @@ class AccountNameValidator(ASCIIUsernameValidator):
class UsernameValidator(ASCIIUsernameValidator):
# match username that has at least 3 characters, letters, numbers, dashes,
# underscores, dots, and spaces but no consecutive whitespaces
regex = r"^[a-zA-Z0-9\.\-_](?!.* {2})[ \w.-_]{2,}$"
regex = USERNAME_REGEX
message = (
"Enter a valid username. This value may contain only English letters, "
"numbers, dashes, underscores, dots, and spaces."
Expand Down
Empty file added src/tests/__init__.py
Empty file.
67 changes: 67 additions & 0 deletions src/tests/test_username_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from accounts.validators import IDENTIFIER_REGEX, USERNAME_REGEX
from django.test import TestCase


class IdentifierRegexTest(TestCase):
# a valid identifier has at least 3 characters with letters, numbers, dashes, underscores, dots and no other special
# characters.
def test_valid_identifier(self):
valid_identifiers = ["username123", "user_name", "user-name", "user.name", "user123", "123", "abc"]

for identifier in valid_identifiers:
with self.subTest(identifier=identifier):
self.assertRegex(identifier, IDENTIFIER_REGEX)

def test_invalid_identifier(self):
invalid_identifiers = [
"us", # Too short
"user!", # Invalid character
"user@name", # Invalid character
"user name", # Invalid character (space)
]

for identifier in invalid_identifiers:
with self.subTest(identifier=identifier):
self.assertNotRegex(identifier, IDENTIFIER_REGEX)


class UsernameRegexTest(TestCase):
# a valid username has at least 3 characters, letters, numbers, dashes, underscores, dots, and spaces but no
# consecutive whitespaces.
def test_valid_username(self):
# List of valid usernames
valid_usernames = [
"username",
"user name",
"user_name",
"user.name",
"user-name",
"user123",
"123 username",
"user name123",
"u n",
"u.n",
"u_n",
"u-n",
]

# Test that each valid username is correctly matched by the USERNAME_REGEX
for username in valid_usernames:
with self.subTest(username=username):
self.assertRegex(username, USERNAME_REGEX)

def test_invalid_username(self):
# List of invalid usernames
invalid_usernames = [
"us", # Too short
"user!name", # Contains an invalid character
"user@name", # Contains an invalid character
" username", # Leading whitespace
"username ", # Trailing whitespace
"user name", # Consecutive whitespaces
]

# Test that each invalid username is not matched by the USERNAME_REGEX
for username in invalid_usernames:
with self.subTest(username=username):
self.assertNotRegex(username, USERNAME_REGEX)