[IMP] http errors refactoring
[odoo/odoo.git] / addons / website / models / ir_http.py
1 # -*- coding: utf-8 -*-
2 import traceback
3 import werkzeug.routing
4 import openerp
5 from openerp.addons.base import ir
6 from openerp.http import request
7 from openerp.osv import orm
8
9 from ..utils import slugify
10 from website import get_current_website
11
12 class ir_http(orm.AbstractModel):
13     _inherit = 'ir.http'
14
15     def _get_converters(self):
16         return dict(
17             super(ir_http, self)._get_converters(),
18             model=ModelConverter,
19             page=PageConverter,
20         )
21
22     def _auth_method_public(self):
23         if not request.session.uid:
24             request.uid = request.registry['website'].get_public_user(
25                 request.cr, openerp.SUPERUSER_ID, request.context).id
26         else:
27             request.uid = request.session.uid
28
29     def _handle_403(self, exception):
30         return self._render_error(403, {
31             'error': exception.message
32         })
33
34     def _handle_404(self, exception):
35         return self._render_error(404)
36
37     def _handle_500(self, exception):
38         # TODO: proper logging
39         return self._render_error(500, {
40             'exception': exception,
41             'traceback': traceback.format_exc(),
42             'qweb_template': getattr(exception, 'qweb_template', None),
43             'qweb_node': getattr(exception, 'qweb_node', None),
44             'qweb_eval': getattr(exception, 'qweb_eval', None),
45         })
46
47     def _render_error(self, code, values=None):
48         self._auth_method_public()
49         if not hasattr(request, 'website'):
50             request.website = get_current_website()
51             request.website.preprocess_request(request)
52         return werkzeug.wrappers.Response(
53             request.website._render('website.%s' % code, values),
54             status=code,
55             content_type='text/html;charset=utf-8')
56
57 class ModelConverter(ir.ir_http.ModelConverter):
58     def __init__(self, url_map, model=False):
59         super(ModelConverter, self).__init__(url_map, model)
60         self.regex = r'(?:[A-Za-z0-9-_]+?-)?(\d+)(?=$|/)'
61
62     def to_url(self, value):
63         if isinstance(value, orm.browse_record):
64             [(id, name)] = value.name_get()
65         else:
66             # assume name_search result tuple
67             id, name = value
68         return "%s-%d" % (slugify(name), id)
69
70     def generate(self, cr, uid, query=None, context=None):
71         return request.registry[self.model].name_search(
72             cr, uid, name=query or '', context=context)
73
74 class PageConverter(werkzeug.routing.PathConverter):
75     """ Only point of this converter is to bundle pages enumeration logic
76
77     Sads got: no way to get the view's human-readable name even if one exists
78     """
79     def generate(self, cr, uid, query=None, context=None):
80         View = request.registry['ir.ui.view']
81         views = View.search_read(
82             cr, uid, [['page', '=', True]],
83             fields=[], order='name', context=context)
84         xids = View.get_external_id(
85             cr, uid, [view['id'] for view in views], context=context)
86
87         for view in views:
88             xid = xids[view['id']]
89             if xid and (not query or query in xid):
90                 yield xid