pam: use a pam object method instead of pam module function
[cascardo/ipsilon.git] / ipsilon / util / page.py
1 # Copyright (C) 2013 Ipsilon project Contributors, for license see COPYING
2
3 import cherrypy
4 from ipsilon.util.endpoint import Endpoint
5 from ipsilon.util.user import UserSession
6 from ipsilon.util.trans import Transaction
7 from urllib import unquote
8 try:
9     from urlparse import urlparse
10     from urlparse import parse_qs
11 except ImportError:
12     # pylint: disable=no-name-in-module, import-error
13     from urllib.parse import urlparse
14     from urllib.parse import parse_qs
15
16
17 def admin_protect(fn):
18
19     def check(*args, **kwargs):
20         if UserSession().get_user().is_admin:
21             return fn(*args, **kwargs)
22
23         raise cherrypy.HTTPError(403)
24
25     return check
26
27
28 class Page(Endpoint):
29     def __init__(self, site, form=False):
30         super(Page, self).__init__(site)
31         if 'template_env' not in site:
32             raise ValueError('Missing template environment')
33         self._site = site
34         self.basepath = cherrypy.config.get('base.mount', "")
35         self.user = None
36         self._is_form_page = form
37         self.auth_protect = False
38
39     def get_url(self):
40         return cherrypy.url(relative=False)
41
42     def instance_base_url(self):
43         url = self.get_url()
44         s = urlparse(unquote(url))
45         return '%s://%s%s' % (s.scheme, s.netloc, self.basepath)
46
47     def _check_referer(self, referer, url):
48         r = urlparse(unquote(referer))
49         u = urlparse(unquote(url))
50         if r.scheme != u.scheme:
51             return False
52         if r.netloc != u.netloc:
53             return False
54         if r.path.startswith(self.basepath):
55             return True
56         return False
57
58     def __call__(self, *args, **kwargs):
59         cherrypy.response.headers.update(self.default_headers)
60
61         self.user = UserSession().get_user()
62
63         if self.auth_protect and self.user.is_anonymous:
64             raise cherrypy.HTTPError(401)
65
66         if len(args) > 0:
67             op = getattr(self, args[0], None)
68             if callable(op) and getattr(op, 'public_function', None):
69                 return op(*args[1:], **kwargs)
70         else:
71             if self._is_form_page:
72                 self.debug("method: %s" % cherrypy.request.method)
73                 op = getattr(self, cherrypy.request.method, None)
74                 if callable(op):
75                     # Basic CSRF protection
76                     if cherrypy.request.method != 'GET':
77                         url = self.get_url()
78                         if 'referer' not in cherrypy.request.headers:
79                             self.debug("Missing referer in %s request to %s"
80                                        % (cherrypy.request.method, url))
81                             raise cherrypy.HTTPError(403)
82                         referer = cherrypy.request.headers['referer']
83                         if not self._check_referer(referer, url):
84                             self.debug("Wrong referer %s in request to %s"
85                                        % (referer, url))
86                             raise cherrypy.HTTPError(403)
87                     return op(*args, **kwargs)
88             else:
89                 op = getattr(self, 'root', None)
90                 if callable(op):
91                     return op(*args, **kwargs)
92
93         return self.default(*args, **kwargs)
94
95     def _template_model(self):
96         model = dict()
97         model['basepath'] = self.basepath
98         model['title'] = 'IPSILON'
99         model['user'] = self.user
100         return model
101
102     def _template(self, *args, **kwargs):
103         t = self._site['template_env'].get_template(args[0])
104         m = self._template_model()
105         m.update(kwargs)
106         return t.render(**m)
107
108     def default(self, *args, **kwargs):
109         raise cherrypy.NotFound()
110
111     def add_subtree(self, name, page):
112         self.__dict__[name] = page
113
114     def del_subtree(self, name):
115         del self.__dict__[name]
116
117     def get_valid_transaction(self, provider, **kwargs):
118         try:
119             t = Transaction(provider)
120             # Try with kwargs first
121             tid = t.find_tid(kwargs)
122             if not tid:
123                 # If no TID yet See if we have it in a referer or in the
124                 # environment in the REDIRECT_URL
125                 url = None
126                 if 'referer' in cherrypy.request.headers:
127                     url = cherrypy.request.headers['referer']
128                     r = urlparse(unquote(url))
129                     if r.query:
130                         tid = t.find_tid(parse_qs(r.query))
131                 if not tid and 'REQUEST_URI' in cherrypy.request.wsgi_environ:
132                     url = cherrypy.request.wsgi_environ['REQUEST_URI']
133                     r = urlparse(unquote(url))
134                     if r.query:
135                         tid = t.find_tid(parse_qs(r.query))
136                 if not tid:
137                     t.create_tid()
138             return t
139         except ValueError:
140             msg = 'Transaction expired, or cookies not available'
141             raise cherrypy.HTTPError(401, msg)
142
143     exposed = True