diff --git a/webservice/models/webservice_backend.py b/webservice/models/webservice_backend.py index 740e729e..3f463799 100644 --- a/webservice/models/webservice_backend.py +++ b/webservice/models/webservice_backend.py @@ -100,6 +100,30 @@ def _valid_field_parameter(self, field, name): extra_params = ("auth_type",) return name in extra_params or super()._valid_field_parameter(field, name) + @api.onchange("auth_type") + def _onchange_auth_type(self): + # Keep `oauth2_flow` in sync in the UI as the user edits `auth_type`, + # regardless of whether `server_environment` is installed (see + # `create`/`write` below for the same guarantee on any other write). + if self.auth_type != "oauth2": + self.oauth2_flow = False + + @api.model_create_multi + def create(self, vals_list): + records = super().create(vals_list) + records.filtered( + lambda r: r.auth_type != "oauth2" and r.oauth2_flow + ).oauth2_flow = False + return records + + def write(self, vals): + res = super().write(vals) + if "auth_type" in vals: + self.filtered( + lambda r: r.auth_type != "oauth2" and r.oauth2_flow + ).oauth2_flow = False + return res + def call(self, method, *args, **kwargs): _logger.debug("backend %s: call %s %s %s", self.name, method, args, kwargs) response = getattr(self._get_adapter(), method)(*args, **kwargs) diff --git a/webservice/tests/test_oauth2.py b/webservice/tests/test_oauth2.py index 180b10aa..b0ef2c25 100644 --- a/webservice/tests/test_oauth2.py +++ b/webservice/tests/test_oauth2.py @@ -271,3 +271,64 @@ def test_oauth2_flow_compute_with_ui(self): self.assertEqual( ws.oauth2_flow, oauth2_flow if ws.auth_type == "oauth2" else False ) + + +class TestWebServiceOauth2FlowReset(CommonWebService): + """``oauth2_flow`` must be reset on any write, not only via the UI. + + This is a plain ORM-level guarantee independent of ``server_environment`` + (see ``webservice_server_env`` for the extra guarantee that applies when + that module is installed). + """ + + @classmethod + def _setup_records(cls): + res = super()._setup_records() + cls.url = "https://localhost.demo.odoo/" + cls.webservice = cls.env["webservice.backend"].create( + { + "name": "WebService OAuth2", + "tech_name": "test_oauth2_reset", + "auth_type": "oauth2", + "protocol": "http", + "url": cls.url, + "oauth2_flow": "backend_application", + "content_type": "application/xml", + "oauth2_clientid": "some_client_id", + "oauth2_client_secret": "shh_secret", + "oauth2_token_url": f"{cls.url}oauth2/token", + "oauth2_audience": cls.url, + } + ) + return res + + def test_write_resets_oauth2_flow_when_auth_type_changes(self): + self.webservice.write({"auth_type": "none"}) + self.assertFalse(self.webservice.oauth2_flow) + + def test_write_keeps_oauth2_flow_when_auth_type_stays_oauth2(self): + self.webservice.write({"oauth2_client_secret": "new_secret"}) + self.assertEqual(self.webservice.oauth2_flow, "backend_application") + + def test_create_resets_oauth2_flow_for_non_oauth2_auth_type(self): + ws = self.env["webservice.backend"].create( + { + "name": "WebService No Auth", + "tech_name": "test_oauth2_reset_create", + "auth_type": "none", + "protocol": "http", + "url": self.url, + # Inconsistent on purpose: no `create`/`write` should ever + # leave this set together with a non-oauth2 `auth_type`. + "oauth2_flow": "backend_application", + } + ) + self.assertFalse(ws.oauth2_flow) + + def test_onchange_resets_oauth2_flow(self): + ws = self.webservice.new( + {"auth_type": "oauth2", "oauth2_flow": "backend_application"} + ) + ws.auth_type = "none" + ws._onchange_auth_type() + self.assertFalse(ws.oauth2_flow)