Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add desktop_certificate #302

Open
wants to merge 1 commit into
base: 14.0
Choose a base branch
from
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
70 changes: 70 additions & 0 deletions desktop_certificate/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
===================
Desktop Certificats
===================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:2bffd83f3e44d4fff1cab3eca36cc7170c1008fed1bf1fea9222d041e920e331
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |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/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fak--odoo--incubator-lightgray.png?logo=github
:target: https://github.com/akretion/ak-odoo-incubator/tree/14.0/desktop_certificate
:alt: akretion/ak-odoo-incubator

|badge1| |badge2| |badge3|

This module allows to manage certificates TLS / MPKI / SSL.
It manages the creation and renewal of certificates and the installation of the certificates on your server.
It allows you to manage your certificates in a simple and efficient way.

**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/akretion/ak-odoo-incubator/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/akretion/ak-odoo-incubator/issues/new?body=module:%20desktop_certificate%0Aversion:%2014.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
~~~~~~~

* Akretion

Contributors
~~~~~~~~~~~~

* Kévin Roche <[email protected]>

Maintainers
~~~~~~~~~~~

.. |maintainer-Kev-Roche| image:: https://github.com/Kev-Roche.png?size=40px
:target: https://github.com/Kev-Roche
:alt: Kev-Roche

Current maintainer:

|maintainer-Kev-Roche|

This module is part of the `akretion/ak-odoo-incubator <https://github.com/akretion/ak-odoo-incubator/tree/14.0/desktop_certificate>`_ project on GitHub.

You are welcome to contribute.
1 change: 1 addition & 0 deletions desktop_certificate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
28 changes: 28 additions & 0 deletions desktop_certificate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2024 Akretion (https://www.akretion.com).
# @author Kévin Roche <[email protected]>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Desktop Certificats",
"summary": "Generate and manage TSL certificates of users",
"version": "14.0.1.0.0",
"category": "tools",
"website": "https://github.com/akretion/ak-odoo-incubator",
"author": "Akretion, Odoo Community Association (OCA)",
"license": "AGPL-3",
"maintainers": ["Kev-Roche"],
"application": False,
"installable": True,
"depends": [
"stock",
"mail",
],
"data": [
"data/data.xml",
"security/res_groups.xml",
"security/ir.model.access.csv",
"security/rule.xml",
"views/desktop.xml",
"views/desktop_certificate.xml",
],
}
56 changes: 56 additions & 0 deletions desktop_certificate/data/data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<record id="mpki_api_url" model="ir.config_parameter">
<field name="key">mpki_api_url</field>
<field name="value">http://front.home.arpa:8096/certs</field>
</record>
<record id="mpki_api_user" model="ir.config_parameter">
<field name="key">mpki_api_user</field>
<field name="value"></field>
</record>
<record id="mpki_api_password" model="ir.config_parameter">
<field name="key">mpki_api_password</field>
<field name="value" />
</record>

<record id="ir_cron_send_email_certificate_expiration" model="ir.cron">
<field
name="name"
>Email d'alerte d'expiration de certificats informatique.</field>
<field name="active" eval="True" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">3</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="model_id" ref="model_desktop" />
<field name="code">model.cron_send_email_certificate_expiration()</field>
</record>
<record id="mail_certificate_expiration" model="mail.template">
<field
name="name"
>Email d'alerte d'expiration de certificats informatique</field>
<field name="model_id" ref="model_desktop" />
<field name="subject">Certificats à renouveler sous 15 jours</field>
<field name="email_to" />
<field name="body_html" type="xml">
<div style="margin: 0px; padding: 0px;">
<p style="margin: 0px; padding: 0px; font-size: 13px;">
--- MAIL AUTOMATIQUE ---<br /><br />
Bonjour,<br /><br />
Voici la liste des certificats qui expireront sous 15 jours:
<br />
<ul>
% for line in object.env.context.get('certifs_ids'):
<li><b>${line.name}</b> : ${line.expiration_date}</li>
% endfor
</ul>

<br />
Cordialement
</p>
</div>
</field>
<field name="report_name">${(object.name or '').replace('/','-')}</field>
<field name="auto_delete" eval="True" />
</record>
</odoo>
3 changes: 3 additions & 0 deletions desktop_certificate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import desktop_certificate

from . import desktop
190 changes: 190 additions & 0 deletions desktop_certificate/models/desktop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# Copyright 2024 Akretion (https://www.akretion.com).
# @author Kévin Roche <[email protected]>

import json
from datetime import datetime

import requests

from odoo import _, api, fields, models
from odoo.exceptions import UserError


class Desktop(models.Model):
_name = "desktop"
_inherit = ["mail.thread"]
_description = "Desktop"

name = fields.Char(string="Nom")
location_id = fields.Many2one(
comodel_name="stock.warehouse", string="Lieu", required=True
)
company_id = fields.Many2one(
comodel_name="res.company",
string="Société",
default=lambda self: self.env.company,
)
certificate_partner_id = fields.Many2one(
comodel_name="res.partner",
string="Certificats envoyés à",
domain=[("user_ids", "!=", False)],
default=lambda self: self.env.user.partner_id,
)
certificate_email = fields.Char(
string="Certificat envoyé à", related="certificate_partner_id.email"
)
certificate_phone = fields.Char(
string="Mot de passe du certificat envoyé à",
related="certificate_partner_id.mobile",
)

certificate_ids = fields.One2many(
comodel_name="desktop.certificate",
inverse_name="desktop_id",
string="Certificats",
)
certificate_state = fields.Selection(
selection=[
("1_short", "< 15 jours"),
("2_medium", "< 3 mois"),
("3_long", "> 3 mois"),
("4_revoked", "Révoqué"),
("5_obsolete", "Obsolète"),
("none", "Aucun certificat"),
],
string="Etat Certificats",
compute="_compute_valid_certificate_state",
store=True,
)

certificate_min_exp_date = fields.Date(
string="Date d'expiration",
compute="_compute_certificate_min_exp_date",
)

valid_certificate_count = fields.Integer(
compute="_compute_valid_certificate_count", string="Certificats Valides"
)

def _compute_certificate_min_exp_date(self):
for rec in self:
rec.certificate_min_exp_date = None
certifs = rec.certificate_ids
if certifs:
current_datetime = datetime.now()
valid_datetime_list = [
certif.expiration_date
for certif in certifs
if certif.expiration_date >= current_datetime
and not certif.revoked
and certif.active
]
if valid_datetime_list:
rec.certificate_min_exp_date = max(valid_datetime_list).date()

def _compute_valid_certificate_state(self):
for rec in self:
certif_states = rec.certificate_ids.mapped("state")
if certif_states:
if "short" in certif_states:
rec.certificate_state = "1_short"
elif "medium" in certif_states:
rec.certificate_state = "2_medium"
elif "long" in certif_states:
rec.certificate_state = "3_long"
elif "revoked" in certif_states:
rec.certificate_state = "4_revoked"
else:
rec.certificate_state = "5_obsolete"
else:
rec.certificate_state = "none"

def cron_send_email_certificate_expiration(self):
certifs = self.env["maintenance.certificate"].search([])
certifs._compute_valid_certificate_state()
short_certifs = certifs.filtered(lambda x: x.state == "short")
if short_certifs:
email_template = self.env.ref("infra.mail_certificate_expiration")
self.with_context(
certifs_ids=short_certifs.equipment_id
).message_post_with_template(email_template.id)

@api.depends("certificate_ids")
def _compute_valid_certificate_count(self):
for record in self:
record.valid_certificate_count = len(
record.certificate_ids.filtered(
lambda c: not c.revoked and c.expiration_date > datetime.now()
)
)

def _get_mpki_api(self):
ir_config_model = self.env["ir.config_parameter"].sudo()
mpki_api = {}
mpki_api["url"] = ir_config_model.get_param("mpki_api_url")
mpki_api["user"] = ir_config_model.get_param("mpki_api_user")
mpki_api["password"] = ir_config_model.get_param("mpki_api_password")
return mpki_api

def generate_certificate(self):
mpki_api = self._get_mpki_api()
for record in self:
partner = record.certificate_partner_id
if not partner.email:
raise UserError(_("L'email du destinataire est vide"))
if not partner.mobile:
raise UserError(_("Le mobile du destinataire est vide"))
location = record.location_id.partner_id
params = {
"certificate": {
"name": record.name,
},
"partner": {
"name": partner.display_name,
"phone": partner.mobile,
"email": partner.email,
},
"location": {
"name": location.name,
"company": location.company_id.name,
"city": location.city,
"zipcode": location.zip,
"country": location.country_id.name,
},
}
res = requests.post(
mpki_api["url"],
auth=(mpki_api["user"], mpki_api["password"]),
json=params,
)
if res.status_code == requests.codes.ok:
res_dict = res.json()
self.env["desktop.certificate"].create(
{
"revoked": not res_dict["valid"],
"name": res_dict["name"],
"expiration_date": datetime.fromisoformat(
res_dict["valid_until"]
),
"desktop_id": record.id,
"sent_to_email": record.certificate_email,
"sent_to_phone": record.certificate_phone,
}
)
else:
try:
raise UserError(json.dumps(res.json(), indent=4))
except ValueError:
raise UserError(res.text)
return None

@api.onchange("location_id")
def _onchange_location(self):
if self.location_id:
self.company_id = self.location_id.company_id.id or False

def unlink(self):
desktops = self.mapped("desktop_id")
super().unlink()
desktops.unlink()
return True
Loading
Loading