Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create change password API for drupal #531

Merged
merged 1 commit into from
Apr 16, 2024
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
5 changes: 5 additions & 0 deletions openedx/core/djangoapps/user_authn/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,8 @@ class MFEContextSerializer(serializers.Serializer):
'extended_profile': []
}
)


class ChangePasswordSerializer(serializers.Serializer):
current_password = serializers.CharField(required=True)
new_password = serializers.CharField(required=True)
2 changes: 2 additions & 0 deletions openedx/core/djangoapps/user_authn/urls_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@

# Password reset api views.
path('password_reset/', password_reset.password_reset, name='password_reset'),
path('api/user/v1/account/change_password/', password_reset.ChangePasswordAPIView.as_view(),
name='user_change_password_api'),
re_path(
r'^password_reset_confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
PasswordResetConfirmWrapper.as_view(),
Expand Down
31 changes: 31 additions & 0 deletions openedx/core/djangoapps/user_authn/views/password_reset.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@
from django.views.decorators.http import require_POST
from edx_ace import ace
from edx_ace.recipient import Recipient
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
from eventtracking import tracker
from django_ratelimit.decorators import ratelimit
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.throttling import AnonRateThrottle
from rest_framework.views import APIView
Expand All @@ -36,6 +39,7 @@
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.theming.helpers import get_current_request, get_current_site
from openedx.core.djangoapps.user_api import accounts, errors, helpers
from openedx.core.djangoapps.user_authn.serializers import ChangePasswordSerializer
from openedx.core.djangoapps.user_authn.toggles import should_redirect_to_authn_microfrontend
from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_feature_enabled
from openedx.core.djangoapps.user_api.helpers import FormDescription
Expand All @@ -44,6 +48,7 @@
from openedx.core.djangoapps.user_authn.message_types import PasswordReset, PasswordResetSuccess
from openedx.core.djangoapps.user_authn.utils import check_pwned_password
from openedx.core.djangolib.markup import HTML
from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
from common.djangoapps.student.forms import send_account_recovery_email_for_user
from common.djangoapps.student.models import AccountRecovery, LoginFailures
from common.djangoapps.util.json_request import JsonResponse
Expand Down Expand Up @@ -244,6 +249,32 @@ def get(self, request):
return HttpResponse(get_password_reset_form().to_json(), content_type="application/json") # lint-amnesty, pylint: disable=http-response-with-content-type-json


class ChangePasswordAPIView(APIView):
authentication_classes = (
JwtAuthentication, BearerAuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser
)
permission_classes = (IsAuthenticated,)

def post(self, request):
serializer = ChangePasswordSerializer(data=request.data)
if serializer.is_valid():
current_password = serializer.validated_data['current_password']
new_password = serializer.validated_data['new_password']
user = request.user

# Check if the current password provided matches the user's actual password
if not user.check_password(current_password):
log.info(f"\nCurrent password is incorrect.")
return Response({"error": "Current password is incorrect."}, status=400)

# Change the user's password
user.set_password(new_password)
user.save()
log.info(f"\nPassword changed successfully.")
return Response({"message": "Password changed successfully."}, status=200)
else:
return Response(serializer.errors, status=400)

@helpers.intercept_errors(errors.UserAPIInternalError, ignore_errors=[errors.UserAPIRequestError])
def request_password_change(email, is_secure):
"""Email a single-use link for performing a password reset.
Expand Down
Loading