validation.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. from dataclasses import dataclass
  2. from django.contrib.auth import get_user_model
  3. from django.core.validators import validate_email
  4. from django.forms import ValidationError
  5. from django.utils.crypto import get_random_string
  6. from unidecode import unidecode
  7. from ..hooks import oauth2_user_data_filters
  8. from ..users.validators import (
  9. validate_new_registration,
  10. validate_username_content,
  11. validate_username_length,
  12. )
  13. from .exceptions import OAuth2UserDataValidationError
  14. User = get_user_model()
  15. class UsernameSettings:
  16. username_length_max: int = 200
  17. username_length_min: int = 1
  18. def validate_user_data(request, user, user_data):
  19. filtered_data = filter_user_data(request, user, user_data)
  20. try:
  21. errors_list = []
  22. def add_error(_field_unused: str | None, error: str | ValidationError):
  23. if isinstance(error, ValidationError):
  24. error = error.message
  25. errors_list.append(str(error))
  26. validate_username_content(user_data["name"])
  27. validate_username_length(UsernameSettings, user_data["name"])
  28. validate_email(user_data["email"])
  29. validate_new_registration(request, filtered_data, add_error)
  30. except ValidationError as exc:
  31. raise OAuth2UserDataValidationError(error_list=[str(exc.message)])
  32. if errors_list:
  33. raise OAuth2UserDataValidationError(error_list=errors_list)
  34. return filtered_data
  35. def filter_user_data(request, user, user_data):
  36. if oauth2_user_data_filters:
  37. return filter_user_data_with_filters(
  38. request, user, user_data, oauth2_user_data_filters
  39. )
  40. else:
  41. user_data["name"] = filter_name(user, user_data["name"])
  42. return user_data
  43. def filter_user_data_with_filters(request, user, user_data, filters):
  44. for filter_user_data in filters:
  45. user_data = filter_user_data(request, user, user_data) or user_data
  46. return user_data
  47. def filter_name(user, name):
  48. if user and user.username == name:
  49. return name
  50. clean_name = "".join(
  51. [c for c in unidecode(name.replace(" ", "_")) if c.isalnum() or c == "_"]
  52. )
  53. if user and user.username == clean_name:
  54. return clean_name # No change in name
  55. if not clean_name.replace("_", ""):
  56. clean_name = "User_%s" % get_random_string(4)
  57. clean_name_root = clean_name
  58. while True:
  59. try:
  60. db_user = User.objects.get_by_username(clean_name)
  61. except User.DoesNotExist:
  62. return clean_name
  63. if not user or user.pk != db_user.pk:
  64. clean_name = f"{clean_name_root}_{get_random_string(4)}"
  65. else:
  66. return clean_name