Esempio n. 1
0
 def test_send_alert_code_can_be_specified(self):
     request = DummyRequest()
     request.registry.settings["project_docs"] = "docs_url"
     send_alert(request, "Message", code="hard-eol")
     self.verify_alert_header(
         request, {"code": "hard-eol", "message": "Message", "url": "docs_url"}
     )
Esempio n. 2
0
 def test_send_alert_default_to_project_url(self):
     request = DummyRequest()
     request.registry.settings["project_docs"] = "docs_url"
     send_alert(request, "Message")
     self.verify_alert_header(
         request, {"code": "soft-eol", "message": "Message", "url": "docs_url"}
     )
Esempio n. 3
0
 def test_send_alert_url_can_be_specified(self):
     request = DummyRequest()
     send_alert(request, 'Message', 'error_url')
     self.verify_alert_header(request, {
         'code': 'soft-eol',
         'message': 'Message',
         'url': 'error_url'
     })
Esempio n. 4
0
 def test_send_alert_url_can_be_specified(self):
     request = DummyRequest()
     send_alert(request, "Message", "error_url")
     self.verify_alert_header(request, {
         "code": "soft-eol",
         "message": "Message",
         "url": "error_url"
     })
Esempio n. 5
0
 def test_send_alert_default_to_project_url(self):
     request = DummyRequest()
     request.registry.settings['project_docs'] = 'docs_url'
     send_alert(request, 'Message')
     self.verify_alert_header(request, {
         'code': 'soft-eol',
         'message': 'Message',
         'url': 'docs_url'
     })
Esempio n. 6
0
 def test_send_alert_code_can_be_specified(self):
     request = DummyRequest()
     request.registry.settings["project_docs"] = "docs_url"
     send_alert(request, "Message", code="hard-eol")
     self.verify_alert_header(request, {
         "code": "hard-eol",
         "message": "Message",
         "url": "docs_url"
     })
Esempio n. 7
0
 def test_send_alert_code_can_be_specified(self):
     request = DummyRequest()
     request.registry.settings['project_docs'] = 'docs_url'
     send_alert(request, 'Message', code='hard-eol')
     self.verify_alert_header(request, {
         'code': 'hard-eol',
         'message': 'Message',
         'url': 'docs_url'
     })
Esempio n. 8
0
 def test_send_alert_default_to_project_url(self):
     request = DummyRequest()
     request.registry.settings["project_docs"] = "docs_url"
     send_alert(request, "Message")
     self.verify_alert_header(request, {
         "code": "soft-eol",
         "message": "Message",
         "url": "docs_url"
     })
Esempio n. 9
0
    def eos_tween(request):
        eos_date = registry.settings["eos"]
        eos_url = registry.settings["eos_url"]
        eos_message = registry.settings["eos_message"]
        if not eos_date:
            return handler(request)

        eos_date = dateparser.parse(eos_date)
        if eos_date > datetime.now():
            code = "soft-eol"
            request.response = handler(request)
        else:
            code = "hard-eol"
            request.response = errors.http_error(
                HTTPGone(), errno=errors.ERRORS.SERVICE_DEPRECATED, message=deprecation_msg
            )

        errors.send_alert(request, eos_message, url=eos_url, code=code)
        return request.response
Esempio n. 10
0
    def eos_tween(request):
        eos_date = registry.settings['eos']
        eos_url = registry.settings['eos_url']
        eos_message = registry.settings['eos_message']
        if not eos_date:
            return handler(request)

        eos_date = dateparser.parse(eos_date)
        if eos_date > datetime.now():
            code = "soft-eol"
            request.response = handler(request)
        else:
            code = "hard-eol"
            request.response = errors.http_error(
                HTTPGone(),
                errno=errors.ERRORS.SERVICE_DEPRECATED,
                message=deprecation_msg)

        errors.send_alert(request, eos_message, url=eos_url, code=code)
        return request.response
Esempio n. 11
0
    def _extract_filters(self):
        """Extracts filters from QueryString parameters."""
        queryparams = self.request.validated["querystring"]

        filters = []

        for param, value in queryparams.items():
            param = param.strip()

            error_details = {
                "name": param,
                "location": "querystring",
                "description": "Invalid value for {}".format(param),
            }

            # Ignore specific fields
            if param.startswith("_") and param not in ("_since", "_to",
                                                       "_before"):
                continue

            # Handle the _since specific filter.
            if param in ("_since", "_to", "_before"):

                if param == "_since":
                    operator = COMPARISON.GT
                else:
                    if param == "_to":
                        message = "_to is now deprecated, " "you should use _before instead"
                        url = ("https://kinto.readthedocs.io/en/2.4.0/api/"
                               "resource.html#list-of-available-url-"
                               "parameters")
                        send_alert(self.request, message, url)
                    operator = COMPARISON.LT

                if value == "":
                    raise_invalid(self.request, **error_details)

                filters.append(
                    Filter(self.model.modified_field, value, operator))
                continue

            all_keywords = "|".join([i.name.lower() for i in COMPARISON])
            m = re.match(r"^(" + all_keywords + r")_([\w\.]+)$", param)
            if m:
                keyword, field = m.groups()
                operator = getattr(COMPARISON, keyword.upper())
            else:
                operator, field = COMPARISON.EQ, param

            if not self.is_known_field(field):
                error_msg = "Unknown filter field '{}'".format(param)
                error_details["description"] = error_msg
                raise_invalid(self.request, **error_details)

            if operator in (COMPARISON.IN, COMPARISON.EXCLUDE):
                all_integers = all([isinstance(v, int) for v in value])
                all_strings = all([isinstance(v, str) for v in value])
                has_invalid_value = (field == self.model.id_field
                                     and not all_strings) or (
                                         field == self.model.modified_field
                                         and not all_integers)
                if has_invalid_value:
                    raise_invalid(self.request, **error_details)

            if "\x00" in field or "\x00" in str(value):
                error_details["description"] = "Invalid character 0x00"
                raise_invalid(self.request, **error_details)

            if field == self.model.modified_field and value == "":
                raise_invalid(self.request, **error_details)

            filters.append(Filter(field, value, operator))

        return filters
Esempio n. 12
0
    def _extract_filters(self, queryparams=None):
        """Extracts filters from QueryString parameters."""
        if not queryparams:
            queryparams = self.request.GET

        filters = []

        for param, paramvalue in queryparams.items():
            param = param.strip()

            error_details = {
                'name': param,
                'location': 'querystring',
                'description': 'Invalid value for %s' % param
            }

            # Ignore specific fields
            if param.startswith('_') and param not in ('_since',
                                                       '_to',
                                                       '_before'):
                continue

            # Handle the _since specific filter.
            if param in ('_since', '_to', '_before'):
                value = native_value(paramvalue.strip('"'))

                if not isinstance(value, six.integer_types):
                    raise_invalid(self.request, **error_details)

                if param == '_since':
                    operator = COMPARISON.GT
                else:
                    if param == '_to':
                        message = ('_to is now deprecated, '
                                   'you should use _before instead')
                        url = ('https://kinto.readthedocs.io/en/2.4.0/api/'
                               'resource.html#list-of-available-url-'
                               'parameters')
                        send_alert(self.request, message, url)
                    operator = COMPARISON.LT
                filters.append(
                    Filter(self.model.modified_field, value, operator)
                )
                continue

            m = re.match(r'^(min|max|not|lt|gt|in|exclude)_(\w+)$', param)
            if m:
                keyword, field = m.groups()
                operator = getattr(COMPARISON, keyword.upper())
            else:
                operator, field = COMPARISON.EQ, param

            if not self.is_known_field(field):
                error_msg = "Unknown filter field '{0}'".format(param)
                error_details['description'] = error_msg
                raise_invalid(self.request, **error_details)

            value = native_value(paramvalue)
            if operator in (COMPARISON.IN, COMPARISON.EXCLUDE):
                value = set([native_value(v) for v in paramvalue.split(',')])

                all_integers = all([isinstance(v, six.integer_types)
                                    for v in value])
                all_strings = all([isinstance(v, six.text_type)
                                   for v in value])
                has_invalid_value = (
                    (field == self.model.id_field and not all_strings) or
                    (field == self.model.modified_field and not all_integers)
                )
                if has_invalid_value:
                    raise_invalid(self.request, **error_details)

            filters.append(Filter(field, value, operator))

        return filters
Esempio n. 13
0
    def _extract_filters(self):
        """Extracts filters from QueryString parameters."""
        queryparams = self.request.validated['querystring']

        filters = []

        for param, value in queryparams.items():
            param = param.strip()

            error_details = {
                'name': param,
                'location': 'querystring',
                'description': 'Invalid value for {}'.format(param)
            }

            # Ignore specific fields
            if param.startswith('_') and param not in ('_since',
                                                       '_to',
                                                       '_before'):
                continue

            # Handle the _since specific filter.
            if param in ('_since', '_to', '_before'):

                if param == '_since':
                    operator = COMPARISON.GT
                else:
                    if param == '_to':
                        message = ('_to is now deprecated, '
                                   'you should use _before instead')
                        url = ('https://kinto.readthedocs.io/en/2.4.0/api/'
                               'resource.html#list-of-available-url-'
                               'parameters')
                        send_alert(self.request, message, url)
                    operator = COMPARISON.LT

                if value == '':
                    raise_invalid(self.request, **error_details)

                filters.append(
                    Filter(self.model.modified_field, value, operator)
                )
                continue

            allKeywords = '|'.join([i.name.lower() for i in COMPARISON])
            m = re.match(r'^('+allKeywords+')_([\w\.]+)$', param)
            if m:
                keyword, field = m.groups()
                operator = getattr(COMPARISON, keyword.upper())
            else:
                operator, field = COMPARISON.EQ, param

            if not self.is_known_field(field):
                error_msg = "Unknown filter field '{}'".format(param)
                error_details['description'] = error_msg
                raise_invalid(self.request, **error_details)

            if operator in (COMPARISON.IN, COMPARISON.EXCLUDE):
                all_integers = all([isinstance(v, int)
                                    for v in value])
                all_strings = all([isinstance(v, str)
                                   for v in value])
                has_invalid_value = (
                    (field == self.model.id_field and not all_strings) or
                    (field == self.model.modified_field and not all_integers)
                )
                if has_invalid_value:
                    raise_invalid(self.request, **error_details)

            if field == self.model.modified_field and value == '':
                raise_invalid(self.request, **error_details)

            filters.append(Filter(field, value, operator))

        return filters
Esempio n. 14
0
 def test_send_alert_url_can_be_specified(self):
     request = DummyRequest()
     send_alert(request, "Message", "error_url")
     self.verify_alert_header(
         request, {"code": "soft-eol", "message": "Message", "url": "error_url"}
     )
Esempio n. 15
0
    def _extract_filters(self, queryparams=None):
        """Extracts filters from QueryString parameters."""
        if not queryparams:
            queryparams = self.request.GET

        filters = []

        for param, paramvalue in queryparams.items():
            param = param.strip()

            error_details = {
                'name': param,
                'location': 'querystring',
                'description': 'Invalid value for %s' % param
            }

            # Ignore specific fields
            if param.startswith('_') and param not in ('_since', '_to',
                                                       '_before'):
                continue

            # Handle the _since specific filter.
            if param in ('_since', '_to', '_before'):
                value = native_value(paramvalue.strip('"'))

                if not isinstance(value, six.integer_types):
                    raise_invalid(self.request, **error_details)

                if param == '_since':
                    operator = COMPARISON.GT
                else:
                    if param == '_to':
                        message = ('_to is now deprecated, '
                                   'you should use _before instead')
                        url = ('http://kinto.rtfd.org/en/2.4.0/api/resource'
                               '.html#list-of-available-url-parameters')
                        send_alert(self.request, message, url)
                    operator = COMPARISON.LT
                filters.append(
                    Filter(self.model.modified_field, value, operator))
                continue

            m = re.match(r'^(min|max|not|lt|gt|in|exclude)_(\w+)$', param)
            if m:
                keyword, field = m.groups()
                operator = getattr(COMPARISON, keyword.upper())
            else:
                operator, field = COMPARISON.EQ, param

            if not self.is_known_field(field):
                error_msg = "Unknown filter field '{0}'".format(param)
                error_details['description'] = error_msg
                raise_invalid(self.request, **error_details)

            value = native_value(paramvalue)
            if operator in (COMPARISON.IN, COMPARISON.EXCLUDE):
                value = set([native_value(v) for v in paramvalue.split(',')])

                all_integers = all(
                    [isinstance(v, six.integer_types) for v in value])
                all_strings = all(
                    [isinstance(v, six.text_type) for v in value])
                has_invalid_value = (
                    (field == self.model.id_field and not all_strings) or
                    (field == self.model.modified_field and not all_integers))
                if has_invalid_value:
                    raise_invalid(self.request, **error_details)

            filters.append(Filter(field, value, operator))

        return filters
Esempio n. 16
0
    def _extract_filters(self, queryparams=None):
        """Extracts filters from QueryString parameters."""
        if not queryparams:
            queryparams = self.request.GET

        filters = []

        for param, paramvalue in queryparams.items():
            param = param.strip()

            error_details = {"name": param, "location": "querystring", "description": "Invalid value for %s" % param}

            # Ignore specific fields
            if param.startswith("_") and param not in ("_since", "_to", "_before"):
                continue

            # Handle the _since specific filter.
            if param in ("_since", "_to", "_before"):
                value = native_value(paramvalue.strip('"'))

                if not isinstance(value, six.integer_types):
                    raise_invalid(self.request, **error_details)

                if param == "_since":
                    operator = COMPARISON.GT
                else:
                    if param == "_to":
                        message = "_to is now deprecated, " "you should use _before instead"
                        url = (
                            "https://kinto.readthedocs.io/en/2.4.0/api/"
                            "resource.html#list-of-available-url-"
                            "parameters"
                        )
                        send_alert(self.request, message, url)
                    operator = COMPARISON.LT
                filters.append(Filter(self.model.modified_field, value, operator))
                continue

            allKeywords = "|".join([i.name.lower() for i in COMPARISON])
            m = re.match(r"^(" + allKeywords + ")_([\w\.]+)$", param)
            if m:
                keyword, field = m.groups()
                operator = getattr(COMPARISON, keyword.upper())
            else:
                operator, field = COMPARISON.EQ, param

            if not self.is_known_field(field):
                error_msg = "Unknown filter field '{0}'".format(param)
                error_details["description"] = error_msg
                raise_invalid(self.request, **error_details)

            value = native_value(paramvalue)
            if operator in (COMPARISON.IN, COMPARISON.EXCLUDE):
                value = set([native_value(v) for v in paramvalue.split(",")])

                all_integers = all([isinstance(v, six.integer_types) for v in value])
                all_strings = all([isinstance(v, six.text_type) for v in value])
                has_invalid_value = (field == self.model.id_field and not all_strings) or (
                    field == self.model.modified_field and not all_integers
                )
                if has_invalid_value:
                    raise_invalid(self.request, **error_details)

            filters.append(Filter(field, value, operator))

        return filters
Esempio n. 17
0
    def _extract_filters(self):
        """Extracts filters from QueryString parameters."""
        queryparams = self.request.validated['querystring']

        filters = []

        for param, value in queryparams.items():
            param = param.strip()

            error_details = {
                'name': param,
                'location': 'querystring',
                'description': 'Invalid value for {}'.format(param)
            }

            # Ignore specific fields
            if param.startswith('_') and param not in ('_since',
                                                       '_to',
                                                       '_before'):
                continue

            # Handle the _since specific filter.
            if param in ('_since', '_to', '_before'):

                if param == '_since':
                    operator = COMPARISON.GT
                else:
                    if param == '_to':
                        message = ('_to is now deprecated, '
                                   'you should use _before instead')
                        url = ('https://kinto.readthedocs.io/en/2.4.0/api/'
                               'resource.html#list-of-available-url-'
                               'parameters')
                        send_alert(self.request, message, url)
                    operator = COMPARISON.LT
                filters.append(
                    Filter(self.model.modified_field, value, operator)
                )
                continue

            allKeywords = '|'.join([i.name.lower() for i in COMPARISON])
            m = re.match(r'^('+allKeywords+')_([\w\.]+)$', param)
            if m:
                keyword, field = m.groups()
                operator = getattr(COMPARISON, keyword.upper())
            else:
                operator, field = COMPARISON.EQ, param

            if not self.is_known_field(field):
                error_msg = "Unknown filter field '{}'".format(param)
                error_details['description'] = error_msg
                raise_invalid(self.request, **error_details)

            if operator in (COMPARISON.IN, COMPARISON.EXCLUDE):
                all_integers = all([isinstance(v, int)
                                    for v in value])
                all_strings = all([isinstance(v, str)
                                   for v in value])
                has_invalid_value = (
                    (field == self.model.id_field and not all_strings) or
                    (field == self.model.modified_field and not all_integers)
                )
                if has_invalid_value:
                    raise_invalid(self.request, **error_details)

            filters.append(Filter(field, value, operator))

        return filters
Esempio n. 18
0
    def _extract_filters(self):
        """Extracts filters from QueryString parameters."""
        queryparams = self.request.validated["querystring"]

        filters = []

        for param, value in queryparams.items():
            param = param.strip()

            error_details = {
                "name": param,
                "location": "querystring",
                "description": f"Invalid value for {param}",
            }

            # Ignore specific fields
            if param.startswith("_") and param not in ("_since", "_to", "_before"):
                continue

            # Handle the _since specific filter.
            if param in ("_since", "_to", "_before"):

                if param == "_since":
                    operator = COMPARISON.GT
                else:
                    if param == "_to":
                        message = "_to is now deprecated, " "you should use _before instead"
                        url = (
                            "https://kinto.readthedocs.io/en/2.4.0/api/"
                            "resource.html#list-of-available-url-"
                            "parameters"
                        )
                        send_alert(self.request, message, url)
                    operator = COMPARISON.LT

                if value == "":
                    raise_invalid(self.request, **error_details)

                filters.append(Filter(self.model.modified_field, value, operator))
                continue

            all_keywords = r"|".join([i.name.lower() for i in COMPARISON])
            m = re.match(r"^(" + all_keywords + r")_([\w\.]+)$", param)
            if m:
                keyword, field = m.groups()
                operator = getattr(COMPARISON, keyword.upper())
            else:
                operator, field = COMPARISON.EQ, param

            if not self.is_known_field(field):
                error_msg = f"Unknown filter field '{param}'"
                error_details["description"] = error_msg
                raise_invalid(self.request, **error_details)

            # Return 400 if _limit is not a string
            if operator == COMPARISON.LIKE:
                if not isinstance(value, str):
                    raise_invalid(self.request, **error_details)

            if operator in (COMPARISON.IN, COMPARISON.EXCLUDE):
                all_integers = all([isinstance(v, int) for v in value])
                all_strings = all([isinstance(v, str) for v in value])
                has_invalid_value = (field == self.model.id_field and not all_strings) or (
                    field == self.model.modified_field and not all_integers
                )
                if has_invalid_value:
                    raise_invalid(self.request, **error_details)

            if "\x00" in field or "\x00" in str(value):
                error_details["description"] = "Invalid character 0x00"
                raise_invalid(self.request, **error_details)

            if field == self.model.modified_field and value == "":
                raise_invalid(self.request, **error_details)

            filters.append(Filter(field, value, operator))

        # If a plural endpoint is reached, and if the user does not have the
        # permission to read/write the whole list, the set is filtered by ids,
        # based on the list of ids returned by the authorization policy.
        ids = self.context.shared_ids
        if ids is not None:
            filter_by_id = Filter(self.model.id_field, ids, COMPARISON.IN)
            filters.insert(0, filter_by_id)

        return filters