Skip to content
Open
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
1 change: 1 addition & 0 deletions trojstenid/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
"reset_password_from_key": "trojstenid.users.forms.allauth.OurResetPasswordKeyForm",
"set_password": "trojstenid.users.forms.allauth.OurSetPasswordForm",
}
ACCOUNT_USERNAME_VALIDATORS = "trojstenid.users.models.username_validators"

SOCIALACCOUNT_PROVIDERS = {
"openid_connect": {
Expand Down
Empty file.
Empty file.
53 changes: 53 additions & 0 deletions trojstenid/users/management/commands/normalize_usernames.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import re
import unicodedata

from django.core.management.base import BaseCommand

from trojstenid.users.models import User, UsernameValidator


def normalize_username(username: str) -> str:
normalized = (
unicodedata.normalize("NFKD", username).encode("ASCII", "ignore").decode()
)

if "@" in normalized:
parts = normalized.split("@", 1)
if parts[0]:
normalized = parts[0]
else:
normalized = parts[1]

normalized = re.sub(r"[^\w.-]", "", normalized)

return normalized


class Command(BaseCommand):
help = "Validate and normalize usernames"

def add_arguments(self, parser):
parser.add_argument(
"--dry-run",
action="store_true",
help="Run without making changes to the database",
)

def handle(self, *args, **options):
dry_run = options["dry_run"]
validator = UsernameValidator()

users = User.objects.all()

for user in users:
try:
validator(user.username)
except Exception:
new_username = normalize_username(user.username)

if new_username != user.username:
self.stdout.write(f"{user.username} ({user.id}) -> {new_username}")

if not dry_run:
user.username = new_username
user.save()
13 changes: 13 additions & 0 deletions trojstenid/users/models.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import re
from datetime import date
from pathlib import PurePath
from typing import TYPE_CHECKING

from django.contrib.auth.models import AbstractUser, Group
from django.core import validators
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models import Q
from django.urls import reverse
from django.utils import timezone
from django.utils.deconstruct import deconstructible
from oauth2_provider.models import AbstractApplication
from ulid import ULID

Expand Down Expand Up @@ -40,6 +43,16 @@ def get_db_converters(self, connection):
return []


@deconstructible()
class UsernameValidator(validators.RegexValidator):
regex = r"^[\w.-]+\Z"
message = "Používateľské meno môže obsahovať len písmená, čísla a znaky ./-/_"
flags = re.ASCII


username_validators = [UsernameValidator()]


class User(AbstractUser):
id: int

Expand Down