summaryrefslogtreecommitdiff
path: root/addons/web/http.py
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/http.py')
-rw-r--r--addons/web/http.py94
1 files changed, 60 insertions, 34 deletions
diff --git a/addons/web/http.py b/addons/web/http.py
index 4f89dbf10bb..61a6a4e1250 100644
--- a/addons/web/http.py
+++ b/addons/web/http.py
@@ -88,12 +88,12 @@ class WebRequest(object):
.. attribute:: db
``str``, the name of the database linked to the current request. Can be ``None``
- if the current request uses the @nodb decorator.
+ if the current request uses the ``nodb`` authentication.
.. attribute:: uid
``int``, the id of the user related to the current request. Can be ``None``
- if the current request uses the @nodb or the @noauth decorator.
+ if the current request uses the ``nodb`` or the ``noauth`` authenticatoin.
"""
def __init__(self, httprequest):
self.httprequest = httprequest
@@ -171,14 +171,14 @@ class WebRequest(object):
def registry(self):
"""
The registry to the database linked to this request. Can be ``None`` if the current request uses the
- @nodb decorator.
+ ``nodb'' authentication.
"""
return openerp.modules.registry.RegistryManager.get(self.db) if self.db else None
@property
def cr(self):
"""
- The cursor initialized for the current method call. If the current request uses the @nodb decorator
+ The cursor initialized for the current method call. If the current request uses the ``nodb`` authentication
trying to access this property will raise an exception.
"""
# some magic to lazy create the cr
@@ -211,22 +211,43 @@ class WebRequest(object):
self.db = None
self.uid = None
-
-def noauth(f):
+def route(route, type="http", authentication="auth"):
"""
+ Decorator marking the decorated method as being a handler for requests. The method must be part of a subclass
+ of ``Controller``.
+
Decorator to put on a controller method to inform it does not require a user to be logged. When this decorator
is used, ``request.uid`` will be ``None``. The request will still try to detect the database and an exception
will be launched if there is no way to guess it.
+
+ :param route: string or array. The route part that will determine which http requests will match the decorated
+ method. Can be a single string or an array of strings. See werkzeug's routing documentation for the format of
+ route expression ( http://werkzeug.pocoo.org/docs/routing/ ).
+ :param type: The type of request, can be ``'http'`` or ``'json'``.
+ :param authentication: The type of authentication method, can on of the following:
+
+ * ``auth``: The user must be authenticated.
+ * ``noauth``: There is no need for the user to be authenticated but there must be a way to find the current
+ database.
+ * ``nodb``: The method is always active, even if there is no database. Mainly used by the framework and
+ authentication modules.
"""
+ def decorator(f):
+ if isinstance(route, list):
+ f.routes = route
+ else:
+ f.routes = [route]
+ f.exposed = type
+ if getattr(f, "auth", None) is None:
+ f.auth = authentication
+ return f
+ return decorator
+
+def noauth(f):
f.auth = "noauth"
return f
def nodb(f):
- """
- Decorator to put on a controller method to inform it does not require authentication nor any link to a database.
- When this decorator is used, ``request.uid`` and ``request.db`` will be ``None``. Trying to use ``request.cr``
- will launch an exception.
- """
f.auth = "nodb"
return f
@@ -398,8 +419,11 @@ def jsonrequest(f):
the ``session_id``, ``context`` and ``debug`` keys (which are stripped out
beforehand)
"""
- f.exposed = 'json'
- return f
+ f.combine = True
+ base = f.__name__
+ if f.__name__ == "index":
+ base = ""
+ return route([base, os.path.join(base, "<path:path>")], type="json", authentication="auth")(f)
class HttpRequest(WebRequest):
""" Regular GET/POST request
@@ -478,8 +502,11 @@ def httprequest(f):
merged in the same dictionary), apart from the ``session_id``, ``context``
and ``debug`` keys (which are stripped out beforehand)
"""
- f.exposed = 'http'
- return f
+ f.combine = True
+ base = f.__name__
+ if f.__name__ == "index":
+ base = ""
+ return route([base, os.path.join(base, "<path:path>")], type="http", authentication="auth")(f)
#----------------------------------------------------------
# Local storage of requests
@@ -526,8 +553,7 @@ class ControllerType(type):
# store the controller in the controllers list
name_class = ("%s.%s" % (cls.__module__, cls.__name__), cls)
class_path = name_class[0].split(".")
- path = attrs.get('_cp_path')
- if not path or not class_path[:2] == ["openerp", "addons"]:
+ if not class_path[:2] == ["openerp", "addons"]:
return
module = class_path[2]
controllers_per_module.setdefault(module, []).append(name_class)
@@ -535,13 +561,13 @@ class ControllerType(type):
class Controller(object):
__metaclass__ = ControllerType
- def __new__(cls, *args, **kwargs):
- subclasses = [c for c in cls.__subclasses__() if c._cp_path == cls._cp_path]
+ """def __new__(cls, *args, **kwargs):
+ subclasses = [c for c in cls.__subclasses__() if getattr(c, "_cp_path", None) == getattr(cls, "_cp_path", None)]
if subclasses:
name = "%s (extended by %s)" % (cls.__name__, ', '.join(sub.__name__ for sub in subclasses))
cls = type(name, tuple(reversed(subclasses)), {})
- return object.__new__(cls)
+ return object.__new__(cls)"""
def get_wrapped_method(self, name):
if name in self.__class__._methods_wrapper:
@@ -791,14 +817,14 @@ class Root(object):
for mk, mv in members:
if inspect.ismethod(mv) and getattr(mv, 'exposed', False) and getattr(mv, 'auth', None) == "nodb":
o = v[1]()
- if mk == "index":
- url = o._cp_path
- else:
- url = os.path.join(o._cp_path, mk)
function = (o.get_wrapped_method(mk), mv)
- routing_map.add(routing.Rule(url, endpoint=function))
- url = os.path.join(url, "<path:path>")
- routing_map.add(routing.Rule(url, endpoint=function))
+ for url in mv.routes:
+ if getattr(mv, "combine", False):
+ url = os.path.join(o._cp_path, url)
+ if url.endswith("/") and len(url) > 1:
+ url = url[: -1]
+ print "<<<<<<<<<<<<<<<< nodb", url
+ routing_map.add(routing.Rule(url, endpoint=function))
if not db:
return routing_map
@@ -817,14 +843,14 @@ class Root(object):
members = inspect.getmembers(o)
for mk, mv in members:
if inspect.ismethod(mv) and getattr(mv, 'exposed', False) and getattr(mv, 'auth', None) != "nodb":
- if mk == "index":
- url = o._cp_path
- else:
- url = os.path.join(o._cp_path, mk)
function = (o.get_wrapped_method(mk), mv)
- routing_map.add(routing.Rule(url, endpoint=function))
- url = os.path.join(url, "<path:path>")
- routing_map.add(routing.Rule(url, endpoint=function))
+ for url in mv.routes:
+ if getattr(mv, "combine", False):
+ url = os.path.join(o._cp_path, url)
+ if url.endswith("/") and len(url) > 1:
+ url = url[: -1]
+ print "<<<<<<<<<<<<<<<< db", url
+ routing_map.add(routing.Rule(url, endpoint=function))
return routing_map
def get_db_router(self, db):