chore: secure ticketing configuration
This commit is contained in:
@@ -1,125 +1,183 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from setuphelpers import *
|
||||
import xmlrpc.client
|
||||
import pickle
|
||||
import os
|
||||
from configparser import ConfigParser
|
||||
import requests
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
from configparser import ConfigParser
|
||||
|
||||
# Configuration
|
||||
url = 'https://odoo.comitari.fr'
|
||||
db = 'comitari'
|
||||
state_file = 'tickets_state.pkl'
|
||||
api_key = "182534f9e754ce1016e86b86b4b5b47199659a6f"
|
||||
headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': f'Bearer {api_key}',
|
||||
}
|
||||
import requests
|
||||
|
||||
# Endpoint URL
|
||||
endpoint = f'{url}/jsonrpc'
|
||||
|
||||
# Payload pour récupérer tous les tickets
|
||||
payload = {
|
||||
'jsonrpc': '2.0',
|
||||
'method': 'call',
|
||||
'params': {
|
||||
'model': 'helpdesk.ticket',
|
||||
'method': 'search_read',
|
||||
'args': [[], ['id', 'write_date']],
|
||||
},
|
||||
'id': 1,
|
||||
}
|
||||
CONFIG_FILE = "ticketing.ini"
|
||||
CONFIG_TEMPLATE_FILE = "ticketing.ini.example"
|
||||
STATE_FILE = "tickets_state.json"
|
||||
DEFAULT_TIMEOUT = 30
|
||||
|
||||
|
||||
def get_config_path():
|
||||
return makepath(WAPT.private_dir, CONFIG_FILE)
|
||||
|
||||
|
||||
def get_state_path():
|
||||
return makepath(WAPT.private_dir, STATE_FILE)
|
||||
|
||||
|
||||
def install():
|
||||
config_path = get_config_path()
|
||||
|
||||
plugin_inifile = makepath(WAPT.private_dir, "rocket.ini")
|
||||
if not isfile(config_path):
|
||||
shutil.copyfile(CONFIG_TEMPLATE_FILE, config_path)
|
||||
|
||||
if not isfile(plugin_inifile):
|
||||
filecopyto("rocket.ini", WAPT.private_dir)
|
||||
|
||||
def audit():
|
||||
|
||||
try:
|
||||
# Récupération de l'état actuel de tous les tickets
|
||||
response = requests.post(endpoint, json=payload, headers=headers)
|
||||
response.raise_for_status() # Vérifie si la requête a réussi
|
||||
response_data = response.json()
|
||||
|
||||
# Vérifie si 'result' est présent dans la réponse
|
||||
if 'result' in response_data:
|
||||
tickets = response_data['result']
|
||||
else:
|
||||
print("Erreur: La clé 'result' n'est pas présente dans la réponse.")
|
||||
print("Réponse complète:", response_data)
|
||||
tickets = []
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Erreur lors de la requête: {e}")
|
||||
tickets = []
|
||||
|
||||
# Vérification si un état précédent existe
|
||||
if os.path.exists(state_file):
|
||||
with open(state_file, 'rb') as f:
|
||||
previous_tickets_state = pickle.load(f)
|
||||
else:
|
||||
previous_tickets_state = {}
|
||||
|
||||
|
||||
# Comparaison et affichage des résultats
|
||||
tickets_updated = []
|
||||
for ticket in tickets:
|
||||
ticket_id = ticket['id']
|
||||
ticket_write_date = ticket['write_date']
|
||||
|
||||
if ticket_id in previous_tickets_state:
|
||||
if ticket_write_date != previous_tickets_state[ticket_id]:
|
||||
tickets_updated.auppend(ticket_id)
|
||||
else:
|
||||
tickets_updated.append(ticket_id)
|
||||
conf_wapt = load_config()
|
||||
tickets = fetch_odoo_tickets(conf_wapt)
|
||||
previous_tickets_state = load_tickets_state(get_state_path())
|
||||
tickets_updated = get_updated_ticket_ids(tickets, previous_tickets_state)
|
||||
|
||||
if tickets_updated:
|
||||
message = f"Les tickets suivants ont été mis à jour depuis la dernière vérification : {tickets_updated}"
|
||||
send_to_rocket(message)
|
||||
|
||||
message = "Les tickets suivants ont ete mis a jour depuis la derniere verification : %s" % tickets_updated
|
||||
else:
|
||||
message = "Aucun ticket n'a été mis à jour depuis la dernière vérification."
|
||||
send_to_rocket(message)
|
||||
# Sauvegarde de l'état actuel pour la prochaine exécution
|
||||
current_tickets_state = {ticket['id']: ticket['write_date'] for ticket in tickets}
|
||||
with open(state_file, 'wb') as f:
|
||||
pickle.dump(current_tickets_state, f)
|
||||
message = "Aucun ticket n'a ete mis a jour depuis la derniere verification."
|
||||
|
||||
send_to_rocket(message, conf_wapt=conf_wapt)
|
||||
save_tickets_state(get_state_path(), build_tickets_state(tickets))
|
||||
return "OK"
|
||||
|
||||
|
||||
def send_to_rocket(message_text, attachments=None):
|
||||
"""
|
||||
Envoie un message à Rocket.Chat via un webhook.
|
||||
|
||||
:param message_text: Texte du message à envoyer
|
||||
:param attachments: Liste de pièces jointes (facultatif)
|
||||
"""
|
||||
smtp_inifile = makepath(WAPT.private_dir, "rocket.ini")
|
||||
def load_config():
|
||||
config_path = get_config_path()
|
||||
conf_wapt = ConfigParser()
|
||||
conf_wapt.read(smtp_inifile)
|
||||
conf_wapt.read(config_path)
|
||||
|
||||
webhook_url = conf_wapt.get("rocket", "url")
|
||||
required_options = [
|
||||
("odoo", "url"),
|
||||
("odoo", "api_key"),
|
||||
("rocket", "webhook_url"),
|
||||
]
|
||||
missing_options = [
|
||||
"%s.%s" % (section, option)
|
||||
for section, option in required_options
|
||||
if not conf_wapt.has_option(section, option)
|
||||
]
|
||||
|
||||
# Construire le message
|
||||
if missing_options:
|
||||
raise Exception(
|
||||
"Configuration incomplete dans %s : %s"
|
||||
% (config_path, ", ".join(missing_options))
|
||||
)
|
||||
|
||||
placeholder_options = [
|
||||
"%s.%s" % (section, option)
|
||||
for section, option in required_options
|
||||
if "CHANGE_ME" in conf_wapt.get(section, option).strip()
|
||||
]
|
||||
if placeholder_options:
|
||||
raise Exception(
|
||||
"Configuration a renseigner dans %s : %s"
|
||||
% (config_path, ", ".join(placeholder_options))
|
||||
)
|
||||
|
||||
return conf_wapt
|
||||
|
||||
|
||||
def get_http_timeout(conf_wapt):
|
||||
return conf_wapt.getint("http", "timeout", fallback=DEFAULT_TIMEOUT)
|
||||
|
||||
|
||||
def build_odoo_payload(conf_wapt):
|
||||
return {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "call",
|
||||
"params": {
|
||||
"model": conf_wapt.get("odoo", "model", fallback="helpdesk.ticket"),
|
||||
"method": "search_read",
|
||||
"args": [[], ["id", "write_date"]],
|
||||
},
|
||||
"id": 1,
|
||||
}
|
||||
|
||||
|
||||
def fetch_odoo_tickets(conf_wapt):
|
||||
odoo_url = conf_wapt.get("odoo", "url").rstrip("/")
|
||||
endpoint = "%s/jsonrpc" % odoo_url
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer %s" % conf_wapt.get("odoo", "api_key"),
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
endpoint,
|
||||
json=build_odoo_payload(conf_wapt),
|
||||
headers=headers,
|
||||
timeout=get_http_timeout(conf_wapt),
|
||||
)
|
||||
response.raise_for_status()
|
||||
response_data = response.json()
|
||||
|
||||
if "error" in response_data:
|
||||
raise Exception("Erreur Odoo JSON-RPC : %s" % response_data["error"])
|
||||
if "result" not in response_data:
|
||||
raise Exception("Reponse Odoo invalide : cle 'result' absente")
|
||||
|
||||
return response_data["result"]
|
||||
|
||||
|
||||
def load_tickets_state(state_path):
|
||||
if not os.path.exists(state_path):
|
||||
return {}
|
||||
|
||||
with open(state_path, "r") as state_file:
|
||||
return json.load(state_file)
|
||||
|
||||
|
||||
def save_tickets_state(state_path, tickets_state):
|
||||
with open(state_path, "w") as state_file:
|
||||
json.dump(tickets_state, state_file, indent=2, sort_keys=True)
|
||||
|
||||
|
||||
def build_tickets_state(tickets):
|
||||
return {
|
||||
str(ticket["id"]): ticket["write_date"]
|
||||
for ticket in tickets
|
||||
}
|
||||
|
||||
|
||||
def get_updated_ticket_ids(tickets, previous_tickets_state):
|
||||
tickets_updated = []
|
||||
|
||||
for ticket in tickets:
|
||||
ticket_id = str(ticket["id"])
|
||||
ticket_write_date = ticket["write_date"]
|
||||
|
||||
if previous_tickets_state.get(ticket_id) != ticket_write_date:
|
||||
tickets_updated.append(ticket["id"])
|
||||
|
||||
return tickets_updated
|
||||
|
||||
|
||||
def send_to_rocket(message_text, attachments=None, conf_wapt=None):
|
||||
"""
|
||||
Envoie un message a Rocket.Chat via un webhook.
|
||||
|
||||
:param message_text: Texte du message a envoyer
|
||||
:param attachments: Liste de pieces jointes (facultatif)
|
||||
:param conf_wapt: Configuration deja chargee (facultatif)
|
||||
"""
|
||||
if conf_wapt is None:
|
||||
conf_wapt = load_config()
|
||||
|
||||
message = {
|
||||
'text': message_text
|
||||
"text": message_text,
|
||||
}
|
||||
if attachments:
|
||||
message['attachments'] = attachments
|
||||
|
||||
# Envoyer la requête POST
|
||||
response = requests.post(webhook_url, data=json.dumps(message), headers={'Content-Type': 'application/json'})
|
||||
|
||||
# Vérifier la réponse
|
||||
if response.status_code == 200:
|
||||
print('Message envoyé avec succès.')
|
||||
else:
|
||||
print(f'Échec de l\'envoi du message. Statut de la réponse : {response.status_code}')
|
||||
print(f'Erreur : {response.text}')
|
||||
message["attachments"] = attachments
|
||||
|
||||
response = requests.post(
|
||||
conf_wapt.get("rocket", "webhook_url"),
|
||||
json=message,
|
||||
headers={"Content-Type": "application/json"},
|
||||
timeout=get_http_timeout(conf_wapt),
|
||||
)
|
||||
response.raise_for_status()
|
||||
print("Message envoye avec succes.")
|
||||
|
||||
Reference in New Issue
Block a user