auth.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. from rest_framework.decorators import api_view, permission_classes
  2. from rest_framework.response import Response
  3. from django.contrib import auth
  4. from django.utils.translation import ugettext as _
  5. from django.views.decorators.csrf import csrf_protect
  6. from django.shortcuts import get_object_or_404
  7. from misago.conf import settings
  8. from misago.core.mail import mail_user
  9. from misago.users.serializers import (
  10. AnonymousUserSerializer, AuthenticatedUserSerializer, LoginSerializer,
  11. ResendActivationSerializer, SendPasswordFormSerializer, ChangePasswordSerializer)
  12. from misago.users.tokens import (
  13. make_activation_token, make_password_change_token)
  14. from .rest_permissions import UnbannedAnonOnly, UnbannedOnly
  15. UserModel = auth.get_user_model()
  16. def gateway(request):
  17. if request.method == 'POST':
  18. return login(request)
  19. else:
  20. return session_user(request)
  21. @api_view(['POST'])
  22. @permission_classes((UnbannedAnonOnly, ))
  23. @csrf_protect
  24. def login(request):
  25. """
  26. POST /auth/ with CSRF, username and password
  27. will attempt to authenticate new user
  28. """
  29. serializer = LoginSerializer(request, data=request.data)
  30. serializer.is_valid(raise_exception=True)
  31. user = serializer.validated_data['user']
  32. auth.login(request, user)
  33. return Response(
  34. AuthenticatedUserSerializer(user).data,
  35. )
  36. @api_view()
  37. def session_user(request):
  38. """GET /auth/ will return current auth user, either User or AnonymousUser"""
  39. if request.user.is_authenticated:
  40. UserSerializer = AuthenticatedUserSerializer
  41. else:
  42. UserSerializer = AnonymousUserSerializer
  43. return Response(UserSerializer(request.user).data)
  44. @api_view(['GET'])
  45. def get_requirements(request):
  46. """GET /auth/requirements/ will return password and username requirements"""
  47. requirements = {
  48. 'username': {
  49. 'min_length': settings.username_length_min,
  50. 'max_length': settings.username_length_max,
  51. },
  52. 'password': [],
  53. }
  54. for validator in settings.AUTH_PASSWORD_VALIDATORS:
  55. validator_dict = {'name': validator['NAME'].split('.')[-1]}
  56. validator_dict.update(validator.get('OPTIONS', {}))
  57. requirements['password'].append(validator_dict)
  58. return Response(requirements)
  59. @api_view(['POST'])
  60. @permission_classes((UnbannedAnonOnly, ))
  61. @csrf_protect
  62. def send_activation(request):
  63. """
  64. POST /auth/send-activation/ with CSRF token and email
  65. will mail account activation link to requester
  66. """
  67. serializer = ResendActivationSerializer(data=request.data)
  68. serializer.is_valid(raise_exception=True)
  69. serializer.raise_if_banned()
  70. user = serializer.validated_data['user']
  71. mail_subject = _("Activate %(user)s account on %(forum_name)s forums") % {
  72. 'user': user.username,
  73. 'forum_name': settings.forum_name,
  74. }
  75. mail_user(
  76. request,
  77. user,
  78. mail_subject,
  79. 'misago/emails/activation/by_user',
  80. {
  81. 'activation_token': make_activation_token(user),
  82. },
  83. )
  84. return Response({
  85. 'username': user.username,
  86. 'email': user.email,
  87. })
  88. @api_view(['POST'])
  89. @permission_classes((UnbannedOnly, ))
  90. @csrf_protect
  91. def send_password_form(request):
  92. """
  93. POST /auth/send-password-form/ with CSRF token and email
  94. will mail change password form link to requester
  95. """
  96. serializer = SendPasswordFormSerializer(data=request.data)
  97. serializer.is_valid(raise_exception=True)
  98. serializer.raise_if_banned()
  99. user = serializer.validated_data['user']
  100. mail_subject = _("Change %(user)s password on %(forum_name)s forums") % {
  101. 'user': user.username,
  102. 'forum_name': settings.forum_name,
  103. }
  104. confirmation_token = make_password_change_token(user)
  105. mail_user(
  106. request,
  107. user,
  108. mail_subject,
  109. 'misago/emails/change_password_form_link',
  110. {
  111. 'confirmation_token': confirmation_token,
  112. },
  113. )
  114. return Response({
  115. 'username': user.username,
  116. 'email': user.email,
  117. })
  118. class PasswordChangeFailed(Exception):
  119. pass
  120. @api_view(['POST'])
  121. @permission_classes((UnbannedOnly, ))
  122. @csrf_protect
  123. def change_forgotten_password(request, pk):
  124. """
  125. POST /auth/change-password/user/ with CSRF and new password
  126. will change forgotten password
  127. """
  128. user = get_object_or_404(UserModel, pk=pk, is_active=True)
  129. serializer = ChangePasswordSerializer(user, data=request.data)
  130. serializer.is_valid(raise_exception=True)
  131. serializer.save()
  132. return Response({'username': user.username})