summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVo Minh Thu <vmt@openerp.com>2011-09-08 14:38:18 +0200
committerVo Minh Thu <vmt@openerp.com>2011-09-08 14:38:18 +0200
commite643ffcc32485723cf0aaaee990bf7985cf9fce1 (patch)
tree347a5e9878faafb187659ec301ec3d70b16035fc
parent17c54e1217ec190bb145a32d7fddc2e53ca1f212 (diff)
[REF] websrv_lib:
- grouped together the concept of auth proxy and auth provider - removed the sec_realms dictionary: it was redundant as the auth proxy was set (in one of the implementation, not all) on the handler by setupAuth. Now the auth proxy is always set on the handler. - reg_http_service accepts the argument of the HTTPDir constructor. bzr revid: vmt@openerp.com-20110908123818-suc53zebgv9kcy3c
-rw-r--r--openerp/service/http_server.py66
-rw-r--r--openerp/service/web_services.py2
-rw-r--r--openerp/service/websrv_lib.py73
-rw-r--r--openerp/wsgi.py15
4 files changed, 48 insertions, 108 deletions
diff --git a/openerp/service/http_server.py b/openerp/service/http_server.py
index 8bf40024282..9bfb9397d19 100644
--- a/openerp/service/http_server.py
+++ b/openerp/service/http_server.py
@@ -250,14 +250,14 @@ class XMLRPCRequestHandler(FixSendError,HttpLogHandler,SimpleXMLRPCServer.Simple
def init_xmlrpc():
if tools.config.get('xmlrpc', False):
# Example of http file serving:
- # reg_http_service(HTTPDir('/test/',HTTPHandler))
- reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler))
+ # reg_http_service('/test/', HTTPHandler)
+ reg_http_service('/xmlrpc/', XMLRPCRequestHandler)
logging.getLogger("web-services").info("Registered XML-RPC over HTTP")
if tools.config.get('xmlrpcs', False) \
and not tools.config.get('xmlrpc', False):
# only register at the secure server
- reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler, secure_only=True))
+ reg_http_service('/xmlrpc/', XMLRPCRequestHandler, secure_only=True)
logging.getLogger("web-services").info("Registered XML-RPC over HTTPS only")
class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
@@ -299,23 +299,34 @@ def init_static_http():
base_path = tools.config.get('static_http_url_prefix', '/')
- reg_http_service(HTTPDir(base_path,StaticHTTPHandler))
+ reg_http_service(base_path, StaticHTTPHandler)
logging.getLogger("web-services").info("Registered HTTP dir %s for %s" % \
(document_root, base_path))
-class OerpAuthProxy(AuthProxy):
- """ Require basic authentication..
+import security
- This is a copy of the BasicAuthProxy, which however checks/caches the db
- as well.
- """
- def __init__(self,provider):
- AuthProxy.__init__(self,provider)
+class OpenERPAuthProvider(AuthProvider):
+ """ Require basic authentication."""
+ def __init__(self,realm='OpenERP User'):
+ self.realm = realm
self.auth_creds = {}
self.auth_tries = 0
self.last_auth = None
+ def authenticate(self, db, user, passwd, client_address):
+ try:
+ uid = security.login(db,user,passwd)
+ if uid is False:
+ return False
+ return (user, passwd, db, uid)
+ except Exception,e:
+ logging.getLogger("auth").debug("Fail auth: %s" % e )
+ return False
+
+ def log(self, msg, lvl=logging.INFO):
+ logging.getLogger("auth").log(lvl,msg)
+
def checkRequest(self,handler,path, db=False):
auth_str = handler.headers.get('Authorization',False)
try:
@@ -329,46 +340,23 @@ class OerpAuthProxy(AuthProxy):
db = psp[0]
else:
#FIXME!
- self.provider.log("Wrong path: %s, failing auth" %path)
+ self.log("Wrong path: %s, failing auth" %path)
raise AuthRejectedExc("Authorization failed. Wrong sub-path.")
if self.auth_creds.get(db):
return True
if auth_str and auth_str.startswith('Basic '):
auth_str=auth_str[len('Basic '):]
(user,passwd) = base64.decodestring(auth_str).split(':')
- self.provider.log("Found user=\"%s\", passwd=\"***\" for db=\"%s\"" %(user,db))
- acd = self.provider.authenticate(db,user,passwd,handler.client_address)
+ self.log("Found user=\"%s\", passwd=\"***\" for db=\"%s\"" %(user,db))
+ acd = self.authenticate(db,user,passwd,handler.client_address)
if acd != False:
self.auth_creds[db] = acd
self.last_auth = db
return True
if self.auth_tries > 5:
- self.provider.log("Failing authorization after 5 requests w/o password")
+ self.log("Failing authorization after 5 requests w/o password")
raise AuthRejectedExc("Authorization failed.")
self.auth_tries += 1
- raise AuthRequiredExc(atype='Basic', realm=self.provider.realm)
-
-import security
-class OpenERPAuthProvider(AuthProvider):
- def __init__(self,realm='OpenERP User'):
- self.realm = realm
-
- def setupAuth(self, multi, handler):
- if not multi.sec_realms.has_key(self.realm):
- multi.sec_realms[self.realm] = OerpAuthProxy(self)
- handler.auth_proxy = multi.sec_realms[self.realm]
-
- def authenticate(self, db, user, passwd, client_address):
- try:
- uid = security.login(db,user,passwd)
- if uid is False:
- return False
- return (user, passwd, db, uid)
- except Exception,e:
- logging.getLogger("auth").debug("Fail auth: %s" % e )
- return False
-
- def log(self, msg, lvl=logging.INFO):
- logging.getLogger("auth").log(lvl,msg)
+ raise AuthRequiredExc(atype='Basic', realm=self.realm)
#eof
diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py
index 8d05b5b776d..c941d3a809f 100644
--- a/openerp/service/web_services.py
+++ b/openerp/service/web_services.py
@@ -379,7 +379,7 @@ class common(netsvc.ExportService):
return res or False
elif method == 'logout':
if auth:
- auth.logout(params[1])
+ auth.logout(params[1]) # TODO I didn't see any AuthProxy implementing this method.
logger.notifyChannel("web-service", netsvc.LOG_INFO,'Logout %s from database %s'%(login,db))
return True
elif method in ['about', 'timezone_get', 'get_server_environment',
diff --git a/openerp/service/websrv_lib.py b/openerp/service/websrv_lib.py
index 5b98714e80e..ac83cb893c0 100644
--- a/openerp/service/websrv_lib.py
+++ b/openerp/service/websrv_lib.py
@@ -52,61 +52,17 @@ class AuthProvider:
def __init__(self,realm):
self.realm = realm
- def setupAuth(self, multi,handler):
- """ Attach an AuthProxy object to handler
- """
- pass
-
def authenticate(self, user, passwd, client_address):
return False
def log(self, msg):
print msg
-class BasicAuthProvider(AuthProvider):
- def setupAuth(self, multi, handler):
- if not multi.sec_realms.has_key(self.realm):
- multi.sec_realms[self.realm] = BasicAuthProxy(self)
-
-
-class AuthProxy:
- """ This class will hold authentication information for a handler,
- i.e. a connection
- """
- def __init__(self, provider):
- self.provider = provider
-
def checkRequest(self,handler,path = '/'):
""" Check if we are allowed to process that request
"""
pass
-class BasicAuthProxy(AuthProxy):
- """ Require basic authentication..
- """
- def __init__(self,provider):
- AuthProxy.__init__(self,provider)
- self.auth_creds = None
- self.auth_tries = 0
-
- def checkRequest(self,handler,path = '/'):
- if self.auth_creds:
- return True
- auth_str = handler.headers.get('Authorization',False)
- if auth_str and auth_str.startswith('Basic '):
- auth_str=auth_str[len('Basic '):]
- (user,passwd) = base64.decodestring(auth_str).split(':')
- self.provider.log("Found user=\"%s\", passwd=\"%s\"" %(user,passwd))
- self.auth_creds = self.provider.authenticate(user,passwd,handler.client_address)
- if self.auth_creds:
- return True
- if self.auth_tries > 5:
- self.provider.log("Failing authorization after 5 requests w/o password")
- raise AuthRejectedExc("Authorization failed.")
- self.auth_tries += 1
- raise AuthRequiredExc(atype = 'Basic', realm=self.provider.realm)
-
-
class HTTPHandler(SimpleHTTPRequestHandler):
def __init__(self,request, client_address, server):
SimpleHTTPRequestHandler.__init__(self,request,client_address,server)
@@ -144,13 +100,19 @@ class HTTPDir:
return self.path
return False
-def reg_http_service(service):
- """ Register some handler to httpd.
- hts must be an HTTPDir
+ def instanciate_handler(self, request, client_address, server):
+ handler = self.handler(noconnection(request), client_address, server)
+ if self.auth_provider:
+ handler.auth_provider = self.auth_provider
+ return handler
+
+def reg_http_service(path, handler, auth_provider=None, secure_only=False):
+ """ Register a HTTP handler at a given path.
+
+ The auth_provider will be set on the handler instances.
"""
- assert isinstance(service, HTTPDir), "Wrong class for http service"
-
global handlers
+ service = HTTPDir(path, handler, auth_provider, secure_only)
pos = len(handlers)
lastpos = pos
while pos > 0:
@@ -286,11 +248,10 @@ class MultiHTTPHandler(FixSendError, HttpOptions, BaseHTTPRequestHandler):
def __init__(self, request, client_address, server):
self.in_handlers = {}
- self.sec_realms = {}
SocketServer.StreamRequestHandler.__init__(self,request,client_address,server)
self.log_message("MultiHttpHandler init for %s" %(str(client_address)))
- def _handle_one_foreign(self,fore, path, auth_provider):
+ def _handle_one_foreign(self, fore, path):
""" This method overrides the handle_one_request for *children*
handlers. It is required, since the first line should not be
read again..
@@ -306,9 +267,9 @@ class MultiHTTPHandler(FixSendError, HttpOptions, BaseHTTPRequestHandler):
return
self.request_version = fore.request_version
- if auth_provider and auth_provider.realm:
+ if hasattr(fore, 'auth_provider'):
try:
- self.sec_realms[auth_provider.realm].checkRequest(fore,path)
+ fore.auth_provider.checkRequest(fore,path)
except AuthRequiredExc,ae:
# Darwin 9.x.x webdav clients will report "HTTP/1.0" to us, while they support (and need) the
# authorisation features of HTTP/1.1
@@ -456,15 +417,13 @@ class MultiHTTPHandler(FixSendError, HttpOptions, BaseHTTPRequestHandler):
npath = '/' + npath
if not self.in_handlers.has_key(p):
- self.in_handlers[p] = vdir.handler(noconnection(self.request),self.client_address,self.server)
- if vdir.auth_provider:
- vdir.auth_provider.setupAuth(self, self.in_handlers[p])
+ self.in_handlers[p] = vdir.instanciate_handler(noconnection(self.request),self.client_address,self.server)
hnd = self.in_handlers[p]
hnd.rfile = self.rfile
hnd.wfile = self.wfile
self.rlpath = self.raw_requestline
try:
- self._handle_one_foreign(hnd,npath, vdir.auth_provider)
+ self._handle_one_foreign(hnd, npath)
except IOError, e:
if e.errno == errno.EPIPE:
self.log_message("Could not complete request %s," \
diff --git a/openerp/wsgi.py b/openerp/wsgi.py
index ad36eb14c26..3519cdf4090 100644
--- a/openerp/wsgi.py
+++ b/openerp/wsgi.py
@@ -173,15 +173,8 @@ def http_to_wsgi(http_dir):
server.server_port = int(environ['SERVER_PORT'])
con = openerp.service.websrv_lib.noconnection(environ['gunicorn.socket']) # None TODO
- # Let's pretend we have a Multi handler (i.e. the
- # websrv_lib.MultiHTTPHandler class) to hand to the auth. provider.
- multi = Dummy()
- multi.sec_realms = {}
-
# Initialize the underlying handler and associated auth. provider.
- handler = http_dir.handler(openerp.service.websrv_lib.noconnection(con), environ['REMOTE_ADDR'], server)
- auth_provider = http_dir.auth_provider
- auth_provider.setupAuth(multi, handler)
+ handler = http_dir.instanciate_handler(openerp.service.websrv_lib.noconnection(con), environ['REMOTE_ADDR'], server)
# Populate the handler as if it is called by a regular HTTP server
# and the request is already parsed.
@@ -197,9 +190,9 @@ def http_to_wsgi(http_dir):
# Handle authentication if there is an auth. provider associated to
# the handler.
- if auth_provider and auth_provider.realm:
+ if hasattr(handler, 'auth_provider'):
try:
- multi.sec_realms[auth_provider.realm].checkRequest(handler, path)
+ handler.auth_provider.checkRequest(handler, path)
except websrv_lib.AuthRequiredExc, ae:
# Darwin 9.x.x webdav clients will report "HTTP/1.0" to us, while they support (and need) the
# authorisation features of HTTP/1.1
@@ -245,7 +238,7 @@ def http_to_wsgi(http_dir):
except (websrv_lib.AuthRejectedExc, websrv_lib.AuthRequiredExc):
raise
except Exception, e:
- start_response("500 Internal error")
+ start_response("500 Internal error", [])
return []
return wsgi_handler