def _extract_filters(self, queryparams=None): """Extracts filters from QueryString parameters.""" if not queryparams: queryparams = self.request.GET filters = [] for param, value in queryparams.items(): param = param.strip() value = native_value(value) # 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 not isinstance(value, six.integer_types): error_details = { 'name': param, 'location': 'querystring', 'description': 'Invalid value for %s' % param } 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://cliquet.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.collection.modified_field, value, operator) ) continue m = re.match(r'^(min|max|not|lt|gt)_(\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_details = { 'location': 'querystring', 'description': "Unknown filter field '{0}'".format(param) } raise_invalid(self.request, **error_details) filters.append(Filter(field, value, operator)) return filters
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' })
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' })
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' })
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
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
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://cliquet.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
def build_sync_client(request): # Get the BID assertion is_authorization_defined = AUTHORIZATION_HEADER in request.headers starts_with_browser_id = False if is_authorization_defined: authorization = request.headers[AUTHORIZATION_HEADER].lower() starts_with_browser_id = authorization.startswith("browserid ") if not is_authorization_defined or not starts_with_browser_id: msg = "Provide a BID assertion %s header." % AUTHORIZATION_HEADER response = http_error(httpexceptions.HTTPUnauthorized(), errno=ERRORS.MISSING_AUTH_TOKEN, message=msg) response.headers.extend(forget(request)) raise response bucket_id = request.matchdict["bucket_id"] is_client_state_header_defined = CLIENT_STATE_HEADER in request.headers if bucket_id == "syncto": if not is_client_state_header_defined: msg = "Provide the tokenserver %s header." % CLIENT_STATE_HEADER response = http_error(httpexceptions.HTTPUnauthorized(), errno=ERRORS.MISSING_AUTH_TOKEN, message=msg) response.headers.extend(forget(request)) raise response client_state = request.headers[CLIENT_STATE_HEADER] elif len(bucket_id) != CLIENT_STATE_LENGTH: msg = "The provided bucket ID is incorrect." response = http_error(httpexceptions.HTTPUnauthorized(), errno=ERRORS.MISSING_AUTH_TOKEN, message=msg) response.headers.extend(forget(request)) raise response else: client_state = bucket_id if is_client_state_header_defined: send_alert(request, "%s header is deprecated and should not be " "provided anymore." % CLIENT_STATE_HEADER) authorization_header = request.headers[AUTHORIZATION_HEADER] bid_assertion = authorization_header.split(" ", 1)[1] settings = request.registry.settings cache = request.registry.cache statsd = request.registry.statsd token_server_url = settings["token_server_url"] hmac_secret = settings["cache_hmac_secret"] cache_key = "credentials_%s" % utils.hmac_digest(hmac_secret, bid_assertion) ca_bundle = settings["certificate_ca_bundle"] encrypted_credentials = cache.get(cache_key) if not encrypted_credentials: settings_ttl = int(settings["cache_credentials_ttl_seconds"]) bid_ttl = _extract_bid_assertion_ttl(bid_assertion) ttl = min(settings_ttl, bid_ttl or settings_ttl) tokenserver = TokenserverClient(bid_assertion, client_state, token_server_url, verify=ca_bundle) if statsd: statsd.watch_execution_time(tokenserver, prefix="tokenserver") credentials = tokenserver.get_hawk_credentials(duration=ttl) encrypted = encrypt(json.dumps(credentials), client_state, hmac_secret) cache.set(cache_key, encrypted, ttl) else: credentials = json.loads(decrypt(encrypted_credentials, client_state, hmac_secret)) if statsd: timer = statsd.timer("syncclient.start_time") timer.start() sync_client = SyncClient(verify=ca_bundle, **credentials) if statsd: timer.stop() statsd.watch_execution_time(sync_client, prefix="syncclient") return sync_client
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://cliquet.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