[MIG] Migrate letsencrypt 2.0.0 to Odoo 11.0

pull/2236/head
Jan Verbeek 2020-04-22 19:39:48 +02:00 committed by Ronald Portier
parent 1428743f50
commit 11623a869c
12 changed files with 121 additions and 71 deletions

View File

@ -14,13 +14,13 @@ Let's Encrypt
: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--tools-lightgray.png?logo=github
:target: https://github.com/OCA/server-tools/tree/10.0/letsencrypt
:target: https://github.com/OCA/server-tools/tree/11.0/letsencrypt
:alt: OCA/server-tools
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-tools-10-0/server-tools-10-0-letsencrypt
:target: https://translation.odoo-community.org/projects/server-tools-11-0/server-tools-11-0-letsencrypt
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/149/10.0
:target: https://runbot.odoo-community.org/runbot/149/11.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@ -148,7 +148,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/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 <https://github.com/OCA/server-tools/issues/new?body=module:%20letsencrypt%0Aversion:%2010.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/server-tools/issues/new?body=module:%20letsencrypt%0Aversion:%2011.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.
@ -160,6 +160,7 @@ Authors
* Therp BV
* Tecnativa
* Acysos S.L
Contributors
~~~~~~~~~~~~
@ -198,6 +199,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-tools <https://github.com/OCA/server-tools/tree/10.0/letsencrypt>`_ project on GitHub.
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/11.0/letsencrypt>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@ -16,7 +16,7 @@
"data": [
"data/ir_config_parameter.xml",
"data/ir_cron.xml",
"views/base_config_settings.xml",
"views/res_config_settings.xml",
],
"demo": [
"demo/ir_cron.xml",

View File

@ -16,9 +16,6 @@
forcecreate="True">
<field name="key">letsencrypt.backoff</field>
<field name="value">3</field>
<field
name="group_ids"
eval="[(6, False, [ref('base.group_system')])]"/>
</record>
</data>

View File

@ -6,6 +6,10 @@ from odoo import api, SUPERUSER_ID
def migrate_altnames(env):
config = env["ir.config_parameter"]
existing = config.search([("key", "=like", "letsencrypt.altname.%")])
if not existing:
# We may be migrating from 10.0.2.0.0, in which case
# letsencrypt.altnames already exists and shouldn't be clobbered.
return
new_domains = "\n".join(existing.mapped("value"))
config.set_param("letsencrypt.altnames", new_domains)
existing.unlink()
@ -18,14 +22,18 @@ def migrate_cron(env):
jobs = (
env["ir.cron"]
.with_context(active_test=False)
.search([("model", "=", "letsencrypt"), ("function", "=", "cron")])
.search(
[
("ir_actions_server_id.model_id.model", "=", "letsencrypt"),
("ir_actions_server_id.code", "=", "model.cron()"),
]
)
)
if not jobs:
# ir.cron._try_lock doesn't handle empty recordsets well
return
jobs.write(
{"function": "_cron", "interval_type": "days", "interval_number": "1"}
)
jobs.write({"interval_type": "days", "interval_number": "1"})
jobs.mapped("ir_actions_server_id").write({"code": "model._cron()"})
def migrate(cr, version):

View File

@ -1,4 +1,4 @@
# © 2016 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import letsencrypt
from . import base_config_settings
from . import res_config_settings

View File

@ -10,7 +10,7 @@ import os
import re
import subprocess
import time
import urlparse
import urllib.parse
from datetime import datetime, timedelta
@ -197,7 +197,7 @@ class Letsencrypt(models.AbstractModel):
def _cron(self):
ir_config_parameter = self.env['ir.config_parameter']
base_url = ir_config_parameter.get_param('web.base.url', 'localhost')
domain = urlparse.urlparse(base_url).hostname
domain = urllib.parse.urlparse(base_url).hostname
cert_file = os.path.join(_get_data_dir(), '%s.crt' % domain)
domains = self._cascade_domains([domain] + self._get_altnames())
@ -403,7 +403,7 @@ class Letsencrypt(models.AbstractModel):
Respond to the HTTP challenge by writing the file to serve.
"""
token = self._base64_encode(challenge.token)
challenge_file = os.path.join(_get_challenge_dir(), token.decode())
challenge_file = os.path.join(_get_challenge_dir(), token)
with open(challenge_file, 'w') as file_:
file_.write(challenge.validation(account_key))

View File

@ -10,8 +10,8 @@ DNS_SCRIPT_DEFAULT = """# Write your script here
"""
class BaseConfigSettings(models.TransientModel):
_inherit = 'base.config.settings'
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
letsencrypt_altnames = fields.Text(
string="Domain names",
@ -69,7 +69,7 @@ class BaseConfigSettings(models.TransientModel):
@api.model
def default_get(self, fields_list):
res = super(BaseConfigSettings, self).default_get(fields_list)
res = super().default_get(fields_list)
get_param = self.env['ir.config_parameter'].get_param
res.update(
{
@ -97,8 +97,9 @@ class BaseConfigSettings(models.TransientModel):
return res
@api.multi
def set_dns_provider(self):
self.ensure_one()
def set_values(self):
super().set_values()
self.letsencrypt_check_dns_required()
if self.letsencrypt_dns_provider == 'shell':

View File

@ -2,5 +2,6 @@
* Antonio Espinosa <antonio.espinosa@tecnativa.com>
* Dave Lasley <dave@laslabs.com>
* Ronald Portier <ronald@therp.nl>
* Ignacio Ibeas <ignacio@acysos.com>
* George Daramouskas <gdaramouskas@therp.nl>
* Jan Verbeek <jverbeek@therp.nl>

View File

@ -367,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" 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" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/server-tools/tree/10.0/letsencrypt"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/server-tools-10-0/server-tools-10-0-letsencrypt"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/149/10.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external" 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" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/server-tools/tree/11.0/letsencrypt"><img alt="OCA/server-tools" src="https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/server-tools-11-0/server-tools-11-0-letsencrypt"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/149/11.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module was written to have your Odoo installation request SSL certificates
from <a class="reference external" href="https://letsencrypt.org">https://letsencrypt.org</a> automatically.</p>
<p><strong>Table of contents</strong></p>
@ -490,7 +490,7 @@ For example, <tt class="docutils literal"><span class="pre">--load=web,letsencry
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/server-tools/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 smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/server-tools/issues/new?body=module:%20letsencrypt%0Aversion:%2010.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<a class="reference external" href="https://github.com/OCA/server-tools/issues/new?body=module:%20letsencrypt%0Aversion:%2011.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">
@ -500,6 +500,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<ul class="simple">
<li>Therp BV</li>
<li>Tecnativa</li>
<li>Acysos S.L</li>
</ul>
</div>
<div class="section" id="contributors">
@ -509,6 +510,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<li>Antonio Espinosa &lt;<a class="reference external" href="mailto:antonio.espinosa&#64;tecnativa.com">antonio.espinosa&#64;tecnativa.com</a>&gt;</li>
<li>Dave Lasley &lt;<a class="reference external" href="mailto:dave&#64;laslabs.com">dave&#64;laslabs.com</a>&gt;</li>
<li>Ronald Portier &lt;<a class="reference external" href="mailto:ronald&#64;therp.nl">ronald&#64;therp.nl</a>&gt;</li>
<li>Ignacio Ibeas &lt;<a class="reference external" href="mailto:ignacio&#64;acysos.com">ignacio&#64;acysos.com</a>&gt;</li>
<li>George Daramouskas &lt;<a class="reference external" href="mailto:gdaramouskas&#64;therp.nl">gdaramouskas&#64;therp.nl</a>&gt;</li>
<li>Jan Verbeek &lt;<a class="reference external" href="mailto:jverbeek&#64;therp.nl">jverbeek&#64;therp.nl</a>&gt;</li>
</ul>
@ -535,7 +537,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<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-tools/tree/10.0/letsencrypt">OCA/server-tools</a> project on GitHub.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/server-tools/tree/11.0/letsencrypt">OCA/server-tools</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>

View File

@ -1,8 +1,6 @@
# Copyright 2018 Therp BV <http://therp.nl>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from __future__ import unicode_literals # cryptography is picky
import os
import shutil
@ -28,21 +26,21 @@ def _poll(order, deadline):
class TestLetsencrypt(SingleTransactionCase):
def setUp(self):
super(TestLetsencrypt, self).setUp()
super().setUp()
self.env['ir.config_parameter'].set_param(
'web.base.url', 'http://www.example.com'
)
self.env['base.config.settings'].create(
self.env['res.config.settings'].create(
{
'letsencrypt_dns_provider': 'shell',
'letsencrypt_dns_shell_script': 'touch /tmp/.letsencrypt_test',
'letsencrypt_altnames': '*.example.com',
'letsencrypt_reload_command': 'true', # i.e. /bin/true
}
).set_dns_provider()
).set_values()
def test_config_settings(self):
setting_vals = self.env['base.config.settings'].default_get([])
setting_vals = self.env['res.config.settings'].default_get([])
self.assertEqual(setting_vals['letsencrypt_dns_provider'], 'shell')
self.assertEqual(
setting_vals['letsencrypt_dns_shell_script'],
@ -57,9 +55,9 @@ class TestLetsencrypt(SingleTransactionCase):
@mock.patch('acme.client.ClientV2.poll_and_finalize', side_effect=_poll)
def test_http_challenge(self, poll, answer_challenge):
letsencrypt = self.env['letsencrypt']
self.env['base.config.settings'].create(
self.env['res.config.settings'].create(
{'letsencrypt_altnames': 'test.example.com'}
).set_dns_provider()
).set_values()
letsencrypt._cron()
poll.assert_called()
self.assertTrue(os.listdir(_get_challenge_dir()))
@ -98,22 +96,22 @@ class TestLetsencrypt(SingleTransactionCase):
)
def test_dns_challenge_error_on_missing_provider(self):
self.env['base.config.settings'].create(
self.env['res.config.settings'].create(
{
'letsencrypt_altnames': '*.example.com',
'letsencrypt_dns_provider': False,
}
).set_dns_provider()
).set_values()
with self.assertRaises(UserError):
self.env['letsencrypt']._cron()
def test_prefer_dns_setting(self):
self.env['base.config.settings'].create(
self.env['res.config.settings'].create(
{
'letsencrypt_altnames': 'example.com',
'letsencrypt_prefer_dns': True,
}
).set_dns_provider()
).set_values()
self.env['ir.config_parameter'].set_param(
'web.base.url', 'http://example.com'
)
@ -327,7 +325,7 @@ class TestLetsencrypt(SingleTransactionCase):
file_.write(cert.public_bytes(serialization.Encoding.PEM))
def tearDown(self):
super(TestLetsencrypt, self).tearDown()
super().tearDown()
shutil.rmtree(_get_data_dir(), ignore_errors=True)
if path.isfile('/tmp/.letsencrypt_test'):
os.remove('/tmp/.letsencrypt_test')

View File

@ -1,33 +0,0 @@
<odoo>
<record id="base_config_settings" model="ir.ui.view">
<field name="name">Letsencrypt base config settings</field>
<field name="model">base.config.settings</field>
<field name="inherit_id" ref="base_setup.view_general_configuration" />
<field name="arch" type="xml">
<xpath expr="./group[last()]" position="after">
<group name="letsencrypt">
<group name="letsencrypt" string="Let's Encrypt">
<field
name="letsencrypt_needs_dns_provider"
readonly="1"
invisible="1"/>
<field
name="letsencrypt_dns_provider"
attrs="{'required':
[('letsencrypt_needs_dns_provider', '=', True)]}" />
<field
name="letsencrypt_dns_shell_script"
attrs="{
'required': [('letsencrypt_dns_provider', '=', 'shell')],
'invisible': [('letsencrypt_dns_provider', '!=', 'shell')],
}" />
<field name="letsencrypt_altnames" />
<field name="letsencrypt_reload_command" />
<field name="letsencrypt_testing_mode" />
<field name="letsencrypt_prefer_dns" />
</group>
</group>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,75 @@
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">Letsencrypt settings view</field>
<field name="model">res.config.settings</field>
<field name="inherit_id"
ref="base_setup.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[hasclass('settings')]" position="inside">
<div class="app_settings_block"
data-string="Let's Encrypt"
string="Let's Encrypt"
data-key="letsencrypt">
<div id="letsencrypt_settings">
<h2>Let's Encrypt</h2>
<field
name="letsencrypt_needs_dns_provider"
readonly="1"
invisible="1"/>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-12 o_setting_box">
<div class="o_setting_right_pane">
<label for="letsencrypt_altnames"/>
<div class="text-muted">List additional domains for the certificate</div>
<field name="letsencrypt_altnames" />
</div>
<div class="o_setting_right_pane">
<label for="letsencrypt_reload_command"/>
<div class="text-muted">Write a command to reload the server</div>
<field name="letsencrypt_reload_command" />
</div>
<div class="o_setting_right_pane">
<label for="letsencrypt_dns_provider"/>
<div class="text-muted">Set a DNS provider if you need wildcard certificates</div>
<div class="content-group">
<div class="mt16 row">
<label for="letsencrypt_dns_provider"
class="col-xs-3 col-md-3 o_light_label"/>
<field
class="oe_inline"
name="letsencrypt_dns_provider"
attrs="{'required': [('letsencrypt_needs_dns_provider', '=', True)]}" />
</div>
</div>
</div>
<span id="letsencrypt_dns_provider_settings">
<div class="o_setting_right_pane"
attrs="{'invisible': [('letsencrypt_dns_provider', '!=', 'shell')]}">
<label for="letsencrypt_dns_shell_script" />
<div class="text-muted">Write a shell script to update your DNS records</div>
<field name="letsencrypt_dns_shell_script"
attrs="{'required': [('letsencrypt_dns_provider', '=', 'shell')]}" />
</div>
</span>
<div class="o_setting_left_pane">
<field name="letsencrypt_testing_mode" />
</div>
<div class="o_setting_right_pane">
<label for="letsencrypt_testing_mode"/>
<div class="text-muted">Use the testing server, which has higher rate limits but creates invalid certificates.</div>
</div>
<div class="o_setting_left_pane">
<field name="letsencrypt_prefer_dns" />
</div>
<div class="o_setting_right_pane">
<label for="letsencrypt_prefer_dns"/>
<div class="text-muted">Validate through DNS even when HTTP validation is possible. Use this if your Odoo instance isn't publicly accessible.</div>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>