diff options
| -rw-r--r-- | addons/gamification/models/gamification_karma_rank.py | 21 | ||||
| -rw-r--r-- | addons/stock/controllers/main.py | 3 | ||||
| -rw-r--r-- | addons/test_website/__manifest__.py | 1 | ||||
| -rw-r--r-- | addons/test_website/controllers/main.py | 9 | ||||
| -rw-r--r-- | addons/test_website/static/tests/tours/error_views.js | 25 | ||||
| -rw-r--r-- | addons/web/controllers/main.py | 7 | ||||
| -rw-r--r-- | addons/web/static/src/js/services/crash_manager.js | 1 | ||||
| -rw-r--r-- | odoo/addons/base/models/ir_http.py | 30 | ||||
| -rw-r--r-- | odoo/http.py | 37 |
9 files changed, 90 insertions, 44 deletions
diff --git a/addons/gamification/models/gamification_karma_rank.py b/addons/gamification/models/gamification_karma_rank.py index 78b8e40ac50..cd4ef6cc28a 100644 --- a/addons/gamification/models/gamification_karma_rank.py +++ b/addons/gamification/models/gamification_karma_rank.py @@ -1,15 +1,24 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. - -from werkzeug.exceptions import Forbidden - -from odoo import api, tools, fields, models +from odoo import api, tools, fields, models, exceptions, http from odoo.tools.translate import html_translate -class KarmaError(Forbidden): +class KarmaError(exceptions.except_orm): """ Karma-related error, used for forum and posts. """ - pass + def __init__(self, msg): + super(KarmaError, self).__init__(msg) + + +class Http(models.AbstractModel): + _inherit = 'ir.http' + + @classmethod + def serialize_exception(self, e): + res = super(Http, self).serialize_exception(e) + if isinstance(e, KarmaError): + res["exception_type"] = "karma_error" + return res class KarmaRank(models.Model): diff --git a/addons/stock/controllers/main.py b/addons/stock/controllers/main.py index e18b0e6da96..05d6f5b0ead 100644 --- a/addons/stock/controllers/main.py +++ b/addons/stock/controllers/main.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- from odoo import http from odoo.http import request -from odoo.addons.web.controllers.main import _serialize_exception from odoo.tools import html_escape import json @@ -37,7 +36,7 @@ class StockReportController(http.Controller): response.set_cookie('fileToken', token) return response except Exception as e: - se = _serialize_exception(e) + se = request.env['ir.http'].serialize_exception(e) error = { 'code': 200, 'message': 'Odoo Server Error', diff --git a/addons/test_website/__manifest__.py b/addons/test_website/__manifest__.py index 557722971d4..e1bac638412 100644 --- a/addons/test_website/__manifest__.py +++ b/addons/test_website/__manifest__.py @@ -14,6 +14,7 @@ dependencies. Neither we want to add in website module some routes, views and models which only purpose is to run tests.""", 'depends': [ 'website', + 'gamification', ], 'data': [ 'views/templates.xml', diff --git a/addons/test_website/controllers/main.py b/addons/test_website/controllers/main.py index cc60ccfd25f..0a8210881c7 100644 --- a/addons/test_website/controllers/main.py +++ b/addons/test_website/controllers/main.py @@ -8,6 +8,7 @@ from odoo import http from odoo.http import request from odoo.addons.portal.controllers.web import Home from odoo.exceptions import UserError, ValidationError, AccessError, MissingError, AccessError, AccessDenied +from odoo.addons.gamification.models.gamification_karma_rank import KarmaError class WebsiteTest(Home): @@ -80,6 +81,14 @@ class WebsiteTest(Home): def test_missing_error_http(self, **kwargs): raise MissingError("This is a missing http test") + @http.route('/test_karma_error_json', type='json', auth='public', website=True) + def test_karma_error_rpc(self, **kwargs): + raise KarmaError("This is a karma rpc test") + + @http.route('/test_karma_error_http', type='http', auth='public', website=True) + def test_karma_error_http(self, **kwargs): + raise KarmaError("This is a karma http test") + @http.route('/test_internal_error_json', type='json', auth='public', website=True) def test_internal_error_json(self, **kwargs): raise werkzeug.exceptions.InternalServerError() diff --git a/addons/test_website/static/tests/tours/error_views.js b/addons/test_website/static/tests/tours/error_views.js index a3d9f3fa035..f76ba28ff8e 100644 --- a/addons/test_website/static/tests/tours/error_views.js +++ b/addons/test_website/static/tests/tours/error_views.js @@ -45,6 +45,13 @@ tour.register('test_error_website', { extra_trigger: 'div.o_dialog_warning.modal-body:contains("This is an access denied rpc test")', trigger: 'button.btn.btn-primary', }, { + content: "trigger rpc missing error", + trigger: 'a[href="/test_karma_error_json"]', + }, { + content: "rpc missing error modal has message", + extra_trigger: 'div.o_dialog_warning.modal-body:contains("This is a karma rpc test")', + trigger: 'button.btn.btn-primary', + }, { content: "trigger rpc error 500", trigger: 'a[href="/test_internal_error_json"]', }, { @@ -132,6 +139,24 @@ tour.register('test_error_website', { window.location.href = window.location.origin + '/test_karma_error_http?debug=0'; }, }, { + content: "http karma error page has title and message", + extra_trigger: 'h1:contains("Oops! Something went wrong.")', + trigger: 'div.container pre:contains("This is a karma http test")', + run: function () { + window.location.href = window.location.origin + '/test_karma_error_http?debug=1'; + }, + }, { + content: "http karma error page debug has title and message open", + extra_trigger: 'h1:contains("Oops! Something went wrong.")', + trigger: 'div#error_main.collapse.show pre:contains("This is a karma http test")', + run: function () {}, + }, { + content: "http karma error page debug has traceback closed", + trigger: 'body:has(div#error_traceback.collapse:not(.show) pre#exception_traceback)', + run: function () { + window.location.href = window.location.origin + '/test_access_denied_http?debug=0'; + }, + }, { content: "http error 403 page has title but no message", extra_trigger: 'h1:contains("403: Forbidden")', trigger: 'div#wrap:not(:has(pre:contains("This is an access denied http test"))', //See ir_http.py handle_exception, the exception is replaced so there is no message ! diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py index 860cf454dd4..7aca92712a8 100644 --- a/addons/web/controllers/main.py +++ b/addons/web/controllers/main.py @@ -42,8 +42,7 @@ from odoo.tools.translate import _ from odoo.tools.misc import str2bool, xlwt, file_open from odoo.tools.safe_eval import safe_eval from odoo import http, tools -from odoo.http import content_disposition, dispatch_rpc, request, \ - serialize_exception as _serialize_exception, Response +from odoo.http import content_disposition, dispatch_rpc, request, Response from odoo.exceptions import AccessError, UserError, AccessDenied from odoo.models import check_method_name from odoo.service import db, security @@ -83,7 +82,7 @@ def serialize_exception(f): return f(*args, **kwargs) except Exception as e: _logger.exception("An exception occured during an http request") - se = _serialize_exception(e) + se = request.registry['ir.http'].serialize_exception(e) error = { 'code': 200, 'message': "Odoo Server Error", @@ -1694,7 +1693,7 @@ class ReportController(http.Controller): else: return except Exception as e: - se = _serialize_exception(e) + se = request.env['ir.http'].serialize_exception(e) error = { 'code': 200, 'message': "Odoo Server Error", diff --git a/addons/web/static/src/js/services/crash_manager.js b/addons/web/static/src/js/services/crash_manager.js index 8681a869aba..a8fafa4b897 100644 --- a/addons/web/static/src/js/services/crash_manager.js +++ b/addons/web/static/src/js/services/crash_manager.js @@ -17,6 +17,7 @@ var map_title ={ validation_error: _lt("Validation Error"), except_orm: _lt("Global Business Error"), access_denied: _lt("Access Denied"), + karma_error: _lt("Karma Error"), }; /** diff --git a/odoo/addons/base/models/ir_http.py b/odoo/addons/base/models/ir_http.py index 897ca1de9ba..3f49b4052fc 100644 --- a/odoo/addons/base/models/ir_http.py +++ b/odoo/addons/base/models/ir_http.py @@ -9,6 +9,7 @@ import mimetypes import os import re import sys +import traceback import werkzeug import werkzeug.exceptions @@ -20,7 +21,7 @@ import odoo from odoo import api, http, models, tools, SUPERUSER_ID from odoo.exceptions import AccessDenied, AccessError from odoo.http import request, STATIC_CACHE, content_disposition -from odoo.tools import pycompat, consteq +from odoo.tools import consteq, pycompat, ustr from odoo.tools.mimetypes import guess_mimetype from odoo.modules.module import get_resource_path, get_module_path @@ -179,6 +180,33 @@ class IrHttp(models.AbstractModel): return False @classmethod + def serialize_exception(self, e): + tmp = { + "name": type(e).__module__ + "." + type(e).__name__ if type(e).__module__ else type(e).__name__, + "debug": traceback.format_exc(), + "message": ustr(e), + "arguments": e.args, + "exception_type": "internal_error" + } + if isinstance(e, odoo.exceptions.UserError): + tmp["exception_type"] = "user_error" + elif isinstance(e, odoo.exceptions.Warning): + tmp["exception_type"] = "warning" + elif isinstance(e, odoo.exceptions.RedirectWarning): + tmp["exception_type"] = "warning" + elif isinstance(e, odoo.exceptions.AccessError): + tmp["exception_type"] = "access_error" + elif isinstance(e, odoo.exceptions.MissingError): + tmp["exception_type"] = "missing_error" + elif isinstance(e, odoo.exceptions.AccessDenied): + tmp["exception_type"] = "access_denied" + elif isinstance(e, odoo.exceptions.ValidationError): + tmp["exception_type"] = "validation_error" + elif isinstance(e, odoo.exceptions.except_orm): + tmp["exception_type"] = "except_orm" + return tmp + + @classmethod def _handle_exception(cls, exception): # in case of Exception, e.g. 404, we don't step into _dispatch cls._handle_debug() diff --git a/odoo/http.py b/odoo/http.py index ab4512a6321..25200ebcecf 100644 --- a/odoo/http.py +++ b/odoo/http.py @@ -98,16 +98,16 @@ def replace_request_password(args): args[2] = '*' return tuple(args) + # don't trigger debugger for those exceptions, they carry user-facing warnings # and indications, they're not necessarily indicative of anything being # *broken* -NO_POSTMORTEM = (odoo.osv.orm.except_orm, - odoo.exceptions.AccessError, - odoo.exceptions.ValidationError, - odoo.exceptions.MissingError, +NO_POSTMORTEM = (odoo.exceptions.except_orm, odoo.exceptions.AccessDenied, odoo.exceptions.Warning, odoo.exceptions.RedirectWarning) + + def dispatch_rpc(service_name, method, params): """ Handle a RPC call. @@ -316,7 +316,7 @@ class WebRequest(object): """Called within an except block to allow converting exceptions to abitrary responses. Anything returned (except None) will be used as response.""" - self._failed = exception # prevent tx commit + self._failed = exception # prevent tx commit if not isinstance(exception, NO_POSTMORTEM) \ and not isinstance(exception, werkzeug.exceptions.HTTPException): odoo.tools.debugger.post_mortem( @@ -641,7 +641,7 @@ class JsonRequest(WebRequest): error = { 'code': 200, 'message': "Odoo Server Error", - 'data': serialize_exception(exception), + 'data': request.registry['ir.http'].serialize_exception(exception), } if isinstance(exception, werkzeug.exceptions.NotFound): error['http_status'] = 404 @@ -691,31 +691,6 @@ class JsonRequest(WebRequest): except Exception as e: return self._handle_exception(e) -def serialize_exception(e): - tmp = { - "name": type(e).__module__ + "." + type(e).__name__ if type(e).__module__ else type(e).__name__, - "debug": traceback.format_exc(), - "message": ustr(e), - "arguments": e.args, - "exception_type": "internal_error" - } - if isinstance(e, odoo.exceptions.UserError): - tmp["exception_type"] = "user_error" - elif isinstance(e, odoo.exceptions.Warning): - tmp["exception_type"] = "warning" - elif isinstance(e, odoo.exceptions.RedirectWarning): - tmp["exception_type"] = "warning" - elif isinstance(e, odoo.exceptions.AccessError): - tmp["exception_type"] = "access_error" - elif isinstance(e, odoo.exceptions.MissingError): - tmp["exception_type"] = "missing_error" - elif isinstance(e, odoo.exceptions.AccessDenied): - tmp["exception_type"] = "access_denied" - elif isinstance(e, odoo.exceptions.ValidationError): - tmp["exception_type"] = "validation_error" - elif isinstance(e, odoo.exceptions.except_orm): - tmp["exception_type"] = "except_orm" - return tmp class HttpRequest(WebRequest): """ Handler for the ``http`` request type. |
