Skip to content

Commit 8e0d23c

Browse files
committed
Merge PR #4875 into 18.0
Signed-off-by pedrobaeza
2 parents 0e5b72b + 16d3f0e commit 8e0d23c

3 files changed

Lines changed: 114 additions & 1 deletion

File tree

l10n_es_aeat/models/aeat_certificate.py

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,34 @@
33
# (c) 2019 Acysos S.L.
44
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
55

6-
from odoo import exceptions, fields, models
6+
import logging
7+
8+
from cryptography.hazmat.primitives.serialization import Encoding
9+
10+
from odoo import api, exceptions, fields, models
11+
12+
_logger = logging.getLogger(__name__)
13+
14+
try:
15+
import cryptography
16+
from cryptography import x509
17+
18+
CRYPTOGRAPHY_VERSION_3 = tuple(map(int, cryptography.__version__.split("."))) >= (
19+
3,
20+
0,
21+
)
22+
if not CRYPTOGRAPHY_VERSION_3:
23+
from cryptography.hazmat.backends import default_backend
24+
25+
def load_pem_x509_certificate(*args, **kwargs):
26+
return x509.load_pem_x509_certificate(
27+
*args, **kwargs, backend=default_backend()
28+
)
29+
30+
else:
31+
load_pem_x509_certificate = x509.load_pem_x509_certificate
32+
except (OSError, ImportError) as err:
33+
_logger.debug(err)
734

835

936
class L10nEsAeatCertificate(models.Model):
@@ -20,6 +47,21 @@ class L10nEsAeatCertificate(models.Model):
2047
date_start = fields.Date(string="Start Date")
2148
date_end = fields.Date(string="End Date")
2249
public_key = fields.Char(readonly=True)
50+
show_public_key = fields.Boolean(store=False)
51+
public_key_data = fields.Text(readonly=True, store=False)
52+
public_key_file = fields.Binary(
53+
readonly=True,
54+
store=False,
55+
attachment=False,
56+
compute="_compute_public_key",
57+
groups="l10n_es_aeat.group_account_aeat",
58+
)
59+
public_key_filename = fields.Char(
60+
readonly=True,
61+
store=False,
62+
compute="_compute_public_key",
63+
groups="l10n_es_aeat.group_account_aeat",
64+
)
2365
private_key = fields.Char(readonly=True)
2466
company_id = fields.Many2one(
2567
comodel_name="res.company",
@@ -28,6 +70,37 @@ class L10nEsAeatCertificate(models.Model):
2870
default=lambda self: self.env.company,
2971
)
3072

73+
@api.onchange("show_public_key")
74+
def onchange_public_key_data(self):
75+
if not self.show_public_key:
76+
self.public_key_data = ""
77+
return
78+
with open(self.public_key, "rb") as f:
79+
certificate = load_pem_x509_certificate(f.read())
80+
self.public_key_data = certificate.public_bytes(Encoding.PEM)
81+
82+
def get_public_key_pem(self):
83+
self.ensure_one()
84+
return {
85+
"type": "ir.actions.act_url",
86+
"target": "self",
87+
"url": "/web/content/l10n.es.aeat.certificate/"
88+
f"{self.id}/public_key_file/{self.public_key_filename}?download=true",
89+
}
90+
91+
@api.depends("public_key")
92+
def _compute_public_key(self):
93+
for record in self:
94+
if not record.public_key:
95+
record.public_key_file = False
96+
record.public_key_filename = False
97+
continue
98+
with open(record.public_key, "rb") as f:
99+
certificate = load_pem_x509_certificate(f.read())
100+
public_key = certificate.public_bytes(Encoding.PEM)
101+
record.public_key_filename = f"{record.name}.pem"
102+
record.public_key_file = public_key
103+
31104
def load_password_wizard(self):
32105
self.ensure_one()
33106
return {

l10n_es_aeat/tests/test_l10n_es_aeat_certificate.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from cryptography.x509 import oid
1313

1414
from odoo import exceptions
15+
from odoo.tests import Form
1516

1617
from odoo.addons.base.tests.common import BaseCommon
1718

@@ -101,6 +102,9 @@ def setUpClass(cls):
101102
certificate,
102103
cls.certificate_password,
103104
)
105+
cls.public_key = certificate.public_bytes(serialization.Encoding.PEM).decode(
106+
"utf-8"
107+
)
104108
cls.sii_cert = cls.env["l10n.es.aeat.certificate"].create(
105109
{
106110
"folder": "Test folder",
@@ -132,3 +136,25 @@ def test_activate_certificate(self):
132136
)
133137
self._activate_certificate(self.certificate_password)
134138
self.assertEqual(self.sii_cert.state, "active")
139+
140+
def test_show_public_key(self):
141+
self._activate_certificate(self.certificate_password)
142+
with Form(self.sii_cert) as f:
143+
self.assertFalse(f.show_public_key)
144+
self.assertFalse(f.public_key_data)
145+
f.show_public_key = True
146+
self.assertTrue(f.public_key_data)
147+
self.assertEqual(f.public_key_data, self.public_key)
148+
f.show_public_key = False
149+
self.assertFalse(f.public_key_data)
150+
151+
def test_get_public_key_pem(self):
152+
self.assertFalse(self.sii_cert.public_key_file)
153+
self._activate_certificate(self.certificate_password)
154+
action = self.sii_cert.get_public_key_pem()
155+
self.assertEqual(action["type"], "ir.actions.act_url")
156+
self.assertEqual(
157+
f"/web/content/l10n.es.aeat.certificate/{self.sii_cert.id}/public_key_file/{self.sii_cert.public_key_filename}?download=true",
158+
action["url"],
159+
)
160+
self.assertTrue(self.sii_cert.public_key_file)

l10n_es_aeat/views/aeat_certificate_view.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
<group>
3434
<field name="private_key" />
3535
<field name="public_key" />
36+
<field
37+
name="show_public_key"
38+
widget="boolean_toggle"
39+
options="{'autosave': False}"
40+
/>
41+
<field name="public_key_data" invisible="not show_public_key" />
42+
<button
43+
name="get_public_key_pem"
44+
type="object"
45+
string="Download Public Key"
46+
colspan="2"
47+
class="btn-primary"
48+
invisible="not show_public_key"
49+
/>
3650
</group>
3751
</form>
3852
</field>

0 commit comments

Comments
 (0)