diff --git a/.badges/code_style-black-000000.svg b/.badges/code_style-black-000000.svg deleted file mode 100644 index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_LmJhZGdlcy9jb2RlX3N0eWxlLWJsYWNrLTAwMDAwMC5zdmc=..0000000000000000000000000000000000000000 --- a/.badges/code_style-black-000000.svg +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20"> - <linearGradient id="b" x2="0" y2="100%"> - <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> - <stop offset="1" stop-opacity=".1" /> - </linearGradient> - <mask id="anybadge_1"> - <rect width="114" height="20" rx="3" fill="#fff" /> - </mask> - <g mask="url(#anybadge_1)"> - <path fill="#555" d="M0 0h72v20H0z" /> - <path fill="#000000" d="M72 0h42v20H72z" /> - <path fill="url(#b)" d="M0 0h114v20H0z" /> - </g> - <g - fill="#fff" - text-anchor="middle" - font-family="DejaVu Sans,Verdana,Geneva,sans-serif" - font-size="11" - > - <text x="37.0" y="15" fill="#010101" fill-opacity=".3">code style</text> - <text x="36.0" y="14">code style</text> - </g> - <g - fill="#fff" - text-anchor="middle" - font-family="DejaVu Sans,Verdana,Geneva,sans-serif" - font-size="11" - > - <text x="94.0" y="15" fill="#010101" fill-opacity=".3">black</text> - <text x="93.0" y="14">black</text> - </g> -</svg> diff --git a/.badges/code_style-ruff.svg b/.badges/code_style-ruff.svg new file mode 100644 index 0000000000000000000000000000000000000000..d1e6e2024d3d882c89f27a1971b9202550abe19d_LmJhZGdlcy9jb2RlX3N0eWxlLXJ1ZmYuc3Zn --- /dev/null +++ b/.badges/code_style-ruff.svg @@ -0,0 +1,49 @@ +<svg + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + width="53" + height="20" + role="img" + aria-label="Ruff" +> + <title>Ruff</title> + <linearGradient id="s" x2="0" y2="100%"> + <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> + <stop offset="1" stop-opacity=".1" /> + </linearGradient> + <clipPath id="r"> + <rect width="53" height="20" rx="3" fill="#fff" /> + </clipPath> + <g clip-path="url(#r)"> + <rect width="20" height="20" fill="#555" /> + <rect x="20" width="33" height="20" fill="#261230" /> + <rect width="53" height="20" fill="url(#s)" /> + </g> + <g + fill="#fff" + text-anchor="middle" + font-family="Verdana,Geneva,DejaVu Sans,sans-serif" + text-rendering="geometricPrecision" + font-size="110" + > + <image + x="5" + y="3" + width="10" + height="14" + xlink:href="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEwIiBoZWlnaHQ9IjYyMiIgdmlld0JveD0iMCAwIDUxMCA2MjIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMDYuNzAxIDBDMjAwLjk2NCAwIDE5Ni4zMTQgNC42NDEzMSAxOTYuMzE0IDEwLjM2NjdWNDEuNDY2N0MxOTYuMzE0IDQ3LjE5MiAxOTEuNjYzIDUxLjgzMzMgMTg1LjkyNyA1MS44MzMzSDE1Ni44NDNDMTUxLjEwNyA1MS44MzMzIDE0Ni40NTYgNTYuNDc0NiAxNDYuNDU2IDYyLjJWMTQ1LjEzM0MxNDYuNDU2IDE1MC44NTkgMTQxLjgwNiAxNTUuNSAxMzYuMDY5IDE1NS41SDEwNi45ODZDMTAxLjI0OSAxNTUuNSA5Ni41OTg4IDE2MC4xNDEgOTYuNTk4OCAxNjUuODY3VjIyMi44ODNDOTYuNTk4OCAyMjguNjA5IDkxLjk0ODQgMjMzLjI1IDg2LjIxMTggMjMzLjI1SDU3LjEyODNDNTEuMzkxNyAyMzMuMjUgNDYuNzQxMyAyMzcuODkxIDQ2Ljc0MTMgMjQzLjYxN1YzMDAuNjMzQzQ2Ljc0MTMgMzA2LjM1OSA0Mi4wOTA5IDMxMSAzNi4zNTQ0IDMxMUgxMC4zODdDNC42NTA0IDMxMSAwIDMxNS42NDEgMCAzMjEuMzY3VjM1Mi40NjdDMCAzNTguMTkyIDQuNjUwNCAzNjIuODMzIDEwLjM4NyAzNjIuODMzSDE0NS40MThDMTUxLjE1NCAzNjIuODMzIDE1NS44MDQgMzY3LjQ3NSAxNTUuODA0IDM3My4yVjQzMC4yMTdDMTU1LjgwNCA0MzUuOTQyIDE1MS4xNTQgNDQwLjU4MyAxNDUuNDE4IDQ0MC41ODNIMTE2LjMzNEMxMTAuNTk3IDQ0MC41ODMgMTA1Ljk0NyA0NDUuMjI1IDEwNS45NDcgNDUwLjk1VjUwNy45NjdDMTA1Ljk0NyA1MTMuNjkyIDEwMS4yOTcgNTE4LjMzMyA5NS41NjAxIDUxOC4zMzNINjYuNDc2NkM2MC43NCA1MTguMzMzIDU2LjA4OTYgNTIyLjk3NSA1Ni4wODk2IDUyOC43VjYxMS42MzNDNTYuMDg5NiA2MTcuMzU5IDYwLjc0IDYyMiA2Ni40NzY2IDYyMkgxNDkuNTcyQzE1NS4zMDkgNjIyIDE1OS45NTkgNjE3LjM1OSAxNTkuOTU5IDYxMS42MzNWNTcwLjE2N0gyMDEuNTA3QzIwNy4yNDQgNTcwLjE2NyAyMTEuODk0IDU2NS41MjUgMjExLjg5NCA1NTkuOFY1MjguN0MyMTEuODk0IDUyMi45NzUgMjE2LjU0NCA1MTguMzMzIDIyMi4yODEgNTE4LjMzM0gyNTEuMzY1QzI1Ny4xMDEgNTE4LjMzMyAyNjEuNzUyIDUxMy42OTIgMjYxLjc1MiA1MDcuOTY3VjQ3Ni44NjdDMjYxLjc1MiA0NzEuMTQxIDI2Ni40MDIgNDY2LjUgMjcyLjEzOCA0NjYuNUgzMDEuMjIyQzMwNi45NTkgNDY2LjUgMzExLjYwOSA0NjEuODU5IDMxMS42MDkgNDU2LjEzM1Y0MjUuMDMzQzMxMS42MDkgNDE5LjMwOCAzMTYuMjU5IDQxNC42NjcgMzIxLjk5NiA0MTQuNjY3SDM1MS4wNzlDMzU2LjgxNiA0MTQuNjY3IDM2MS40NjYgNDEwLjAyNSAzNjEuNDY2IDQwNC4zVjM3My4yQzM2MS40NjYgMzY3LjQ3NSAzNjYuMTE3IDM2Mi44MzMgMzcxLjg1MyAzNjIuODMzSDQwMC45MzdDNDA2LjY3MyAzNjIuODMzIDQxMS4zMjQgMzU4LjE5MiA0MTEuMzI0IDM1Mi40NjdWMzIxLjM2N0M0MTEuMzI0IDMxNS42NDEgNDE1Ljk3NCAzMTEgNDIxLjcxMSAzMTFINDUwLjc5NEM0NTYuNTMxIDMxMSA0NjEuMTgxIDMwNi4zNTkgNDYxLjE4MSAzMDAuNjMzVjIxNy43QzQ2MS4xODEgMjExLjk3NSA0NTYuNTMxIDIwNy4zMzMgNDUwLjc5NCAyMDcuMzMzSDQyMC42NzJDNDE0LjkzNiAyMDcuMzMzIDQxMC4yODUgMjAyLjY5MiA0MTAuMjg1IDE5Ni45NjdWMTY1Ljg2N0M0MTAuMjg1IDE2MC4xNDEgNDE0LjkzNiAxNTUuNSA0MjAuNjcyIDE1NS41SDQ0OS43NTZDNDU1LjQ5MiAxNTUuNSA0NjAuMTQzIDE1MC44NTkgNDYwLjE0MyAxNDUuMTMzVjExNC4wMzNDNDYwLjE0MyAxMDguMzA4IDQ2NC43OTMgMTAzLjY2NyA0NzAuNTMgMTAzLjY2N0g0OTkuNjEzQzUwNS4zNSAxMDMuNjY3IDUxMCA5OS4wMjUzIDUxMCA5My4zVjEwLjM2NjdDNTEwIDQuNjQxMzIgNTA1LjM1IDAgNDk5LjYxMyAwSDIwNi43MDFaTTE2OC4yNjkgNDQwLjU4M0MxNjIuNTMyIDQ0MC41ODMgMTU3Ljg4MiA0NDUuMjI1IDE1Ny44ODIgNDUwLjk1VjUwNy45NjdDMTU3Ljg4MiA1MTMuNjkyIDE1My4yMzEgNTE4LjMzMyAxNDcuNDk1IDUxOC4zMzNIMTE4LjQxMUMxMTIuNjc1IDUxOC4zMzMgMTA4LjAyNCA1MjIuOTc1IDEwOC4wMjQgNTI4LjdWNTU5LjhDMTA4LjAyNCA1NjUuNTI1IDExMi42NzUgNTcwLjE2NyAxMTguNDExIDU3MC4xNjdIMTU5Ljk1OVY1MjguN0MxNTkuOTU5IDUyMi45NzUgMTY0LjYxIDUxOC4zMzMgMTcwLjM0NiA1MTguMzMzSDE5OS40M0MyMDUuMTY2IDUxOC4zMzMgMjA5LjgxNyA1MTMuNjkyIDIwOS44MTcgNTA3Ljk2N1Y0NzYuODY3QzIwOS44MTcgNDcxLjE0MSAyMTQuNDY3IDQ2Ni41IDIyMC4yMDQgNDY2LjVIMjQ5LjI4N0MyNTUuMDI0IDQ2Ni41IDI1OS42NzQgNDYxLjg1OSAyNTkuNjc0IDQ1Ni4xMzNWNDI1LjAzM0MyNTkuNjc0IDQxOS4zMDggMjY0LjMyNSA0MTQuNjY3IDI3MC4wNjEgNDE0LjY2N0gyOTkuMTQ1QzMwNC44ODEgNDE0LjY2NyAzMDkuNTMyIDQxMC4wMjUgMzA5LjUzMiA0MDQuM1YzNzMuMkMzMDkuNTMyIDM2Ny40NzUgMzE0LjE4MiAzNjIuODMzIDMxOS45MTkgMzYyLjgzM0gzNDkuMDAyQzM1NC43MzkgMzYyLjgzMyAzNTkuMzg5IDM1OC4xOTIgMzU5LjM4OSAzNTIuNDY3VjMyMS4zNjdDMzU5LjM4OSAzMTUuNjQxIDM2NC4wMzkgMzExIDM2OS43NzYgMzExSDM5OC44NTlDNDA0LjU5NiAzMTEgNDA5LjI0NiAzMDYuMzU5IDQwOS4yNDYgMzAwLjYzM1YyNjkuNTMzQzQwOS4yNDYgMjYzLjgwOCA0MDQuNTk2IDI1OS4xNjcgMzk4Ljg1OSAyNTkuMTY3SDMxOC44OEMzMTMuMTQzIDI1OS4xNjcgMzA4LjQ5MyAyNTQuNTI1IDMwOC40OTMgMjQ4LjhWMjE3LjdDMzA4LjQ5MyAyMTEuOTc1IDMxMy4xNDMgMjA3LjMzMyAzMTguODggMjA3LjMzM0gzNDcuOTYzQzM1My43IDIwNy4zMzMgMzU4LjM1IDIwMi42OTIgMzU4LjM1IDE5Ni45NjdWMTY1Ljg2N0MzNTguMzUgMTYwLjE0MSAzNjMuMDAxIDE1NS41IDM2OC43MzcgMTU1LjVIMzk3LjgyMUM0MDMuNTU3IDE1NS41IDQwOC4yMDggMTUwLjg1OSA0MDguMjA4IDE0NS4xMzNWMTE0LjAzM0M0MDguMjA4IDEwOC4zMDggNDEyLjg1OCAxMDMuNjY3IDQxOC41OTUgMTAzLjY2N0g0NDcuNjc4QzQ1My40MTUgMTAzLjY2NyA0NTguMDY1IDk5LjAyNTMgNDU4LjA2NSA5My4zVjYyLjJDNDU4LjA2NSA1Ni40NzQ2IDQ1My40MTUgNTEuODMzMyA0NDcuNjc4IDUxLjgzMzNIMjA4Ljc3OEMyMDMuMDQxIDUxLjgzMzMgMTk4LjM5MSA1Ni40NzQ2IDE5OC4zOTEgNjIuMlYxNDUuMTMzQzE5OC4zOTEgMTUwLjg1OSAxOTMuNzQxIDE1NS41IDE4OC4wMDQgMTU1LjVIMTU4LjkyMUMxNTMuMTg0IDE1NS41IDE0OC41MzQgMTYwLjE0MSAxNDguNTM0IDE2NS44NjdWMjIyLjg4M0MxNDguNTM0IDIyOC42MDkgMTQzLjg4MyAyMzMuMjUgMTM4LjE0NyAyMzMuMjVIMTA5LjA2M0MxMDMuMzI3IDIzMy4yNSA5OC42NzYyIDIzNy44OTEgOTguNjc2MiAyNDMuNjE3VjMwMC42MzNDOTguNjc2MiAzMDYuMzU5IDEwMy4zMjcgMzExIDEwOS4wNjMgMzExSDE5Ny4zNTJDMjAzLjA4OSAzMTEgMjA3LjczOSAzMTUuNjQxIDIwNy43MzkgMzIxLjM2N1Y0MzAuMjE3QzIwNy43MzkgNDM1Ljk0MiAyMDMuMDg5IDQ0MC41ODMgMTk3LjM1MiA0NDAuNTgzSDE2OC4yNjlaIiBmaWxsPSIjRDdGRjY0Ii8+PC9zdmc+" + /> + <text + aria-hidden="true" + x="355" + y="150" + fill="#010101" + fill-opacity=".3" + transform="scale(.1)" + textLength="230" + > + Ruff + </text> + <text x="355" y="140" transform="scale(.1)" fill="#fff" textLength="230">Ruff</text> + </g> +</svg> diff --git a/.badges/pylint.svg b/.badges/pylint.svg deleted file mode 100644 index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_LmJhZGdlcy9weWxpbnQuc3Zn..0000000000000000000000000000000000000000 --- a/.badges/pylint.svg +++ /dev/null @@ -1,33 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<svg xmlns="http://www.w3.org/2000/svg" width="103" height="20"> - <linearGradient id="b" x2="0" y2="100%"> - <stop offset="0" stop-color="#bbb" stop-opacity=".1" /> - <stop offset="1" stop-opacity=".1" /> - </linearGradient> - <mask id="anybadge_1"> - <rect width="103" height="20" rx="3" fill="#fff" /> - </mask> - <g mask="url(#anybadge_1)"> - <path fill="#555" d="M0 0h44v20H0z" /> - <path fill="#808080" d="M44 0h59v20H44z" /> - <path fill="url(#b)" d="M0 0h103v20H0z" /> - </g> - <g - fill="#fff" - text-anchor="middle" - font-family="DejaVu Sans,Verdana,Geneva,sans-serif" - font-size="11" - > - <text x="23.0" y="15" fill="#010101" fill-opacity=".3">pylint</text> - <text x="22.0" y="14">pylint</text> - </g> - <g - fill="#fff" - text-anchor="middle" - font-family="DejaVu Sans,Verdana,Geneva,sans-serif" - font-size="11" - > - <text x="74.5" y="15" fill="#010101" fill-opacity=".3">unknown</text> - <text x="73.5" y="14">unknown</text> - </g> -</svg> diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_LmdpdGxhYi1jaS55bWw=..d1e6e2024d3d882c89f27a1971b9202550abe19d_LmdpdGxhYi1jaS55bWw= 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,3 @@ include: - project: xcg/ci-templates - file: /odoo/15.0/gitlab-ci.yaml - -variables: - CI_TEMPLATE_NO_INSTALL_MODULE: "" + file: /odoo/17.0/gitlab-ci.yaml diff --git a/NEWS.rst b/NEWS.rst index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_TkVXUy5yc3Q=..d1e6e2024d3d882c89f27a1971b9202550abe19d_TkVXUy5yc3Q= 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -1,4 +1,3 @@ -========= Changelog ========= @@ -2,6 +1,6 @@ Changelog ========= -15.0.1.0.1 +17.0.1.0.0 ---------- @@ -6,9 +5,3 @@ ---------- -Package the module so that it can be installed. - -15.0.1.0.0 ----------- - -Port to Odoo 15 - +Migration to Odoo 17. diff --git a/README.rst b/README.rst index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_UkVBRE1FLnJzdA==..d1e6e2024d3d882c89f27a1971b9202550abe19d_UkVBRE1FLnJzdA== 100644 --- a/README.rst +++ b/README.rst @@ -2,18 +2,9 @@ Menu Redirector =============== -.. |pipeline| image:: https://orus.io/xcg/odoo-modules/menuredir/badges/branch/15.0/pipeline.svg - :target: https://orus.io/xcg/odoo-modules/menuredir/commits/branch/15.0 - :alt: pipeline status -.. |coverage| image:: https://orus.io/xcg/odoo-modules/menuredir/badges/branch/15.0/coverage.svg - :target: https://orus.io/xcg/odoo-modules/menuredir/commits/branch/15.0 - :alt: Coverage report -.. |pylint| image:: .badges/pylint.svg - :target: https://orus.io/xcg/odoo-modules/menuredir/-/pipelines?ref=branch/15.0 - :alt: pylint score .. |maturity| image:: .badges/maturity.svg :target: https://odoo-community.org/page/development-status :alt: Stable .. |license| image:: .badges/licence-AGPL--3-blue.svg :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 @@ -14,13 +5,13 @@ .. |maturity| image:: .badges/maturity.svg :target: https://odoo-community.org/page/development-status :alt: Stable .. |license| image:: .badges/licence-AGPL--3-blue.svg :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 -.. |black| image:: .badges/code_style-black-000000.svg - :target: https://github.com/psf/black - :alt: Black +.. |ruff| image:: .badges/code_style-ruff.svg + :target: https://github.com/astral-sh/ruff + :alt: Ruff .. |prettier| image:: .badges/code_style-prettier-ff69b4.svg :target: https://github.com/prettier/prettier :alt: Prettier @@ -23,8 +14,8 @@ .. |prettier| image:: .badges/code_style-prettier-ff69b4.svg :target: https://github.com/prettier/prettier :alt: Prettier -|pipeline| |coverage| |pylint| |maturity| |license| |black| |prettier| +|maturity| |license| |ruff| |prettier| A simple web controller that redirects the web browser to the proper application and menu_id after looking up for them in the database. @@ -34,3 +25,18 @@ avoids to use internal database ids that may change between database instances depending on the order in which modules were installed. +Usage +===== + +A new controller is added that redirect /menuredir/go?app=base&db=odoo&menu=menu_ir_access_act to the menu item whose external id is base.menu_ir_access_act in the database odoo. + +The db parameter can be omitted when the server is running a single database. + +When used with multiple database, the module needs to be added to the list of modules for server wide modules. + +When defined in server wide modules, the module does not need to be installed. + +If a db filter is defined in Odoo’s configuration file, the provided name is checked against the filter. + +If the database name is filtered or does not exist, or if the menu item is not found or is not a menu item, the module redirects to /web and log the error. + diff --git a/__init__.py b/__init__.py index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_X19pbml0X18ucHk=..d1e6e2024d3d882c89f27a1971b9202550abe19d_X19pbml0X18ucHk= 100644 --- a/__init__.py +++ b/__init__.py @@ -1,1 +1,1 @@ -from . import controllers # noqa: F401 +from . import controllers diff --git a/__manifest__.py b/__manifest__.py index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_X19tYW5pZmVzdF9fLnB5..d1e6e2024d3d882c89f27a1971b9202550abe19d_X19tYW5pZmVzdF9fLnB5 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -20,8 +20,8 @@ { "name": "Menu Redirector", "license": "AGPL-3", - "version": "15.0.1.0.1", + "version": "17.0.1.0.0", "category": "Web", "author": "XCG Consulting", "website": "https://orbeet.io/", "depends": ["web"], @@ -24,7 +24,6 @@ "category": "Web", "author": "XCG Consulting", "website": "https://orbeet.io/", "depends": ["web"], - "data": [], "installable": True, } diff --git a/controllers/main.py b/controllers/main.py index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_Y29udHJvbGxlcnMvbWFpbi5weQ==..d1e6e2024d3d882c89f27a1971b9202550abe19d_Y29udHJvbGxlcnMvbWFpbi5weQ== 100644 --- a/controllers/main.py +++ b/controllers/main.py @@ -1,7 +1,8 @@ ############################################################################## # # Menu redirector for Odoo -# Copyright © 2015, 2018, 2019, 2022 XCG Consulting (https://xcg-consulting.fr/) +# Copyright © 2015, 2018, 2019, 2022, 2024 XCG Consulting +# (https://xcg-consulting.fr/) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -19,10 +20,10 @@ ############################################################################## import logging -import werkzeug.utils - -from odoo.http import Controller, request, route -from odoo.modules.registry import Registry +from odoo import SUPERUSER_ID, registry +from odoo.api import Environment +from odoo.http import Controller, db_filter, request, route +from werkzeug import utils log = logging.getLogger(__name__) @@ -57,8 +58,7 @@ Find the correct menu id and redirect the client to the proper URL as if he had clicked on the menu. """ - dbname, app, menu = ( - kw.get("db", None), + app, menu = ( kw.get("app", None), kw.get("menu", None), ) @@ -62,6 +62,13 @@ kw.get("app", None), kw.get("menu", None), ) + # Inspired by code in auth_oauth controller + dbname = kw.get("db", None) + if not dbname: + dbname = request.db + if dbname and not db_filter([dbname]): + # filter out any filtered dbname + dbname = None url = "/web" error_ = request_error(dbname, app, menu) @@ -69,5 +76,5 @@ if not error_: try: - registry = Registry(dbname) + odoo_registry = registry(dbname) @@ -73,3 +80,3 @@ - with registry.cursor(): + with odoo_registry.cursor() as cr: try: @@ -75,7 +82,8 @@ try: - log.info( + env = Environment(cr, SUPERUSER_ID, {}) + log.debug( "Searching menu item %s.%s for database %s", app, menu, dbname, ) @@ -77,11 +85,11 @@ "Searching menu item %s.%s for database %s", app, menu, dbname, ) - irmd = request.env["ir.model.data"] + irmd = env["ir.model.data"] # pylint: disable=protected-access res_model, res_id = irmd._xmlid_to_res_model_res_id( f"{app}.{menu}", True ) if res_model == "ir.ui.menu": @@ -83,10 +91,14 @@ # pylint: disable=protected-access res_model, res_id = irmd._xmlid_to_res_model_res_id( f"{app}.{menu}", True ) if res_model == "ir.ui.menu": - url = f"/web?&db={dbname}#menu_id={res_id}&action=" - log.info(REDIRECT_MSG, url) + url = ( + "/web" + + (f"?db={dbname}" if "db" in kw else "") + + f"#menu_id={res_id}&action=" + ) + log.debug(REDIRECT_MSG, url) else: log.error("%s.%s is not a menu xmlid", app, menu) # this almost could be a permanent redirect, but if the menu @@ -102,5 +114,5 @@ log.exception("Unknown error searching for menu item") except Exception: - log.error("Invalid dbname provided: redirecting to /") + log.exception("Invalid db provided: redirecting to /") @@ -106,5 +118,5 @@ - redirect = werkzeug.utils.redirect(url, 302) + redirect = utils.redirect(url, 302) redirect.autocorrect_location_header = True if cache_header: redirect.headers.add("Cache-Control", cache_header) diff --git a/pyproject.toml b/pyproject.toml index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_cHlwcm9qZWN0LnRvbWw=..d1e6e2024d3d882c89f27a1971b9202550abe19d_cHlwcm9qZWN0LnRvbWw= 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,4 +11,5 @@ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Framework :: Odoo", @@ -14,4 +15,4 @@ "Framework :: Odoo", - "Framework :: Odoo :: 15.0", + "Framework :: Odoo :: 17.0", "License :: OSI Approved :: GNU Affero General Public License v3" ] @@ -16,6 +17,6 @@ "License :: OSI Approved :: GNU Affero General Public License v3" ] -dependencies = ["odoo==15.0.*"] +dependencies = ["odoo==17.0.*"] [project.optional-dependencies] doc = ["sphinx", "sphinx-odoo-autodoc", "odoo-scripts"] @@ -23,7 +24,7 @@ [project.urls] repository = "https://orus.io/xcg/odoo-modules/menuredir" -changelog = "https://orus.io/xcg/odoo-modules/menuredir/-/blob/branch/15.0/NEWS.rst" +changelog = "https://orus.io/xcg/odoo-modules/menuredir/-/blob/branch/17.0/NEWS.rst" [build-system] requires = ["hatchling >=1.19", "hatch-vcs"] @@ -60,7 +61,18 @@ [tool.hatch.version] source = "vcs" -[tool.black] -target-version = ["py39", "py310", "py311"] -required-version = "22" +[tool.isort] +section-order = [ + "future", + "standard-library", + "third-party", + "odoo", + "odoo-addons", + "first-party", + "local-folder" +] + +[tool.isort.sections] +"odoo" = ["odoo"] +"odoo-addons" = ["odoo.addons"] @@ -66,15 +78,16 @@ -[tool.isort] -py_version = 39 -profile = "black" -known_odoo = ['odoo'] -known_odoo_addons = ['odoo.addons'] -sections = [ - 'FUTURE', - 'STDLIB', - 'THIRDPARTY', - 'ODOO', - 'ODOO_ADDONS', - 'FIRSTPARTY', - 'LOCALFOLDER' +[tool.ruff.lint.mccabe] +max-complexity = 16 + +[tool.ruff] +target-version = "py39" + +[tool.ruff.lint] +extend-select = [ + "B", + "C90", + "E501", # line too long (default 88) + "I", # isort + "UP", # pyupgrade + ] @@ -80,1 +93,5 @@ ] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py +"__manifest__.py" = ["B018"] # useless expression diff --git a/tests/test_controller.py b/tests/test_controller.py index 0355916963e6ae96e60f1cf2a6aa3abce451cc9d_dGVzdHMvdGVzdF9jb250cm9sbGVyLnB5..d1e6e2024d3d882c89f27a1971b9202550abe19d_dGVzdHMvdGVzdF9jb250cm9sbGVyLnB5 100644 --- a/tests/test_controller.py +++ b/tests/test_controller.py @@ -1,4 +1,4 @@ -from odoo.tests.common import HttpCase, tagged +from odoo.tests import HttpCase, tagged from odoo.tools import mute_logger @@ -11,9 +11,10 @@ dbname = self.env.cr.dbname menu = "menu_action_res_users" url = f"/menuredir/go?db={dbname}&app=base&menu={menu}" - res = self.url_open(url, allow_redirects=False) - self.assertEqual(res.status_code, 302, "Response should be a redirect") - res = self.url_open(url, allow_redirects=True) + with mute_logger("odoo.addons.menuredir.controllers.main", "werkzeug"): + res = self.url_open(url, allow_redirects=False) + self.assertEqual(res.status_code, 302, "Response should be a redirect") + res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") menu_id = self.env.ref(f"base.{menu}").id self.assertTrue(res.url.endswith(f"#menu_id={menu_id}&action=")) @@ -22,8 +23,8 @@ """Test the redirect when the database name is missing""" menu = "menu_action_res_users" url = f"/menuredir/go?app=base&menu={menu}" - with mute_logger("odoo.addons.menuredir.controllers.main"): + with mute_logger("odoo.addons.menuredir.controllers.main", "werkzeug"): res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") @@ -26,10 +27,26 @@ res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") + # Tests are run with a single database, so it should redirect correctly + menu_id = self.env.ref(f"base.{menu}").id + self.assertTrue(res.url.endswith(f"#menu_id={menu_id}&action=")) + + def test_invalid_db(self): + """Test the redirect when the database name is incorrect""" + # Assumes <dbname>-invalid is not a valid database name + dbname = self.env.cr.dbname + "-invalid" + menu = "menu_action_res_users" + url = f"/menuredir/go?db={dbname}&app=base&menu={menu}" + with mute_logger("odoo.addons.menuredir.controllers.main", "werkzeug"): + res = self.url_open(url, allow_redirects=False) + self.assertEqual(res.status_code, 302, "Response should be a redirect") + res = self.url_open(url, allow_redirects=True) + self.assertEqual(res.status_code, 200, "Response should = OK") + self.assertTrue(res.url.endswith("/web/login")) def test_missing_app(self): """Test the redirect when the module name is missing""" dbname = self.env.cr.dbname menu = "menu_action_res_users" url = f"/menuredir/go?db={dbname}&menu={menu}" @@ -30,11 +47,11 @@ def test_missing_app(self): """Test the redirect when the module name is missing""" dbname = self.env.cr.dbname menu = "menu_action_res_users" url = f"/menuredir/go?db={dbname}&menu={menu}" - with mute_logger("odoo.addons.menuredir.controllers.main"): + with mute_logger("odoo.addons.menuredir.controllers.main", "werkzeug"): res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") @@ -37,9 +54,10 @@ res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") + self.assertTrue(res.url.endswith("/web/login")) def test_messing_menu(self): """Test the redirect when the menu xmlid is missing""" dbname = self.env.cr.dbname url = f"/menuredir/go?db={dbname}&app=base" @@ -41,10 +59,10 @@ def test_messing_menu(self): """Test the redirect when the menu xmlid is missing""" dbname = self.env.cr.dbname url = f"/menuredir/go?db={dbname}&app=base" - with mute_logger("odoo.addons.menuredir.controllers.main"): + with mute_logger("odoo.addons.menuredir.controllers.main", "werkzeug"): res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") @@ -47,10 +65,11 @@ res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") + self.assertTrue(res.url.endswith("/web/login")) def test_invalid_menu(self): """Test the redirect when the menu xmlid is incorrect""" dbname = self.env.cr.dbname menu = "made_up_id" url = f"/menuredir/go?db={dbname}&app=base&menu={menu}" @@ -51,11 +70,11 @@ def test_invalid_menu(self): """Test the redirect when the menu xmlid is incorrect""" dbname = self.env.cr.dbname menu = "made_up_id" url = f"/menuredir/go?db={dbname}&app=base&menu={menu}" - with mute_logger("odoo.addons.menuredir.controllers.main"): + with mute_logger("odoo.addons.menuredir.controllers.main", "werkzeug"): res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") @@ -58,10 +77,11 @@ res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") + self.assertTrue(res.url.endswith("/web/login")) def test_not_a_menu(self): """Test the redirect when the menu xmlid is not a menu""" dbname = self.env.cr.dbname menu = "group_user" url = f"/menuredir/go?db={dbname}&app=base&menu={menu}" @@ -62,11 +82,11 @@ def test_not_a_menu(self): """Test the redirect when the menu xmlid is not a menu""" dbname = self.env.cr.dbname menu = "group_user" url = f"/menuredir/go?db={dbname}&app=base&menu={menu}" - with mute_logger("odoo.addons.menuredir.controllers.main"): + with mute_logger("odoo.addons.menuredir.controllers.main", "werkzeug"): res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") @@ -69,4 +89,5 @@ res = self.url_open(url, allow_redirects=False) self.assertEqual(res.status_code, 302, "Response should be a redirect") res = self.url_open(url, allow_redirects=True) self.assertEqual(res.status_code, 200, "Response should = OK") + self.assertTrue(res.url.endswith("/web/login"))