예제 #1
0
def public_register(username, password, email, full_name):
    """
    Given a parsed parameters, try register a new user
    knowing that it follows a public register flow.

    This can raise `exc.IntegrityError` exceptions in
    case of conflics found.

    :returns: User
    """

    is_registered, reason = is_user_already_registered(username=username,
                                                       email=email)
    if is_registered:
        raise exc.WrongArguments(reason)

    user_model = get_user_model()
    user = user_model(username=username, email=email, full_name=full_name)
    user.set_password(password)
    try:
        user.save()
    except IntegrityError:
        raise exc.WrongArguments(_("User is already registered."))

    send_register_email(user)
    user_registered_signal.send(sender=user.__class__, user=user)
    return user
예제 #2
0
    def change_email(self, request, pk=None):
        """
        Verify the email change to current logged user.
        """
        validator = serializers.ChangeEmailValidator(data=request.data,
                                                     many=False)
        if not validator.is_valid():
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct and you "
                  "didn't use it before?"))

        try:
            user = models.User.objects.get(
                email_token=validator.data["email_token"])
        except models.User.DoesNotExist:
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct and you "
                  "didn't use it before?"))

        old_email = user.email
        new_email = user.new_email

        user.email = new_email
        user.new_email = None
        user.email_token = None
        user.save(update_fields=["email", "new_email", "email_token"])

        user_change_email_signal.send(sender=user.__class__,
                                      user=user,
                                      old_email=old_email,
                                      new_email=new_email)

        return response.NoContent()
예제 #3
0
    def cancel(self, request, pk=None):
        """
        Cancel an account via token
        """
        validator = serializers.CancelAccountValidator(data=request.data,
                                                       many=False)
        if not validator.is_valid():
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct?"))

        try:
            max_age_cancel_account = getattr(settings,
                                             "MAX_AGE_CANCEL_ACCOUNT", None)
            user = get_user_for_token(validator.data["cancel_token"],
                                      "cancel_account",
                                      max_age=max_age_cancel_account)

        except exc.NotAuthenticated:
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct?"))

        if not user.is_active:
            raise exc.WrongArguments(
                _("Invalid, are you sure the token is correct?"))

        user.cancel()
        return response.NoContent()
예제 #4
0
    def change_avatar(self, request):
        """
        Change avatar to current logged user.
        """
        avatar = request.FILES.get('avatar', None)
        id = request.data.get('id', None)
        if not avatar:
            raise exc.WrongArguments(_("Incomplete arguments"))

        try:
            pil_image(avatar)
        except Exception:
            raise exc.WrongArguments(_("Invalid image format"))

        if id is None:
            request.user.photo = avatar
            request.user.save(update_fields=["photo"])
            user_data = self.admin_serializer_class(request.user).data
        else:
            user = get_object_or_404(models.User, id=id)
            user.photo = avatar
            user.save(update_fields=["photo"])
            user_data = self.admin_serializer_class(user).data

        return response.Ok(user_data)
예제 #5
0
    def change_password(self, request, pk=None):
        """
        Change password to current logged user.
        """

        current_password = request.data.get("current_password")
        password = request.data.get("password")

        if not current_password:
            raise exc.WrongArguments(_("Current password parameter needed"))

        if not password:
            raise exc.WrongArguments(_("New password parameter needed"))

        if len(password) < 6:
            raise exc.WrongArguments(
                _("Invalid password length at least 6 charaters needed"))

        if current_password and not request.user.check_password(
                current_password):
            raise exc.WrongArguments(_("Invalid current password"))

        request.user.set_password(password)
        request.user.save(update_fields=["password"])
        return response.NoContent()
예제 #6
0
    def change_password_from_recovery(self, request, pk=None):
        """
        Change password with token (from password recovery step).
        """
        validator = serializers.RecoveryValidator(data=request.data,
                                                  many=False)

        if not validator.is_valid():
            raise exc.WrongArguments(_("Token is invalid"))

        try:
            user = models.User.objects.get(token=validator.data["token"])
        except models.User.DoesNotExist:
            raise exc.WrongArguments(_("Token is invalid"))

        user.set_password(validator.data["password"])
        user.token = None
        user.save(update_fields=["password", "token"])

        return response.NoContent()
예제 #7
0
def get_and_validate_user(*, username: str, password: str) -> bool:
    """
    Check if user with username/email exists and specified
    password matchs well with existing user password.

    if user is valid,  user is returned else, corresponding
    exception is raised.
    """

    user = get_user_by_username_or_email(username)
    if not user.check_password(password):
        raise exc.WrongArguments(
            _("Username or password does not match user."))

    return user
예제 #8
0
    def password_recovery(self, request, pk=None):
        username_or_email = request.data.get('username', None)

        if not username_or_email:
            raise exc.WrongArguments(_("Invalid username or email"))

        user = get_user_by_username_or_email(username_or_email)
        user.token = str(uuid.uuid1())
        user.save(update_fields=["token"])

        email = mail_builder.password_recovery(user, {"user": user})
        email.send()

        return response.Ok(
            {"detail": _("A Mail has been sent to you successful!")})
예제 #9
0
    def partial_update(self, request, *args, **kwargs):
        """
        We must detect if the user is trying to change his email so we can
        save that value and generate a token that allows him to validate it in
        the new email account
        """

        new_email = request.data.pop('email', None)

        if new_email is not None:
            valid_new_email = True
            duplicated_email = models.User.objects.filter(
                email=new_email).exists()

            try:
                validate_email(new_email)
                self.validate_user_email_allowed_domains(new_email)
            except ValidationError:
                valid_new_email = False

            valid_new_email = valid_new_email and new_email != request.user.email

            if duplicated_email:
                raise exc.WrongArguments(_("Duplicated email"))
            elif not valid_new_email:
                raise exc.WrongArguments(_("Not valid email"))

            # We need to generate a token for the email
            request.user.email_token = str(uuid.uuid1())
            request.user.new_email = new_email
            request.user.save(update_fields=["email_token", "new_email"])
            email = mail_builder.change_email(request.user.new_email,
                                              {"user": request.user})
            email.send()

        return super().partial_update(request, *args, **kwargs)
예제 #10
0
def get_user_by_username_or_email(username_or_email):
    user_model = get_user_model()
    qs = user_model.objects.filter(
        Q(username__iexact=username_or_email)
        | Q(email__iexact=username_or_email))

    if len(qs) > 1:
        qs = qs.filter(
            Q(username=username_or_email) | Q(email=username_or_email))

    if len(qs) == 0:
        raise exc.WrongArguments(
            _("Username or password does not match user."))

    user = qs[0]
    return user