From 8e677924d75260853c7ac5f0ecf7088df8c95dfd Mon Sep 17 00:00:00 2001 From: Maksym Yankin Date: Thu, 9 Jul 2026 17:12:13 +0300 Subject: [PATCH 1/3] [19.0][IMP] webservice: neutralize webservice backend credentials --- webservice/README.rst | 7 ++++ webservice/data/neutralize.sql | 9 +++++ webservice/readme/CONFIGURE.md | 3 ++ webservice/static/description/index.html | 27 ++++++++----- webservice/tests/__init__.py | 1 + webservice/tests/test_neutralize.py | 49 ++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 webservice/data/neutralize.sql create mode 100644 webservice/readme/CONFIGURE.md create mode 100644 webservice/tests/test_neutralize.py diff --git a/webservice/README.rst b/webservice/README.rst index a01025ef..0155b1a4 100644 --- a/webservice/README.rst +++ b/webservice/README.rst @@ -43,6 +43,13 @@ HTTP call returns by default the content of the response. A context .. contents:: :local: +Configuration +============= + +When a database is neutralized, stored webservice backend credentials +(username, password, API key, OAuth2 client id/secret/token, custom +OAuth2 auth header value) are cleared. + Bug Tracker =========== diff --git a/webservice/data/neutralize.sql b/webservice/data/neutralize.sql new file mode 100644 index 00000000..264b1b17 --- /dev/null +++ b/webservice/data/neutralize.sql @@ -0,0 +1,9 @@ +-- remove webservice backend credentials +UPDATE webservice_backend + SET username = NULL, + password = NULL, + api_key = NULL, + oauth2_clientid = NULL, + oauth2_client_secret = NULL, + oauth2_client_auth_value = NULL, + oauth2_token = NULL; diff --git a/webservice/readme/CONFIGURE.md b/webservice/readme/CONFIGURE.md new file mode 100644 index 00000000..62002601 --- /dev/null +++ b/webservice/readme/CONFIGURE.md @@ -0,0 +1,3 @@ +When a database is neutralized, stored webservice backend credentials +(username, password, API key, OAuth2 client id/secret/token, custom +OAuth2 auth header value) are cleared. diff --git a/webservice/static/description/index.html b/webservice/static/description/index.html index ebcfdd44..f5fcfc3b 100644 --- a/webservice/static/description/index.html +++ b/webservice/static/description/index.html @@ -382,17 +382,24 @@

WebService

Table of contents

+
+

Configuration

+

When a database is neutralized, stored webservice backend credentials +(username, password, API key, OAuth2 client id/secret/token, custom +OAuth2 auth header value) are cleared.

+
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -400,23 +407,23 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Creu Blanca
  • Camptocamp
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association diff --git a/webservice/tests/__init__.py b/webservice/tests/__init__.py index 70d7ce42..88a07b8f 100644 --- a/webservice/tests/__init__.py +++ b/webservice/tests/__init__.py @@ -1,3 +1,4 @@ from . import test_oauth2 from . import test_webservice from . import test_utils +from . import test_neutralize diff --git a/webservice/tests/test_neutralize.py b/webservice/tests/test_neutralize.py new file mode 100644 index 00000000..e1e10959 --- /dev/null +++ b/webservice/tests/test_neutralize.py @@ -0,0 +1,49 @@ +# Copyright 2026 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.modules import neutralize +from odoo.tests import tagged + +from .common import CommonWebService + + +@tagged("neutralize") +class TestWebserviceNeutralize(CommonWebService): + @classmethod + def _setup_records(cls): + res = super()._setup_records() + # `auth_type="none"` skips the `_check_auth_type` constraint so all + # credential fields can be populated at once regardless of which + # auth method would normally require them. + cls.backend = cls.env["webservice.backend"].create( + { + "name": "Neutralize WebService", + "protocol": "http", + "url": "https://localhost.demo.odoo/", + "tech_name": "neutralize_ws", + "auth_type": "none", + "username": "secret-user", + "password": "secret-password", + "api_key": "secret-api-key", + "oauth2_clientid": "secret-client-id", + "oauth2_client_secret": "secret-client-secret", + "oauth2_client_auth_value": "secret-header-value", + "oauth2_token": '{"access_token": "secret-token"}', + } + ) + return res + + def test_neutralize_removes_webservice_credentials(self): + """Test database neutralization clears stored webservice backend credentials.""" + installed_modules = neutralize.get_installed_modules(self.cr) + queries = neutralize.get_neutralization_queries(installed_modules) + for query in queries: + self.cr.execute(query) + self.backend.invalidate_recordset() + self.assertFalse(self.backend.username) + self.assertFalse(self.backend.password) + self.assertFalse(self.backend.api_key) + self.assertFalse(self.backend.oauth2_clientid) + self.assertFalse(self.backend.oauth2_client_secret) + self.assertFalse(self.backend.oauth2_client_auth_value) + self.assertFalse(self.backend.oauth2_token) From 8c4f41d4e742951f86546c8fb6d13aeba0c28cd2 Mon Sep 17 00:00:00 2001 From: Maksym Yankin Date: Thu, 9 Jul 2026 18:25:24 +0300 Subject: [PATCH 2/3] [19.0][IMP] webservice_server_env: neutralize webservice backend credentials If both webservice and server_environment are installed we also need neutralization for webservice_server_env so the plain columns nulled by webservice/data/neutralize.sql can be properly cleared --- webservice_server_env/README.rst | 8 ++++ webservice_server_env/data/neutralize.sql | 16 +++++++ webservice_server_env/readme/CONFIGURE.md | 3 ++ .../static/description/index.html | 28 +++++++---- webservice_server_env/tests/__init__.py | 1 + .../tests/test_neutralize.py | 47 +++++++++++++++++++ 6 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 webservice_server_env/data/neutralize.sql create mode 100644 webservice_server_env/readme/CONFIGURE.md create mode 100644 webservice_server_env/tests/test_neutralize.py diff --git a/webservice_server_env/README.rst b/webservice_server_env/README.rst index 657979b9..35d7bb6e 100644 --- a/webservice_server_env/README.rst +++ b/webservice_server_env/README.rst @@ -40,6 +40,14 @@ Webservice addon. .. contents:: :local: +Configuration +============= + +When a database is neutralized, webservice backend credentials +(username, password, API key, OAuth2 client id/secret, custom OAuth2 +auth header value) stored as server environment defaults are cleared as +well. + Bug Tracker =========== diff --git a/webservice_server_env/data/neutralize.sql b/webservice_server_env/data/neutralize.sql new file mode 100644 index 00000000..ae619e29 --- /dev/null +++ b/webservice_server_env/data/neutralize.sql @@ -0,0 +1,16 @@ +-- remove webservice backend credentials stored as server environment defaults +-- (this module turns username/password/api_key/oauth2_clientid/oauth2_client_secret +-- into non-stored fields backed by the server_env_defaults JSON column +-- this neutralization is needed if both webservice and server_environment are installed, +-- so the plain columns nulled by webservice/data/neutralize.sql can be properly cleared) +UPDATE webservice_backend + SET server_env_defaults = ( + server_env_defaults::jsonb + - 'x_username_env_default' + - 'x_password_env_default' + - 'x_api_key_env_default' + - 'x_oauth2_clientid_env_default' + - 'x_oauth2_client_secret_env_default' + - 'x_oauth2_client_auth_value_env_default' + )::text + WHERE server_env_defaults IS NOT NULL; diff --git a/webservice_server_env/readme/CONFIGURE.md b/webservice_server_env/readme/CONFIGURE.md new file mode 100644 index 00000000..6c80484f --- /dev/null +++ b/webservice_server_env/readme/CONFIGURE.md @@ -0,0 +1,3 @@ +When a database is neutralized, webservice backend credentials (username, +password, API key, OAuth2 client id/secret, custom OAuth2 auth header +value) stored as server environment defaults are cleared as well. diff --git a/webservice_server_env/static/description/index.html b/webservice_server_env/static/description/index.html index 053d2fa2..69aa880a 100644 --- a/webservice_server_env/static/description/index.html +++ b/webservice_server_env/static/description/index.html @@ -380,17 +380,25 @@

WebService Server Environment

Table of contents

+
+

Configuration

+

When a database is neutralized, webservice backend credentials +(username, password, API key, OAuth2 client id/secret, custom OAuth2 +auth header value) stored as server environment defaults are cleared as +well.

+
-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed @@ -398,23 +406,23 @@

Bug Tracker

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • Creu Blanca
  • Camptocamp
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association diff --git a/webservice_server_env/tests/__init__.py b/webservice_server_env/tests/__init__.py index 38fb5cf0..e228ba19 100644 --- a/webservice_server_env/tests/__init__.py +++ b/webservice_server_env/tests/__init__.py @@ -1 +1,2 @@ from . import test_oauth2 +from . import test_neutralize diff --git a/webservice_server_env/tests/test_neutralize.py b/webservice_server_env/tests/test_neutralize.py new file mode 100644 index 00000000..906630e0 --- /dev/null +++ b/webservice_server_env/tests/test_neutralize.py @@ -0,0 +1,47 @@ +# Copyright 2026 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.modules import neutralize +from odoo.tests import tagged + +from odoo.addons.webservice.tests.common import CommonWebService + + +@tagged("neutralize") +class TestWebserviceServerEnvNeutralize(CommonWebService): + @classmethod + def _setup_records(cls): + res = super()._setup_records() + # No `SERVER_ENV_CONFIG` section is defined for this tech_name, so + # these credentials are stored as env-default values inside + # `server_env_defaults` instead of the (now unused) plain columns. + cls.backend = cls.env["webservice.backend"].create( + { + "name": "Neutralize WebService Server Env", + "protocol": "http", + "url": "https://localhost.demo.odoo/", + "tech_name": "neutralize_server_env_ws", + "auth_type": "none", + "username": "secret-user", + "password": "secret-password", + "api_key": "secret-api-key", + "oauth2_clientid": "secret-client-id", + "oauth2_client_secret": "secret-client-secret", + "oauth2_client_auth_value": "secret-header-value", + } + ) + return res + + def test_neutralize_removes_server_env_default_credentials(self): + """Test neutralization clears credentials stored as server-env defaults.""" + installed_modules = neutralize.get_installed_modules(self.cr) + queries = neutralize.get_neutralization_queries(installed_modules) + for query in queries: + self.cr.execute(query) + self.backend.invalidate_recordset() + self.assertFalse(self.backend.username) + self.assertFalse(self.backend.password) + self.assertFalse(self.backend.api_key) + self.assertFalse(self.backend.oauth2_clientid) + self.assertFalse(self.backend.oauth2_client_secret) + self.assertFalse(self.backend.oauth2_client_auth_value) From 87b843a0c7735ebe72a4448b4a39ed2ffd55ffbd Mon Sep 17 00:00:00 2001 From: Maksym Yankin Date: Mon, 13 Jul 2026 12:01:12 +0300 Subject: [PATCH 3/3] dont merge test-requirements --- test-requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 test-requirements.txt diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 00000000..ba343211 --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +odoo-addon-webservice @ git+https://github.com/OCA/web-api.git@refs/pull/143/head#subdirectory=webservice +odoo-addon-webservice_server_env @ git+https://github.com/OCA/web-api.git@refs/pull/143/head#subdirectory=webservice_server_env