def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        token = serializer.validated_data['token']

        # get token validation time
        password_reset_token_validation_time = get_password_reset_token_expiry_time(
        )

        # find token
        reset_password_token = ResetPasswordToken.objects.filter(
            key=token).first()

        if reset_password_token is None:
            return Response({'status': 'notfound'},
                            status=status.HTTP_404_NOT_FOUND)

        # check expiry date
        expiry_date = reset_password_token.created_at + timedelta(
            hours=password_reset_token_validation_time)

        if timezone.now() > expiry_date:
            # delete expired token
            reset_password_token.delete()
            return Response({'status': 'expired'},
                            status=status.HTTP_404_NOT_FOUND)

        return Response({'status': 'OK'})
Exemplo n.º 2
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        token = serializer.validated_data['token']
        response_dict = dict({"status_code": None, "status": None, "message": None})
        # get token validation time
        password_reset_token_validation_time = get_password_reset_token_expiry_time()

        # find token
        reset_password_token = ResetPasswordToken.objects.filter(key=token).first()

        if reset_password_token is None:
            message = get_response_message("TOKEN_NOT_FOUND")
            response_dict.update({"status_code": 404, "status": "notfound", "message": message})
            return Response(response_dict, status=status.HTTP_404_NOT_FOUND)

        # check expiry date
        expiry_date = reset_password_token.created_at + timedelta(hours=password_reset_token_validation_time)

        if timezone.now() > expiry_date:
            # delete expired token
            reset_password_token.delete()
            message = get_response_message("TOKEN_EXPIRED")
            response_dict.update({"status_code": 401, 'status': 'expired', "message": message})
            return Response(response_dict, status=status.HTTP_404_NOT_FOUND)

        message = get_response_message("TOKEN_VALID")
        response_dict.update({"status_code": 200, 'status': 'OK', "message": message})
        return Response(response_dict)
    def validate(self, data):
        token = data.get('token')

        # get token validation time
        password_reset_token_validation_time = get_password_reset_token_expiry_time(
        )

        # find token
        try:
            reset_password_token = _get_object_or_404(
                models.ResetPasswordToken, key=token)
        except (TypeError, ValueError, ValidationError, Http404,
                models.ResetPasswordToken.DoesNotExist):
            raise Http404(
                _("The OTP password entered is not valid. Please check and try again."
                  ))

        # check expiry date
        expiry_date = reset_password_token.created_at + timedelta(
            hours=password_reset_token_validation_time)

        if timezone.now() > expiry_date:
            # delete expired token
            reset_password_token.delete()
            raise Http404(_("The token has expired"))
        return data
Exemplo n.º 4
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        email = serializer.validated_data['email']

        # before we continue, delete all existing expired tokens
        password_reset_token_validation_time = get_password_reset_token_expiry_time()

        # datetime.now minus expiry hours
        now_minus_expiry_time = timezone.now() - timedelta(hours=password_reset_token_validation_time)

        # delete all tokens where created_at < now - 24 hours
        clear_expired(now_minus_expiry_time)

        # find a user by email address (case insensitive search)
        users = User.objects.filter(**{'{}__iexact'.format(get_password_reset_lookup_field()): email})

        active_user_found = False

        # iterate over all users and check if there is any user that is active
        # also check whether the password can be changed (is useable), as there could be users that are not allowed
        # to change their password (e.g., LDAP user)
        for user in users:
            if user.eligible_for_reset():
                active_user_found = True

        # No active user found, raise a validation error
        # but not if DJANGO_REST_PASSWORDRESET_NO_INFORMATION_LEAKAGE == True
        if not active_user_found and not getattr(settings, 'DJANGO_REST_PASSWORDRESET_NO_INFORMATION_LEAKAGE', False):
            raise exceptions.ValidationError({

                'email': [_(
                    "There is no active user associated with this e-mail address or the password can not be changed")],
            })

        # last but not least: iterate over all users that are active and can change their password
        # and create a Reset Password Token and send a signal with the created token
        for user in users:
            if user.eligible_for_reset():
                # define the token as none for now
                token = None

                # check if the user already has a token
                if user.password_reset_tokens.all().count() > 0:
                    # yes, already has a token, re-use this token
                    token = user.password_reset_tokens.all()[0]
                else:
                    # no token exists, generate a new token
                    token = ResetPasswordToken.objects.create(
                        user=user,
                        user_agent=request.META.get(HTTP_USER_AGENT_HEADER, ''),
                        ip_address=request.META.get(HTTP_IP_ADDRESS_HEADER, ''),
                    )
                # send a signal that the password token was created
                # let whoever receives this signal handle sending the email for the password reset
                reset_password_token_created.send(sender=self.__class__, instance=self, reset_password_token=token)
        # done
        message = get_response_message("PASSWORD_REQUEST_ACCEPT")
        return Response({"status_code": 200, "status": "OK", "message": message})
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        email = serializer.validated_data['email']

        # before we continue, delete all existing expired tokens
        password_reset_token_validation_time = get_password_reset_token_expiry_time()

        # datetime.now minus expiry hours
        now_minus_expiry_time = timezone.now() - timedelta(hours=password_reset_token_validation_time)

        # delete all tokens where created_at < now - 24 hours
        clear_expired(now_minus_expiry_time)

        # find a user by email address (case insensitive search)
        users = User.objects.filter(email__iexact=email)

        active_user_found = False

        # iterate over all users and check if there is any user that is active
        # also check whether the password can be changed (is useable), as there could be users that are not allowed
        # to change their password (e.g., LDAP user)
        for user in users:
            if user.is_active and user.has_usable_password():
                active_user_found = True

        # No active user found, raise a validation error
        if not active_user_found:
            raise exceptions.ValidationError({
                'email': [_(
                    "There is no active user associated with this e-mail address or the password can not be changed")],
            })

        # last but not least: iterate over all users that are active and can change their password
        # and create a Reset Password Token and send a signal with the created token
        for user in users:
            if user.is_active and user.has_usable_password():
                # define the token as none for now
                token = None

                # check if the user already has a token
                if user.password_reset_tokens.all().count() > 0:
                    # yes, already has a token, re-use this token
                    token = user.password_reset_tokens.all()[0]
                else:
                    # no token exists, generate a new token
                    token = ResetPasswordToken.objects.create(
                        user=user,
                        user_agent=request.META.get('HTTP_USER_AGENT',
                                                    getattr(settings, 'DJANGO_REST_PASSWORDRESET_HTTP_USER_AGENT', '')),
                        ip_address=request.META.get('REMOTE_ADDR',
                                                    getattr(settings, 'DJANGO_REST_PASSWORDRESET_REMOTE_ADDR', ''))
                    )
                # send a signal that the password token was created
                # let whoever receives this signal handle sending the email for the password reset
                reset_password_token_created.send(sender=self.__class__, instance=self, reset_password_token=token)
        # done
        return Response({'status': 'OK'})
Exemplo n.º 6
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        password = serializer.validated_data['password']
        token = serializer.validated_data['token']
        response_dict = dict({"status_code": None, "message": None, "status": None})

        # get token validation time
        password_reset_token_validation_time = get_password_reset_token_expiry_time()

        # find token
        reset_password_token = ResetPasswordToken.objects.filter(key=token).first()

        if reset_password_token is None:
            message = get_response_message("TOKEN_NOT_FOUND")
            response_dict.update({"status_code": 404, 'status': 'notfound', "message": message})
            return Response(response_dict, status=status.HTTP_404_NOT_FOUND)

        # check expiry date
        expiry_date = reset_password_token.created_at + timedelta(hours=password_reset_token_validation_time)

        if timezone.now() > expiry_date:
            # delete expired token
            reset_password_token.delete()
            message = get_response_message("TOKEN_EXPIRED")
            response_dict.update({"status_code": 404, 'status': 'expired', "message": message})

            return Response(response_dict, status=status.HTTP_404_NOT_FOUND)

        # change users password (if we got to this code it means that the user is_active)
        if reset_password_token.user.eligible_for_reset():
            pre_password_reset.send(sender=self.__class__, user=reset_password_token.user)
            try:
                # validate the password against existing validators
                validate_password(
                    password,
                    user=reset_password_token.user,
                    password_validators=get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)
                )
            except ValidationError as e:
                # raise a validation error for the serializer
                raise exceptions.ValidationError({
                    'password': e.messages
                })

            reset_password_token.user.set_password(password)
            reset_password_token.user.save()
            post_password_reset.send(sender=self.__class__, user=reset_password_token.user)

        # Delete all password reset tokens for this user
        ResetPasswordToken.objects.filter(user=reset_password_token.user).delete()

        # done
        message = get_response_message("PASSWORD_CHANGED")
        response_dict.update({"status_code": 200, "status": "OK", "message": message})

        return Response(response_dict)
Exemplo n.º 7
0
def clear_expired_tokens():
    """Function used to clear existing and expired tokens."""
    password_reset_token_validation_time = (
        get_password_reset_token_expiry_time())

    # datetime.now minus expiry hours
    now_minus_expiry_time = timezone.now() - timedelta(
        hours=password_reset_token_validation_time)

    # delete all tokens where created_at < now - 24 hours
    clear_expired(now_minus_expiry_time)
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        password = serializer.validated_data['password']
        token = serializer.validated_data['token']

        # get token validation time
        password_reset_token_validation_time = get_password_reset_token_expiry_time(
        )

        # find token
        reset_password_token = ResetPasswordToken.objects.filter(
            key=token).first()

        if reset_password_token is None:
            return Response({'status': 'notfound'},
                            status=status.HTTP_404_NOT_FOUND)

        # check expiry date
        expiry_date = reset_password_token.created_at + timedelta(
            hours=password_reset_token_validation_time)

        if timezone.now() > expiry_date:
            # delete expired token
            reset_password_token.delete()
            return Response({'status': 'expired'},
                            status=status.HTTP_404_NOT_FOUND)

        # change users password
        if reset_password_token.user.has_usable_password():
            pre_password_reset.send(sender=self.__class__,
                                    user=reset_password_token.user)
            try:
                # validate the password against existing validators
                validate_password(password,
                                  user=reset_password_token.user,
                                  password_validators=get_password_validators(
                                      settings.AUTH_PASSWORD_VALIDATORS))
            except ValidationError as e:
                # raise a validation error for the serializer
                raise exceptions.ValidationError({'password': e.messages})

            reset_password_token.user.set_password(password)
            reset_password_token.user.save()
            post_password_reset.send(sender=self.__class__,
                                     user=reset_password_token.user)

        # Delete all password reset tokens for this user
        ResetPasswordToken.objects.filter(
            user=reset_password_token.user).delete()

        return Response({'status': 'OK'})
Exemplo n.º 9
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        password = serializer.validated_data['password']
        confirm  = serializer.validated_data['confirm']
        token = serializer.validated_data['token']

        if password == confirm:
            # get token validation time
            password_reset_token_validation_time = get_password_reset_token_expiry_time()

            # find token
            reset_password_token = ResetPasswordToken.objects.filter(key=token).first()

            if reset_password_token is None:
                return Response({'Estado': 'No encontrado'}, status=status.HTTP_404_NOT_FOUND)

            # check expiry date
            expiry_date = reset_password_token.created_at + timedelta(hours=password_reset_token_validation_time)

            if timezone.now() > expiry_date:
                # delete expired token
                reset_password_token.delete()
                return Response({'Estado': 'Caducado'}, status=status.HTTP_404_NOT_FOUND)

            # change users password (if we got to this code it means that the user is_active)
            if reset_password_token.user.eligible_for_reset():
                pre_password_reset.send(sender=self.__class__, user=reset_password_token.user)
                try:
                    # validate the password against existing validators
                    validate_password(
                        password,
                        user=reset_password_token.user,
                        password_validators=get_password_validators(settings.AUTH_PASSWORD_VALIDATORS)
                    )
                except ValidationError as e:
                    # raise a validation error for the serializer
                    raise exceptions.ValidationError({
                        'password': e.messages
                    })

                reset_password_token.user.set_password(password)
                reset_password_token.user.save()
                post_password_reset.send(sender=self.__class__, user=reset_password_token.user)

            # Delete all password reset tokens for this user
            ResetPasswordToken.objects.filter(user=reset_password_token.user).delete()

            return Response({'Estado': 'Contraseña modificada'})
        else:
            return Response({'Estado': 'Contraseñas diferentes'})
Exemplo n.º 10
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        password = serializer.validated_data['new_password']
        token = serializer.validated_data['token']

        password_reset_token_validation_time = get_password_reset_token_expiry_time()

        reset_password_token = ResetPasswordToken.objects.filter(
            key=token).first()

        if reset_password_token is None:
            return Response({'status': 'notfound'}, status=status.HTTP_404_NOT_FOUND)

        expiry_date = reset_password_token.created_at + \
            timedelta(hours=password_reset_token_validation_time)

        if timezone.now() > expiry_date:
            reset_password_token.delete()
            return Response({'status': 'expired'}, status=status.HTTP_404_NOT_FOUND)

        if reset_password_token.user.eligible_for_reset():
            pre_password_reset.send(
                sender=self.__class__, user=reset_password_token.user)
            try:
                validate_password(
                    password,
                    user=reset_password_token.user,
                    password_validators=get_password_validators(
                        settings.AUTH_PASSWORD_VALIDATORS)
                )
            except ValidationError as e:
                raise exceptions.ValidationError({
                    'password': e.messages
                })

            reset_password_token.user.set_password(password)
            reset_password_token.user.save()
            post_password_reset.send(
                sender=self.__class__, user=reset_password_token.user)

        ResetPasswordToken.objects.filter(
            user=reset_password_token.user).delete()

        return Response({'status': 'OK'})
Exemplo n.º 11
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        email = serializer.validated_data['email']

        password_reset_token_validation_time = get_password_reset_token_expiry_time()

        now_minus_expiry_time = timezone.now(
        ) - timedelta(hours=password_reset_token_validation_time)

        clear_expired(now_minus_expiry_time)

        users = User.objects.filter(
            **{'{}__iexact'.format(get_password_reset_lookup_field()): email})

        active_user_found = False

        for user in users:
            if user.eligible_for_reset():
                active_user_found = True

        if not active_user_found and not getattr(settings, 'DJANGO_REST_PASSWORDRESET_NO_INFORMATION_LEAKAGE', False):
            raise exceptions.ValidationError({
                'email': [_(
                    "There is no active user associated with this e-mail address or the password can not be changed")],
            })

        for user in users:
            if user.eligible_for_reset():
                token = None

                if user.password_reset_tokens.all().count() > 0:
                    token = user.password_reset_tokens.all()[0]
                else:
                    token = ResetPasswordToken.objects.create(
                        user=user,
                        user_agent=request.META.get(
                            HTTP_USER_AGENT_HEADER, ''),
                        ip_address=request.META.get(
                            HTTP_IP_ADDRESS_HEADER, ''),
                    )

                reset_password_token_created.send(
                    sender=self.__class__, instance=self, reset_password_token=token)
        return Response({'status': 'OK'})
Exemplo n.º 12
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        password = serializer.validated_data['password']
        token = serializer.validated_data['token']

        # get token validation time
        password_reset_token_validation_time = get_password_reset_token_expiry_time(
        )

        # find token
        reset_password_token = ResetPasswordToken.objects.filter(
            key=token).first()

        if reset_password_token is None:
            return Response({'status': 'notfound'},
                            status=status.HTTP_404_NOT_FOUND)

        # check expiry date
        expiry_date = reset_password_token.created_at + timedelta(
            hours=password_reset_token_validation_time)

        if timezone.now() > expiry_date:
            # delete expired token
            reset_password_token.delete()
            return Response({'status': 'expired'},
                            status=status.HTTP_404_NOT_FOUND)

        # change users password
        if reset_password_token.user.has_usable_password():
            pre_password_reset.send(sender=self.__class__,
                                    user=reset_password_token.user)
            reset_password_token.user.set_password(password)
            reset_password_token.user.save()
            post_password_reset.send(sender=self.__class__,
                                     user=reset_password_token.user)

        # Delete all password reset tokens for this user
        ResetPasswordToken.objects.filter(
            user=reset_password_token.user).delete()

        return Response({'status': 'OK'})
Exemplo n.º 13
0
def password_reset_token_created(
        sender,  # pylint: disable=unused-argument
        reset_password_token,
        *_args,
        **_kwargs):
    """Handles password reset tokens.
    When a token is created, an e-mail needs to be sent to the user.
    """

    reset_password_base_url = urljoin(settings.BASE_SITE_URL,
                                      '/reset-password/confirm/')
    context = {
        'current_user': reset_password_token.user,
        'username': reset_password_token.user.username,
        'email': reset_password_token.user.email,
        'reset_password_url':
        f'{reset_password_base_url}?token={reset_password_token.key}',
        'base_site_url': settings.BASE_SITE_URL,
        'site_name': settings.DEFAULT_SITE_NAME,
        'token_expiry_time': get_password_reset_token_expiry_time(),
    }
    email_html_message = render_to_string('email/user_reset_password.html',
                                          context)
    email_plaintext_message = render_to_string('email/user_reset_password.txt',
                                               context)

    msg = EmailMultiAlternatives(
        subject=f'Password reset for {settings.DEFAULT_SITE_NAME}',
        body=email_plaintext_message,
        from_email=settings.DEFAULT_FROM_EMAIL,
        bcc=[reset_password_token.user.email],
        headers={
            'From':
            f'{settings.DEFAULT_SITE_NAME} <{settings.DEFAULT_FROM_EMAIL}>',
            'To': reset_password_token.user.email,
        })
    msg.attach_alternative(email_html_message, 'text/html')
    msg.send()
Exemplo n.º 14
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        email = serializer.validated_data['email']

        # before we continue, delete all existing expired tokens
        password_reset_token_validation_time = get_password_reset_token_expiry_time(
        )

        # datetime.now minus expiry hours
        now_minus_expiry_time = timezone.now() - timedelta(
            hours=password_reset_token_validation_time)

        # delete all tokens where created_at < now - 24 hours
        clear_expired(now_minus_expiry_time)

        # find a user by email address (case insensitive search)
        users = User.objects.filter(email__iexact=email)

        active_user_found = False

        # iterate over all users and check if there is any user that is active
        # also check whether the password can be changed (is useable), as there could be users that are not allowed
        # to change their password (e.g., LDAP user)
        for user in users:
            if user.is_active and user.has_usable_password():
                active_user_found = True

        # No active user found, raise a validation error
        if not active_user_found:
            raise exceptions.ValidationError({
                'email': [
                    _("There is no active user associated with this e-mail address or the password can not be changed"
                      )
                ],
            })

        # last but not least: iterate over all users that are active and can change their password
        # and create a Reset Password Token and send a signal with the created token
        for user in users:
            if user.is_active and user.has_usable_password():
                # define the token as none for now
                token = None

                # check if the user already has a token
                if user.password_reset_tokens.all().count() > 0:
                    # yes, already has a token, re-use this token
                    token = user.password_reset_tokens.all()[0]
                else:
                    ip = request.META.get('REMOTE_ADDR', None)

                    # REMOTE_ADDR may be blank if socket server or load balancer are used, causing an exception
                    # HTTP_X_FORWARDED_FOR as a fallback would be acceptable, since it's for logging purposes
                    # and not authentication (also hard to spoof if load balancer is configured corrrectly)
                    if ip is None or ip == b'':
                        ip = request.META['HTTP_X_FORWARDED_FOR'].split(',')[
                            0]  # grab the first entry

                    # no token exists, generate a new token
                    token = ResetPasswordToken.objects.create(
                        user=user,
                        user_agent=request.META['HTTP_USER_AGENT'],
                        ip_address=ip or '127.0.0.1')
                # send a signal that the password token was created
                # let whoever receives this signal handle sending the email for the password reset
                reset_password_token_created.send(sender=self.__class__,
                                                  instance=self,
                                                  reset_password_token=token)
        # done
        return Response({'status': 'OK'})
Exemplo n.º 15
0
 def handle(self, *args, **options):
     # datetime.now minus expiry hours
     now_minus_expiry_time = timezone.now() - datetime.timedelta(
         hours=get_password_reset_token_expiry_time())
     clear_expired(now_minus_expiry_time)
Exemplo n.º 16
0
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        password = serializer.validated_data['password']
        token = serializer.validated_data['token']
        register = serializer.validated_data['register']

        # get token validation time
        password_reset_token_validation_time = get_password_reset_token_expiry_time(
            register_token=register)

        # find token
        reset_password_token = ResetPasswordToken.objects.filter(
            key=token).first()

        if reset_password_token is None:
            return Response({'status': 'notfound'},
                            status=status.HTTP_404_NOT_FOUND)

        # check expiry date
        expiry_date = reset_password_token.created_at + timedelta(
            hours=password_reset_token_validation_time)

        if timezone.now() > expiry_date:
            # delete expired token
            reset_password_token.delete()
            return Response({'status': 'expired'},
                            status=status.HTTP_404_NOT_FOUND)

        # change users password (if we got to this code it means that the user is_active)
        if reset_password_token.user.eligible_for_reset(
                register_token=register):
            pre_password_reset.send(sender=self.__class__,
                                    user=reset_password_token.user)
            try:
                # validate the password against existing validators
                validate_password(password,
                                  user=reset_password_token.user,
                                  password_validators=get_password_validators(
                                      settings.AUTH_PASSWORD_VALIDATORS))
            except ValidationError as e:
                # raise a validation error for the serializer
                raise exceptions.ValidationError({'password': e.messages})

            reset_password_token.user.set_password(password)
            reset_password_token.user.save()
            post_password_reset.send(sender=self.__class__,
                                     user=reset_password_token.user)

            # Log the user in
            refresh = RefreshToken.for_user(reset_password_token.user)

            # Delete all password reset tokens for this user
            ResetPasswordToken.objects.filter(
                user=reset_password_token.user).delete()

            return Response({
                'refresh': str(refresh),
                'access': str(refresh.access_token),
            })

        else:
            #User is ineligible for password reset
            return Response({'status': 'User ineligible for password reset'},
                            status=status.HTTP_403_FORBIDDEN)