diff --git a/auth_api_key/README.rst b/auth_api_key/README.rst new file mode 100644 index 0000000000..6fc2d05e57 --- /dev/null +++ b/auth_api_key/README.rst @@ -0,0 +1,123 @@ +============ +Auth Api Key +============ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:455a0f8646088cc228c9423fcbabbc1d81cabbebd0cac6dcf07bbbe000a6fc87 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png + :target: https://odoo-community.org/page/development-status + :alt: Production/Stable +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github + :target: https://github.com/OCA/server-auth/tree/18.0/auth_api_key + :alt: OCA/server-auth +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-auth-18-0/server-auth-18-0-auth_api_key + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-auth&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Authenticate http requests from an API key. + +API keys are codes passed in (in the http header API-KEY) by programs +calling an API in order to identify -in this case- the calling program's +user. + +Take care while using this kind of mechanism since information into http +headers are visible in clear. Thus, use it only to authenticate requests +from known sources. + +For unknown sources, it is a good practice to filter out this header at +proxy level. + +**Table of contents** + +.. contents:: + :local: + +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. + +If you want to manage them via serve environment settings use +auth_api_key_server_env. + +Usage +===== + +To apply this authentication system to your http request you must set +'api_key' as value for the 'auth' parameter of your route definition +into your controller. + +.. code:: python + + class MyController(Controller): + + @route('/my_service', auth='api_key', ...) + def my_service(self, *args, **kwargs): + pass + +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 +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* ACSONE SA/NV + +Contributors +------------ + +- Denis Robinet +- Laurent Mignon +- Quentin Groulard +- Sébastien Beau +- Chafique Delli +- Thien Vo Hong + +Other credits +------------- + +The migration of this module from 17.0 to 18.0 was financially supported +by Camptocamp. + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/server-auth `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/auth_api_key/__init__.py b/auth_api_key/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/auth_api_key/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/auth_api_key/__manifest__.py b/auth_api_key/__manifest__.py new file mode 100644 index 0000000000..a8fa4ae7a4 --- /dev/null +++ b/auth_api_key/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2018 ACSONE SA/NV +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "Auth Api Key", + "summary": """ + Authenticate http requests from an API key""", + "version": "18.0.1.0.0", + "license": "LGPL-3", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/server-auth", + "development_status": "Production/Stable", + "depends": ["base_setup"], + "data": [ + "security/ir.model.access.csv", + "views/auth_api_key.xml", + "views/res_config_settings.xml", + ], +} diff --git a/auth_api_key/i18n/auth_api_key.pot b/auth_api_key/i18n/auth_api_key.pot new file mode 100644 index 0000000000..16489df0cb --- /dev/null +++ b/auth_api_key/i18n/auth_api_key.pot @@ -0,0 +1,108 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * auth_api_key +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 17.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: auth_api_key +#: model:ir.model,name:auth_api_key.model_auth_api_key +msgid "API Key" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.constraint,message:auth_api_key.constraint_auth_api_key_name_uniq +msgid "Api Key name must be unique." +msgstr "" + +#. module: auth_api_key +#: model:ir.actions.act_window,name:auth_api_key.auth_api_key_act_window +#: model:ir.ui.menu,name:auth_api_key.auth_api_key_menu +msgid "Auth Api Key" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__create_uid +msgid "Created by" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__create_date +msgid "Created on" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__display_name +msgid "Display Name" +msgstr "" + +#. module: auth_api_key +#: model:ir.model,name:auth_api_key.model_ir_http +msgid "HTTP Routing" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__id +msgid "ID" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__key +msgid "Key" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__write_date +msgid "Last Updated on" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__name +msgid "Name" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,help:auth_api_key.field_auth_api_key__key +msgid "" +"The API key. Enter a dummy value in this field if it is\n" +" obtained from the server environment configuration." +msgstr "" + +#. module: auth_api_key +#. odoo-python +#: code:addons/auth_api_key/models/auth_api_key.py:0 +#, python-format +msgid "The key %s is not allowed" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,help:auth_api_key.field_auth_api_key__user_id +msgid "" +"The user used to process the requests authenticated by\n" +" the api key" +msgstr "" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__user_id +msgid "User" +msgstr "" + +#. module: auth_api_key +#. odoo-python +#: code:addons/auth_api_key/models/auth_api_key.py:0 +#, python-format +msgid "User is not allowed" +msgstr "" diff --git a/auth_api_key/i18n/it.po b/auth_api_key/i18n/it.po new file mode 100644 index 0000000000..cfb1f39043 --- /dev/null +++ b/auth_api_key/i18n/it.po @@ -0,0 +1,121 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * auth_api_key +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-08-17 18:58+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: auth_api_key +#: model:ir.model,name:auth_api_key.model_auth_api_key +msgid "API Key" +msgstr "Chiave API" + +#. module: auth_api_key +#: model:ir.model.constraint,message:auth_api_key.constraint_auth_api_key_name_uniq +msgid "Api Key name must be unique." +msgstr "La chiave API deve essere univoca." + +#. module: auth_api_key +#: model:ir.actions.act_window,name:auth_api_key.auth_api_key_act_window +#: model:ir.ui.menu,name:auth_api_key.auth_api_key_menu +msgid "Auth Api Key" +msgstr "Chiave API di autenticazione" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: auth_api_key +#: model:ir.model,name:auth_api_key.model_ir_http +msgid "HTTP Routing" +msgstr "Instradamento HTTP" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__id +msgid "ID" +msgstr "ID" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__key +msgid "Key" +msgstr "Chiave" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__name +msgid "Name" +msgstr "Nome" + +#. module: auth_api_key +#: model:ir.model.fields,help:auth_api_key.field_auth_api_key__key +msgid "" +"The API key. Enter a dummy value in this field if it is\n" +" obtained from the server environment configuration." +msgstr "" +"Chiave API. Se viene acquisita dalla configurazione\n" +" ambiente del server, inserire nel campo un valore fittizio." + +#. module: auth_api_key +#. odoo-python +#: code:addons/auth_api_key/models/auth_api_key.py:0 +#, python-format +msgid "The key %s is not allowed" +msgstr "Chiave %s non autorizzata" + +#. module: auth_api_key +#: model:ir.model.fields,help:auth_api_key.field_auth_api_key__user_id +msgid "" +"The user used to process the requests authenticated by\n" +" the api key" +msgstr "" +"Utente utilizzato per elaborare le richieste autenticate\n" +" dalla chiave API" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__user_id +msgid "User" +msgstr "Utente" + +#. module: auth_api_key +#. odoo-python +#: code:addons/auth_api_key/models/auth_api_key.py:0 +#, python-format +msgid "User is not allowed" +msgstr "Utente non autorizzato" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#~ msgid "Server Env Defaults" +#~ msgstr "Variabili ambiente predefinite del server" diff --git a/auth_api_key/models/__init__.py b/auth_api_key/models/__init__.py new file mode 100644 index 0000000000..7c1ac84290 --- /dev/null +++ b/auth_api_key/models/__init__.py @@ -0,0 +1,4 @@ +from . import ir_http +from . import auth_api_key +from . import res_company +from . import res_config_settings diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py new file mode 100644 index 0000000000..cdbda3b93e --- /dev/null +++ b/auth_api_key/models/auth_api_key.py @@ -0,0 +1,78 @@ +# Copyright 2018 ACSONE SA/NV +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import _, api, fields, models, tools +from odoo.exceptions import AccessError, ValidationError +from odoo.tools import consteq + + +class AuthApiKey(models.Model): + _name = "auth.api.key" + _description = "API Key" + + name = fields.Char(required=True) + key = fields.Char( + required=True, + help="""The API key. Enter a dummy value in this field if it is + obtained from the server environment configuration.""", + ) + user_id = fields.Many2one( + comodel_name="res.users", + string="User", + required=True, + help="""The user used to process the requests authenticated by + the api key""", + ) + # Not using related to stay backward compatible with having active keys + # for archived users (no need being invoiced by Odoo for api request users) + active = fields.Boolean( + compute="_compute_active", readonly=False, store=True, default=True + ) + + _sql_constraints = [("name_uniq", "unique(name)", "Api Key name must be unique.")] + + @api.model + def _retrieve_api_key(self, key): + return self.browse(self._retrieve_api_key_id(key)) + + @api.model + @tools.ormcache("key") + def _retrieve_api_key_id(self, key): + if not self.env.user.has_group("base.group_system"): + raise AccessError(_("User is not allowed")) + for api_key in self.search([]): + if api_key.key and consteq(key, api_key.key): + return api_key.id + raise ValidationError(_(f"The key {key} is not allowed")) + + @api.model + @tools.ormcache("key") + def _retrieve_uid_from_api_key(self, key): + return self._retrieve_api_key(key).user_id.id + + def _clear_key_cache(self): + self.env.registry.clear_cache() + + @api.depends( + "user_id.active", "user_id.company_id.archived_user_disable_auth_api_key" + ) + def _compute_active(self): + option_disable_key = self.user_id.company_id.archived_user_disable_auth_api_key + for record in self: + if option_disable_key: + record.active = record.user_id.active + # To stay coherent if the option is disabled the active field is not + # changed. Because the field is stored, it should not be an issue. + + @api.model_create_multi + def create(self, vals_list): + records = super().create(vals_list) + if any(["key" in vals or "user_id" in vals for vals in vals_list]): + self._clear_key_cache() + return records + + def write(self, vals): + super().write(vals) + if "key" in vals or "user_id" in vals: + self._clear_key_cache() + return True diff --git a/auth_api_key/models/ir_http.py b/auth_api_key/models/ir_http.py new file mode 100644 index 0000000000..7b02f0c39c --- /dev/null +++ b/auth_api_key/models/ir_http.py @@ -0,0 +1,36 @@ +# Copyright 2018 ACSONE SA/NV +# Copyright 2017 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import logging + +from odoo import models +from odoo.exceptions import AccessDenied +from odoo.http import request + +_logger = logging.getLogger(__name__) + + +class IrHttp(models.AbstractModel): + _inherit = "ir.http" + + @classmethod + def _auth_method_api_key(cls): + headers = request.httprequest.environ + api_key = headers.get("HTTP_API_KEY") + if api_key: + request.update_env(user=1) + auth_api_key = request.env["auth.api.key"]._retrieve_api_key(api_key) + if auth_api_key: + # reset _env on the request since we change the uid... + # the next call to env will instantiate an new + # odoo.api.Environment with the user defined on the + # auth.api_key + request._env = None + request.update_env(user=auth_api_key.user_id.id) + request.auth_api_key = api_key + request.auth_api_key_id = auth_api_key.id + return True + _logger.error("Wrong HTTP_API_KEY, access denied") + raise AccessDenied() diff --git a/auth_api_key/models/res_company.py b/auth_api_key/models/res_company.py new file mode 100644 index 0000000000..adfdf2cb78 --- /dev/null +++ b/auth_api_key/models/res_company.py @@ -0,0 +1,17 @@ +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import fields, models + + +class ResCompany(models.Model): + _inherit = "res.company" + + archived_user_disable_auth_api_key = fields.Boolean( + string="Disable API key for archived user", + help=( + "If checked, when a user is archived/unactivated the same change is " + "propagated to his related api key. It is not retroactive (nothing is done " + " when enabling/disabling this option)." + ), + ) diff --git a/auth_api_key/models/res_config_settings.py b/auth_api_key/models/res_config_settings.py new file mode 100644 index 0000000000..f7cc3aeaff --- /dev/null +++ b/auth_api_key/models/res_config_settings.py @@ -0,0 +1,12 @@ +# Copyright 2023 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + archived_user_disable_auth_api_key = fields.Boolean( + related="company_id.archived_user_disable_auth_api_key", readonly=False + ) diff --git a/auth_api_key/pyproject.toml b/auth_api_key/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/auth_api_key/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/auth_api_key/readme/CONFIGURE.md b/auth_api_key/readme/CONFIGURE.md new file mode 100644 index 0000000000..f791dd13ab --- /dev/null +++ b/auth_api_key/readme/CONFIGURE.md @@ -0,0 +1,6 @@ +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. + +If you want to manage them via serve environment settings use +auth_api_key_server_env. diff --git a/auth_api_key/readme/CONTRIBUTORS.md b/auth_api_key/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..efda422667 --- /dev/null +++ b/auth_api_key/readme/CONTRIBUTORS.md @@ -0,0 +1,6 @@ +- Denis Robinet \<\> +- Laurent Mignon \<\> +- Quentin Groulard \<\> +- Sébastien Beau \<\> +- Chafique Delli \<\> +- Thien Vo Hong \<\> diff --git a/auth_api_key/readme/CREDITS.md b/auth_api_key/readme/CREDITS.md new file mode 100644 index 0000000000..a2a771b1ca --- /dev/null +++ b/auth_api_key/readme/CREDITS.md @@ -0,0 +1 @@ +The migration of this module from 17.0 to 18.0 was financially supported by Camptocamp. \ No newline at end of file diff --git a/auth_api_key/readme/DESCRIPTION.md b/auth_api_key/readme/DESCRIPTION.md new file mode 100644 index 0000000000..4cac579599 --- /dev/null +++ b/auth_api_key/readme/DESCRIPTION.md @@ -0,0 +1,19 @@ +Authenticate http requests from an API key. + +API keys are codes passed in (in the http header API-KEY) by programs +calling an API in order to identify -in this case- the calling program's +user. + +Take care while using this kind of mechanism since information into http +headers are visible in clear. Thus, use it only to authenticate requests +from known sources. + +For unknown sources, it is a good practice to filter out this header at +proxy level. + +Odoo allows users to authenticate `XMLRPC/JSONRPC` calls using their API key instead of a password by native API keys (`res.users.apikey`). However, `auth_api_key` has some special features of its own such as: +- API keys remain usable even when the user is inactive, if enabled via settings (e.g., for system users in a shopinvader case). +- Supports dual authentication via Basic Auth and API_KEY in separate HTTP headers. +- Admins can manage API keys for all users + +Given these advantages, particularly in use case like system user authentication, we have decided to keep the `auth_api_key` module \ No newline at end of file diff --git a/auth_api_key/readme/USAGE.md b/auth_api_key/readme/USAGE.md new file mode 100644 index 0000000000..547d48759c --- /dev/null +++ b/auth_api_key/readme/USAGE.md @@ -0,0 +1,11 @@ +To apply this authentication system to your http request you must set +'api_key' as value for the 'auth' parameter of your route definition +into your controller. + +``` python +class MyController(Controller): + + @route('/my_service', auth='api_key', ...) + def my_service(self, *args, **kwargs): + pass +``` diff --git a/auth_api_key/security/ir.model.access.csv b/auth_api_key/security/ir.model.access.csv new file mode 100644 index 0000000000..b964d8c1de --- /dev/null +++ b/auth_api_key/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_auth_api_key,access_auth_api_key,model_auth_api_key,base.group_system,1,1,1,1 diff --git a/auth_api_key/static/description/icon.png b/auth_api_key/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/auth_api_key/static/description/icon.png differ diff --git a/auth_api_key/static/description/index.html b/auth_api_key/static/description/index.html new file mode 100644 index 0000000000..c1b7ac4c31 --- /dev/null +++ b/auth_api_key/static/description/index.html @@ -0,0 +1,465 @@ + + + + + +Auth Api Key + + + +
+

Auth Api Key

+ + +

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

+

Authenticate http requests from an API key.

+

API keys are codes passed in (in the http header API-KEY) by programs +calling an API in order to identify -in this case- the calling program’s +user.

+

Take care while using this kind of mechanism since information into http +headers are visible in clear. Thus, use it only to authenticate requests +from known sources.

+

For unknown sources, it is a good practice to filter out this header at +proxy level.

+

Table of contents

+ +
+

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.

+

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

+
+
+

Usage

+

To apply this authentication system to your http request you must set +‘api_key’ as value for the ‘auth’ parameter of your route definition +into your controller.

+
+class MyController(Controller):
+
+    @route('/my_service', auth='api_key', ...)
+    def my_service(self, *args, **kwargs):
+        pass
+
+
+
+

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 +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Other credits

+

The migration of this module from 17.0 to 18.0 was financially supported +by Camptocamp.

+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/server-auth project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/auth_api_key/tests/__init__.py b/auth_api_key/tests/__init__.py new file mode 100644 index 0000000000..56e3e32a3a --- /dev/null +++ b/auth_api_key/tests/__init__.py @@ -0,0 +1 @@ +from . import test_auth_api_key diff --git a/auth_api_key/tests/test_auth_api_key.py b/auth_api_key/tests/test_auth_api_key.py new file mode 100644 index 0000000000..7908c42eb7 --- /dev/null +++ b/auth_api_key/tests/test_auth_api_key.py @@ -0,0 +1,70 @@ +# Copyright 2018 ACSONE SA/NV +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +from odoo.exceptions import AccessError, ValidationError +from odoo.tests.common import TransactionCase + + +class TestAuthApiKey(TransactionCase): + @classmethod + def setUpClass(cls, *args, **kwargs): + super().setUpClass(*args, **kwargs) + cls.AuthApiKey = cls.env["auth.api.key"] + cls.demo_user = cls.env.ref("base.user_demo") + cls.api_key_good = cls.AuthApiKey.create( + {"name": "good", "user_id": cls.demo_user.id, "key": "api_key"} + ) + + def test_lookup_key_from_db(self): + demo_user = self.env.ref("base.user_demo") + self.assertEqual( + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_key"), demo_user.id + ) + + def test_wrong_key(self): + with self.assertRaises(ValidationError), self.env.cr.savepoint(): + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_wrong_key") + + def test_user_not_allowed(self): + # only system users can check for key + with self.assertRaises(AccessError), self.env.cr.savepoint(): + self.env["auth.api.key"].with_user( + user=self.demo_user + )._retrieve_uid_from_api_key("api_wrong_key") + + def test_cache_invalidation(self): + self.assertEqual( + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_key"), + self.demo_user.id, + ) + self.api_key_good.write({"key": "updated_key"}) + self.assertEqual( + self.env["auth.api.key"]._retrieve_uid_from_api_key("updated_key"), + self.demo_user.id, + ) + with self.assertRaises(ValidationError): + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_key") + + def test_user_archived_unarchived_with_option_on(self): + self.env.company.archived_user_disable_auth_api_key = True + demo_user = self.env.ref("base.user_demo") + self.assertEqual( + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_key"), demo_user.id + ) + demo_user.active = False + with self.assertRaises(ValidationError): + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_key") + demo_user.active = True + self.assertEqual( + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_key"), demo_user.id + ) + + def test_user_archived_unarchived_with_option_off(self): + self.env.company.archived_user_disable_auth_api_key = False + demo_user = self.env.ref("base.user_demo") + self.assertEqual( + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_key"), demo_user.id + ) + demo_user.active = False + self.assertEqual( + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_key"), demo_user.id + ) diff --git a/auth_api_key/views/auth_api_key.xml b/auth_api_key/views/auth_api_key.xml new file mode 100644 index 0000000000..d536772b34 --- /dev/null +++ b/auth_api_key/views/auth_api_key.xml @@ -0,0 +1,53 @@ + + + + + auth.api.key.form (in auth_api_key) + auth.api.key + +
+ + + + +
+
+
+ + auth.api.key.list (in auth_api_key) + auth.api.key + + + + + + + + + Auth Api Key + auth.api.key + list,form + [] + {} + + + Auth Api Key + + + + +
diff --git a/auth_api_key/views/res_config_settings.xml b/auth_api_key/views/res_config_settings.xml new file mode 100644 index 0000000000..61438d4a22 --- /dev/null +++ b/auth_api_key/views/res_config_settings.xml @@ -0,0 +1,25 @@ + + + + + + res.config.settings.form.inherit + res.config.settings + + + + + + + + + + + + +