validation.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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_validators, oauth2_user_data_filters
  8. from ..users.validators import (
  9. validate_username_content,
  10. validate_username_length,
  11. )
  12. from .exceptions import OAuth2UserDataValidationError
  13. User = get_user_model()
  14. class UsernameSettings:
  15. username_length_max: int = 200
  16. username_length_min: int = 1
  17. def validate_user_data(request, user, user_data, response_json):
  18. filtered_data = filter_user_data(request, user, user_data)
  19. try:
  20. validate_username_content(filtered_data["name"])
  21. validate_username_length(UsernameSettings, filtered_data["name"])
  22. validate_email(filtered_data["email"])
  23. for plugin_oauth2_validator in oauth2_validators:
  24. plugin_oauth2_validator(request, user, user_data, response_json)
  25. except ValidationError as exc:
  26. raise OAuth2UserDataValidationError(error_list=[str(exc.message)])
  27. return filtered_data
  28. def filter_user_data(request, user, user_data):
  29. filtered_data = {
  30. "id": user_data["id"],
  31. "name": str(user_data["name"] or "").strip(),
  32. "email": str(user_data["email"] or "").strip(),
  33. "avatar": filter_user_avatar(user_data["avatar"]),
  34. }
  35. if oauth2_user_data_filters:
  36. return filter_user_data_with_filters(
  37. request, user, filtered_data, oauth2_user_data_filters
  38. )
  39. else:
  40. filtered_data["name"] = filter_name(user, filtered_data["name"])
  41. return filtered_data
  42. def filter_user_avatar(user_avatar):
  43. if user_avatar:
  44. return str(user_avatar).strip() or None
  45. return None
  46. def filter_user_data_with_filters(request, user, user_data, filters):
  47. for filter_user_data in filters:
  48. user_data = filter_user_data(request, user, user_data.copy()) or user_data
  49. return user_data
  50. def filter_name(user, name):
  51. if user and user.username == name:
  52. return name
  53. clean_name = "".join(
  54. [c for c in unidecode(name.replace(" ", "_")) if c.isalnum() or c == "_"]
  55. )
  56. if user and user.username == clean_name:
  57. return clean_name # No change in name
  58. if not clean_name.replace("_", ""):
  59. clean_name = "User_%s" % get_random_string(4)
  60. clean_name_root = clean_name
  61. while True:
  62. try:
  63. db_user = User.objects.get_by_username(clean_name)
  64. except User.DoesNotExist:
  65. return clean_name
  66. if not user or user.pk != db_user.pk:
  67. clean_name = f"{clean_name_root}_{get_random_string(4)}"
  68. else:
  69. return clean_name