def _patch_put(self, request, response, is_optional): """Update the header match.""" try: header_match = self.header_matches[self._position] except IndexError: not_found( response, 'No header match at this position: {}'.format(self._position)) return kws = dict( header=lowercase, pattern=str, position=int, action=enum_validator(Action), ) if is_optional: # For a PATCH, all attributes are optional. kws['_optional'] = kws.keys() else: # For a PUT, position can remain unchanged and action can be None. kws['_optional'] = ('action', 'position') validator = Validator(**kws) try: arguments = validator(request) action = arguments.pop('action', None) if action is not None: arguments['chain'] = action.name for key, value in arguments.items(): setattr(header_match, key, value) except ValueError as error: bad_request(response, str(error)) return else: no_content(response)
def create_user(api, arguments, response): """Create a new user.""" # We can't pass the 'password' argument to the user creation method, so # strip that out (if it exists), then create the user, adding the password # after the fact if successful. password = arguments.pop('password', None) is_server_owner = arguments.pop('is_server_owner', False) user_manager = getUtility(IUserManager) try: user = user_manager.create_user(**arguments) except ExistingAddressError as error: # The address already exists. If the address already has a user # linked to it, raise an error, otherwise create a new user and link # it to this address. email = arguments.pop('email') user = user_manager.get_user(email) if user is None: address = user_manager.get_address(email) user = user_manager.create_user(**arguments) user.link(address) else: bad_request( response, 'User already exists: {}'.format(error.address)) return None if password is None: # This will have to be reset since it cannot be retrieved. password = generate(int(config.passwords.password_length)) user.password = config.password_context.encrypt(password) user.is_server_owner = is_server_owner user_id = api.from_uuid(user.user_id) location = api.path_to('users/{}'.format(user_id)) created(response, location) return user
def patch_put(self, request, response, is_optional): """Update the header match.""" try: header_match = self.header_matches[self._position] except IndexError: not_found(response, "No header match at this position: {}".format(self._position)) return kws = dict(header=lowercase, pattern=str, position=int, action=enum_validator(Action)) if is_optional: # For a PATCH, all attributes are optional. kws["_optional"] = kws.keys() else: # For a PUT, position can remain unchanged and action can be None. kws["_optional"] = ("action", "position") validator = Validator(**kws) try: arguments = validator(request) action = arguments.pop("action", None) if action is not None: arguments["chain"] = action.name for key, value in arguments.items(): setattr(header_match, key, value) except ValueError as error: bad_request(response, str(error)) return else: no_content(response)
def on_get(self, request, response): """/lists/listname/requests""" validator = Validator( token_owner=enum_validator(TokenOwner), request_type=enum_validator(PendType), page=int, count=int, _optional=['token_owner', 'page', 'count', 'request_type'], ) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) else: data.pop('page', None) data.pop('count', None) token_owner = data.pop('token_owner', None) pend_type = data.pop('request_type', PendType.subscription) pendings = getUtility(IPendings).find( mlist=self._mlist, pend_type=pend_type.name, token_owner=token_owner) resource = _SubscriptionRequestsFound( [token for token, pendable in pendings]) okay(response, etag(resource._make_collection(request)))
def _find(self, request, response): validator = Validator( subscriber=subscriber_validator(self.api), role=enum_validator(MemberRole), # Allow pagination. page=int, count=int, _optional=('role', 'page', 'count')) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) return else: # Remove any optional pagination query elements. data.pop('page', None) data.pop('count', None) service = getUtility(ISubscriptionService) # Get all membership records for given subscriber. memberships = service.find_members(**data) # Get all the lists from from the membership records. lists = [ getUtility(IListManager).get_by_list_id(member.list_id) for member in memberships ] # If there are no matching lists, return a 404. if not len(lists): return not_found(response) resource = _ListOfLists(lists, self.api) okay(response, etag(resource._make_collection(request)))
def on_put(self, request, response): """Set or replace the addresses's user.""" if self._user: self._user.unlink(self._address) # Process post data and check for an existing user. fields = CREATION_FIELDS.copy() fields['user_id'] = int fields['_optional'] = fields['_optional'] + ( 'user_id', 'email', 'is_server_owner') try: validator = Validator(**fields) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return user_manager = getUtility(IUserManager) if 'user_id' in arguments: raw_uid = arguments['user_id'] user_id = UUID(int=raw_uid) user = user_manager.get_user_by_id(user_id) if user is None: not_found(response, b'No user with ID {}'.format(raw_uid)) return okay(response) else: user = create_user(arguments, request, response) if user is None: return user.link(self._address)
def _find(self, request, response): """Find a member""" service = getUtility(ISubscriptionService) validator = Validator( list_id=str, subscriber=str, role=enum_validator(MemberRole), # Allow pagination. page=int, count=int, fields=list_of_strings_validator, _optional=('list_id', 'subscriber', 'role', 'page', 'count', 'fields')) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) else: # Remove any optional pagination query elements; they will be # handled later. data.pop('page', None) data.pop('count', None) fields = data.pop('fields', None) members = service.find_members(**data) resource = _FoundMembers(members, self.api) try: collection = resource._make_collection(request, fields) except ValueError as ex: bad_request(response, str(ex)) return okay(response, etag(collection))
def on_post(self, request, response): try: validator = Validator(send=as_boolean, bump=as_boolean, periodic=as_boolean, _optional=('send', 'bump', 'periodic')) values = validator(request) except ValueError as error: bad_request(response, str(error)) return if values.get('send', False) and values.get('periodic', False): # Send and periodic and mutually exclusive options. bad_request(response, 'send and periodic options are mutually exclusive') return if len(values) == 0: # There's nothing to do, but that's okay. okay(response) return if values.get('bump', False): bump_digest_number_and_volume(self._mlist) if values.get('send', False): maybe_send_digest_now(self._mlist, force=True) if values.get('periodic', False) and self._mlist.digest_send_periodic: maybe_send_digest_now(self._mlist, force=True) accepted(response)
def create_user(arguments, request, response): """Create a new user.""" # We can't pass the 'password' argument to the user creation method, so # strip that out (if it exists), then create the user, adding the password # after the fact if successful. password = arguments.pop('password', None) is_server_owner = arguments.pop('is_server_owner', False) user_manager = getUtility(IUserManager) try: user = user_manager.create_user(**arguments) except ExistingAddressError as error: # The address already exists. If the address already has a user # linked to it, raise an error, otherwise create a new user and link # it to this address. email = arguments.pop('email') user = user_manager.get_user(email) if user is None: address = user_manager.get_address(email) user = user_manager.create_user(**arguments) user.link(address) else: bad_request( response, 'User already exists: {}'.format(error.address)) return None if password is None: # This will have to be reset since it cannot be retrieved. password = generate(int(config.passwords.password_length)) user.password = config.password_context.encrypt(password) user.is_server_owner = is_server_owner location = path_to('users/{}'.format(user.user_id.int), request.context['api_version']) created(response, location) return user
def on_put(self, request, response): """Set or replace the addresses's user.""" if self._user: self._user.unlink(self._address) # Process post data and check for an existing user. fields = CREATION_FIELDS.copy() fields['user_id'] = self.api.to_uuid fields['_optional'] = fields['_optional'] + ( 'user_id', 'email', 'is_server_owner') try: validator = Validator(**fields) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return user_manager = getUtility(IUserManager) if 'user_id' in arguments: user_id = arguments['user_id'] user = user_manager.get_user_by_id(user_id) if user is None: not_found(response, b'No user with ID {}'.format(user_id)) return okay(response) else: user = create_user(self.api, arguments, response) if user is None: return user.link(self._address)
def _find(self, request, response): validator = Validator( header=str, action=enum_validator(Action), tag=str, _optional=('action', 'tag', 'header') ) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) return # Remove any optional pagination elements. action = data.pop('action', None) if action is not None: data['chain'] = action.name service = IHeaderMatchList(self._mlist) self.header_matches = list(service.filter(**data)) # Return 404 if no values were found. if len(self.header_matches) == 0: return not_found( response, 'Cound not find any HeaderMatch for provided search options.') resource = self._make_collection(request) okay(response, etag(resource))
def on_post(self, request, response): """Create a new user.""" try: validator = Validator(email=unicode, display_name=unicode, password=unicode, _optional=('display_name', 'password')) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return # We can't pass the 'password' argument to the user creation method, # so strip that out (if it exists), then create the user, adding the # password after the fact if successful. password = arguments.pop('password', None) try: user = getUtility(IUserManager).create_user(**arguments) except ExistingAddressError as error: bad_request( response, b'Address already exists: {0}'.format(error.address)) return if password is None: # This will have to be reset since it cannot be retrieved. password = generate(int(config.passwords.password_length)) user.password = config.password_context.encrypt(password) location = path_to('users/{0}'.format(user.user_id.int)) created(response, location)
def on_post(self, request, response): try: resource = Validator(number=int)(request) self._plugin.number = resource['number'] except ValueError as error: bad_request(response, str(error)) else: no_content(response)
def on_post(self, request, response): """Create a new user.""" try: validator = Validator(**CREATION_FIELDS) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return create_user(self.api, arguments, response)
def on_post(self, request, response): """Create a new user.""" try: validator = Validator(**CREATION_FIELDS) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return create_user(arguments, request, response)
def test_bad_request_with_body(self): response = FakeResponse() helpers.bad_request(response, 'Missing Parameter: random') self.assertEqual(response.content_type, 'application/json; charset=UTF-8') self.assertEqual( json.loads(response.body), { 'title': '400 Bad Request', 'description': 'Missing Parameter: random', })
def on_get(self, request, response): try: request_id = int(self._request_id) except ValueError: bad_request(response) return resource = self._make_resource(request_id) if resource is None: not_found(response) else: okay(response, etag(resource))
def handle_ValueError(exc, request, response, params): """Handle ValueErrors in API code to return HTTPBadRequest. ValueErrors are raised often by Validator and should not return a 500 error resposne to the client. This is a stop-gap for 500 errors due to ValueErrors, it is recommended that they be handled at the call-site, instead of here. """ # Only handle ValueError, raise anything else right back. if not isinstance(exc, ValueError): raise exc bad_request(response, str(exc))
def on_post(self, request, response): """Ban some email from subscribing.""" validator = Validator(email=str) try: email = validator(request)['email'] except ValueError as error: bad_request(response, str(error)) return if self.ban_manager.is_banned(email): bad_request(response, b'Address is already banned') else: self.ban_manager.ban(email) created(response, self._location(email))
def on_get(self, request, response): try: request_id = int(self._request_id) except ValueError: bad_request(response) return resource = self._make_resource(request_id, MEMBERSHIP_CHANGE_REQUESTS) if resource is None: not_found(response) else: # Remove unnecessary keys. del resource['key'] okay(response, etag(resource))
def on_post(self, request, response): """POST to /domains/<domain>/owners """ if self._domain is None: not_found(response) return validator = Validator( owner=ListOfDomainOwners(list_of_strings_validator)) try: validator.update(self._domain, request) except ValueError as error: bad_request(response, str(error)) return return no_content(response)
def patch_put(self, request, response, is_optional): archiver_set = IListArchiverSet(self._mlist) kws = {archiver.name: ArchiverGetterSetter(self._mlist) for archiver in archiver_set.archivers} if is_optional: # For a PATCH, all attributes are optional. kws['_optional'] = kws.keys() try: Validator(**kws).update(self._mlist, request) except ValueError as error: bad_request(response, str(error)) else: no_content(response)
def on_post(self, request, response): """Find a member""" service = getUtility(ISubscriptionService) validator = Validator(list_id=str, subscriber=str, role=enum_validator(MemberRole), _optional=('list_id', 'subscriber', 'role')) try: members = service.find_members(**validator(request)) except ValueError as error: bad_request(response, str(error)) else: resource = _FoundMembers(members, self.api_version) okay(response, etag(resource._make_collection(request)))
def on_post(self, request, response): try: validator = Validator(action=enum_validator(Action)) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return requests = IListRequests(self._mlist) try: request_id = int(self._request_id) except ValueError: bad_request(response) return results = requests.get_request(request_id) if results is None: not_found(response) return key, data = results try: request_type = RequestType[data['_request_type']] except ValueError: bad_request(response) return if request_type is RequestType.subscription: handle_subscription(self._mlist, request_id, **arguments) elif request_type is RequestType.unsubscription: handle_unsubscription(self._mlist, request_id, **arguments) else: bad_request(response) return no_content(response)
def on_put(self, request, response): """Set a mailing list configuration.""" attribute = self._attribute if attribute is None: validator = Validator(**VALIDATORS) try: validator.update(self._mlist, request) except ValueError as error: bad_request(response, str(error)) return elif attribute not in ATTRIBUTES: bad_request(response, b'Unknown attribute: {}'.format(attribute)) return elif ATTRIBUTES[attribute].decoder is None: bad_request( response, b'Read-only attribute: {}'.format(attribute)) return else: validator = Validator(**{attribute: VALIDATORS[attribute]}) try: validator.update(self._mlist, request) except ValueError as error: bad_request(response, str(error)) return no_content(response)
def on_post(self, request, response): """Create a new mailing list.""" try: validator = Validator(fqdn_listname=str, style_name=str, _optional=('style_name',)) mlist = create_list(**validator(request)) except ListAlreadyExistsError: bad_request(response, b'Mailing list exists') except BadDomainSpecificationError as error: reason = 'Domain does not exist: {}'.format(error.domain) bad_request(response, reason.encode('utf-8')) else: location = self.api.path_to('lists/{0}'.format(mlist.list_id)) created(response, location)
def on_post(self, request, response): """Find a member""" service = getUtility(ISubscriptionService) validator = Validator( list_id=unicode, subscriber=unicode, role=enum_validator(MemberRole), _optional=('list_id', 'subscriber', 'role')) try: members = service.find_members(**validator(request)) except ValueError as error: bad_request(response, str(error)) else: resource = _FoundMembers(members)._make_collection(request) okay(response, etag(resource))
def on_post(self, request, response): """Create a new mailing list.""" try: validator = Validator(fqdn_listname=str, style_name=str, _optional=('style_name', )) mlist = create_list(**validator(request)) except ListAlreadyExistsError: bad_request(response, b'Mailing list exists') except BadDomainSpecificationError as error: reason = 'Domain does not exist: {}'.format(error.domain) bad_request(response, reason.encode('utf-8')) else: location = self.api.path_to('lists/{0}'.format(mlist.list_id)) created(response, location)
def on_patch(self, request, response): """Patch the user's configuration (i.e. partial update).""" if self._user is None: not_found(response) return try: validator = PatchValidator(request, ATTRIBUTES) except UnknownPATCHRequestError as error: bad_request( response, b'Unknown attribute: {0}'.format(error.attribute)) except ReadOnlyPATCHRequestError as error: bad_request( response, b'Read-only attribute: {0}'.format(error.attribute)) else: validator.update(self._user, request) no_content(response)
def on_delete(self, request, response): """DELETE to /domains/<domain>/owners""" if self._domain is None: not_found(response) try: # No arguments. Validator()(request) except ValueError as error: bad_request(response, str(error)) return owner_email = [ owner.addresses[0].email for owner in self._domain.owners ] for email in owner_email: self._domain.remove_owner(email) return no_content(response)
def on_get(self, request, response): validator = Validator( token_owner=enum_validator(TokenOwner), request_type=enum_validator(PendType), _optional=['token_owner', 'request_type']) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) else: token_owner = data.pop('token_owner', None) pend_type = data.pop('request_type', PendType.subscription) count = getUtility(IPendings).count( mlist=self._mlist, pend_type=pend_type.name, token_owner=token_owner) okay(response, etag(dict(count=count)))
def on_post(self, request, response): """Create a new domain.""" domain_manager = getUtility(IDomainManager) try: validator = Validator(mail_host=str, description=str, base_url=str, contact_address=str, _optional=('description', 'base_url', 'contact_address')) domain = domain_manager.add(**validator(request)) except BadDomainSpecificationError: bad_request(response, b'Domain exists') except ValueError as error: bad_request(response, str(error)) else: created(response, path_to('domains/{0}'.format(domain.mail_host)))
def on_delete(self, request, response): """Delete the members of the named mailing list.""" status = {} try: validator = Validator(emails=list_of_strings_validator) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return emails = arguments.pop('emails') success, fail = getUtility(ISubscriptionService).unsubscribe_members( self._mlist.list_id, emails) # There should be no email in both sets. assert success.isdisjoint(fail), (success, fail) status.update({email: True for email in success}) status.update({email: False for email in fail}) okay(response, etag(status))
def on_get(self, request, response): """Get a mailing list configuration.""" resource = {} if self._attribute is None: # Return all readable attributes. for attribute in ATTRIBUTES: value = ATTRIBUTES[attribute].get(self._mlist, attribute) resource[attribute] = value elif self._attribute not in ATTRIBUTES: bad_request( response, b'Unknown attribute: {}'.format(self._attribute)) return else: attribute = self._attribute value = ATTRIBUTES[attribute].get(self._mlist, attribute) resource[attribute] = value okay(response, etag(resource))
def patch_put(self, request, response, is_optional): domain = getUtility(IDomainManager).get(self._domain) if domain is None: not_found(response) kws = dict( description=GetterSetter(str), owner=ListOfDomainOwners(list_of_strings_validator), ) if is_optional: # For a PATCH, all attributes are optional. kws['_optional'] = kws.keys() try: Validator(**kws).update(domain, request) except ValueError as error: bad_request(response, str(error)) else: no_content(response)
def on_post(self, request, response): """Create a new domain.""" domain_manager = getUtility(IDomainManager) try: validator = Validator(mail_host=unicode, description=unicode, base_url=unicode, contact_address=unicode, _optional=('description', 'base_url', 'contact_address')) domain = domain_manager.add(**validator(request)) except BadDomainSpecificationError: bad_request(response, b'Domain exists') except ValueError as error: bad_request(response, str(error)) else: created(response, path_to('domains/{0}'.format(domain.mail_host)))
def on_patch(self, request, response): """Patch an existing Address.""" if self._address is None: not_found(response) else: # The only attribute of a address that can be PATCH'd is the # display_name. To change the verified_on, use the /verify # endpoint. validator = Validator(display_name=str) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) return display_name = data.pop('display_name') self._address.display_name = display_name no_content(response)
def on_post(self, request, response): try: validator = Validator(action=enum_validator(Action), reason=str, _optional=('reason',)) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return action = arguments['action'] if action in (Action.defer, Action.hold): # At least see if the token is in the database. pendable = self._pendings.confirm(self._token, expunge=False) if pendable is None: not_found(response) else: no_content(response) elif action is Action.accept: try: self._registrar.confirm(self._token) except LookupError: not_found(response) except AlreadySubscribedError: conflict(response, 'Already subscribed') else: no_content(response) elif action is Action.discard: # At least see if the token is in the database. pendable = self._pendings.confirm(self._token, expunge=True) if pendable is None: not_found(response) else: no_content(response) else: assert action is Action.reject, action # Like discard but sends a rejection notice to the user. pendable = self._pendings.confirm(self._token, expunge=True) if pendable is None: not_found(response) else: no_content(response) reason = arguments.get('reason', _('[No reason given]')) send_rejection( self._mlist, _('Subscription request'), pendable['email'], reason)
def on_post(self, request, response): # We do not want to encrypt the plaintext password given in the POST # data. That would hash the password, but we need to have the # plaintext in order to pass into passlib. validator = Validator(cleartext_password=GetterSetter(str)) try: values = validator(request) except ValueError as error: bad_request(response, str(error)) return is_valid, new_hash = config.password_context.verify( values['cleartext_password'], self._user.password) if is_valid: if new_hash is not None: self._user.password = new_hash no_content(response) else: forbidden(response)
def on_post(self, request, response): """Add a header match.""" validator = Validator(header=str, pattern=str, action=enum_validator(Action), _optional=("action",)) try: arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return action = arguments.pop("action", None) if action is not None: arguments["chain"] = action.name try: self.header_matches.append(**arguments) except ValueError: bad_request(response, b"This header match already exists") else: header_match = self.header_matches[-1] created(response, self._location(header_match.position))
def on_post(self, request, response): try: validator = Validator( send=as_boolean, bump=as_boolean, _optional=('send', 'bump')) values = validator(request) except ValueError as error: bad_request(response, str(error)) return if len(values) == 0: # There's nothing to do, but that's okay. okay(response) return if values.get('bump', False): bump_digest_number_and_volume(self._mlist) if values.get('send', False): maybe_send_digest_now(self._mlist, force=True) accepted(response)
def on_post(self, request, response): try: validator = Validator(action=enum_validator(Action)) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return action = arguments['action'] if action in (Action.defer, Action.hold): # At least see if the token is in the database. pendable = self._pendings.confirm(self._token, expunge=False) if pendable is None: not_found(response) else: no_content(response) elif action is Action.accept: try: self._registrar.confirm(self._token) except LookupError: not_found(response) except AlreadySubscribedError: conflict(response, 'Already subscribed') else: no_content(response) elif action is Action.discard: # At least see if the token is in the database. pendable = self._pendings.confirm(self._token, expunge=True) if pendable is None: not_found(response) else: no_content(response) else: assert action is Action.reject, action # Like discard but sends a rejection notice to the user. pendable = self._pendings.confirm(self._token, expunge=True) if pendable is None: not_found(response) else: no_content(response) send_rejection( self._mlist, _('Subscription request'), pendable['email'], _('[No reason given]'))
def on_post(self, request, response): try: validator = Validator(action=enum_validator(Action)) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return requests = IListRequests(self._mlist) try: request_id = int(self._request_id) except ValueError: bad_request(response) return results = requests.get_request(request_id, RequestType.held_message) if results is None: not_found(response) else: handle_message(self._mlist, request_id, **arguments) no_content(response)
def on_post(self, request, response): """Link a user to the address, and create it if needed.""" if self._user: conflict(response) return # When creating a linked user by POSTing, the user either must already # exist, or it can be automatically created, if the auto_create flag # is given and true (if missing, it defaults to true). However, in # this case we do not accept 'email' as a POST field. fields = CREATION_FIELDS.copy() del fields['email'] fields['user_id'] = int fields['auto_create'] = as_boolean fields['_optional'] = fields['_optional'] + ( 'user_id', 'auto_create', 'is_server_owner') try: validator = Validator(**fields) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return user_manager = getUtility(IUserManager) if 'user_id' in arguments: raw_uid = arguments['user_id'] user_id = UUID(int=raw_uid) user = user_manager.get_user_by_id(user_id) if user is None: not_found(response, b'No user with ID {}'.format(raw_uid)) return okay(response) else: auto_create = arguments.pop('auto_create', True) if auto_create: # This sets the 201 or 400 status. user = create_user(arguments, request, response) if user is None: return else: forbidden(response) return user.link(self._address)
def create_user(arguments, response): """Create a new user.""" # We can't pass the 'password' argument to the user creation method, so # strip that out (if it exists), then create the user, adding the password # after the fact if successful. password = arguments.pop('password', None) is_server_owner = arguments.pop('is_server_owner', False) try: user = getUtility(IUserManager).create_user(**arguments) except ExistingAddressError as error: bad_request( response, 'Address already exists: {}'.format(error.address)) return None if password is None: # This will have to be reset since it cannot be retrieved. password = generate(int(config.passwords.password_length)) user.password = config.password_context.encrypt(password) user.is_server_owner = is_server_owner location = path_to('users/{}'.format(user.user_id.int)) created(response, location) return user
def on_post(self, request, response): """Create a new member.""" service = getUtility(ISubscriptionService) try: validator = Validator( list_id=unicode, subscriber=subscriber_validator, display_name=unicode, delivery_mode=enum_validator(DeliveryMode), role=enum_validator(MemberRole), _optional=('delivery_mode', 'display_name', 'role')) member = service.join(**validator(request)) except AlreadySubscribedError: conflict(response, b'Member already subscribed') except NoSuchListError: bad_request(response, b'No such list') except InvalidEmailAddressError: bad_request(response, b'Invalid email address') except ValueError as error: bad_request(response, str(error)) else: # The member_id are UUIDs. We need to use the integer equivalent # in the URL. member_id = member.member_id.int location = path_to('members/{0}'.format(member_id)) created(response, location)
def on_post(self, request, response): """POST to /addresses Add a new address to the user record. """ if self._user is None: not_found(response) return user_manager = getUtility(IUserManager) validator = Validator(email=str, display_name=str, _optional=('display_name',)) try: address = user_manager.create_address(**validator(request)) except ValueError as error: bad_request(response, str(error)) except InvalidEmailAddressError: bad_request(response, b'Invalid email address') except ExistingAddressError: # Check if the address is not linked to any user, link it to the # current user and return it. Since we're linking to an existing # address, ignore any given display_name attribute. address = user_manager.get_address(validator(request)['email']) if address.user is None: address.user = self._user location = self.path_to('addresses/{}'.format(address.email)) created(response, location) else: bad_request(response, 'Address belongs to other user.') else: # Link the address to the current user and return it. address.user = self._user location = self.path_to('addresses/{}'.format(address.email)) created(response, location)
def on_patch(self, request, response): """Patch the membership. This is how subscription changes are done. """ if self._member is None: not_found(response) return try: values = Validator( address=str, delivery_mode=enum_validator(DeliveryMode), moderation_action=enum_validator(Action), _optional=('address', 'delivery_mode', 'moderation_action'), )(request) except ValueError as error: bad_request(response, str(error)) return if 'address' in values: email = values['address'] address = getUtility(IUserManager).get_address(email) if address is None: bad_request(response, b'Address not registered') return try: self._member.address = address except (MembershipError, UnverifiedAddressError) as error: bad_request(response, str(error)) return if 'delivery_mode' in values: self._member.preferences.delivery_mode = values['delivery_mode'] if 'moderation_action' in values: self._member.moderation_action = values['moderation_action'] no_content(response)
def patch_put(self, request, response, is_optional): if self._parent is None: not_found(response) return kws = dict( acknowledge_posts=GetterSetter(as_boolean), hide_address = GetterSetter(as_boolean), delivery_mode=GetterSetter(enum_validator(DeliveryMode)), delivery_status=GetterSetter(enum_validator(DeliveryStatus)), preferred_language=GetterSetter(language_validator), receive_list_copy=GetterSetter(as_boolean), receive_own_postings=GetterSetter(as_boolean), ) if is_optional: # For a PUT, all attributes are optional. kws['_optional'] = kws.keys() try: Validator(**kws).update(self._parent, request) except ValueError as error: bad_request(response, str(error)) else: no_content(response)