From 1069a5be6a6384b8852fd2445e58fbe2e4b0b065 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Wed, 31 Jan 2018 17:30:50 +0100 Subject: [PATCH 01/76] New generic module du define REST services --- auth_api_key/models/__init__.py | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 auth_api_key/models/__init__.py diff --git a/auth_api_key/models/__init__.py b/auth_api_key/models/__init__.py new file mode 100644 index 0000000000..01b3640a45 --- /dev/null +++ b/auth_api_key/models/__init__.py @@ -0,0 +1,2 @@ +from . import ir_http +from . import invader_entrypoint From cccbd8721f58e308ca07dcd3e53b30288744c1b3 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Thu, 1 Feb 2018 00:20:26 +0100 Subject: [PATCH 02/76] auth_api_key: New module to provide authentication by api_key --- auth_api_key/README.rst | 85 +++++++++++++++++++++++ auth_api_key/__init__.py | 1 + auth_api_key/__manifest__.py | 22 ++++++ auth_api_key/models/__init__.py | 3 +- auth_api_key/models/auth_api_key.py | 49 +++++++++++++ auth_api_key/models/ir_http.py | 39 +++++++++++ auth_api_key/models/keychain_account.py | 21 ++++++ auth_api_key/security/auth_api_key.xml | 17 +++++ auth_api_key/static/description/icon.png | Bin 0 -> 9455 bytes auth_api_key/views/auth_api_key.xml | 51 ++++++++++++++ 10 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 auth_api_key/README.rst create mode 100644 auth_api_key/__init__.py create mode 100644 auth_api_key/__manifest__.py create mode 100644 auth_api_key/models/auth_api_key.py create mode 100644 auth_api_key/models/ir_http.py create mode 100644 auth_api_key/models/keychain_account.py create mode 100644 auth_api_key/security/auth_api_key.xml create mode 100644 auth_api_key/static/description/icon.png create mode 100644 auth_api_key/views/auth_api_key.xml diff --git a/auth_api_key/README.rst b/auth_api_key/README.rst new file mode 100644 index 0000000000..f562e2611f --- /dev/null +++ b/auth_api_key/README.rst @@ -0,0 +1,85 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +============ +Auth Api Key +============ + +Authenticate http requests from an API key + + +Configuration +============= + +The api key must be provided by the coniguration parameter named +'auth_api_key.api_key'. +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 + +Usage +===== + +To use this module, you need to: + +#. Go to ... + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "8.0" for example + +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 smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Firstname Lastname +* Second Person + +Funders +------- + +The development of this module has been financially supported by: + +* Company 1 name +* Company 2 name + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +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. + +To contribute to this module, please visit https://odoo-community.org. 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..8294eb056a --- /dev/null +++ b/auth_api_key/__manifest__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Auth Api Key', + 'summary': """ + Authenticate http requests from an API key""", + 'version': '10.0.1.0.0', + 'license': 'AGPL-3', + 'author': 'ACSONE SA/NV,Odoo Community Association (OCA)', + 'website': 'https://acsone.eu/', + 'depends': [ + 'keychain' + ], + 'data': [ + 'security/auth_api_key.xml', + 'views/auth_api_key.xml', + ], + 'demo': [ + ], +} diff --git a/auth_api_key/models/__init__.py b/auth_api_key/models/__init__.py index 01b3640a45..389ec3bba5 100644 --- a/auth_api_key/models/__init__.py +++ b/auth_api_key/models/__init__.py @@ -1,2 +1,3 @@ from . import ir_http -from . import invader_entrypoint +from . import keychain_account +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..2adf2c25bb --- /dev/null +++ b/auth_api_key/models/auth_api_key.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, tools + + +class AuthApiKey(models.Model): + _name = 'auth.api.key' + _inherit = 'keychain.backend' + _backend_name = 'auth_api_key' + + @api.model + def _default_user_id(self): + return self.env.user + + user_id = fields.Many2one( + 'res.users', + 'User', + required=True, + help="The user used to execute the code into Odoo when user is called " + "with this api key.", + default=_default_user_id + ) + + @api.multi + def _inverse_password(self): + self.retrieve_id_by_api_key.clear_cache(self) + ret = super(AuthApiKey, self)._inverse_password() + return ret + + @api.model + def retrieve_from_api_key(self, api_key): + return self.browse(self.retrieve_id_by_api_key().get(api_key, [])) + + @api.model + @tools.ormcache('self.env.uid', 'self._backend_name', 'self._name') + def retrieve_id_by_api_key(self): + keychain_account = self.env['keychain.account'] + keychain_accounts = keychain_account.search([ + ('namespace', '=', self._backend_name), + ('technical_name', 'like', self._name) + ]) + res = {} + for key in keychain_accounts: + _id = int(key.technical_name.split(',')[1]) + api_key = key.get_password() + res[api_key] = _id + return res diff --git a/auth_api_key/models/ir_http.py b/auth_api_key/models/ir_http.py new file mode 100644 index 0000000000..5ae09d91d5 --- /dev/null +++ b/auth_api_key/models/ir_http.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ACSONE SA/NV +# Copyright 2017 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging + +from odoo.http import request +from odoo import models +from werkzeug.exceptions import Unauthorized + + +_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.uid = 1 + auth_api_key = request.env['auth.api.key'].retrieve_from_api_key( + api_key + ) + if 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.uid = auth_api_key.user_id.id + request.auth_api_key = auth_api_key + return True + _logger.error("Wrong HTTP_API_KEY, access denied") + raise Unauthorized("Access denied") diff --git a/auth_api_key/models/keychain_account.py b/auth_api_key/models/keychain_account.py new file mode 100644 index 0000000000..02f46c76a3 --- /dev/null +++ b/auth_api_key/models/keychain_account.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class KeychainAccount(models.Model): + + _inherit = 'keychain.account' + + namespace = fields.Selection( + selection_add=[('auth_api_key', 'Search Engine Backend')]) + + @api.multi + def _auth_api_key_validate_data(self, data): + return True + + @api.multi + def _auth_api_key_init_data(self): + return {} diff --git a/auth_api_key/security/auth_api_key.xml b/auth_api_key/security/auth_api_key.xml new file mode 100644 index 0000000000..2ad7762da0 --- /dev/null +++ b/auth_api_key/security/auth_api_key.xml @@ -0,0 +1,17 @@ + + + + + + + auth.api.key access manage + + + + + + + + + diff --git a/auth_api_key/static/description/icon.png b/auth_api_key/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 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..6937bab749 --- /dev/null +++ b/auth_api_key/views/auth_api_key.xml @@ -0,0 +1,51 @@ + + + + + + + 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 + + + + + +
From 0fd65cd98427da4ae1ebc4e1f774cb2908c322a7 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Fri, 2 Feb 2018 16:26:45 +0100 Subject: [PATCH 03/76] auth_api_key: Remove useless code --- auth_api_key/models/auth_api_key.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index 2adf2c25bb..7528db41de 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -26,8 +26,7 @@ def _default_user_id(self): @api.multi def _inverse_password(self): self.retrieve_id_by_api_key.clear_cache(self) - ret = super(AuthApiKey, self)._inverse_password() - return ret + return super(AuthApiKey, self)._inverse_password() @api.model def retrieve_from_api_key(self, api_key): From b16d703a8672162afbb585f55c5e7f368c421356 Mon Sep 17 00:00:00 2001 From: "Denis Robinet (ACSONE)" Date: Mon, 19 Feb 2018 15:30:01 +0100 Subject: [PATCH 04/76] Update the auth_api_key for keychan 10.0.2 (renamed method) --- auth_api_key/models/auth_api_key.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index 7528db41de..8a7d401712 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -43,6 +43,6 @@ def retrieve_id_by_api_key(self): res = {} for key in keychain_accounts: _id = int(key.technical_name.split(',')[1]) - api_key = key.get_password() + api_key = key._get_password() res[api_key] = _id return res From 84c36af683cfca6cc37a2b07fade94ac370586a3 Mon Sep 17 00:00:00 2001 From: "Denis Robinet (ACSONE)" Date: Mon, 19 Feb 2018 15:31:24 +0100 Subject: [PATCH 05/76] Fix the authentification method and show the user_id on the form --- auth_api_key/models/ir_http.py | 2 +- auth_api_key/views/auth_api_key.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/auth_api_key/models/ir_http.py b/auth_api_key/models/ir_http.py index 5ae09d91d5..6e77c0738b 100644 --- a/auth_api_key/models/ir_http.py +++ b/auth_api_key/models/ir_http.py @@ -26,7 +26,7 @@ def _auth_method_api_key(cls): auth_api_key = request.env['auth.api.key'].retrieve_from_api_key( api_key ) - if 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 diff --git a/auth_api_key/views/auth_api_key.xml b/auth_api_key/views/auth_api_key.xml index 6937bab749..eca677d51e 100644 --- a/auth_api_key/views/auth_api_key.xml +++ b/auth_api_key/views/auth_api_key.xml @@ -15,6 +15,7 @@ + From 1fd62eca56be9aac20ac7467d5a522e9b9b923ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Sun, 25 Feb 2018 19:39:24 +0100 Subject: [PATCH 06/76] refactor code in order to use generic code from base_rest instead of custom one from shopinvader --- auth_api_key/models/ir_http.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auth_api_key/models/ir_http.py b/auth_api_key/models/ir_http.py index 6e77c0738b..dd777c239a 100644 --- a/auth_api_key/models/ir_http.py +++ b/auth_api_key/models/ir_http.py @@ -8,7 +8,7 @@ from odoo.http import request from odoo import models -from werkzeug.exceptions import Unauthorized +from odoo.exceptions import AccessDenied _logger = logging.getLogger(__name__) @@ -36,4 +36,4 @@ def _auth_method_api_key(cls): request.auth_api_key = auth_api_key return True _logger.error("Wrong HTTP_API_KEY, access denied") - raise Unauthorized("Access denied") + raise AccessDenied() From e036e069ddfdd023dcf1523ff4f4426f9c93771a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Wed, 29 Aug 2018 09:05:14 +0200 Subject: [PATCH 07/76] fix wrong name in selection box --- auth_api_key/models/keychain_account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth_api_key/models/keychain_account.py b/auth_api_key/models/keychain_account.py index 02f46c76a3..3c919fa458 100644 --- a/auth_api_key/models/keychain_account.py +++ b/auth_api_key/models/keychain_account.py @@ -10,7 +10,7 @@ class KeychainAccount(models.Model): _inherit = 'keychain.account' namespace = fields.Selection( - selection_add=[('auth_api_key', 'Search Engine Backend')]) + selection_add=[('auth_api_key', 'Authentification Api key')]) @api.multi def _auth_api_key_validate_data(self, data): From 828f08cb39f1ccf2de234a5881d1c08d86ea4a38 Mon Sep 17 00:00:00 2001 From: hparfr Date: Wed, 17 Oct 2018 12:51:51 +0200 Subject: [PATCH 08/76] Since keychain 10.0.2.0.1 there is a default validation method --- auth_api_key/models/keychain_account.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/auth_api_key/models/keychain_account.py b/auth_api_key/models/keychain_account.py index 3c919fa458..80168d751d 100644 --- a/auth_api_key/models/keychain_account.py +++ b/auth_api_key/models/keychain_account.py @@ -2,7 +2,7 @@ # Copyright 2018 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models +from odoo import fields, models class KeychainAccount(models.Model): @@ -11,11 +11,3 @@ class KeychainAccount(models.Model): namespace = fields.Selection( selection_add=[('auth_api_key', 'Authentification Api key')]) - - @api.multi - def _auth_api_key_validate_data(self, data): - return True - - @api.multi - def _auth_api_key_init_data(self): - return {} From bbbd0d6a9d4a5e82fbc94fccb33d97361252d05f Mon Sep 17 00:00:00 2001 From: Quentin Groulard Date: Tue, 6 Nov 2018 12:34:52 +0100 Subject: [PATCH 09/76] Keychain removed Get rid of keychain dependency --- auth_api_key/__manifest__.py | 24 ++++------ auth_api_key/models/__init__.py | 1 - auth_api_key/models/auth_api_key.py | 61 ++++++++++--------------- auth_api_key/models/ir_http.py | 12 ++--- auth_api_key/models/keychain_account.py | 13 ------ auth_api_key/readme/CONFIGURE.rst | 2 + auth_api_key/readme/CONTRIBUTORS.rst | 4 ++ auth_api_key/readme/DESCRIPTION.rst | 1 + auth_api_key/readme/USAGE.rst | 9 ++++ auth_api_key/security/auth_api_key.xml | 17 ------- auth_api_key/tests/__init__.py | 1 + auth_api_key/tests/test_auth_api_key.py | 35 ++++++++++++++ auth_api_key/views/auth_api_key.xml | 52 --------------------- 13 files changed, 90 insertions(+), 142 deletions(-) delete mode 100644 auth_api_key/models/keychain_account.py create mode 100644 auth_api_key/readme/CONFIGURE.rst create mode 100644 auth_api_key/readme/CONTRIBUTORS.rst create mode 100644 auth_api_key/readme/DESCRIPTION.rst create mode 100644 auth_api_key/readme/USAGE.rst delete mode 100644 auth_api_key/security/auth_api_key.xml create mode 100644 auth_api_key/tests/__init__.py create mode 100644 auth_api_key/tests/test_auth_api_key.py delete mode 100644 auth_api_key/views/auth_api_key.xml diff --git a/auth_api_key/__manifest__.py b/auth_api_key/__manifest__.py index 8294eb056a..7b68da7c41 100644 --- a/auth_api_key/__manifest__.py +++ b/auth_api_key/__manifest__.py @@ -3,20 +3,14 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Auth Api Key', - 'summary': """ + "name": "Auth Api Key", + "summary": """ Authenticate http requests from an API key""", - 'version': '10.0.1.0.0', - 'license': 'AGPL-3', - 'author': 'ACSONE SA/NV,Odoo Community Association (OCA)', - 'website': 'https://acsone.eu/', - 'depends': [ - 'keychain' - ], - 'data': [ - 'security/auth_api_key.xml', - 'views/auth_api_key.xml', - ], - 'demo': [ - ], + "version": "10.0.1.0.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "website": "https://acsone.eu/", + "depends": ["server_environment"], + "data": [], + "demo": [], } diff --git a/auth_api_key/models/__init__.py b/auth_api_key/models/__init__.py index 389ec3bba5..dee3379fea 100644 --- a/auth_api_key/models/__init__.py +++ b/auth_api_key/models/__init__.py @@ -1,3 +1,2 @@ from . import ir_http -from . import keychain_account 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 index 8a7d401712..733bd10f03 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -4,45 +4,32 @@ from odoo import api, fields, models, tools +from odoo.addons.server_environment import serv_config -class AuthApiKey(models.Model): - _name = 'auth.api.key' - _inherit = 'keychain.backend' - _backend_name = 'auth_api_key' +from odoo.exceptions import ValidationError, AccessError - @api.model - def _default_user_id(self): - return self.env.user - - user_id = fields.Many2one( - 'res.users', - 'User', - required=True, - help="The user used to execute the code into Odoo when user is called " - "with this api key.", - default=_default_user_id - ) - - @api.multi - def _inverse_password(self): - self.retrieve_id_by_api_key.clear_cache(self) - return super(AuthApiKey, self)._inverse_password() - @api.model - def retrieve_from_api_key(self, api_key): - return self.browse(self.retrieve_id_by_api_key().get(api_key, [])) +class AuthApiKey(models.TransientModel): + _name = "auth.api.key" @api.model - @tools.ormcache('self.env.uid', 'self._backend_name', 'self._name') - def retrieve_id_by_api_key(self): - keychain_account = self.env['keychain.account'] - keychain_accounts = keychain_account.search([ - ('namespace', '=', self._backend_name), - ('technical_name', 'like', self._name) - ]) - res = {} - for key in keychain_accounts: - _id = int(key.technical_name.split(',')[1]) - api_key = key._get_password() - res[api_key] = _id - return res + @tools.ormcache("api_key") + def _retrieve_uid_from_api_key(self, api_key): + if not self.env.user.has_group("base.group_system"): + raise AccessError("User is not allowed") + + for section in serv_config.sections(): + if section.startswith("api_key_") and serv_config.has_option( + section, "key" + ): + if api_key != serv_config.get(section, "key"): + continue + + login_name = serv_config.get(section, "user") + uid = self.env["res.users"].search([("login", "=", login_name)]).id + + if not uid: + raise ValidationError("No user found with login %s" % login_name) + + return uid + return False diff --git a/auth_api_key/models/ir_http.py b/auth_api_key/models/ir_http.py index dd777c239a..dd1483a644 100644 --- a/auth_api_key/models/ir_http.py +++ b/auth_api_key/models/ir_http.py @@ -15,24 +15,22 @@ class IrHttp(models.AbstractModel): - _inherit = 'ir.http' + _inherit = "ir.http" @classmethod def _auth_method_api_key(cls): headers = request.httprequest.environ - api_key = headers.get('HTTP_API_KEY') + api_key = headers.get("HTTP_API_KEY") if api_key: request.uid = 1 - auth_api_key = request.env['auth.api.key'].retrieve_from_api_key( - api_key - ) - if auth_api_key: + uid = request.env["auth.api.key"].retrieve_uid_from_api_key(api_key) + if uid: # 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.uid = auth_api_key.user_id.id + request.uid = uid request.auth_api_key = auth_api_key return True _logger.error("Wrong HTTP_API_KEY, access denied") diff --git a/auth_api_key/models/keychain_account.py b/auth_api_key/models/keychain_account.py deleted file mode 100644 index 80168d751d..0000000000 --- a/auth_api_key/models/keychain_account.py +++ /dev/null @@ -1,13 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright 2018 ACSONE SA/NV -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - -from odoo import fields, models - - -class KeychainAccount(models.Model): - - _inherit = 'keychain.account' - - namespace = fields.Selection( - selection_add=[('auth_api_key', 'Authentification Api key')]) diff --git a/auth_api_key/readme/CONFIGURE.rst b/auth_api_key/readme/CONFIGURE.rst new file mode 100644 index 0000000000..0c2c0538e5 --- /dev/null +++ b/auth_api_key/readme/CONFIGURE.rst @@ -0,0 +1,2 @@ +The api key must be provided by the coniguration parameter named +'api_key_*.key', and the user under the same option 'api_key_*.user'. \ No newline at end of file diff --git a/auth_api_key/readme/CONTRIBUTORS.rst b/auth_api_key/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..765b551496 --- /dev/null +++ b/auth_api_key/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* Denis Robinet <> +* Laurent Mignon <> +* Quentin Groulard <> +* Sébastien Beau <> \ No newline at end of file diff --git a/auth_api_key/readme/DESCRIPTION.rst b/auth_api_key/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..dd9562ef54 --- /dev/null +++ b/auth_api_key/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Authenticate http requests from an API key. \ No newline at end of file diff --git a/auth_api_key/readme/USAGE.rst b/auth_api_key/readme/USAGE.rst new file mode 100644 index 0000000000..4464ca59c9 --- /dev/null +++ b/auth_api_key/readme/USAGE.rst @@ -0,0 +1,9 @@ +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 \ No newline at end of file diff --git a/auth_api_key/security/auth_api_key.xml b/auth_api_key/security/auth_api_key.xml deleted file mode 100644 index 2ad7762da0..0000000000 --- a/auth_api_key/security/auth_api_key.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - auth.api.key access manage - - - - - - - - - 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..dd43eb4f30 --- /dev/null +++ b/auth_api_key/tests/test_auth_api_key.py @@ -0,0 +1,35 @@ +from odoo.tests.common import TransactionCase +from odoo.addons.server_environment import serv_config +from odoo.exceptions import ValidationError, AccessError + + +class TestAuthApiKey(TransactionCase): + @classmethod + def setUpClass(cls, *args, **kwargs): + super(TestAuthApiKey, cls).setUpClass(*args, **kwargs) + + serv_config.add_section("api_key_good") + serv_config.set("api_key_good", "user", "demo") + serv_config.set("api_key_good", "key", "api_right_key") + serv_config.add_section("api_key_bad") + serv_config.set("api_key_bad", "user", "not_demo") + serv_config.set("api_key_bad", "key", "api_wrong_key") + + def test_lookup(self): + demo_user = self.env.ref("base.user_demo") + self.assertEqual( + self.env["auth.api.key"]._retrieve_uid_from_api_key("api_right_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): + demo_user = self.env.ref("base.user_demo") + with self.assertRaises(AccessError), self.env.cr.savepoint(): + self.env["auth.api.key"].sudo(user=demo_user)._retrieve_uid_from_api_key( + "api_wrong_key" + ) + diff --git a/auth_api_key/views/auth_api_key.xml b/auth_api_key/views/auth_api_key.xml deleted file mode 100644 index eca677d51e..0000000000 --- a/auth_api_key/views/auth_api_key.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - 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 - - - - - -
From a50166442462bf62f33d5a6199770008718fa09a Mon Sep 17 00:00:00 2001 From: Quentin Groulard Date: Thu, 8 Nov 2018 11:06:58 +0100 Subject: [PATCH 10/76] Update Readme with more details --- auth_api_key/README.rst | 85 ---------------------------- auth_api_key/readme/CONFIGURE.rst | 10 +++- auth_api_key/readme/CONTRIBUTORS.rst | 8 +-- auth_api_key/readme/DESCRIPTION.rst | 6 +- 4 files changed, 17 insertions(+), 92 deletions(-) delete mode 100644 auth_api_key/README.rst diff --git a/auth_api_key/README.rst b/auth_api_key/README.rst deleted file mode 100644 index f562e2611f..0000000000 --- a/auth_api_key/README.rst +++ /dev/null @@ -1,85 +0,0 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html - :alt: License: AGPL-3 - -============ -Auth Api Key -============ - -Authenticate http requests from an API key - - -Configuration -============= - -The api key must be provided by the coniguration parameter named -'auth_api_key.api_key'. -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 - -Usage -===== - -To use this module, you need to: - -#. Go to ... - -.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas - :alt: Try me on Runbot - :target: https://runbot.odoo-community.org/runbot/{repo_id}/{branch} - -.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt -.. branch is "8.0" for example - -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 smash it by providing detailed and welcomed feedback. - -Credits -======= - -Images ------- - -* Odoo Community Association: `Icon `_. - -Contributors ------------- - -* Firstname Lastname -* Second Person - -Funders -------- - -The development of this module has been financially supported by: - -* Company 1 name -* Company 2 name - -Maintainer ----------- - -.. image:: https://odoo-community.org/logo.png - :alt: Odoo Community Association - :target: https://odoo-community.org - -This module is maintained by the OCA. - -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. - -To contribute to this module, please visit https://odoo-community.org. diff --git a/auth_api_key/readme/CONFIGURE.rst b/auth_api_key/readme/CONFIGURE.rst index 0c2c0538e5..0d403e1f65 100644 --- a/auth_api_key/readme/CONFIGURE.rst +++ b/auth_api_key/readme/CONFIGURE.rst @@ -1,2 +1,8 @@ -The api key must be provided by the coniguration parameter named -'api_key_*.key', and the user under the same option 'api_key_*.user'. \ No newline at end of file +The api key must be provided by the configuration parameter named +'api_key_*.key', and the user under the same option 'api_key_*.user'. + +For instance : + + [api_key_mykey] + key=my_api_key + user=my_user \ No newline at end of file diff --git a/auth_api_key/readme/CONTRIBUTORS.rst b/auth_api_key/readme/CONTRIBUTORS.rst index 765b551496..14d8f94b83 100644 --- a/auth_api_key/readme/CONTRIBUTORS.rst +++ b/auth_api_key/readme/CONTRIBUTORS.rst @@ -1,4 +1,4 @@ -* Denis Robinet <> -* Laurent Mignon <> -* Quentin Groulard <> -* Sébastien Beau <> \ No newline at end of file +* Denis Robinet +* Laurent Mignon +* Quentin Groulard +* Sébastien Beau \ No newline at end of file diff --git a/auth_api_key/readme/DESCRIPTION.rst b/auth_api_key/readme/DESCRIPTION.rst index dd9562ef54..575f75544b 100644 --- a/auth_api_key/readme/DESCRIPTION.rst +++ b/auth_api_key/readme/DESCRIPTION.rst @@ -1 +1,5 @@ -Authenticate http requests from an API key. \ No newline at end of file +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. \ No newline at end of file From b5c91d077c6bdfddf16c1238a0440b08045f990c Mon Sep 17 00:00:00 2001 From: qgroulard <43472442+qgroulard@users.noreply.github.com> Date: Thu, 8 Nov 2018 11:22:06 +0100 Subject: [PATCH 11/76] Quick fix CONFIGURE.rst --- auth_api_key/readme/CONFIGURE.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auth_api_key/readme/CONFIGURE.rst b/auth_api_key/readme/CONFIGURE.rst index 0d403e1f65..5118d0b936 100644 --- a/auth_api_key/readme/CONFIGURE.rst +++ b/auth_api_key/readme/CONFIGURE.rst @@ -2,7 +2,7 @@ The api key must be provided by the configuration parameter named 'api_key_*.key', and the user under the same option 'api_key_*.user'. For instance : - +:: [api_key_mykey] key=my_api_key - user=my_user \ No newline at end of file + user=my_user From 750cbc16e0d1296d1a757dffcf6a341ba4ba4de6 Mon Sep 17 00:00:00 2001 From: qgroulard <43472442+qgroulard@users.noreply.github.com> Date: Thu, 8 Nov 2018 11:32:09 +0100 Subject: [PATCH 12/76] Developmet status: Beta --- auth_api_key/__manifest__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/auth_api_key/__manifest__.py b/auth_api_key/__manifest__.py index 7b68da7c41..c0680ffcc2 100644 --- a/auth_api_key/__manifest__.py +++ b/auth_api_key/__manifest__.py @@ -10,6 +10,7 @@ "license": "AGPL-3", "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://acsone.eu/", + "development_status": "Beta", "depends": ["server_environment"], "data": [], "demo": [], From c59dc5110e84041e8febfa0dc49048d0e0609ffd Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Tue, 13 Nov 2018 11:32:39 +0100 Subject: [PATCH 13/76] [FIX] auth_api_key: fix api and flake8 --- auth_api_key/README.rst | 108 +++++ auth_api_key/models/auth_api_key.py | 12 +- auth_api_key/models/ir_http.py | 5 +- auth_api_key/readme/CONFIGURE.rst | 4 +- auth_api_key/readme/USAGE.rst | 3 +- auth_api_key/static/description/index.html | 449 +++++++++++++++++++++ auth_api_key/tests/test_auth_api_key.py | 15 +- 7 files changed, 581 insertions(+), 15 deletions(-) create mode 100644 auth_api_key/README.rst create mode 100644 auth_api_key/static/description/index.html diff --git a/auth_api_key/README.rst b/auth_api_key/README.rst new file mode 100644 index 0000000000..cbdf2d6b2d --- /dev/null +++ b/auth_api_key/README.rst @@ -0,0 +1,108 @@ +============ +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-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github + :target: https://github.com/OCA/server-auth/tree/10.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-10-0/server-auth-10-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/10.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 must be provided by the configuration parameter named +'api_key_*.key', and the user under the same option 'api_key_*.user'. + +For instance : + +.. code-block:: ini + + [api_key_mykey] + key=my_api_key + user=my_user + +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 + +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/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index 733bd10f03..4b8efd52d8 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -2,7 +2,7 @@ # Copyright 2018 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models, tools +from odoo import api, models, tools, _ from odoo.addons.server_environment import serv_config @@ -16,20 +16,22 @@ class AuthApiKey(models.TransientModel): @tools.ormcache("api_key") def _retrieve_uid_from_api_key(self, api_key): if not self.env.user.has_group("base.group_system"): - raise AccessError("User is not allowed") + raise AccessError(_("User is not allowed")) for section in serv_config.sections(): if section.startswith("api_key_") and serv_config.has_option( - section, "key" + section, "key" ): if api_key != serv_config.get(section, "key"): continue login_name = serv_config.get(section, "user") - uid = self.env["res.users"].search([("login", "=", login_name)]).id + uid = self.env["res.users"].search( + [("login", "=", login_name)]).id if not uid: - raise ValidationError("No user found with login %s" % login_name) + raise ValidationError( + _("No user found with login %s") % login_name) return uid return False diff --git a/auth_api_key/models/ir_http.py b/auth_api_key/models/ir_http.py index dd1483a644..d79da075c8 100644 --- a/auth_api_key/models/ir_http.py +++ b/auth_api_key/models/ir_http.py @@ -23,7 +23,8 @@ def _auth_method_api_key(cls): api_key = headers.get("HTTP_API_KEY") if api_key: request.uid = 1 - uid = request.env["auth.api.key"].retrieve_uid_from_api_key(api_key) + uid = request.env["auth.api.key"]._retrieve_uid_from_api_key( + api_key) if uid: # reset _env on the request since we change the uid... # the next call to env will instantiate an new @@ -31,7 +32,7 @@ def _auth_method_api_key(cls): # auth.api_key request._env = None request.uid = uid - request.auth_api_key = auth_api_key + request.auth_api_key = api_key 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 index 5118d0b936..d65bfb4dba 100644 --- a/auth_api_key/readme/CONFIGURE.rst +++ b/auth_api_key/readme/CONFIGURE.rst @@ -2,7 +2,9 @@ The api key must be provided by the configuration parameter named 'api_key_*.key', and the user under the same option 'api_key_*.user'. For instance : -:: + +.. code-block:: ini + [api_key_mykey] key=my_api_key user=my_user diff --git a/auth_api_key/readme/USAGE.rst b/auth_api_key/readme/USAGE.rst index 4464ca59c9..d8ff4460eb 100644 --- a/auth_api_key/readme/USAGE.rst +++ b/auth_api_key/readme/USAGE.rst @@ -1,9 +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 \ No newline at end of file + pass diff --git a/auth_api_key/static/description/index.html b/auth_api_key/static/description/index.html new file mode 100644 index 0000000000..c5d2d31987 --- /dev/null +++ b/auth_api_key/static/description/index.html @@ -0,0 +1,449 @@ + + + + + + +Auth Api Key + + + +
+

Auth Api Key

+ + +

Beta License: AGPL-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 must be provided by the configuration parameter named +‘api_key_*.key’, and the user under the same option ‘api_key_*.user’.

+

For instance :

+
+[api_key_mykey]
+key=my_api_key
+user=my_user
+
+
+
+

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/test_auth_api_key.py b/auth_api_key/tests/test_auth_api_key.py index dd43eb4f30..284a5aeba9 100644 --- a/auth_api_key/tests/test_auth_api_key.py +++ b/auth_api_key/tests/test_auth_api_key.py @@ -1,3 +1,6 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 ACSONE SA/NV +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.tests.common import TransactionCase from odoo.addons.server_environment import serv_config from odoo.exceptions import ValidationError, AccessError @@ -18,18 +21,18 @@ def setUpClass(cls, *args, **kwargs): def test_lookup(self): demo_user = self.env.ref("base.user_demo") self.assertEqual( - self.env["auth.api.key"]._retrieve_uid_from_api_key("api_right_key"), + self.env["auth.api.key"]._retrieve_uid_from_api_key( + "api_right_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") + self.env["auth.api.key"]._retrieve_uid_from_api_key( + "api_wrong_key") def test_user_not_allowed(self): demo_user = self.env.ref("base.user_demo") with self.assertRaises(AccessError), self.env.cr.savepoint(): - self.env["auth.api.key"].sudo(user=demo_user)._retrieve_uid_from_api_key( - "api_wrong_key" - ) - + self.env["auth.api.key"].sudo(user=demo_user).\ + _retrieve_uid_from_api_key("api_wrong_key") From 573ea22b4775de4835c57be446585b80841e4ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Tue, 20 Nov 2018 17:58:49 +0100 Subject: [PATCH 14/76] [MIG] server_auth from 10 to 12 --- auth_api_key/__manifest__.py | 2 +- auth_api_key/models/auth_api_key.py | 1 - auth_api_key/models/ir_http.py | 1 - auth_api_key/tests/test_auth_api_key.py | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/auth_api_key/__manifest__.py b/auth_api_key/__manifest__.py index c0680ffcc2..ae027c0310 100644 --- a/auth_api_key/__manifest__.py +++ b/auth_api_key/__manifest__.py @@ -6,7 +6,7 @@ "name": "Auth Api Key", "summary": """ Authenticate http requests from an API key""", - "version": "10.0.1.0.0", + "version": "12.0.1.0.0", "license": "AGPL-3", "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://acsone.eu/", diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index 4b8efd52d8..387073c627 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2018 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/auth_api_key/models/ir_http.py b/auth_api_key/models/ir_http.py index d79da075c8..2a14cac38f 100644 --- a/auth_api_key/models/ir_http.py +++ b/auth_api_key/models/ir_http.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2018 ACSONE SA/NV # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU diff --git a/auth_api_key/tests/test_auth_api_key.py b/auth_api_key/tests/test_auth_api_key.py index 284a5aeba9..0e3c7d9f88 100644 --- a/auth_api_key/tests/test_auth_api_key.py +++ b/auth_api_key/tests/test_auth_api_key.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2018 ACSONE SA/NV # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo.tests.common import TransactionCase From 2c8648a73a951aaf2305f8209921bdaf63ce9e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Tue, 20 Nov 2018 19:22:57 +0100 Subject: [PATCH 15/76] auth_api_key: add description to model --- auth_api_key/models/auth_api_key.py | 1 + 1 file changed, 1 insertion(+) diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index 387073c627..b302d2da5b 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -10,6 +10,7 @@ class AuthApiKey(models.TransientModel): _name = "auth.api.key" + _description = "API Key Retriever" @api.model @tools.ormcache("api_key") From c5dc798dd7f27900e070b7f89c7e157633048cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Wed, 21 Nov 2018 11:07:12 +0100 Subject: [PATCH 16/76] [CHG] auth_api_key is LGPL --- auth_api_key/__manifest__.py | 4 ++-- auth_api_key/models/auth_api_key.py | 2 +- auth_api_key/models/ir_http.py | 2 +- auth_api_key/tests/test_auth_api_key.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/auth_api_key/__manifest__.py b/auth_api_key/__manifest__.py index ae027c0310..896e30b8a9 100644 --- a/auth_api_key/__manifest__.py +++ b/auth_api_key/__manifest__.py @@ -1,13 +1,13 @@ # -*- coding: utf-8 -*- # Copyright 2018 ACSONE SA/NV -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# 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": "12.0.1.0.0", - "license": "AGPL-3", + "license": "LGPL-3", "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://acsone.eu/", "development_status": "Beta", diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index b302d2da5b..b39735f2c3 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -1,5 +1,5 @@ # Copyright 2018 ACSONE SA/NV -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo import api, models, tools, _ diff --git a/auth_api_key/models/ir_http.py b/auth_api_key/models/ir_http.py index 2a14cac38f..1e6638a07d 100644 --- a/auth_api_key/models/ir_http.py +++ b/auth_api_key/models/ir_http.py @@ -1,7 +1,7 @@ # Copyright 2018 ACSONE SA/NV # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). import logging diff --git a/auth_api_key/tests/test_auth_api_key.py b/auth_api_key/tests/test_auth_api_key.py index 0e3c7d9f88..a187aed1b9 100644 --- a/auth_api_key/tests/test_auth_api_key.py +++ b/auth_api_key/tests/test_auth_api_key.py @@ -1,5 +1,5 @@ # Copyright 2018 ACSONE SA/NV -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo.tests.common import TransactionCase from odoo.addons.server_environment import serv_config from odoo.exceptions import ValidationError, AccessError From 65420d2c90d015c5234ced463114f417661b64d3 Mon Sep 17 00:00:00 2001 From: Andreas Perhab <38032588+ap-wtioit@users.noreply.github.com> Date: Fri, 30 Nov 2018 11:23:10 +0100 Subject: [PATCH 17/76] Use consteq to compare keys Co-Authored-By: qgroulard <43472442+qgroulard@users.noreply.github.com> --- auth_api_key/models/auth_api_key.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index b39735f2c3..1c435a09f0 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -4,6 +4,7 @@ from odoo import api, models, tools, _ from odoo.addons.server_environment import serv_config +from odoo.tools import consteq from odoo.exceptions import ValidationError, AccessError @@ -22,7 +23,7 @@ def _retrieve_uid_from_api_key(self, api_key): if section.startswith("api_key_") and serv_config.has_option( section, "key" ): - if api_key != serv_config.get(section, "key"): + if not consteq(api_key, serv_config.get(section, "key")): continue login_name = serv_config.get(section, "user") From 637ba56e692afee27d79abbf2cbf71d27a8e1b9b Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 14 Feb 2019 10:29:14 +0000 Subject: [PATCH 18/76] [UPD] README.rst --- auth_api_key/README.rst | 16 ++++++++-------- auth_api_key/static/description/index.html | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/auth_api_key/README.rst b/auth_api_key/README.rst index cbdf2d6b2d..dc5e5bc240 100644 --- a/auth_api_key/README.rst +++ b/auth_api_key/README.rst @@ -10,17 +10,17 @@ Auth Api Key .. |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-AGPL--3-blue.png - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html - :alt: License: AGPL-3 +.. |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/10.0/auth_api_key + :target: https://github.com/OCA/server-auth/tree/12.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-10-0/server-auth-10-0-auth_api_key + :target: https://translation.odoo-community.org/projects/server-auth-12-0/server-auth-12-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/10.0 + :target: https://runbot.odoo-community.org/runbot/251/12.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -70,7 +70,7 @@ 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 `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -103,6 +103,6 @@ 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. +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/static/description/index.html b/auth_api_key/static/description/index.html index c5d2d31987..f70369a5af 100644 --- a/auth_api_key/static/description/index.html +++ b/auth_api_key/static/description/index.html @@ -367,7 +367,7 @@

Auth Api Key

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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.

@@ -413,7 +413,7 @@

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.

+feedback.

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

@@ -440,7 +440,7 @@

Maintainers

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.

+

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.

From 14ef36836854b27248e9055174cc3183712902ee Mon Sep 17 00:00:00 2001 From: Mourad Date: Thu, 18 Jul 2019 13:47:24 +0200 Subject: [PATCH 19/76] [IMP] ADD possibility to save api keys in database by using server.env.mixin obj --- auth_api_key/models/auth_api_key.py | 62 +++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index 1c435a09f0..8059bd304c 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -3,36 +3,64 @@ from odoo import api, models, tools, _ -from odoo.addons.server_environment import serv_config from odoo.tools import consteq from odoo.exceptions import ValidationError, AccessError -class AuthApiKey(models.TransientModel): +class AuthApiKey(models.Model): _name = "auth.api.key" + _inherit = "server.env.mixin" _description = "API Key Retriever" + name = fields.Char(required=True) + key = fields.Char(required=True) + user = fields.Char(required=True) + + _sql_constraints = [ + ('key_uniq', 'unique(key)', 'API Key Retriever must be unique !'), + ] + + @property + def _server_env_fields(self): + base_fields = super()._server_env_fields + api_key_fields = { + "key": {}, + "user": {}, + } + api_key_fields.update(base_fields) + return api_key_fields + @api.model @tools.ormcache("api_key") - def _retrieve_uid_from_api_key(self, api_key): + def _retrieve_api_key(self, api_key): if not self.env.user.has_group("base.group_system"): raise AccessError(_("User is not allowed")) + ap_keys = self.search([]) + # api key are a computed field in the context of server env + # so we can't use a domain in search method + key = False + for ap_key in ap_keys: + if consteq(api_key, ap_key.key): + key = ap_key + + if not key: + raise ValidationError( + _("The key %s is not defined") % api_key) - for section in serv_config.sections(): - if section.startswith("api_key_") and serv_config.has_option( - section, "key" - ): - if not consteq(api_key, serv_config.get(section, "key")): - continue + return key + + @api.model + @tools.ormcache("api_key") + def _retrieve_uid_from_api_key(self, api_key): + ap_key = self._retrieve_api_key(api_key) + uid = self.env["res.users"].search( + [("login", "=", ap_key.user)]).id - login_name = serv_config.get(section, "user") - uid = self.env["res.users"].search( - [("login", "=", login_name)]).id + if not uid: + raise ValidationError( + _("No user found with login %s") % login_name) - if not uid: - raise ValidationError( - _("No user found with login %s") % login_name) + return uid + return False - return uid - return False From 3d5484208a1ad0f2e13dffee993a72751541e303 Mon Sep 17 00:00:00 2001 From: Mourad Date: Thu, 18 Jul 2019 13:52:33 +0200 Subject: [PATCH 20/76] [FIX] login_name error --- auth_api_key/models/auth_api_key.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index 8059bd304c..e767ff833a 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -59,7 +59,7 @@ def _retrieve_uid_from_api_key(self, api_key): if not uid: raise ValidationError( - _("No user found with login %s") % login_name) + _("No user found with login %s") % ap_key.user) return uid return False From 4e295fe027525f0735b795308a7cc4747c4b6e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Fri, 19 Jul 2019 17:13:54 +0200 Subject: [PATCH 21/76] [IMP] make auth_api_key compatible in multi-db Api key is now based on the new version of server env Key belong to a specifiv database that can be requested based on the domain name. Just setup the db_filter with "%d^" to filter based on domain name --- auth_api_key/__manifest__.py | 2 +- auth_api_key/models/auth_api_key.py | 64 +++++++++++------------ auth_api_key/models/ir_http.py | 8 +-- auth_api_key/security/ir.model.access.csv | 2 + 4 files changed, 39 insertions(+), 37 deletions(-) create mode 100644 auth_api_key/security/ir.model.access.csv diff --git a/auth_api_key/__manifest__.py b/auth_api_key/__manifest__.py index 896e30b8a9..c75d1f01c0 100644 --- a/auth_api_key/__manifest__.py +++ b/auth_api_key/__manifest__.py @@ -12,6 +12,6 @@ "website": "https://acsone.eu/", "development_status": "Beta", "depends": ["server_environment"], - "data": [], + "data": ['security/ir.model.access.csv'], "demo": [], } diff --git a/auth_api_key/models/auth_api_key.py b/auth_api_key/models/auth_api_key.py index e767ff833a..df979551d4 100644 --- a/auth_api_key/models/auth_api_key.py +++ b/auth_api_key/models/auth_api_key.py @@ -1,7 +1,7 @@ # Copyright 2018 ACSONE SA/NV # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). -from odoo import api, models, tools, _ +from odoo import api, fields, models, tools, _ from odoo.tools import consteq @@ -15,52 +15,52 @@ class AuthApiKey(models.Model): name = fields.Char(required=True) key = fields.Char(required=True) - user = fields.Char(required=True) - - _sql_constraints = [ - ('key_uniq', 'unique(key)', 'API Key Retriever must be unique !'), - ] + user_id = fields.Many2one( + comodel_name="res.users", + string="User", + required=True) @property def _server_env_fields(self): base_fields = super()._server_env_fields api_key_fields = { "key": {}, - "user": {}, } api_key_fields.update(base_fields) return api_key_fields @api.model - @tools.ormcache("api_key") - def _retrieve_api_key(self, api_key): + 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")) - ap_keys = self.search([]) - # api key are a computed field in the context of server env - # so we can't use a domain in search method - key = False - for ap_key in ap_keys: - if consteq(api_key, ap_key.key): - key = ap_key - - if not key: - raise ValidationError( - _("The key %s is not defined") % api_key) - - return key + for api_key in self.search([]): + if consteq(key, api_key.key): + return api_key.id + raise ValidationError(_("The key %s is not allowed") % key) @api.model - @tools.ormcache("api_key") - def _retrieve_uid_from_api_key(self, api_key): - ap_key = self._retrieve_api_key(api_key) - uid = self.env["res.users"].search( - [("login", "=", ap_key.user)]).id + @tools.ormcache("key") + def _retrieve_uid_from_api_key(self, key): + return self._retrieve_api_key(key).user_id.id - if not uid: - raise ValidationError( - _("No user found with login %s") % ap_key.user) + def _clear_key_cache(self): + self._retrieve_api_key_id.clear_cache() + self._retrieve_uid_from_api_key.clear_cache() - return uid - return False + @api.model + def create(self, vals): + record = super(AuthApikey, self).create(vals) + if 'key' in vals: + self._clear_key_cache() + return record + def write(self, vals): + super(AuthApikey, self).write(vals) + if 'key' 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 index 1e6638a07d..f28183abb0 100644 --- a/auth_api_key/models/ir_http.py +++ b/auth_api_key/models/ir_http.py @@ -22,16 +22,16 @@ def _auth_method_api_key(cls): api_key = headers.get("HTTP_API_KEY") if api_key: request.uid = 1 - uid = request.env["auth.api.key"]._retrieve_uid_from_api_key( - api_key) - if uid: + api = request.env["auth.api.key"]._retrieve_api_key(api_key) + if api: # 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.uid = uid + request.uid = api.user_id.id request.auth_api_key = api_key + request.auth_api_key_id = api.id return True _logger.error("Wrong HTTP_API_KEY, access denied") raise AccessDenied() 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 From dc93895908d7619e7280ddc883dcc1726e074bda Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 29 Jul 2019 03:37:25 +0000 Subject: [PATCH 22/76] [UPD] README.rst --- auth_api_key/static/description/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth_api_key/static/description/index.html b/auth_api_key/static/description/index.html index f70369a5af..8a5bd04cac 100644 --- a/auth_api_key/static/description/index.html +++ b/auth_api_key/static/description/index.html @@ -3,7 +3,7 @@ - + Auth Api Key