summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2015-02-20 10:57:32 -0500
committerSimo Sorce <simo@redhat.com>2015-02-27 16:04:13 -0500
commita35c8bca80226a935dc5dab33e716e79ef820fd4 (patch)
treee6b49d7e0fe98a129f64e038a91066947f80f3b4
parent707d48d5fc506c2a45b875b4b585c6c168c599fd (diff)
downloadipsilon-a35c8bca80226a935dc5dab33e716e79ef820fd4.tar.gz
ipsilon-a35c8bca80226a935dc5dab33e716e79ef820fd4.tar.xz
ipsilon-a35c8bca80226a935dc5dab33e716e79ef820fd4.zip
Low-level class for managing request endpoints
An Endpoint is different from a Page in that it doesn't have menus, templates, transactions, etc. It is only defines a URL that can be mounted. https://fedorahosted.org/ipsilon/ticket/38 Signed-off-by: Rob Crittenden <rcritten@redhat.com> Reviewed-by: Simo Sorce <simo@redhat.com>
-rw-r--r--ipsilon/util/endpoint.py82
1 files changed, 82 insertions, 0 deletions
diff --git a/ipsilon/util/endpoint.py b/ipsilon/util/endpoint.py
new file mode 100644
index 0000000..f6fd667
--- /dev/null
+++ b/ipsilon/util/endpoint.py
@@ -0,0 +1,82 @@
+# Copyright (C) 2015 Ipsilon Contributors see COPYING for license
+
+import cherrypy
+from ipsilon.util.log import Log
+from ipsilon.util.user import UserSession
+from urllib import unquote
+try:
+ from urlparse import urlparse
+except ImportError:
+ # pylint: disable=no-name-in-module, import-error
+ from urllib.parse import urlparse
+
+
+class Endpoint(Log):
+ def __init__(self, site):
+ self._site = site
+ self.basepath = cherrypy.config.get('base.mount', "")
+ self.user = None
+ self.default_headers = dict()
+ self.auth_protect = False
+
+ def get_url(self):
+ return cherrypy.url(relative=False)
+
+ def instance_base_url(self):
+ url = self.get_url()
+ s = urlparse(unquote(url))
+ return '%s://%s%s' % (s.scheme, s.netloc, self.basepath)
+
+ def _check_referer(self, referer, url):
+ r = urlparse(unquote(referer))
+ u = urlparse(unquote(url))
+ if r.scheme != u.scheme:
+ return False
+ if r.netloc != u.netloc:
+ return False
+ if r.path.startswith(self.basepath):
+ return True
+ return False
+
+ def __call__(self, *args, **kwargs):
+ # pylint: disable=star-args
+ cherrypy.response.headers.update(self.default_headers)
+
+ self.user = UserSession().get_user()
+
+ if self.auth_protect and self.user.is_anonymous:
+ raise cherrypy.HTTPError(401)
+
+ self._debug("method: %s" % cherrypy.request.method)
+ op = getattr(self, cherrypy.request.method, None)
+ if callable(op):
+ # Basic CSRF protection
+ if cherrypy.request.method != 'GET':
+ url = self.get_url()
+ if 'referer' not in cherrypy.request.headers:
+ self._debug("Missing referer in %s request to %s"
+ % (cherrypy.request.method, url))
+ raise cherrypy.HTTPError(403)
+ referer = cherrypy.request.headers['referer']
+ if not self._check_referer(referer, url):
+ self._debug("Wrong referer %s in request to %s"
+ % (referer, url))
+ raise cherrypy.HTTPError(403)
+ return op(*args, **kwargs)
+ else:
+ op = getattr(self, 'root', None)
+ if callable(op):
+ return op(*args, **kwargs)
+
+ return self.default(*args, **kwargs)
+
+ def default(self, *args, **kwargs):
+ raise cherrypy.NotFound()
+
+ def add_subtree(self, name, page):
+ self.__dict__[name] = page
+
+ def del_subtree(self, name):
+ del self.__dict__[name]
+
+ exposed = True