Skip to content

Commit 5c0011e

Browse files
committed
Merge PR #950 into 19.0
Signed-off-by etobella
2 parents 2a908b4 + b7b7c81 commit 5c0011e

8 files changed

Lines changed: 49 additions & 2 deletions

File tree

auth_api_key/README.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ The api key menu is available into Settings > Technical in debug mode.
7070
By default, when you create an API key, the key is saved into the
7171
database.
7272

73+
When a database is neutralized, stored API key values are cleared.
74+
7375
If you want to manage them via serve environment settings use
7476
auth_api_key_server_env.
7577

auth_api_key/data/neutralize.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
-- remove API keys
2+
UPDATE auth_api_key
3+
SET key = NULL;

auth_api_key/models/auth_api_key.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class AuthApiKey(models.Model):
1212

1313
name = fields.Char(required=True)
1414
key = fields.Char(
15-
required=True,
1615
help="""The API key. Enter a dummy value in this field if it is
1716
obtained from the server environment configuration.""",
1817
)
@@ -31,6 +30,12 @@ class AuthApiKey(models.Model):
3130

3231
_name_uniq = models.Constraint("unique(name)", "Api Key name must be unique.")
3332

33+
@api.constrains("key")
34+
def _check_key_required(self):
35+
for api_key in self:
36+
if not api_key.key:
37+
raise ValidationError(self.env._("The API key is required."))
38+
3439
@api.model
3540
def _retrieve_api_key(self, key):
3641
return self.browse(self._retrieve_api_key_id(key))
@@ -40,7 +45,7 @@ def _retrieve_api_key(self, key):
4045
def _retrieve_api_key_id(self, key):
4146
if not self.env.user.has_group("base.group_system"):
4247
raise AccessError(self.env._("User is not allowed"))
43-
for api_key in self.search([], limit=None):
48+
for api_key in self.search([("key", "!=", False)], limit=None):
4449
if api_key.key and consteq(key, api_key.key):
4550
return api_key.id
4651
raise ValidationError(self.env._("The key '%s' is not allowed", key))

auth_api_key/readme/CONFIGURE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@ The api key menu is available into Settings \> Technical in debug mode.
22
By default, when you create an API key, the key is saved into the
33
database.
44

5+
When a database is neutralized, stored API key values are cleared.
6+
57
If you want to manage them via serve environment settings use
68
auth_api_key_server_env.

auth_api_key/static/description/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ <h2><a class="toc-backref" href="#toc-entry-1">Configuration</a></h2>
416416
<p>The api key menu is available into Settings &gt; Technical in debug mode.
417417
By default, when you create an API key, the key is saved into the
418418
database.</p>
419+
<p>When a database is neutralized, stored API key values are cleared.</p>
419420
<p>If you want to manage them via serve environment settings use
420421
auth_api_key_server_env.</p>
421422
</div>

auth_api_key/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
from . import test_auth_api_key
22
from . import test_controllers
3+
from . import test_neutralize

auth_api_key/tests/test_auth_api_key.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ def test_wrong_key(self):
3535
with self.assertRaises(ValidationError), self.env.cr.savepoint():
3636
self.env["auth.api.key"]._retrieve_uid_from_api_key("api_wrong_key")
3737

38+
def test_empty_key_is_rejected(self):
39+
with self.assertRaises(ValidationError), self.env.cr.savepoint():
40+
self.AuthApiKey.create(
41+
{"name": "empty", "user_id": self.demo_user.id, "key": ""}
42+
)
43+
with self.assertRaises(ValidationError), self.env.cr.savepoint():
44+
self.api_key_good.key = False
45+
3846
def test_user_not_allowed(self):
3947
# only system users can check for key
4048
with self.assertRaises(AccessError), self.env.cr.savepoint():
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Copyright 2026 Camptocamp SA
2+
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
3+
4+
from odoo.modules import neutralize
5+
from odoo.tests import tagged
6+
from odoo.tests.common import TransactionCase
7+
8+
9+
@tagged("post_install", "-at_install", "neutralize")
10+
class TestAuthApiKeyNeutralize(TransactionCase):
11+
def test_neutralize_removes_api_key_values(self):
12+
"""Test database neutralization clears stored API key secrets."""
13+
api_key = self.env["auth.api.key"].create(
14+
{
15+
"name": "neutralize",
16+
"user_id": self.env.ref("base.user_admin").id,
17+
"key": "secret-key",
18+
}
19+
)
20+
21+
queries = neutralize.get_neutralization_queries(["auth_api_key"])
22+
for query in queries:
23+
self.cr.execute(query)
24+
api_key.invalidate_recordset(["key"])
25+
self.assertFalse(api_key.key)

0 commit comments

Comments
 (0)