fixup! [ADD] server_environment_iap

This commit is contained in:
Maksym Yankin 2021-12-28 19:00:51 +02:00
parent 4aae255531
commit 383f877097
10 changed files with 96 additions and 174 deletions

View File

@ -2,15 +2,12 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
"name": "Server Environment IAP Account", "name": "IAP Account configuration with server_environment",
"summary": """ "summary": "Configure IAP Account with server_environment_files",
Override IAP Accounts from server environment file""",
"version": "14.0.1.0.0", "version": "14.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"author": "Camptocamp, Odoo Community Association (OCA)", "author": "Camptocamp, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/server-env", "website": "https://github.com/OCA/server-env",
"depends": ["iap", "server_environment"], "depends": ["iap", "server_environment"],
"data": [ "data": ["views/iap_views.xml"],
"views/iap_views.xml",
],
} }

View File

@ -1,70 +1,31 @@
# Copyright 2021 Camptocamp SA <https://www.camptocamp.com/> # Copyright 2021 Camptocamp SA <https://www.camptocamp.com/>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
from odoo import _, api, fields, models from odoo import api, models
from odoo.exceptions import UserError
from odoo.addons.server_environment.server_env import serv_config
SECTION = "iap.account"
class IapAccount(models.Model): class IapAccount(models.Model):
_name = "iap.account"
_inherit = [
"iap.account",
"server.env.techname.mixin",
"server.env.mixin",
]
_inherit = "iap.account" @property
def _server_env_fields(self):
is_environment = fields.Boolean( base_fields = super()._server_env_fields
string="Defined by environment", iap_fields = {
compute="_compute_is_environment", "service_name": {},
help="If check, the value in the database will be ignored" "account_token": {},
" and alternatively, the system will use the service name defined" }
" in your odoo.cfg environment file.", iap_fields.update(base_fields)
) return iap_fields
def _compute_is_environment(self):
for account in self:
account.is_environment = serv_config.has_option(
SECTION, account.service_name
)
@api.model @api.model
def get(self, service_name, force_create=True): def _server_env_global_section_name(self):
account = super().get(service_name, force_create=True) """Name of the global section in the configuration files
if serv_config.has_option(SECTION, service_name):
cvalue = serv_config.get(SECTION, service_name)
if not cvalue:
# if service name is empty it's probably not a production instance,
# so we need to remove it from database
account.unlink()
raise UserError(
_("Service name %s is empty in " "server_environment_file")
% (service_name,)
)
if cvalue != account.account_token:
# we write in db on first access;
# should we have preloaded values in database at,
# server startup, modules loading their parameters
# from data files would break on unique key error.
account.account_token = cvalue
return account
@api.model Can be customized in your model
def create(self, vals): """
service_name = vals.get("service_name") return "iap_account"
if serv_config.has_option(SECTION, service_name):
# enforce account_token from config file
vals = dict(vals, account_token=serv_config.get(SECTION, service_name))
return super().create(vals)
def write(self, vals):
for rec in self:
service_name = vals.get("service_name") or rec.service_name
if serv_config.has_option(SECTION, service_name):
# enforce account_token from config file
newvals = dict(
vals, account_token=serv_config.get(SECTION, service_name)
)
else:
newvals = vals
super().write(newvals)
return True

View File

@ -1,16 +1,4 @@
To configure this module, you need to add a section ``[iap.account]`` to With this module installed, the IAP Accounts can be configured
you server_environment_files configurations, where the keys are service names in the `server_environment_files` module, or in the environment variable ``SERVER_ENV_CONFIG``
as would normally be set in the Technical / IAP Accounts Odoo menu. and/or ``SERVER_ENV_CONFIG_SECRET``. See the documentation of `server_environment` for
more information.
When first using a value, the system will read it from the server environment file
and override any value that would be present in the database, so the server environment file has precedence.
When creating or modifying values that are in the server environment file, the
module replace changes, enforcing the configuration value.
For example you can use this module like that:
.. code::
[iap.account]
partner_autocomplete=secret_token

View File

@ -1,2 +0,0 @@
This module is maintained by:
* Odoo Community Association

View File

@ -1 +1,3 @@
Override IAP Accounts from the server environment file. This module allows to configure the IAP Accounts
using the `server_environment` mechanism: you can then have different
IAP Accounts for the production and the test environment.

View File

@ -1,2 +1,2 @@
It would be nice to set IAP Accounts in the server environment file, possibly make their key and value * Due to the special nature of this addon, you cannot test it on the OCA
readonly in the user interface and remove them from database except production. runbot.

View File

@ -1,2 +0,0 @@
Before using this module, you must be familiar with the
server_environment module.

View File

@ -1,5 +1,6 @@
<odoo> <odoo>
<record model="iap.account" id="some_record_id"> <record model="iap.account" id="some_record_id">
<field name="tech_name">account_xml</field>
<field name="service_name">iap_from_config</field> <field name="service_name">iap_from_config</field>
<field name="account_token">value_from_xml</field> <field name="account_token">value_from_xml</field>
</record> </record>

View File

@ -1,28 +1,30 @@
# Copyright 2016-2018 ACSONE SA/NV # Copyright 2016-2018 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import psycopg2
from odoo.exceptions import UserError
from odoo.modules.module import get_resource_path from odoo.modules.module import get_resource_path
from odoo.tests import tagged from odoo.tests.common import Form
from odoo.tools import convert_file from odoo.tools import convert_file
from odoo.tools.misc import mute_logger
from odoo.addons.server_environment.tests.common import ServerEnvironmentCase from odoo.addons.server_environment.tests.common import ServerEnvironmentCase
from ..models import iap_account
@tagged("post_install", "-at_install")
class TestEnv(ServerEnvironmentCase): class TestEnv(ServerEnvironmentCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.IAP = self.env["iap.account"] self.IAP = self.env["iap.account"]
self.env_config = ( self.env_config = (
"[iap.account]\n" "iap_from_config=config_value\n" "iap_empty=\n" "[iap_account.account_1]\n"
"service_name=partner_autocomplete_1\n"
"account_token=my_secret_token_1\n"
"[iap_account.account_2]\n"
"service_name=partner_autocomplete_2\n"
"account_token=my_secret_token_2\n"
"[iap_account.account_xml]\n"
"service_name=partner_autocomplete_xml\n"
"account_token=my_secret_token_xml\n"
) )
self.service_name = "iap_from_config"
self.account_token = "config_value"
self.some_service = "some.service"
self.some_token = "some.token"
def _load_xml(self, module, filepath): def _load_xml(self, module, filepath):
convert_file( convert_file(
@ -35,67 +37,51 @@ class TestEnv(ServerEnvironmentCase):
kind="test", kind="test",
) )
def _search_account(self, service, token): def test_create_account_from_config(self):
return self.IAP.search(
[("service_name", "=", service), ("account_token", "=", token)]
)
def test_empty(self):
"""Empty config values cause error"""
with self.load_config(public=self.env_config, serv_config_class=iap_account):
with self.assertRaises(UserError):
self.IAP.get("iap_empty")
iap_nonexistant = self.IAP.get("iap_nonexistant")
self.assertTrue(iap_nonexistant.account_token)
def test_get_account(self):
"""Get account data from config""" """Get account data from config"""
with self.load_config(public=self.env_config, serv_config_class=iap_account): with self.load_config(public=self.env_config):
# it's not in db account = self.IAP.create({"tech_name": "account_1"})
res = self._search_account(self.service_name, self.account_token) self.assertEqual(account.service_name, "partner_autocomplete_1")
self.assertFalse(res) self.assertEqual(account.account_token, "my_secret_token_1")
# read so it's created in db # `tech_name` must be unique
account = self.IAP.get("iap_from_config") with self.assertRaises(psycopg2.IntegrityError):
self.assertEqual(account.account_token, "config_value") with mute_logger("odoo.sql_db"), self.cr.savepoint():
self.assertEqual(len(account), 1) self.IAP.create({"tech_name": "account_1"})
def test_override_xmldata(self): def test_create_account_not_in_config(self):
with self.load_config(public=self.env_config, serv_config_class=iap_account): """We can set account data that is not in config file"""
self._load_xml("server_environment_iap", "tests/config_iap_test.xml") with self.load_config(public=self.env_config):
self.assertEqual( account = self.IAP.create(
self.IAP.get("iap_from_config").account_token, "config_value" {
"tech_name": "account_4",
"service_name": "new_partner_autocomplete",
"account_token": "my_new_secret_token",
}
) )
self.assertEqual(account.service_name, "new_partner_autocomplete")
self.assertEqual(account.account_token, "my_new_secret_token")
def test_set_param_1(self): # TODO: should it be overriden on xml import?
# def test_override_xmldata(self):
# with self.load_config(public=self.env_config):
# self._load_xml("server_environment_iap", "tests/config_iap_test.xml")
# account = self.IAP.search([("tech_name", "=", "account_xml")])
# self.assertEqual(account.service_name, "partner_autocomplete_xml")
# self.assertEqual(account.account_token, "my_secret_token_xml")
def test_update_account_data(self):
"""We can't set account data that is in config file""" """We can't set account data that is in config file"""
with self.load_config(public=self.env_config, serv_config_class=iap_account): with self.load_config(public=self.env_config):
# when creating, the value is overridden by config file # when creating, the value is overridden by config file
self.IAP.create( account = self.IAP.create(
{"service_name": "iap_from_config", "account_token": "new_value"} {
"tech_name": "account_2",
}
) )
acc = self.IAP.get("iap_from_config") account_form = Form(account)
self.assertEqual(acc.account_token, "config_value") self.assertEqual(account.service_name, "partner_autocomplete_2")
# when writing, the value is overridden by config file self.assertEqual(account.account_token, "my_secret_token_2")
res = self._search_account(self.service_name, self.account_token) with self.assertRaises(AssertionError):
self.assertEqual(len(res), 1) account_form.service_name = "new_partner_autocomplete"
res.write({"account_token": "new_value"}) with self.assertRaises(AssertionError):
acc = self.IAP.get("iap_from_config") account_form.account_token = "my_new_secret_token"
self.assertEqual(acc.account_token, "config_value")
# unlink works normally...
res = self._search_account(self.service_name, self.account_token)
self.assertEqual(len(res), 1)
res.unlink()
res = self._search_account(self.service_name, self.account_token)
self.assertEqual(len(res), 0)
# but the value is recreated when getting param again
acc = self.IAP.get("iap_from_config")
self.assertEqual(acc.account_token, "config_value")
self.assertEqual(len(acc), 1)
def test_set_param_2(self):
"""We can set parameters that are not in config file"""
with self.load_config(public=self.env_config, serv_config_class=iap_account):
self.IAP.create(
{"service_name": "some.service", "account_token": "some.token"}
)
self.assertEqual(self.IAP.get("some.service").account_token, "some.token")

View File

@ -1,34 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<odoo> <odoo>
<record id="iap_account_view_form" model="ir.ui.view"> <record id="iap_account_view_form" model="ir.ui.view">
<field name="name">iap.account.form.inherit</field>
<field name="model">iap.account</field> <field name="model">iap.account</field>
<field name="inherit_id" ref="iap.iap_account_view_form" /> <field name="inherit_id" ref="iap.iap_account_view_form" />
<field name="groups_id" eval="[(4, ref('base.group_system'))]" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="account_token" position="after"> <field name="service_name" position="before">
<field name="is_environment" /> <field name="tech_name" groups="base.group_no_one" />
</field>
<field name="service_name" position="attributes">
<attribute
name="attrs"
>{'readonly': [('is_environment', '=', True)]}</attribute>
</field>
<field name="account_token" position="attributes">
<attribute
name="attrs"
>{'readonly': [('is_environment', '=', True)]}</attribute>
</field> </field>
</field> </field>
</record> </record>
<record id="iap_account_view_tree" model="ir.ui.view"> <record id="iap_account_view_tree" model="ir.ui.view">
<field name="name">iap.account.tree.inherit</field>
<field name="model">iap.account</field> <field name="model">iap.account</field>
<field name="inherit_id" ref="iap.iap_account_view_tree" /> <field name="inherit_id" ref="iap.iap_account_view_tree" />
<field name="groups_id" eval="[(4, ref('base.group_system'))]" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="account_token" position="after"> <field name="service_name" position="before">
<field name="is_environment" /> <field name="tech_name" groups="base.group_no_one" />
</field> </field>
</field> </field>
</record> </record>
</odoo> </odoo>