diff --git a/apps/users/api/profile.py b/apps/users/api/profile.py index 3f1f04e843ee0683beb425d18ae9ec3db73d353e..321ef54e1e8fa1d90e88bb128de3ffb977171bd4 100644 --- a/apps/users/api/profile.py +++ b/apps/users/api/profile.py @@ -14,6 +14,7 @@ from .mixins import UserQuerysetMixin __all__ = [ 'UserResetPasswordApi', 'UserResetPKApi', 'UserProfileApi', 'UserUpdatePKApi', + 'UserPasswordApi', 'UserPublicKeyApi' ] @@ -66,3 +67,24 @@ class UserProfileApi(generics.RetrieveUpdateAPIView): age = request.session.get_expiry_age() request.session.set_expiry(age) return super().retrieve(request, *args, **kwargs) + + +class UserPasswordApi(generics.RetrieveUpdateAPIView): + permission_classes = (IsAuthenticated,) + serializer_class = serializers.UserUpdatePasswordSerializer + + def get_object(self): + return self.request.user + + +class UserPublicKeyApi(generics.RetrieveUpdateAPIView): + permission_classes = (IsAuthenticated,) + serializer_class = serializers.UserUpdatePublicKeySerializer + + def get_object(self): + return self.request.user + + def perform_update(self, serializer): + user = self.get_object() + user.public_key = serializer.validated_data['public_key'] + user.save() diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index e6e55a18be9bdd091b26aca61f16fadc3cd9ed0d..20c412d32caa406e8d07fe10a273b4643716e49b 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -14,7 +14,8 @@ from ..models import User __all__ = [ 'UserSerializer', 'UserPKUpdateSerializer', 'ChangeUserPasswordSerializer', 'ResetOTPSerializer', - 'UserProfileSerializer', 'UserOrgSerializer' + 'UserProfileSerializer', 'UserOrgSerializer', + 'UserUpdatePasswordSerializer', 'UserUpdatePublicKeySerializer' ] @@ -234,3 +235,42 @@ class UserProfileSerializer(UserSerializer): if callable(obj.public_key_obj.hash_md5): return obj.public_key_obj.hash_md5() return '' + + +class UserUpdatePasswordSerializer(serializers.ModelSerializer): + old_password = serializers.CharField(required=True, max_length=128, write_only=True) + new_password = serializers.CharField(required=True, max_length=128, write_only=True) + new_password_again = serializers.CharField(required=True, max_length=128, write_only=True) + + class Meta: + model = User + fields = ['old_password', 'new_password', 'new_password_again'] + + def validate_old_password(self, value): + if not self.instance.check_password(value): + msg = 'The old password is incorrect' + raise serializers.ValidationError(msg) + return value + + @staticmethod + def validate_new_password(value): + from ..utils import check_password_rules + if not check_password_rules(value): + msg = _('Password does not match security rules') + raise serializers.ValidationError(msg) + return value + + def validate_new_password_again(self, value): + if value != self.initial_data.get('new_password', ''): + msg = 'The newly set password is inconsistent' + raise serializers.ValidationError(msg) + return value + + def update(self, instance, validated_data): + new_password = self.validated_data.get('new_password') + instance.reset_password(new_password) + return instance + + +class UserUpdatePublicKeySerializer(serializers.ModelSerializer): + pass diff --git a/apps/users/urls/api_urls.py b/apps/users/urls/api_urls.py index b3a75f9ba4f86aa6a0982c6196bec7e14c0885b1..ea1101eaedc3f36e0689fc3ad568f3e0ce78c9df 100644 --- a/apps/users/urls/api_urls.py +++ b/apps/users/urls/api_urls.py @@ -21,6 +21,8 @@ urlpatterns = [ path('connection-token/', auth_api.UserConnectionTokenApi.as_view(), name='connection-token'), path('profile/', api.UserProfileApi.as_view(), name='user-profile'), + path('profile/password/', api.UserPasswordApi.as_view(), name='user-password'), + path('profile/public-key/', api.UserPublicKeyApi.as_view(), name='user-public-key'), path('otp/reset/', api.UserResetOTPApi.as_view(), name='my-otp-reset'), path('users//otp/reset/', api.UserResetOTPApi.as_view(), name='user-reset-otp'), path('users//password/', api.UserChangePasswordApi.as_view(), name='change-user-password'),