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 on_post(self, request, response): """Create a new member.""" service = getUtility(ISubscriptionService) try: validator = Validator(list_id=str, subscriber=subscriber_validator, display_name=str, 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 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_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_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_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): """POST to /addresses Add a new address to the user record. """ assert self._user is not None preferred = None user_manager = getUtility(IUserManager) validator = Validator(email=str, display_name=str, preferred=as_boolean, absorb_existing=bool, _optional=('display_name', 'absorb_existing', 'preferred')) try: data = validator(request) # We cannot set the address to be preferred when it is # created so remove it from the arguments here and # set it below. preferred = data.pop('preferred', False) except ValueError as error: bad_request(response, str(error)) return absorb_existing = data.pop('absorb_existing', False) try: address = user_manager.create_address(**data) except InvalidEmailAddressError: bad_request(response, b'Invalid email address') return except ExistingAddressError: # 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(data['email']) if address.user is None: address.user = self._user location = self.api.path_to('addresses/{}'.format( address.email)) created(response, location) return elif not absorb_existing: bad_request(response, 'Address belongs to other user') return else: # The address exists and is linked but we can merge the users. address = user_manager.get_address(data['email']) self._user.absorb(address.user) else: # Link the address to the current user and return it. address.user = self._user # Set the preferred address here if we were signalled to do so. if preferred: address.verified_on = now() self._user.preferred_address = address location = self.api.path_to('addresses/{}'.format(address.email)) created(response, location)
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_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_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): """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): """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_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_post(self, request, response): """POST to /addresses Add a new address to the user record. """ assert self._user is not None user_manager = getUtility(IUserManager) validator = Validator(email=str, display_name=str, absorb_existing=bool, _optional=('display_name', 'absorb_existing')) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) return absorb_existing = data.pop('absorb_existing', False) try: address = user_manager.create_address(**data) except InvalidEmailAddressError: bad_request(response, b'Invalid email address') return except ExistingAddressError: # 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(data['email']) if address.user is None: address.user = self._user location = self.api.path_to( 'addresses/{}'.format(address.email)) created(response, location) return elif not absorb_existing: bad_request(response, 'Address belongs to other user') return else: # The address exists and is linked but we can merge the users. address = user_manager.get_address(data['email']) self._user.absorb(address.user) else: # Link the address to the current user and return it. address.user = self._user location = self.api.path_to('addresses/{}'.format(address.email)) created(response, location)
def on_post(self, request, response): """POST to /addresses Add a new address to the user record. """ assert self._user is not None user_manager = getUtility(IUserManager) validator = Validator(email=str, display_name=str, absorb_existing=bool, _optional=('display_name', 'absorb_existing')) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) return absorb_existing = data.pop('absorb_existing', False) try: address = user_manager.create_address(**data) except InvalidEmailAddressError: bad_request(response, b'Invalid email address') return except ExistingAddressError: # 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(data['email']) if address.user is None: address.user = self._user location = self.api.path_to( 'addresses/{}'.format(address.email)) created(response, location) return elif not absorb_existing: bad_request(response, 'Address belongs to other user') return else: # The address exists and is linked but we can merge the users. address = user_manager.get_address(data['email']) self._user.absorb(address.user) else: # Link the address to the current user and return it. address.user = self._user location = self.api.path_to('addresses/{}'.format(address.email)) created(response, location)
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): user_manager = getUtility(IUserManager) validator = Validator(email=email_validator) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) return addr = user_manager.get_address(data['email']) if addr is None: bad_request(response, 'Address does not exist: {}'.format(data['email'])) return try: self._user.preferred_address = addr created(response, self._resource_as_dict(addr)['self_link']) except (UnverifiedAddressError, AddressAlreadyLinkedError) as e: bad_request(response, str(e))
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) 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) location = path_to('users/{}'.format(user.user_id.int)) created(response, location) return user
def on_post(self, request, response): """Create a new domain.""" domain_manager = getUtility(IDomainManager) try: validator = Validator(mail_host=str, description=str, owner=list_of_strings_validator, _optional=('description', 'owner')) values = validator(request) # For consistency, owners are passed in as multiple `owner` keys, # but .add() requires an `owners` keyword. Match impedence. owners = values.pop('owner', None) if owners is not None: values['owners'] = owners domain = domain_manager.add(**values) except BadDomainSpecificationError as error: bad_request(response, str(error)) else: location = self.api.path_to('domains/{}'.format(domain.mail_host)) created(response, location)
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 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): """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: bad_request(response, b"Address already exists") else: # Link the address to the current user and return it. address.user = self._user created(response, path_to("addresses/{0}".format(address.email)))
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, owner=list_of_strings_validator, _optional=( 'description', 'base_url', 'owner')) values = validator(request) # For consistency, owners are passed in as multiple `owner` keys, # but .add() requires an `owners` keyword. Match impedence. owners = values.pop('owner', None) if owners is not None: values['owners'] = owners domain = domain_manager.add(**values) except BadDomainSpecificationError as error: bad_request(response, str(error)) else: location = self.api.path_to('domains/{}'.format(domain.mail_host)) created(response, location)
def on_post(self, request, response): """Inject a message into the queue.""" try: validator = Validator(list_id=str, text=str) values = validator(request) except ValueError as error: bad_request(response, str(error)) return list_id = values['list_id'] mlist = getUtility(IListManager).get_by_list_id(list_id) if mlist is None: bad_request(response, 'No such list: {}'.format(list_id)) return try: filebase = inject_text( mlist, values['text'], switchboard=self._name) except Exception as error: bad_request(response, str(error)) return else: location = path_to('queues/{}/{}'.format(self._name, filebase)) created(response, location)
def on_post(self, request, response): """Inject a message into the queue.""" try: validator = Validator(list_id=str, text=str) values = validator(request) except ValueError as error: bad_request(response, str(error)) return list_id = values['list_id'] mlist = getUtility(IListManager).get_by_list_id(list_id) if mlist is None: bad_request(response, 'No such list: {}'.format(list_id)) return try: filebase = inject_text(mlist, values['text'], switchboard=self._name) except Exception as error: bad_request(response, str(error)) return else: location = path_to('queues/{}/{}'.format(self._name, filebase)) 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: bad_request(response, b'Address already exists') else: # Link the address to the current user and return it. address.user = self._user created(response, path_to('addresses/{0}'.format(address.email)))
def on_post(self, request, response): """Create a new member.""" try: validator = Validator(list_id=str, subscriber=subscriber_validator(self.api), display_name=str, delivery_mode=enum_validator(DeliveryMode), role=enum_validator(MemberRole), pre_verified=bool, pre_confirmed=bool, pre_approved=bool, _optional=('delivery_mode', 'display_name', 'role', 'pre_verified', 'pre_confirmed', 'pre_approved')) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return # Dig the mailing list out of the arguments. list_id = arguments.pop('list_id') mlist = getUtility(IListManager).get_by_list_id(list_id) if mlist is None: bad_request(response, b'No such list') return # Figure out what kind of subscriber is being registered. Either it's # a user via their preferred email address or it's an explicit address. # If it's a UUID, then it must be associated with an existing user. subscriber = arguments.pop('subscriber') user_manager = getUtility(IUserManager) # We use the display name if there is one. display_name = arguments.pop('display_name', '') if isinstance(subscriber, UUID): user = user_manager.get_user_by_id(subscriber) if user is None: bad_request(response, b'No such user') return subscriber = user else: # This must be an email address. See if there's an existing # address object associated with this email. address = user_manager.get_address(subscriber) if address is None: # Create a new address, which of course will not be validated. address = user_manager.create_address(subscriber, display_name) subscriber = address # What role are we subscribing? Regular members go through the # subscription policy workflow while owners, moderators, and # nonmembers go through the legacy API for now. role = arguments.pop('role', MemberRole.member) if role is MemberRole.member: # Get the pre_ flags for the subscription workflow. pre_verified = arguments.pop('pre_verified', False) pre_confirmed = arguments.pop('pre_confirmed', False) pre_approved = arguments.pop('pre_approved', False) # Now we can run the registration process until either the # subscriber is subscribed, or the workflow is paused for # verification, confirmation, or approval. registrar = ISubscriptionManager(mlist) try: token, token_owner, member = registrar.register( subscriber, pre_verified=pre_verified, pre_confirmed=pre_confirmed, pre_approved=pre_approved) except AlreadySubscribedError: conflict(response, b'Member already subscribed') return except MissingPreferredAddressError: bad_request(response, b'User has no preferred address') return except MembershipIsBannedError: bad_request(response, b'Membership is banned') return except SubscriptionPendingError: conflict(response, b'Subscription request already pending') return if token is None: assert token_owner is TokenOwner.no_one, token_owner # The subscription completed. Let's get the resulting member # and return the location to the new member. Member ids are # UUIDs and need to be converted to URLs because JSON doesn't # directly support UUIDs. member_id = self.api.from_uuid(member.member_id) location = self.api.path_to('members/{}'.format(member_id)) created(response, location) return # The member could not be directly subscribed because there are # some out-of-band steps that need to be completed. E.g. the user # must confirm their subscription or the moderator must approve # it. In this case, an HTTP 202 Accepted is exactly the code that # we should use, and we'll return both the confirmation token and # the "token owner" so the client knows who should confirm it. assert token is not None, token assert token_owner is not TokenOwner.no_one, token_owner assert member is None, member content = dict(token=token, token_owner=token_owner.name) accepted(response, etag(content)) return # 2015-04-15 BAW: We're subscribing some role other than a regular # member. Use the legacy API for this for now. assert role in (MemberRole.owner, MemberRole.moderator, MemberRole.nonmember) # 2015-04-15 BAW: We're limited to using an email address with this # legacy API, so if the subscriber is a user, the user must have a # preferred address, which we'll use, even though it will subscribe # the explicit address. It is an error if the user does not have a # preferred address. # # If the subscriber is an address object, just use that. if IUser.providedBy(subscriber): if subscriber.preferred_address is None: bad_request(response, b'User without preferred address') return email = subscriber.preferred_address.email else: assert IAddress.providedBy(subscriber) email = subscriber.email delivery_mode = arguments.pop('delivery_mode', DeliveryMode.regular) record = RequestRecord(email, display_name, delivery_mode) try: member = add_member(mlist, record, role) except MembershipIsBannedError: bad_request(response, b'Membership is banned') return except AlreadySubscribedError: bad_request( response, '{} is already an {} of {}'.format(email, role.name, mlist.fqdn_listname)) return # The subscription completed. Let's get the resulting member # and return the location to the new member. Member ids are # UUIDs and need to be converted to URLs because JSON doesn't # directly support UUIDs. member_id = self.api.from_uuid(member.member_id) location = self.api.path_to('members/{}'.format(member_id)) created(response, location)
def on_post(self, request, response): """Create a new member.""" try: validator = Validator( list_id=str, subscriber=subscriber_validator(self.api), display_name=str, delivery_mode=enum_validator(DeliveryMode), role=enum_validator(MemberRole), pre_verified=bool, pre_confirmed=bool, pre_approved=bool, _optional=('delivery_mode', 'display_name', 'role', 'pre_verified', 'pre_confirmed', 'pre_approved')) arguments = validator(request) except ValueError as error: bad_request(response, str(error)) return # Dig the mailing list out of the arguments. list_id = arguments.pop('list_id') mlist = getUtility(IListManager).get_by_list_id(list_id) if mlist is None: bad_request(response, b'No such list') return # Figure out what kind of subscriber is being registered. Either it's # a user via their preferred email address or it's an explicit address. # If it's a UUID, then it must be associated with an existing user. subscriber = arguments.pop('subscriber') user_manager = getUtility(IUserManager) # We use the display name if there is one. display_name = arguments.pop('display_name', '') if isinstance(subscriber, UUID): user = user_manager.get_user_by_id(subscriber) if user is None: bad_request(response, b'No such user') return subscriber = user else: # This must be an email address. See if there's an existing # address object associated with this email. address = user_manager.get_address(subscriber) if address is None: # Create a new address, which of course will not be validated. address = user_manager.create_address( subscriber, display_name) subscriber = address # What role are we subscribing? Regular members go through the # subscription policy workflow while owners, moderators, and # nonmembers go through the legacy API for now. role = arguments.pop('role', MemberRole.member) if role is MemberRole.member: # Get the pre_ flags for the subscription workflow. pre_verified = arguments.pop('pre_verified', False) pre_confirmed = arguments.pop('pre_confirmed', False) pre_approved = arguments.pop('pre_approved', False) # Now we can run the registration process until either the # subscriber is subscribed, or the workflow is paused for # verification, confirmation, or approval. registrar = IRegistrar(mlist) try: token, token_owner, member = registrar.register( subscriber, pre_verified=pre_verified, pre_confirmed=pre_confirmed, pre_approved=pre_approved) except AlreadySubscribedError: conflict(response, b'Member already subscribed') return except MissingPreferredAddressError: bad_request(response, b'User has no preferred address') return except MembershipIsBannedError: bad_request(response, b'Membership is banned') return except SubscriptionPendingError: conflict(response, b'Subscription request already pending') return if token is None: assert token_owner is TokenOwner.no_one, token_owner # The subscription completed. Let's get the resulting member # and return the location to the new member. Member ids are # UUIDs and need to be converted to URLs because JSON doesn't # directly support UUIDs. member_id = self.api.from_uuid(member.member_id) location = self.api.path_to('members/{}'.format(member_id)) created(response, location) return # The member could not be directly subscribed because there are # some out-of-band steps that need to be completed. E.g. the user # must confirm their subscription or the moderator must approve # it. In this case, an HTTP 202 Accepted is exactly the code that # we should use, and we'll return both the confirmation token and # the "token owner" so the client knows who should confirm it. assert token is not None, token assert token_owner is not TokenOwner.no_one, token_owner assert member is None, member content = dict(token=token, token_owner=token_owner.name) accepted(response, etag(content)) return # 2015-04-15 BAW: We're subscribing some role other than a regular # member. Use the legacy API for this for now. assert role in (MemberRole.owner, MemberRole.moderator, MemberRole.nonmember) # 2015-04-15 BAW: We're limited to using an email address with this # legacy API, so if the subscriber is a user, the user must have a # preferred address, which we'll use, even though it will subscribe # the explicit address. It is an error if the user does not have a # preferred address. # # If the subscriber is an address object, just use that. if IUser.providedBy(subscriber): if subscriber.preferred_address is None: bad_request(response, b'User without preferred address') return email = subscriber.preferred_address.email else: assert IAddress.providedBy(subscriber) email = subscriber.email delivery_mode = arguments.pop('delivery_mode', DeliveryMode.regular) record = RequestRecord(email, display_name, delivery_mode) try: member = add_member(mlist, record, role) except MembershipIsBannedError: bad_request(response, b'Membership is banned') return except AlreadySubscribedError: bad_request(response, '{} is already an {} of {}'.format( email, role.name, mlist.fqdn_listname)) return # The subscription completed. Let's get the resulting member # and return the location to the new member. Member ids are # UUIDs and need to be converted to URLs because JSON doesn't # directly support UUIDs. member_id = self.api.from_uuid(member.member_id) location = self.api.path_to('members/{}'.format(member_id)) created(response, location)