Exemplo n.º 1
0
    def update(self, group, **kwargs):
        """
        Update a group model with the args provided.

        :arg group: the group to update
        :type group: ~h.models.Group

        :raise ValidationError: if setting an attribute on the model raises :exc:`ValueError`
        :raise ConflictError: if the ``authority_provided_id`` is already in use

        :rtype: ~h.models.Group
        """

        for key, value in kwargs.items():
            try:
                setattr(group, key, value)
            except ValueError as err:
                raise ValidationError(err) from err

        try:
            self.session.flush()

        except SQLAlchemyError as err:
            # Handle DB integrity issues with duplicate ``authority_provided_id``
            if ('duplicate key value violates unique constraint "ix__group__groupid"'
                    in repr(err)):
                raise ConflictError(
                    "authority_provided_id '{id}' is already in use".format(
                        id=kwargs["authority_provided_id"])) from err

            # Re-raise as this is an unexpected problem
            raise

        return group
Exemplo n.º 2
0
    def test_post_displays_heading_and_message_on_conflict_error(
            self, controller, pyramid_request, user_signup_service):
        user_signup_service.signup.side_effect = ConflictError(
            "The account [email protected] is already registered.")

        result = controller.post()

        assert result["heading"] == "Account already registered"
        assert result["message"] == (
            "The account [email protected] is already registered.")
Exemplo n.º 3
0
    def test_post_displays_heading_and_message_on_conflict_error(
            self, form_validating_to, pyramid_request, user_signup_service):
        user_signup_service.signup.side_effect = ConflictError(
            "The account [email protected] is already registered.")
        controller = views.SignupController(pyramid_request)
        controller.form = form_validating_to({
            "username": "******",
            "email": "*****@*****.**",
            "password": "******"
        })

        result = controller.post()

        assert result["heading"] == "Account already registered"
        assert result["message"] == (
            "The account [email protected] is already registered.")
Exemplo n.º 4
0
    def update(self, user, **kwargs):
        """
        Update a user model with the args provided.

        :arg user: the group to update
        :type user: ~h.models.User

        :raise ValidationError: if setting an attribute on the model raises :exc:`ValueError`
                                or if ``authority`` is present in ``kwargs``

        :rtype: ~h.models.User
        """

        # Much repurcussion if a user's authority is changed at this point.
        # May wish to re-evaluate later if users need to be moved between
        # authorities.
        if "authority" in kwargs:
            raise ValidationError("A user's authority may not be changed")

        for key, value in kwargs.items():
            try:
                setattr(user, key, value)
            except ValueError as err:
                raise ValidationError(err) from err

        try:
            self.session.flush()

        except SQLAlchemyError as err:
            # Handle DB integrity issues with duplicate ``authority_provided_id``
            if (
                'duplicate key value violates unique constraint "ix__user__userid"'
                in repr(err)
            ):
                # This conflict can arise from changes to either username or authority.
                # We know this isn't authority, because the presence of authority
                # would have already raised.
                raise ConflictError(
                    f"""username '{kwargs["username"]}' is already in use"""
                ) from err

            # Re-raise as this is an unexpected problem
            raise

        return user
Exemplo n.º 5
0
    def signup(self, require_activation=True, **kwargs):
        """
        Create a new user.

        If *require_activation* is ``True``, the user will be flagged as
        requiring activation and an activation email will be sent.

        :param require_activation: The name to use.
        :type require_activation: bool.

        Remaining keyword arguments are used to construct a new
        :py:class:`h.models.User` object.

            * *identities*  A list of dictionaries representing identities to
              add to the new user. Each dictionary will be passed as keyword args
              to `h.models.UserIdentity`.

        :returns: the newly-created user object.
        :rtype: h.models.User
        """
        kwargs.setdefault("authority", self.default_authority)

        # We extract any passed password as we use that separately to set the
        # user's password.
        password = kwargs.pop("password", None)

        # Extract any passed identities for this new user
        identities = kwargs.pop("identities", [])

        user = User(**kwargs)

        # Add identity relations to this new user, if provided
        user.identities = [
            UserIdentity(user=user, **i_args) for i_args in identities
        ]

        self.session.add(user)

        if password is not None:
            self.password_service.update_password(user, password)

        # Create a new activation for the user
        if require_activation:
            try:
                self._require_activation(user)
            except IntegrityError as err:
                # When identical signup requests get issued at nearly the same time, they
                # race each other to the database and result in unique contraint integrity
                # errors on the user's email or username within the authority.
                if ('duplicate key value violates unique constraint "uq__user__email"'
                        in err.args[0] or
                        'duplicate key value violates unique constraint "ix__user__userid"'
                        in err.args[0]):
                    log.warning(
                        "concurrent account signup conflict error occurred during user signup %s",
                        err.args[0],
                    )
                    raise ConflictError(
                        "The email address {} has already been registered.".
                        format(user.email)) from err
                # If the exception is not related to the email or username, re-raise it.
                raise

        # FIXME: this is horrible, but is needed until the
        # notification/subscription system is made opt-out rather than opt-in
        # (at least from the perspective of the database).
        sub = Subscriptions(uri=user.userid, type="reply", active=True)
        self.session.add(sub)

        return user