Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 74 additions & 1 deletion l10n_es_aeat/models/aeat_certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,34 @@
# (c) 2019 Acysos S.L.
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from odoo import exceptions, fields, models
import logging

from cryptography.hazmat.primitives.serialization import Encoding

from odoo import api, exceptions, fields, models

_logger = logging.getLogger(__name__)

try:
import cryptography
from cryptography import x509

CRYPTOGRAPHY_VERSION_3 = tuple(map(int, cryptography.__version__.split("."))) >= (
3,
0,
)
if not CRYPTOGRAPHY_VERSION_3:
from cryptography.hazmat.backends import default_backend

def load_pem_x509_certificate(*args, **kwargs):
return x509.load_pem_x509_certificate(
*args, **kwargs, backend=default_backend()
)

else:
load_pem_x509_certificate = x509.load_pem_x509_certificate
except (OSError, ImportError) as err:
_logger.debug(err)


class L10nEsAeatCertificate(models.Model):
Expand All @@ -20,6 +47,21 @@ class L10nEsAeatCertificate(models.Model):
date_start = fields.Date(string="Start Date")
date_end = fields.Date(string="End Date")
public_key = fields.Char(readonly=True)
show_public_key = fields.Boolean(store=False)
public_key_data = fields.Text(readonly=True, store=False)
public_key_file = fields.Binary(
readonly=True,
store=False,
attachment=False,
compute="_compute_public_key",
groups="l10n_es_aeat.group_account_aeat",
)
public_key_filename = fields.Char(
readonly=True,
store=False,
compute="_compute_public_key",
groups="l10n_es_aeat.group_account_aeat",
)
private_key = fields.Char(readonly=True)
company_id = fields.Many2one(
comodel_name="res.company",
Expand All @@ -28,6 +70,37 @@ class L10nEsAeatCertificate(models.Model):
default=lambda self: self.env.company,
)

@api.onchange("show_public_key")
def onchange_public_key_data(self):
if not self.show_public_key:
self.public_key_data = ""
return
with open(self.public_key, "rb") as f:
certificate = load_pem_x509_certificate(f.read())
self.public_key_data = certificate.public_bytes(Encoding.PEM)

def get_public_key_pem(self):
self.ensure_one()
return {
"type": "ir.actions.act_url",
"target": "self",
"url": "/web/content/l10n.es.aeat.certificate/"
f"{self.id}/public_key_file/{self.public_key_filename}?download=true",
}

@api.depends("public_key")
def _compute_public_key(self):
for record in self:
if not record.public_key:
record.public_key_file = False
record.public_key_filename = False
continue
with open(record.public_key, "rb") as f:
certificate = load_pem_x509_certificate(f.read())
public_key = certificate.public_bytes(Encoding.PEM)
record.public_key_filename = f"{record.name}.pem"
record.public_key_file = public_key

def load_password_wizard(self):
self.ensure_one()
return {
Expand Down
26 changes: 26 additions & 0 deletions l10n_es_aeat/tests/test_l10n_es_aeat_certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from cryptography.x509 import oid

from odoo import exceptions
from odoo.tests import Form

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

Expand Down Expand Up @@ -101,6 +102,9 @@ def setUpClass(cls):
certificate,
cls.certificate_password,
)
cls.public_key = certificate.public_bytes(serialization.Encoding.PEM).decode(
"utf-8"
)
cls.sii_cert = cls.env["l10n.es.aeat.certificate"].create(
{
"folder": "Test folder",
Expand Down Expand Up @@ -132,3 +136,25 @@ def test_activate_certificate(self):
)
self._activate_certificate(self.certificate_password)
self.assertEqual(self.sii_cert.state, "active")

def test_show_public_key(self):
self._activate_certificate(self.certificate_password)
with Form(self.sii_cert) as f:
self.assertFalse(f.show_public_key)
self.assertFalse(f.public_key_data)
f.show_public_key = True
self.assertTrue(f.public_key_data)
self.assertEqual(f.public_key_data, self.public_key)
f.show_public_key = False
self.assertFalse(f.public_key_data)

def test_get_public_key_pem(self):
self.assertFalse(self.sii_cert.public_key_file)
self._activate_certificate(self.certificate_password)
action = self.sii_cert.get_public_key_pem()
self.assertEqual(action["type"], "ir.actions.act_url")
self.assertEqual(
f"/web/content/l10n.es.aeat.certificate/{self.sii_cert.id}/public_key_file/{self.sii_cert.public_key_filename}?download=true",
action["url"],
)
self.assertTrue(self.sii_cert.public_key_file)
14 changes: 14 additions & 0 deletions l10n_es_aeat/views/aeat_certificate_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@
<group>
<field name="private_key" />
<field name="public_key" />
<field
name="show_public_key"
widget="boolean_toggle"
options="{'autosave': False}"
/>
<field name="public_key_data" invisible="not show_public_key" />
<button
name="get_public_key_pem"
type="object"
string="Download Public Key"
colspan="2"
class="btn-primary"
invisible="not show_public_key"
/>
</group>
</form>
</field>
Expand Down
Loading