diff --git a/README.md b/README.md index c5a7d87305..337cafdf24 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Available addons ---------------- addon | version | maintainers | summary --- | --- | --- | --- -[auth_api_key](auth_api_key/) | 19.0.1.0.3 | | Authenticate http requests from an API key +[auth_api_key](auth_api_key/) | 19.0.1.1.0 | | Authenticate http requests from an API key [auth_api_key_group](auth_api_key_group/) | 19.0.1.0.0 | simahawk | Allow grouping API keys together. Grouping per se does nothing. This feature is supposed to be used by other modules to limit access to services or records based on groups of keys. [auth_oauth_multi_token](auth_oauth_multi_token/) | 19.0.1.0.0 | | Allow multiple connection with the same OAuth account [auth_oidc](auth_oidc/) | 19.0.1.0.0 | sbidoul | Allow users to login through OpenID Connect Provider diff --git a/auth_api_key/README.rst b/auth_api_key/README.rst index 0b185c4574..cd03129c30 100644 --- a/auth_api_key/README.rst +++ b/auth_api_key/README.rst @@ -11,7 +11,7 @@ Auth Api Key !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:13e40ab685d9417f6461852e3c3c37fec5967c3a7a956fdb54b3fcc5f1b42115 + !! source digest: sha256:e7679893d3301998264999e637352ed54ac21f411be14f01b7f8b2ab102b3b50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png @@ -70,6 +70,11 @@ The api key menu is available into Settings > Technical in debug mode. By default, when you create an API key, the key is saved into the database. +When you create an API key, a random key is generated automatically. You +can replace it manually, or use the Generate Random Token button if an +existing record has no key. The key field is masked by default, and the +password widget provides a button to reveal the value when needed. + When a database is neutralized, stored API key values are cleared. If you want to manage them via serve environment settings use diff --git a/auth_api_key/__manifest__.py b/auth_api_key/__manifest__.py index 856447f9dc..9f480f74f5 100644 --- a/auth_api_key/__manifest__.py +++ b/auth_api_key/__manifest__.py @@ -5,7 +5,7 @@ "name": "Auth Api Key", "summary": """ Authenticate http requests from an API key""", - "version": "19.0.1.0.3", + "version": "19.0.1.1.0", "license": "LGPL-3", "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/server-auth", diff --git a/auth_api_key/i18n/auth_api_key.pot b/auth_api_key/i18n/auth_api_key.pot index 910901518c..00b53accdb 100644 --- a/auth_api_key/i18n/auth_api_key.pot +++ b/auth_api_key/i18n/auth_api_key.pot @@ -78,6 +78,11 @@ msgstr "" msgid "Display Name" msgstr "" +#. module: auth_api_key +#: model_terms:ir.ui.view,arch_db:auth_api_key.auth_api_key_form_view +msgid "Generate Random Token" +msgstr "" + #. module: auth_api_key #: model:ir.model,name:auth_api_key.model_ir_http msgid "HTTP Routing" diff --git a/auth_api_key/i18n/it.po b/auth_api_key/i18n/it.po index 4a8682150d..6786d9b125 100644 --- a/auth_api_key/i18n/it.po +++ b/auth_api_key/i18n/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 15.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2026-07-20 08:46+0000\n" +"PO-Revision-Date: 2026-07-27 11:46+0000\n" "Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" @@ -81,6 +81,11 @@ msgstr "Disabilita la chiave API quando si archivia un utente" msgid "Display Name" msgstr "Nome visualizzato" +#. module: auth_api_key +#: model_terms:ir.ui.view,arch_db:auth_api_key.auth_api_key_form_view +msgid "Generate Random Token" +msgstr "Genera token casuale" + #. module: auth_api_key #: model:ir.model,name:auth_api_key.model_ir_http msgid "HTTP Routing" diff --git a/auth_api_key/i18n/ja.po b/auth_api_key/i18n/ja.po index baf16ead11..2f6c91489f 100644 --- a/auth_api_key/i18n/ja.po +++ b/auth_api_key/i18n/ja.po @@ -79,6 +79,11 @@ msgstr "" msgid "Display Name" msgstr "" +#. module: auth_api_key +#: model_terms:ir.ui.view,arch_db:auth_api_key.auth_api_key_form_view +msgid "Generate Random Token" +msgstr "" + #. module: auth_api_key #: model:ir.model,name:auth_api_key.model_ir_http msgid "HTTP Routing" diff --git a/auth_api_key/i18n/zh_CN.po b/auth_api_key/i18n/zh_CN.po index dd912a4421..e4f022d4ce 100644 --- a/auth_api_key/i18n/zh_CN.po +++ b/auth_api_key/i18n/zh_CN.po @@ -79,6 +79,11 @@ msgstr "" msgid "Display Name" msgstr "" +#. module: auth_api_key +#: model_terms:ir.ui.view,arch_db:auth_api_key.auth_api_key_form_view +msgid "Generate Random Token" +msgstr "" + #. module: auth_api_key #: model:ir.model,name:auth_api_key.model_ir_http msgid "HTTP Routing" diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index ee8564a6f1..63eef6b735 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -1,6 +1,8 @@ # Copyright 2018 ACSONE SA/NV # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +import secrets + from odoo import api, fields, models, tools from odoo.exceptions import AccessError, ValidationError from odoo.tools import consteq @@ -12,6 +14,7 @@ class AuthApiKey(models.Model): name = fields.Char(required=True) key = fields.Char( + default=lambda self: self._generate_random_key_value(), help="""The API key. Enter a dummy value in this field if it is obtained from the server environment configuration.""", ) @@ -36,6 +39,28 @@ def _check_key_required(self): if not api_key.key: raise ValidationError(self.env._("The API key is required.")) + @api.model + def _generate_random_key_value(self): + """Return a random API key value. + + The token is generated by the Odoo server instance so XML data and the + UI button can create a secret without storing any default value in the + module sources. + """ + return secrets.token_urlsafe(32) + + def generate_random_key(self, api_key_ids=None): + """Generate a key for records that do not have one yet. + + :param list api_key_ids: optional record IDs, mainly used by XML data + function calls where the method is invoked on the model. + :return: True when the operation completed. + """ + api_keys = self.browse(api_key_ids) if api_key_ids else self + for api_key in api_keys.filtered(lambda record: not record.key): + api_key.key = api_key._generate_random_key_value() + return True + @api.model def _retrieve_api_key(self, key): return self.browse(self._retrieve_api_key_id(key)) diff --git a/auth_api_key/readme/CONFIGURE.md b/auth_api_key/readme/CONFIGURE.md index d333318925..12f823bb97 100644 --- a/auth_api_key/readme/CONFIGURE.md +++ b/auth_api_key/readme/CONFIGURE.md @@ -2,6 +2,11 @@ The api key menu is available into Settings \> Technical in debug mode. By default, when you create an API key, the key is saved into the database. +When you create an API key, a random key is generated automatically. You +can replace it manually, or use the Generate Random Token button if an +existing record has no key. The key field is masked by default, and the +password widget provides a button to reveal the value when needed. + When a database is neutralized, stored API key values are cleared. If you want to manage them via serve environment settings use diff --git a/auth_api_key/static/description/index.html b/auth_api_key/static/description/index.html index 0aec51591d..2eb3f9372f 100644 --- a/auth_api_key/static/description/index.html +++ b/auth_api_key/static/description/index.html @@ -372,7 +372,7 @@

Auth Api Key

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:13e40ab685d9417f6461852e3c3c37fec5967c3a7a956fdb54b3fcc5f1b42115 +!! source digest: sha256:e7679893d3301998264999e637352ed54ac21f411be14f01b7f8b2ab102b3b50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Production/Stable License: LGPL-3 OCA/server-auth Translate me on Weblate Try me on Runboat

Authenticate http requests from an API key.

@@ -416,6 +416,10 @@

Configuration

The api key menu is available into Settings > Technical in debug mode. By default, when you create an API key, the key is saved into the database.

+

When you create an API key, a random key is generated automatically. You +can replace it manually, or use the Generate Random Token button if an +existing record has no key. The key field is masked by default, and the +password widget provides a button to reveal the value when needed.

When a database is neutralized, stored API key values are cleared.

If you want to manage them via serve environment settings use auth_api_key_server_env.

diff --git a/auth_api_key/tests/test_auth_api_key.py b/auth_api_key/tests/test_auth_api_key.py index d78e299bff..93c4a0f446 100644 --- a/auth_api_key/tests/test_auth_api_key.py +++ b/auth_api_key/tests/test_auth_api_key.py @@ -25,6 +25,25 @@ def setUpClass(cls, *args, **kwargs): {"name": "good", "user_id": cls.demo_user.id, "key": "api_key"} ) + def test_create_without_key_generates_random_key(self): + """Test API key creation generates an API key when no key is provided.""" + api_key = self.AuthApiKey.create( + {"name": "generated", "user_id": self.demo_user.id} + ) + self.assertTrue(api_key.key) + self.assertEqual( + self.AuthApiKey._retrieve_uid_from_api_key(api_key.key), + self.demo_user.id, + ) + + def test_generate_random_key_keeps_existing_key(self): + """Test random key generation does not overwrite an existing key.""" + api_key = self.AuthApiKey.create( + {"name": "existing", "user_id": self.demo_user.id, "key": "existing_key"} + ) + api_key.generate_random_key() + self.assertEqual(api_key.key, "existing_key") + def test_lookup_key_from_db(self): demo_user = self.demo_user self.assertEqual( diff --git a/auth_api_key/views/auth_api_key.xml b/auth_api_key/views/auth_api_key.xml index e52a8d8698..0518264407 100644 --- a/auth_api_key/views/auth_api_key.xml +++ b/auth_api_key/views/auth_api_key.xml @@ -21,7 +21,18 @@ - + diff --git a/auth_session_timeout/i18n/sl.po b/auth_session_timeout/i18n/sl.po index 7701ff8588..971f29fdca 100644 --- a/auth_session_timeout/i18n/sl.po +++ b/auth_session_timeout/i18n/sl.po @@ -8,31 +8,32 @@ msgstr "" "Project-Id-Version: server-tools (8.0)\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2015-09-29 11:14+0000\n" -"PO-Revision-Date: 2015-09-24 11:47+0000\n" -"Last-Translator: Matjaž Mozetič \n" +"PO-Revision-Date: 2026-07-25 09:46+0000\n" +"Last-Translator: Matjaz Mozetic \n" "Language-Team: Slovenian (http://www.transifex.com/oca/OCA-server-tools-8-0/" "language/sl/)\n" "Language: sl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" -"%100==4 ? 2 : 3);\n" +"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3;\n" +"X-Generator: Weblate 5.15.2\n" #. module: auth_session_timeout #: model:ir.model,name:auth_session_timeout.model_ir_http msgid "HTTP Routing" -msgstr "" +msgstr "HTTP usmerjanje" #. module: auth_session_timeout #: model:ir.model,name:auth_session_timeout.model_ir_config_parameter msgid "System Parameter" -msgstr "" +msgstr "Sistemski parameter" #. module: auth_session_timeout #: model:ir.model,name:auth_session_timeout.model_res_users msgid "User" -msgstr "" +msgstr "Uporabnik" #~ msgid "Users" #~ msgstr "Uporabniki" diff --git a/auth_user_case_insensitive/i18n/sl.po b/auth_user_case_insensitive/i18n/sl.po index 336a0df979..e882da6185 100644 --- a/auth_user_case_insensitive/i18n/sl.po +++ b/auth_user_case_insensitive/i18n/sl.po @@ -9,37 +9,39 @@ msgstr "" "Project-Id-Version: Odoo Server 10.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-05-17 21:08+0000\n" -"PO-Revision-Date: 2017-05-17 21:08+0000\n" -"Last-Translator: OCA Transbot , 2017\n" +"PO-Revision-Date: 2026-07-25 09:46+0000\n" +"Last-Translator: Matjaz Mozetic \n" "Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n" "Language: sl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" -"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" -"%100==4 ? 2 : 3);\n" +"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || " +"n%100==4 ? 2 : 3;\n" +"X-Generator: Weblate 5.15.2\n" #. module: auth_user_case_insensitive #. odoo-python #: code:addons/auth_user_case_insensitive/hooks.py:0 #, python-format msgid "Conflicting user logins exist for `%s`" -msgstr "" +msgstr "Za `%s` obstajajo konfliktne uporabniške prijave" #. module: auth_user_case_insensitive #: model:ir.model.fields,field_description:auth_user_case_insensitive.field_res_users__login msgid "Login" -msgstr "" +msgstr "Prijava" #. module: auth_user_case_insensitive #: model:ir.model.fields,help:auth_user_case_insensitive.field_res_users__login msgid "Used to log into the system. Case insensitive." msgstr "" +"Uporablja se za prijavo v sistem. Ne razlikuje med velikimi in malimi črkami." #. module: auth_user_case_insensitive #: model:ir.model,name:auth_user_case_insensitive.model_res_users msgid "User" -msgstr "" +msgstr "Uporabnik" #~ msgid "Users" #~ msgstr "Uporabniki"