Example #1
0
 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)
Example #2
0
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)))
Example #5
0
 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)))
Example #6
0
 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)
Example #7
0
 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))
Example #8
0
 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)
Example #9
0
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
Example #10
0
 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))
Example #12
0
 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)
Example #13
0
 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)
Example #14
0
 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)
Example #15
0
 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)
Example #16
0
 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',
         })
Example #17
0
 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))
Example #19
0
 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))
Example #20
0
 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))
Example #21
0
 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))
Example #22
0
 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)
Example #23
0
 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))
Example #24
0
 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)
Example #25
0
 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)
Example #26
0
 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)
Example #27
0
 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)))
Example #28
0
 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)
Example #29
0
 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)
Example #30
0
 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)
Example #31
0
 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)
Example #32
0
 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)
Example #33
0
 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))
Example #34
0
 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)
Example #35
0
 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)
Example #36
0
 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)
Example #37
0
 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_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)))
Example #39
0
 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)))
Example #40
0
 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))
Example #41
0
 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))
Example #42
0
 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)
Example #43
0
 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))
Example #44
0
 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)
Example #45
0
 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)
Example #47
0
 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 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)
Example #49
0
 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))
Example #51
0
 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)
Example #52
0
 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]'))
Example #53
0
 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)
Example #54
0
 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)
Example #55
0
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
Example #56
0
 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)
Example #57
0
    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)
Example #58
0
    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)
Example #59
0
 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)