From 183f1b6d8868068dc167e43af709abf47bfe3b7c Mon Sep 17 00:00:00 2001 From: miguelpadin Date: Thu, 19 May 2022 15:07:26 +0100 Subject: [PATCH] [FIX] manage error responses from login --- pms_api_rest/__init__.py | 1 + pms_api_rest/http.py | 87 ++++++++++++++++++++++ pms_api_rest/services/pms_login_service.py | 11 ++- 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 pms_api_rest/http.py diff --git a/pms_api_rest/__init__.py b/pms_api_rest/__init__.py index 420420767..e95aba4ab 100644 --- a/pms_api_rest/__init__.py +++ b/pms_api_rest/__init__.py @@ -2,3 +2,4 @@ from . import controllers from . import datamodels from . import services from . import models +from . import http diff --git a/pms_api_rest/http.py b/pms_api_rest/http.py new file mode 100644 index 000000000..fae00d147 --- /dev/null +++ b/pms_api_rest/http.py @@ -0,0 +1,87 @@ +from werkzeug.exceptions import InternalServerError, Unauthorized, NotFound, Forbidden, BadRequest, HTTPException + +import odoo +from odoo.addons.base_rest.http import HttpRestRequest, wrapJsonException +from odoo.addons.base_rest.http import _rest_services_routes +from odoo.exceptions import MissingError, AccessError, AccessDenied, UserError, ValidationError +from odoo.http import Root, SessionExpiredException, HttpRequest +from odoo.loglevels import ustr + + +class HttpRestRequestPms(HttpRestRequest): + def __init__(self, httprequest): + super(HttpRestRequestPms, self).__init__(httprequest) + + def _handle_exception(self, exception): + """Called within an except block to allow converting exceptions + to abitrary responses. Anything returned (except None) will + be used as response.""" + if isinstance(exception, SessionExpiredException): + # we don't want to return the login form as plain html page + # we want to raise a proper exception + print('session expired exception') + return wrapJsonException(Unauthorized(ustr(exception))) + try: + return super(HttpRequest, self)._handle_exception(exception) + except MissingError as e: + extra_info = getattr(e, "rest_json_info", None) + return wrapJsonException( + NotFound(ustr(e)), + include_description=True, + extra_info=extra_info + ) + except (AccessError, AccessDenied) as e: + print('access error / access denied exception') + extra_info = getattr(e, "rest_json_info", None) + return wrapJsonException( + Forbidden(ustr(e)), + include_description=True, + extra_info=extra_info + ) + except (UserError, ValidationError) as e: + extra_info = getattr(e, "rest_json_info", None) + return wrapJsonException( + BadRequest(e.args[0]), + include_description=True, + extra_info=extra_info + ) + except HTTPException as e: + extra_info = getattr(e, "rest_json_info", None) + return wrapJsonException( + e, + include_description=True, + extra_info=extra_info + ) + except Unauthorized as e: + print('Unauthorized exception') + extra_info = getattr(e, "rest_json_info", None) + return wrapJsonException( + e, + include_description=True, + extra_info=extra_info), + + except Exception as e: # flake8: noqa: E722 + extra_info = getattr(e, "rest_json_info", None) + return wrapJsonException( + InternalServerError(e), + extra_info=extra_info + ) + +ori_get_request = Root.get_request + +def get_request(self, httprequest): + db = httprequest.session.db + if db and odoo.service.db.exp_db_exist(db): + # on the very first request processed by a worker, + # registry is not loaded yet + # so we enforce its loading here to make sure that + # _rest_services_databases is not empty + odoo.registry(db) + rest_routes = _rest_services_routes.get(db, []) + for root_path in rest_routes: + if httprequest.path.startswith(root_path): + return HttpRestRequestPms(httprequest) + return ori_get_request(self, httprequest) + + +Root.get_request = get_request diff --git a/pms_api_rest/services/pms_login_service.py b/pms_api_rest/services/pms_login_service.py index 3a3aa3839..673349cc0 100644 --- a/pms_api_rest/services/pms_login_service.py +++ b/pms_api_rest/services/pms_login_service.py @@ -1,9 +1,10 @@ import time +import werkzeug.exceptions from jose import jwt from odoo import _ -from odoo.exceptions import ValidationError +from odoo.exceptions import AccessDenied, UserError from odoo.addons.base_rest import restapi from odoo.addons.base_rest_datamodel.restapi import Datamodel @@ -40,8 +41,12 @@ class PmsLoginService(Component): timestamp_expire_in_a_min = int(time.time() * 1000.0) + 1000 * 60 * minutes if not user_record: - raise ValidationError(_("user or password not valid")) - user_record.with_user(user_record)._check_credentials(user.password, None) + raise werkzeug.exceptions.Unauthorized(_("wrong user/pass")) + try: + user_record.with_user(user_record)._check_credentials(user.password, None) + except AccessDenied: + raise werkzeug.exceptions.Unauthorized(_("wrong user/pass")) + PmsApiRestUserOutput = self.env.datamodels["pms.api.rest.user.output"] token = jwt.encode(