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
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.")
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.")
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
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