Initial commit: OCA Server Auth packages (29 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:06 +02:00
commit 3ed80311c4
1325 changed files with 127292 additions and 0 deletions

View file

@ -0,0 +1,46 @@
# Auth Api Key
Odoo addon: auth_api_key
## Installation
```bash
pip install odoo-bringout-oca-server-auth-auth_api_key
```
## Dependencies
This addon depends on:
## Manifest Information
- **Name**: Auth Api Key
- **Version**: 16.0.1.0.1
- **Category**: N/A
- **License**: LGPL-3
- **Installable**: False
## Source
Based on [OCA/server-auth](https://github.com/OCA/server-auth) branch 16.0, addon `auth_api_key`.
## License
This package maintains the original LGPL-3 license from the upstream Odoo project.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Reports: doc/REPORTS.md
- Security: doc/SECURITY.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md

View file

@ -0,0 +1,114 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association
============
Auth Api Key
============
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:1d519ddd25033f9a32033563edf36cc5df3ef91de4d6555d4889bf2f44c62cb9
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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/license-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/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/server-auth&target_branch=16.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-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 <https://github.com/OCA/server-auth/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 <https://github.com/OCA/server-auth/issues/new?body=module:%20auth_api_key%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* ACSONE SA/NV
Contributors
~~~~~~~~~~~~
* Denis Robinet <denis.robinet@acsone.eu>
* Laurent Mignon <laurent.mignon@acsone.eu>
* Quentin Groulard <quentin.groulard@acsone.eu>
* Sébastien Beau <sebastien.beau@akretion.com>
* Chafique Delli <chafique.delli@akretion.com>
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 <https://github.com/OCA/server-auth/tree/16.0/auth_api_key>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1 @@
from . import models

View file

@ -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.1",
"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"],
}

View file

@ -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 ""

View file

@ -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 "API ključ"
#. 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 "Naziv API ključa mora biti jedinstven."
#. 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 "Auth API ključ"
#. module: auth_api_key
#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__create_uid
msgid "Created by"
msgstr "Kreirao"
#. module: auth_api_key
#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__create_date
msgid "Created on"
msgstr "Kreirano"
#. module: auth_api_key
#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__display_name
msgid "Display Name"
msgstr "Prikazani naziv"
#. module: auth_api_key
#: model:ir.model,name:auth_api_key.model_ir_http
msgid "HTTP Routing"
msgstr "HTTP usmjeravanje"
#. 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 "Ključ"
#. module: auth_api_key
#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key____last_update
msgid "Last Modified on"
msgstr "Zadnje mijenjano"
#. module: auth_api_key
#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__write_uid
msgid "Last Updated by"
msgstr "Zadnji ažurirao"
#. module: auth_api_key
#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__write_date
msgid "Last Updated on"
msgstr "Zadnje ažurirano"
#. module: auth_api_key
#: model:ir.model.fields,field_description:auth_api_key.field_auth_api_key__name
msgid "Name"
msgstr "Naziv:"
#. 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 "Ključ %s nije dozvoljen"
#. 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 "Korisnik"
#. 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 "Korisnik nije dozvoljen"

View file

@ -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: 2024-08-17 18:58+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\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____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"

View file

@ -0,0 +1,2 @@
from . import ir_http
from . import auth_api_key

View file

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

View file

@ -0,0 +1,37 @@
# Copyright 2018 ACSONE SA/NV
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
import logging
from werkzeug.exceptions import Unauthorized
from odoo import models
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 Unauthorized()

View file

@ -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`.

View file

@ -0,0 +1,5 @@
* Denis Robinet <denis.robinet@acsone.eu>
* Laurent Mignon <laurent.mignon@acsone.eu>
* Quentin Groulard <quentin.groulard@acsone.eu>
* Sébastien Beau <sebastien.beau@akretion.com>
* Chafique Delli <chafique.delli@akretion.com>

View file

@ -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.

View file

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

View file

@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_auth_api_key access_auth_api_key model_auth_api_key base.group_system 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,458 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>README.rst</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document">
<a class="reference external image-reference" href="https://odoo-community.org/get-involved?utm_source=readme">
<img alt="Odoo Community Association" src="https://odoo-community.org/readme-banner-image" />
</a>
<div class="section" id="auth-api-key">
<h1>Auth Api Key</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:1d519ddd25033f9a32033563edf36cc5df3ef91de4d6555d4889bf2f44c62cb9
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/license-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/server-auth/tree/16.0/auth_api_key"><img alt="OCA/server-auth" src="https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/server-auth-16-0/server-auth-16-0-auth_api_key"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/server-auth&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>Authenticate http requests from an API key.</p>
<p>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 programs user.</p>
<p>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.</p>
<p>For unknown sources, it is a good practice to filter out this header at proxy level.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h2><a class="toc-backref" href="#toc-entry-1">Configuration</a></h2>
<p>The api key menu is available into Settings &gt; Technical in debug mode.
By default, when you create an API key, the key is saved into the database.</p>
<p>If you want to manage them via serve environment settings use <cite>auth_api_key_server_env</cite>.</p>
</div>
<div class="section" id="usage">
<h2><a class="toc-backref" href="#toc-entry-2">Usage</a></h2>
<p>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.</p>
<pre class="code python literal-block">
<span class="k">class</span><span class="w"> </span><span class="nc">MyController</span><span class="p">(</span><span class="n">Controller</span><span class="p">):</span><span class="w">
</span> <span class="nd">&#64;route</span><span class="p">(</span><span class="s1">'/my_service'</span><span class="p">,</span> <span class="n">auth</span><span class="o">=</span><span class="s1">'api_key'</span><span class="p">,</span> <span class="o">...</span><span class="p">)</span><span class="w">
</span> <span class="k">def</span><span class="w"> </span><span class="nf">my_service</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span><span class="w">
</span> <span class="k">pass</span>
</pre>
</div>
<div class="section" id="bug-tracker">
<h2><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h2>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-auth/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/server-auth/issues/new?body=module:%20auth_api_key%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h2><a class="toc-backref" href="#toc-entry-4">Credits</a></h2>
<div class="section" id="authors">
<h3><a class="toc-backref" href="#toc-entry-5">Authors</a></h3>
<ul class="simple">
<li>ACSONE SA/NV</li>
</ul>
</div>
<div class="section" id="contributors">
<h3><a class="toc-backref" href="#toc-entry-6">Contributors</a></h3>
<ul class="simple">
<li>Denis Robinet &lt;<a class="reference external" href="mailto:denis.robinet&#64;acsone.eu">denis.robinet&#64;acsone.eu</a>&gt;</li>
<li>Laurent Mignon &lt;<a class="reference external" href="mailto:laurent.mignon&#64;acsone.eu">laurent.mignon&#64;acsone.eu</a>&gt;</li>
<li>Quentin Groulard &lt;<a class="reference external" href="mailto:quentin.groulard&#64;acsone.eu">quentin.groulard&#64;acsone.eu</a>&gt;</li>
<li>Sébastien Beau &lt;<a class="reference external" href="mailto:sebastien.beau&#64;akretion.com">sebastien.beau&#64;akretion.com</a>&gt;</li>
<li>Chafique Delli &lt;<a class="reference external" href="mailto:chafique.delli&#64;akretion.com">chafique.delli&#64;akretion.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h3><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h3>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-auth/tree/16.0/auth_api_key">OCA/server-auth</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1 @@
from . import test_auth_api_key

View file

@ -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")

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 ACSONE SA/NV
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="auth_api_key_form_view">
<field name="name">auth.api.key.form (in auth_api_key)</field>
<field name="model">auth.api.key</field>
<field name="arch" type="xml">
<form create="false" edit="false">
<sheet>
<label for="name" class="oe_edit_only" />
<h1>
<field name="name" class="oe_inline" />
</h1>
<group name="config" colspan="4" col="4">
<field name="user_id" colspan="4" />
<field name="key" colspan="4" />
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="auth_api_key_tree_view">
<field name="name">auth.api.key.tree (in auth_api_key)</field>
<field name="model">auth.api.key</field>
<field name="arch" type="xml">
<tree>
<field name="name" />
<field name="user_id" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="auth_api_key_act_window">
<field name="name">Auth Api Key</field>
<field name="res_model">auth.api.key</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.ui.menu" id="auth_api_key_menu">
<field name="name">Auth Api Key</field>
<field name="parent_id" ref="base.menu_custom" />
<field name="action" ref="auth_api_key_act_window" />
<field name="sequence" eval="100" />
</record>
</odoo>

View file

@ -0,0 +1,32 @@
# Architecture
```mermaid
flowchart TD
U[Users] -->|HTTP| V[Views and QWeb Templates]
V --> C[Controllers]
V --> W[Wizards Transient Models]
C --> M[Models and ORM]
W --> M
M --> R[Reports]
DX[Data XML] --> M
S[Security ACLs and Groups] -. enforces .-> M
subgraph Auth_api_key Module - auth_api_key
direction LR
M:::layer
W:::layer
C:::layer
V:::layer
R:::layer
S:::layer
DX:::layer
end
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
```
Notes
- Views include tree/form/kanban templates and report templates.
- Controllers provide website/portal routes when present.
- Wizards are UI flows implemented with `models.TransientModel`.
- Data XML loads data/demo records; Security defines groups and access.

View file

@ -0,0 +1,3 @@
# Configuration
Refer to Odoo settings for auth_api_key. Configure related models, access rights, and options as needed.

View file

@ -0,0 +1,3 @@
# Controllers
This module does not define custom HTTP controllers.

View file

@ -0,0 +1,3 @@
# Dependencies
No explicit module dependencies declared.

View file

@ -0,0 +1,4 @@
# FAQ
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
- Q: How to enable? A: Start server with --addon auth_api_key or install in UI.

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-server-auth-auth_api_key"
# or
uv pip install odoo-bringout-oca-server-auth-auth_api_key"
```

View file

@ -0,0 +1,13 @@
# Models
Detected core models and extensions in auth_api_key.
```mermaid
classDiagram
class auth_api_key
class ir_http
```
Notes
- Classes show model technical names; fields omitted for brevity.
- Items listed under _inherit are extensions of existing models.

View file

@ -0,0 +1,6 @@
# Overview
Packaged Odoo addon: auth_api_key. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon auth_api_key
- License: LGPL-3

View file

@ -0,0 +1,3 @@
# Reports
This module does not define custom reports.

View file

@ -0,0 +1,34 @@
# Security
Access control and security definitions in auth_api_key.
## Access Control Lists (ACLs)
Model access permissions defined in:
- **[ir.model.access.csv](../auth_api_key/security/ir.model.access.csv)**
- 1 model access rules
## Record Rules
Row-level security rules defined in:
```mermaid
graph TB
subgraph "Security Layers"
A[Users] --> B[Groups]
B --> C[Access Control Lists]
C --> D[Models]
B --> E[Record Rules]
E --> F[Individual Records]
end
```
Security files overview:
- **[ir.model.access.csv](../auth_api_key/security/ir.model.access.csv)**
- Model access permissions (CRUD rights)
Notes
- Access Control Lists define which groups can access which models
- Record Rules provide row-level security (filter records by user/group)
- Security groups organize users and define permission sets
- All security is enforced at the ORM level by Odoo

View file

@ -0,0 +1,5 @@
# Troubleshooting
- Ensure Python and Odoo environment matches repo guidance.
- Check database connectivity and logs if startup fails.
- Validate that dependent addons listed in DEPENDENCIES.md are installed.

View file

@ -0,0 +1,7 @@
# Usage
Start Odoo including this addon (from repo root):
```bash
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon auth_api_key
```

View file

@ -0,0 +1,3 @@
# Wizards
This module does not include UI wizards.

View file

@ -0,0 +1,42 @@
[project]
name = "odoo-bringout-oca-server-auth-auth_api_key"
version = "16.0.0"
description = "Auth Api Key -
Authenticate http requests from an API key"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"requests>=2.25.1"
]
readme = "README.md"
requires-python = ">= 3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Office/Business",
]
[project.urls]
homepage = "https://github.com/bringout/0"
repository = "https://github.com/bringout/0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["auth_api_key"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]