[service] allow repo_stats for users
It's used by the siteinfo view, which is available to managers and
users. This change prevents a crash in that view.
# -*- coding: utf-8 -*-# copyright 2014 Logilab, PARIS"""A set of utility functions to handle CORS requestsUnless specified, all references in this file are related to: http://www.w3.org/TR/corsThe provided implementation roughly follows: http://www.html5rocks.com/static/images/cors_server_flowchart.pngSee also: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS"""importurlparsefromcubicweb.webimportLOGGERinfo=LOGGER.infoclassCORSFailed(Exception):"""Raised when cross origin resource sharing checks failed"""classCORSPreflight(Exception):"""Raised when cross origin resource sharing checks detects the request as a valid preflight request"""defprocess_request(req,config):""" Process a request to apply CORS specification algorithms Check whether the CORS specification is respected and set corresponding headers to ensure response complies with the specification. In case of non-compliance, no CORS-related header is set. """base_url=urlparse.urlsplit(req.base_url())expected_host='://'.join((base_url.scheme,base_url.netloc))ifnotreq.get_header('Origin')orreq.get_header('Origin')==expected_host:# not a CORS request, nothing to doreturntry:# handle cross origin resource sharing (CORS)ifreq.http_method()=='OPTIONS':ifreq.get_header('Access-Control-Request-Method'):# preflight CORS requestprocess_preflight(req,config)else:# Simple CORS or actual requestprocess_simple(req,config)exceptCORSFailed,exc:info('Cross origin resource sharing failed: %s'%exc)exceptCORSPreflight:info('Cross origin resource sharing: valid Preflight request %s')raisedefprocess_preflight(req,config):"""cross origin resource sharing (preflight) Cf http://www.w3.org/TR/cors/#resource-preflight-requests """origin=check_origin(req,config)allowed_methods=set(config['access-control-allow-methods'])allowed_headers=set(config['access-control-allow-headers'])try:method=req.get_header('Access-Control-Request-Method')exceptValueError:raiseCORSFailed('Access-Control-Request-Method is incorrect')ifmethodnotinallowed_methods:raiseCORSFailed('Method is not allowed')try:req.get_header('Access-Control-Request-Headers',())exceptValueError:raiseCORSFailed('Access-Control-Request-Headers is incorrect')req.set_header('Access-Control-Allow-Methods',allowed_methods,raw=False)req.set_header('Access-Control-Allow-Headers',allowed_headers,raw=False)process_common(req,config,origin)raiseCORSPreflight()defprocess_simple(req,config):"""Handle the Simple Cross-Origin Request case """origin=check_origin(req,config)exposed_headers=config['access-control-expose-headers']ifexposed_headers:req.set_header('Access-Control-Expose-Headers',exposed_headers,raw=False)process_common(req,config,origin)defprocess_common(req,config,origin):req.set_header('Access-Control-Allow-Origin',origin)# in CW, we always support credential/authenticationreq.set_header('Access-Control-Allow-Credentials','true')defcheck_origin(req,config):origin=req.get_header('Origin').lower()allowed_origins=config.get('access-control-allow-origin')ifnotallowed_origins:raiseCORSFailed('access-control-allow-origin is not configured')if'*'notinallowed_originsandoriginnotinallowed_origins:raiseCORSFailed('Origin is not allowed')# bit of sanity check; see "6.3 Security"myhost=urlparse.urlsplit(req.base_url()).netlochost=req.get_header('Host')ifhost!=myhost:info('cross origin resource sharing detected possible ''DNS rebinding attack Host header != host of base_url: ''%s != %s'%(host,myhost))raiseCORSFailed('Host header and hostname do not match')# include "Vary: Origin" header (see 6.4)req.set_header('Vary','Origin')returnorigin