Display caught errors on the page itself
[Melange.git] / app / soc / views / helper / decorators.py
blob9dbb41390018c69b819177a0d82472938ab18a90
1 #!/usr/bin/python2.5
3 # Copyright 2008 the Melange authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Views decorators.
18 """
20 __authors__ = [
21 '"Pawel Solyga" <pawel.solyga@gmail.com>',
22 '"Sverre Rabbelier" <sverre@rabbelier.nl>',
26 import logging
28 from functools import wraps
30 from google.appengine.runtime import DeadlineExceededError
31 from google.appengine.runtime.apiproxy_errors import CapabilityDisabledError
33 from django import http
34 from django.utils.translation import ugettext
36 from soc.logic import dicts
37 from soc.views.helper import responses
40 DEF_DOWN_FOR_MAINTENANCE_MSG = ugettext("Down for maintenance")
41 DEF_IN_UNEXPECTED_MAINTENANCE_MSG = ugettext(
42 "Down for unexpected maintenance.")
46 class Error(Exception):
47 """Base class for all exceptions raised by this module.
48 """
50 pass
53 def maintenance(request):
54 """Returns a 'down for maintenance' view.
55 """
57 context = responses.getUniversalContext(request)
58 context['page_name'] = ugettext('Maintenance')
60 notice = context.pop('site_notice')
62 if not notice:
63 context['body_content'] = DEF_IN_UNEXPECTED_MAINTENANCE_MSG
64 else:
65 context['body_content'] = notice
67 context['header_title'] = DEF_DOWN_FOR_MAINTENANCE_MSG
68 context['sidebar_menu_items'] = [
69 {'heading': DEF_DOWN_FOR_MAINTENANCE_MSG,
70 'group': ''},
73 template = 'soc/base.html'
75 return responses.respond(request, template, context=context)
78 def view(func):
79 """Decorator that insists that exceptions are handled by view.
80 """
82 from soc.views import out_of_band
84 @wraps(func)
85 def view_wrapper(request, *args, **kwds):
86 """View decorator wrapper method.
87 """
89 context = responses.getUniversalContext(request)
91 try:
92 if not context['is_admin'] and context['in_maintenance']:
93 return maintenance(request)
95 return func(request, *args, **kwds)
96 except CapabilityDisabledError, exception:
97 logging.exception(exception)
98 # assume the site is in maintenance if we get CDE
99 return maintenance(request)
100 except DeadlineExceededError, exception:
101 template = 'soc/deadline_exceeded.html'
102 except MemoryError, exception:
103 template = 'soc/memory_error.html'
104 except AssertionError, exception:
105 template = 'soc/assertion_error.html'
106 except out_of_band.Error, error:
107 return responses.errorResponse(error, request)
109 logging.exception(exception)
110 return responses.respond(request, template, context=context)
112 return view_wrapper
115 def merge_params(func):
116 """Decorator that merges 'params' with self._params.
119 @wraps(func)
120 def wrapper(self, *args, **kwargs):
121 """Decorator wrapper method.
123 params = kwargs.get('params', {})
124 kwargs['params'] = dicts.merge(params, self._params)
125 return func(self, *args, **kwargs)
127 return wrapper
130 def check_access(func):
131 """This decorator does access checks for the specified view method.
133 The rights dictionary is extracted from 'params', or, if either 'params' or
134 'rights' do not exist, from self._params['rights'].
137 # Do not pollute helper.decorators with access specific imports
138 from soc.views import out_of_band
139 from soc.views import helper
140 from soc.views.helper import responses
142 @wraps(func)
143 def wrapper(self, request, access_type, *args, **kwargs):
144 """Decorator wrapper method.
146 params = kwargs.get('params', {})
148 # Try to extract rights
149 if 'rights' in params:
150 rights = params['rights']
151 else:
152 rights = self._params['rights']
154 check_kwargs = kwargs.copy()
155 context = responses.getUniversalContext(request)
156 responses.useJavaScript(context, self._params['js_uses_all'])
158 id = context['account']
159 user = context['user']
161 check_kwargs['GET'] = request.GET
162 check_kwargs['POST'] = request.POST
163 check_kwargs['context'] = context
165 # reset and pre-fill the Checker's cache
166 rights.setCurrentUser(id, user)
168 # Do the access check dance
169 try:
170 rights.checkAccess(access_type, check_kwargs)
171 except out_of_band.Error, error:
172 return helper.responses.errorResponse(error, request)
173 return func(self, request, access_type, *args, **kwargs)
175 return wrapper