diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a48d521164..bbf4fc5477 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -118,7 +118,9 @@ repos: hooks: - id: flake8 name: flake8 - additional_dependencies: ["flake8-bugbear==21.9.2"] + additional_dependencies: + ["flake8-bugbear==21.9.2", "importlib-metadata==4.13.0"] + - repo: https://github.com/OCA/pylint-odoo rev: 7.0.2 hooks: diff --git a/README.md b/README.md index 85bd59bd30..da6ed05144 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,11 @@ Modules for handling various authentication schemes [//]: # (addons) -This part will be replaced when running the oca-gen-addons-table script from OCA/maintainer-tools. +Available addons +---------------- +addon | version | maintainers | summary +--- | --- | --- | --- +[auth_api_key](auth_api_key/) | 16.0.1.0.0 | | Authenticate http requests from an API key [//]: # (end addons) diff --git a/auth_api_key/README.rst b/auth_api_key/README.rst new file mode 100644 index 0000000000..689efcd4a0 --- /dev/null +++ b/auth_api_key/README.rst @@ -0,0 +1,107 @@ +============ +Auth Api Key +============ + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |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/16.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-16-0/server-auth-16-0-auth_api_key + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/251/16.0 + :alt: Try me on Runbot + +|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-block:: 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 smashing 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 + +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..3cfe4fbe69 --- /dev/null +++ b/auth_api_key/__manifest__.py @@ -0,0 +1,14 @@ +# 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": "16.0.1.0.0", + "license": "LGPL-3", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/server-auth", + "development_status": "Beta", + "data": ["security/ir.model.access.csv", "views/auth_api_key.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..7e919c3767 --- /dev/null +++ b/auth_api_key/i18n/auth_api_key.pot @@ -0,0 +1,113 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * auth_api_key +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.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____last_update +msgid "Last Modified on" +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..c87f446a17 --- /dev/null +++ b/auth_api_key/i18n/it.po @@ -0,0 +1,123 @@ +# 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: 2021-02-12 10:45+0000\n" +"Last-Translator: Sergio Zanchetta \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 4.3.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 "Creata da" + +#. module: auth_api_key +#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__create_date +msgid "Created on" +msgstr "Creata 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____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. 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 "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..dee3379fea --- /dev/null +++ b/auth_api_key/models/__init__.py @@ -0,0 +1,2 @@ +from . import ir_http +from . import auth_api_key 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..4913fc7b63 --- /dev/null +++ b/auth_api_key/models/auth_api_key.py @@ -0,0 +1,63 @@ +# 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""", + ) + + _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(_("The key %s is not allowed") % key) + + @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._retrieve_api_key_id.clear_cache(self.env[self._name]) + self._retrieve_uid_from_api_key.clear_cache(self.env[self._name]) + + @api.model_create_multi + def create(self, vals_list): + records = super(AuthApiKey, self).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(AuthApiKey, self).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/readme/CONFIGURE.rst b/auth_api_key/readme/CONFIGURE.rst new file mode 100644 index 0000000000..ad40ead98a --- /dev/null +++ b/auth_api_key/readme/CONFIGURE.rst @@ -0,0 +1,4 @@ +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.rst b/auth_api_key/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..a0cd887895 --- /dev/null +++ b/auth_api_key/readme/CONTRIBUTORS.rst @@ -0,0 +1,5 @@ +* Denis Robinet +* Laurent Mignon +* Quentin Groulard +* Sébastien Beau +* Chafique Delli diff --git a/auth_api_key/readme/DESCRIPTION.rst b/auth_api_key/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..81c98219c7 --- /dev/null +++ b/auth_api_key/readme/DESCRIPTION.rst @@ -0,0 +1,9 @@ +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. diff --git a/auth_api_key/readme/USAGE.rst b/auth_api_key/readme/USAGE.rst new file mode 100644 index 0000000000..d8ff4460eb --- /dev/null +++ b/auth_api_key/readme/USAGE.rst @@ -0,0 +1,10 @@ +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-block:: 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..840942b8fc --- /dev/null +++ b/auth_api_key/static/description/index.html @@ -0,0 +1,448 @@ + + + + + + +Auth Api Key + + + +
+

Auth Api Key

+ + +

Beta License: LGPL-3 OCA/server-auth Translate me on Weblate Try me on Runbot

+

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 smashing 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

+ +
+
+

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..b8e0804097 --- /dev/null +++ b/auth_api_key/tests/test_auth_api_key.py @@ -0,0 +1,45 @@ +# 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") 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..c2305274ae --- /dev/null +++ b/auth_api_key/views/auth_api_key.xml @@ -0,0 +1,46 @@ + + + + + auth.api.key.form (in auth_api_key) + auth.api.key + +
+ + +
+
+
+ + auth.api.key.tree (in auth_api_key) + auth.api.key + + + + + + + + + Auth Api Key + auth.api.key + tree,form + [] + {} + + + Auth Api Key + + + + +
diff --git a/setup/_metapackage/VERSION.txt b/setup/_metapackage/VERSION.txt new file mode 100644 index 0000000000..74453f5de6 --- /dev/null +++ b/setup/_metapackage/VERSION.txt @@ -0,0 +1 @@ +16.0.20221205.0 \ No newline at end of file diff --git a/setup/_metapackage/setup.py b/setup/_metapackage/setup.py new file mode 100644 index 0000000000..0dae484122 --- /dev/null +++ b/setup/_metapackage/setup.py @@ -0,0 +1,18 @@ +import setuptools + +with open('VERSION.txt', 'r') as f: + version = f.read().strip() + +setuptools.setup( + name="odoo-addons-oca-server-auth", + description="Meta package for oca-server-auth Odoo addons", + version=version, + install_requires=[ + 'odoo-addon-auth_api_key>=16.0dev,<16.1dev', + ], + classifiers=[ + 'Programming Language :: Python', + 'Framework :: Odoo', + 'Framework :: Odoo :: 16.0', + ] +) diff --git a/setup/auth_api_key/odoo/addons/auth_api_key b/setup/auth_api_key/odoo/addons/auth_api_key new file mode 120000 index 0000000000..8cc2273270 --- /dev/null +++ b/setup/auth_api_key/odoo/addons/auth_api_key @@ -0,0 +1 @@ +../../../../auth_api_key \ No newline at end of file diff --git a/setup/auth_api_key/setup.py b/setup/auth_api_key/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/auth_api_key/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)