From 7c80540c8d51a29d69697a9e23c817a56005705b Mon Sep 17 00:00:00 2001 From: Christopher Rogos Date: Mon, 3 Feb 2025 18:24:24 +0000 Subject: [PATCH] [IMP] auth_oauth_multi_token: make it compatible with odoo.sh "login as" --- auth_oauth_multi_token/models/res_users.py | 55 ++++++++++++------- .../tests/test_multi_token.py | 7 ++- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/auth_oauth_multi_token/models/res_users.py b/auth_oauth_multi_token/models/res_users.py index 53c4bff115..548d94ffe0 100644 --- a/auth_oauth_multi_token/models/res_users.py +++ b/auth_oauth_multi_token/models/res_users.py @@ -5,10 +5,6 @@ from odoo import api, exceptions, fields, models -from odoo.addons import base - -base.models.res_users.USER_PRIVATE_FIELDS.append("oauth_master_uuid") - class ResUsers(models.Model): _inherit = "res.users" @@ -24,14 +20,14 @@ def _generate_oauth_master_uuid(self): readonly=True, groups="base.group_system", ) + oauth_access_max_token = fields.Integer( string="Max Number of Simultaneous Connections", default=10, required=True ) - oauth_master_uuid = fields.Char( + + # use the oauth_access_token field as oauth_master_uuid + oauth_access_token = fields.Char( string="Master UUID", - copy=False, - readonly=True, - required=True, default=lambda self: self._generate_oauth_master_uuid(), ) @@ -39,22 +35,36 @@ def _generate_oauth_master_uuid(self): def multi_token_model(self): return self.env["auth.oauth.multi.token"] + @api.model + def _generate_signup_values(self, provider, validation, params): + """Because access_token was replace in + _auth_oauth_signin we need to replace it here.""" + res = super()._generate_signup_values(provider, validation, params) + res["oauth_access_token"] = params["access_token_multi"] + return res + @api.model def _auth_oauth_signin(self, provider, validation, params): """Override to handle sign-in with multi token.""" - res = super()._auth_oauth_signin(provider, validation, params) + params["access_token_multi"] = params["access_token"] - oauth_uid = validation["user_id"] # Lookup for user by oauth uid and provider + oauth_uid = validation["user_id"] user = self.search( [("oauth_uid", "=", oauth_uid), ("oauth_provider_id", "=", provider)] ) + + # Because access_token is automatically written to the user, + # we need to replace this by the existing oauth_access_token + params["access_token"] = user.oauth_access_token + res = super()._auth_oauth_signin(provider, validation, params) + if not user: raise exceptions.AccessDenied() user.ensure_one() # user found and unique: create a token self.multi_token_model.create( - {"user_id": user.id, "oauth_access_token": params["access_token"]} + {"user_id": user.id, "oauth_access_token": params["access_token_multi"]} ) return res @@ -62,8 +72,7 @@ def action_oauth_clear_token(self): """Inactivate current user tokens.""" self.mapped("oauth_access_token_ids")._oauth_clear_token() for res in self: - res.oauth_access_token = False - res.oauth_master_uuid = self._generate_oauth_master_uuid() + res.oauth_access_token = self._generate_oauth_master_uuid() @api.model def _check_credentials(self, password, env): @@ -71,13 +80,17 @@ def _check_credentials(self, password, env): try: return super()._check_credentials(password, env) except exceptions.AccessDenied: - res = self.multi_token_model.sudo().search( - [("user_id", "=", self.env.uid), ("oauth_access_token", "=", password)] + passwd_allowed = ( + env["interactive"] or not self.env.user._rpc_api_keys_only() ) - if not res: - raise + if passwd_allowed and self.env.user.active: + res = self.multi_token_model.sudo().search( + [ + ("user_id", "=", self.env.uid), + ("oauth_access_token", "=", password), + ] + ) + if res: + return - def _get_session_token_fields(self): - res = super()._get_session_token_fields() - res.remove("oauth_access_token") - return res | {"oauth_master_uuid"} + raise diff --git a/auth_oauth_multi_token/tests/test_multi_token.py b/auth_oauth_multi_token/tests/test_multi_token.py index f63affd9b8..b80bdfd21a 100644 --- a/auth_oauth_multi_token/tests/test_multi_token.py +++ b/auth_oauth_multi_token/tests/test_multi_token.py @@ -80,10 +80,11 @@ def test_access_multi_token(self): len(self.user.oauth_access_token_ids), self.user.oauth_access_max_token ) - def test_remove_oauth_access_token(self): + def test_oauth_access_token_odoo_sh(self): + # do not change the _get_session_token_fields result to stay compatible with odoo.sh res = self.user._get_session_token_fields() - self.assertFalse("oauth_access_token" in res) - self.assertTrue("oauth_master_uuid" in res) + self.assertTrue("oauth_access_token" in res) + self.assertFalse("oauth_master_uuid" in res) def test_action_oauth_clear_token(self): self.user.action_oauth_clear_token()