From dadb1d4f23ba12dcd00d207d3f3cde80e66d7283 Mon Sep 17 00:00:00 2001 From: Laurent Chedanne Date: Fri, 26 Jun 2026 10:39:30 +0200 Subject: [PATCH] OVea version --- .gitignore | 3 +- crealead-caldav.py | 11 +++- csv-to-timemanager.py | 1 + docs/specs.md | 2 + exec-reset-timemanager.sh | 4 ++ reset-timemanager.py | 116 ++++++++++++++++++++++++++++++++++++++ support/ovea/ssh | 3 + 7 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 exec-reset-timemanager.sh create mode 100644 reset-timemanager.py create mode 100755 support/ovea/ssh diff --git a/.gitignore b/.gitignore index 87bb8b4..ad6dd79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ env/* config.json -config.json.orig +config.json.* +csv/* diff --git a/crealead-caldav.py b/crealead-caldav.py index 4c42ebc..e386bd0 100644 --- a/crealead-caldav.py +++ b/crealead-caldav.py @@ -20,7 +20,8 @@ import csv import calendar from datetime import date, datetime, timezone import pytz - +from urllib.parse import unquote +import re class EventRow(): @@ -170,7 +171,7 @@ def get_all_events(config, calendars_find): elif field == "LOCATION": event_row.set_location(event_field[1]) elif field == "DESCRIPTION": - event_row.set_description(event_field[1]) + event_row.set_description(clean_description(event_field[1])) event_rows.append(event_row) sorted_rows = sorted(event_rows, key=lambda l: datetime.strptime(str(l.start_date)+'T'+str(l.start_time), "%Y-%m-%dT%H:%M:%S")) @@ -179,6 +180,12 @@ def get_all_events(config, calendars_find): return calendars_to_write +def clean_description(value): + if value.startswith("text/html,"): + value = value[len("text/html,"):] + value = unquote(value) + value = re.sub(r'<[^>]+>', '', value) + return value.strip().strip('"') def write_csv(filename, rows): """Write CSV file""" diff --git a/csv-to-timemanager.py b/csv-to-timemanager.py index ce77c7a..de1c9bc 100644 --- a/csv-to-timemanager.py +++ b/csv-to-timemanager.py @@ -264,6 +264,7 @@ def create_project(name, client_uuid): #print(json.dumps(response.json(), indent=1)) else: print("Erreur de création project") + print(response) print(response.reason) def create_client(name): diff --git a/docs/specs.md b/docs/specs.md index 9897e77..5a331bc 100644 --- a/docs/specs.md +++ b/docs/specs.md @@ -23,6 +23,8 @@ Chaque entrée doit contenir au minimum : - `user_name` : login Nextcloud utilisé pour authentifier les requêtes, - `api_password` : mot de passe ou mot de passe d'application Nextcloud. +> Il est important de générer la clé API en s'étant connecté avec l'identifiant et non l'email car le script user_name utilise le champ "user_name" pour faire des vérifications en bases de données avant d'ajouter des données. + Colonnes CSV utilisées ---------------------- diff --git a/exec-reset-timemanager.sh b/exec-reset-timemanager.sh new file mode 100644 index 0000000..b36dba4 --- /dev/null +++ b/exec-reset-timemanager.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +source env/bin/activate +python3 remove-users-data-timemanager.py $1 diff --git a/reset-timemanager.py b/reset-timemanager.py new file mode 100644 index 0000000..4f58160 --- /dev/null +++ b/reset-timemanager.py @@ -0,0 +1,116 @@ +import csv +import requests +import json +import uuid +import re +import base64 +import sys +import mysql.connector +from unidecode import unidecode + +########################################## +# Config +########################################## +# Récupération de la config +with open('config.json', 'r') as f: + config = json.load(f) + +mydb = mysql.connector.connect( + host=config['db_host'], + user=config['db_user'], + password=config['db_password'], + database=config['db_database'] +) +cursor = mydb.cursor(buffered=True) + +# Argument --yes pour auto-valider toutes les suppressions +valid_args = {'-y', '--yes'} +extra_args = [arg for arg in sys.argv[1:] if arg not in valid_args] + +if extra_args: + print(f"Erreur : argument(s) non reconnu(s) : {' '.join(extra_args)}") + print(f"Usage : python {sys.argv[0]} [--yes | -y]") + sys.exit(1) + +auto_confirm = bool(set(sys.argv[1:]) & valid_args) + +########################################## +# Fonctions +########################################## + +def check_users_exist(user_id): + """Vérifie si l'utilisateur existe dans oc_users.""" + cursor.execute("SELECT uid FROM oc_users WHERE uid = %s", (user_id,)) + return cursor.fetchone() is not None + +def remove_row_on_table_for_user(user_id, table): + """Supprime toutes les entrées d'une table pour un utilisateur donné.""" + query = f"DELETE FROM `{table}` WHERE user_id = %s" + cursor.execute(query, (user_id,)) + affected = cursor.rowcount + mydb.commit() + print(f" [{table}] {affected} ligne(s) supprimée(s)") + +########################################## +# Main +########################################## + +tables = [ + "oc_timemanager_client", + "oc_timemanager_commit", + "oc_timemanager_project", + "oc_timemanager_task", + "oc_timemanager_time" +] + +# Listing de tous les utilisateurs configurés avant toute action +print("==========================================") +print("Utilisateurs configurés dans config.json :") +print("==========================================") +valid_users = [] +for user_info in config['calendars']: + user_id = user_info.get('user_name', '') + if not user_id: + print(f" ⚠ [{user_id or '???'}] — infos de connexion incomplètes, ignoré") + continue + exists = check_users_exist(user_id) + status = "✔ existe en BDD" if exists else "✘ introuvable en BDD" + print(f" • {user_id} — {status}") + if exists: + valid_users.append(user_info) + +print() + +if not valid_users: + print("Aucun utilisateur valide à traiter. Fin du script.") + cursor.close() + mydb.close() + sys.exit(0) + +if auto_confirm: + print("Mode auto-confirmation activé (--yes) : toutes les suppressions seront effectuées sans demande.\n") + +# Traitement par utilisateur +for user_info in valid_users: + user_id = user_info['user_name'] + print("==========================================") + print(f"User : {user_id}") + print("==========================================") + + if auto_confirm: + confirmed = True + else: + reponse = input(f"\nSupprimer toutes les données TimeManager de '{user_id}' ? [o/N] : ").strip().lower() + confirmed = reponse in ('o', 'oui', 'y', 'yes') + + if confirmed: + print("Suppression en cours...") + for table in tables: + remove_row_on_table_for_user(user_id, table) + print(f"✔ Données de '{user_id}' supprimées.\n") + else: + print(f"✘ Suppression annulée pour '{user_id}'.\n") + +cursor.close() +mydb.close() +print("Terminé.") diff --git a/support/ovea/ssh b/support/ovea/ssh new file mode 100755 index 0000000..b83ec60 --- /dev/null +++ b/support/ovea/ssh @@ -0,0 +1,3 @@ +#!/bin/bash + +ssh execcsv@crl-01.ovea.com