From b4eee312df41f0988b3a05d0c534e63b40cb5f73 Mon Sep 17 00:00:00 2001 From: Fanch Date: Fri, 25 Jul 2025 14:49:46 +0200 Subject: [PATCH] python --- bin/lib/ldap.py | 4 +- bin/lib/mattermost.py | 122 ++++++++++++++++++++++++++++++++++++ bin/lib/sympa.py | 37 +++++++++++ bin/lib/user.py | 140 ++++++++++++++++++------------------------ bin/lib/utils.py | 5 -- 5 files changed, 222 insertions(+), 86 deletions(-) create mode 100644 bin/lib/mattermost.py create mode 100644 bin/lib/sympa.py delete mode 100644 bin/lib/utils.py diff --git a/bin/lib/ldap.py b/bin/lib/ldap.py index d849495..e04c92f 100644 --- a/bin/lib/ldap.py +++ b/bin/lib/ldap.py @@ -1,6 +1,7 @@ import ldap from passlib.hash import sha512_crypt from email_validator import validate_email, EmailNotValidError +import subprocess from .config import getDockersConfig, getSecretConfig @@ -11,7 +12,8 @@ class Ldap: self.ldap_root = getDockersConfig("ldap_root") self.ldap_admin_username = getSecretConfig("ldapServ", "LDAP_ADMIN_USERNAME") self.ldap_admin_password = getSecretConfig("ldapServ", "LDAP_ADMIN_PASSWORD") - self.ldap_host = "10.0.0.146" + cmd="docker inspect -f '{{.NetworkSettings.Networks.ldapNet.IPAddress}}' ldapServ" + self.ldap_host = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT).strip().decode() def __enter__(self): self.ldap_connection = ldap.initialize(f"ldap://{self.ldap_host}") diff --git a/bin/lib/mattermost.py b/bin/lib/mattermost.py new file mode 100644 index 0000000..0e6d7e3 --- /dev/null +++ b/bin/lib/mattermost.py @@ -0,0 +1,122 @@ +import subprocess + +from .config import getDockersConfig, getSecretConfig + +mattermost_user = getSecretConfig("mattermostServ", "MM_ADMIN_USER") +mattermost_pass = getSecretConfig("mattermostServ", "MM_ADMIN_PASSWORD") +mattermost_url = f"https://{getDockersConfig('matterHost')}.{getDockersConfig('domain')}" +mmctl = "docker exec -i mattermostServ bin/mmctl" + +class Mattermost: + + def __init__(self): + self.authenticate() + + + def authenticate(self): + # Authentification sur MM + cmd = f"{mmctl} auth login {mattermost_url} --name local-server --username {mattermost_user} --password {mattermost_pass}" + subprocess.run(cmd, shell=True, stderr=subprocess.STDOUT, check=True) + + + def post_message(self, message, equipe="kaz", canal="creation-comptes"): + """ + Envoyer un message dans une Equipe/Canal de MM + """ + cmd = f"{mmctl} post create {equipe}:{canal} --message \"{message}\"" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + return output.decode() + + + def get_user(self, user): + """ + Le user existe t-il sur MM ? + """ + try: + cmd = f"{mmctl} user search {user} --json" + user_list_output = subprocess.check_output(cmd, shell=True) + return True # Le nom d'utilisateur existe + except subprocess.CalledProcessError: + return False + + + def create_user(self, user, email, password): + """ + Créer un utilisateur sur MM + """ + cmd = f"{mmctl} user create --email {email} --username {user} --password {password}" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + return output.decode() + + + def delete_user(self, email): + """ + Supprimer un utilisateur sur MM + """ + cmd = f"{mmctl} user delete {email} --confirm" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + return output.decode() + + + def update_password(self, email, new_password): + """ + Changer un password pour un utilisateur de MM + """ + cmd = f"{mmctl} user change-password {email} --password {new_password}" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + return output.decode() + + + def add_user_to_team(self, email, equipe): + """ + Affecte un utilisateur à une équipe MM + """ + cmd = f"{mmctl} team users add {equipe} {email}" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + return output.decode() + + + def add_user_to_channel(self, email, equipe, canal): + """ + Affecte un utilisateur à un canal MM + """ + cmd = f'{mmctl} channel users add {equipe}:{canal} {email}' + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + return output.decode() + + + def get_teams(self): + """ + Lister les équipes sur MM + """ + cmd = f"{mmctl} team list --disable-pager" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + data_list = output.decode("utf-8").strip().split('\n') + data_list.pop() + return data_list + + + def create_team(self, equipe, email): + """ + Créer une équipe sur MM et affecter un admin si email est renseigné (set admin marche pô) + """ + + #DANGER: l'option --email ne rend pas le user admin de l'équipe comme c'est indiqué dans la doc :( + cmd = f"{mmctl} team create --name {equipe} --display-name {equipe} --private --email {email}" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + + #Workaround: on récup l'id du user et de l'équipe pour affecter le rôle "scheme_admin": true, "scheme_user": true avec l'api MM classique. + #TODO: + + return output.decode() + + + def delete_tem(self, equipe): + """ + Supprimer une équipe sur MM + """ + + cmd = f"{mmctl} team delete {equipe} --confirm" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + return output.decode() + diff --git a/bin/lib/sympa.py b/bin/lib/sympa.py new file mode 100644 index 0000000..ac74635 --- /dev/null +++ b/bin/lib/sympa.py @@ -0,0 +1,37 @@ +import subprocess + +from .config import getDockersConfig, getSecretConfig + +sympa_user = getSecretConfig("sympaServ", "SOAP_USER") +sympa_pass = getSecretConfig("sympaServ", "SOAP_PASSWORD") +sympa_listmaster = getSecretConfig("sympaServ", "ADMINEMAIL") +sympa_url = f"https://{getDockersConfig('sympaHost')}.{getDockersConfig('domain')}" +sympa_soap = "docker exec -i sympaServ /usr/lib/sympa/bin/sympa_soap_client.pl" +sympa_liste_info = f"info@{getDockersConfig('domain_sympa')}" + +# docker exec -i sympaServ /usr/lib/sympa/bin/sympa_soap_client.pl --soap_url=${httpProto}://${URL_LISTE}/sympasoap --trusted_application=${sympa_SOAP_USER} --trusted_application_password=${sympa_SOAP_PASSWORD} --proxy_vars=\"USER_EMAIL=${LISTMASTER}\" --service=add --service_parameters=\"${NL_LIST},${EMAIL_SOUHAITE}\"" | tee -a "${CMD_SYMPA}" + +class Sympa: + + def _execute_sympa_command(self, email, liste, service): + if validate_email(email) and validate_email(liste): + cmd = f'{sympa_soap} --soap_url={sympa_url}/sympasoap --trusted_application={sympa_user} --trusted_application_password={sympa_pass} --proxy_vars=USER_EMAIL={sympa_listmaster} --service={service} --service_parameters="{liste},{email}" && echo $?' + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + return output.decode() + + def add_email_to_list(self, email, liste=sympa_liste_info): + """ + Ajouter un email dans une liste sympa + """ + output = self._execute_sympa_command(email, liste, 'add') + return output + + def delete_email_from_list(self, email, liste=sympa_liste_info): + """ + Supprimer un email dans une liste sympa + """ + output = self._execute_sympa_command(email, liste, 'del') + return output + + + diff --git a/bin/lib/user.py b/bin/lib/user.py index bbbe76c..15eb449 100644 --- a/bin/lib/user.py +++ b/bin/lib/user.py @@ -1,37 +1,27 @@ from email_validator import validate_email, EmailNotValidError from glob import glob import tempfile +import subprocess import re from .paheko import Paheko from .ldap import Ldap -from .utils import generate_password +from .mattermost import Mattermost DEFAULT_FILE = "/kaz/tmp/createUser.txt" -#class Kaz_user: +def _generate_password(self): + cmd="apg -n 1 -m 10 -M NCL -d" + output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) + new_password="_"+output.decode("utf-8")+"_" + return new_password - # def __init__(self): - # self.paheko = Paheko() - # self.ldap = Ldap() - # global sympa_liste_info - # - # self.paheko_users_action_resource = Paheko_users_action() - # self.paheko_user_resource=Paheko_user() - # self.ldap_user_resource = Ldap_user() - # self.password_create_resource = Password_create() - # self.mattermost_message_resource=Mattermost_message() - # self.mattermost_user_resource=Mattermost_user() - # self.mattermost_user_team_resource=Mattermost_user_team() - # self.mattermost_user_channel_resource=Mattermost_user_channel() - # self.mattermost_team_resource=Mattermost_team() - # self.sympa_user_resource=Sympa_user() def create_user(email, email_secours, admin_orga, nom_orga, quota_disque, nom, prenom, nc_orga, garradin_orga, wp_orga, agora_orga, wiki_orga, nc_base, groupe_nc_base, equipe_agora, password=None): - with Ldap() as ldap: - email = email.lower() + email = email.lower() + with Ldap() as ldap: # est-il déjà dans le ldap ? (mail ou alias) if ldap.get_email(email): print(f"ERREUR 1: {email} déjà existant dans ldap. on arrête tout") @@ -59,7 +49,7 @@ def create_user(email, email_secours, admin_orga, nom_orga, quota_disque, nom, p return #on génère un password - password = password or generate_password() + password = password or _generate_password() #on créé dans le ldap #à quoi servent prenom/nom dans le ldap ? @@ -74,66 +64,56 @@ def create_user(email, email_secours, admin_orga, nom_orga, quota_disque, nom, p print("Erreur LDAP") return - # #on créé dans MM - # user = email.split('@')[0] - # res, status_code = self.mattermost_user_resource.post(user,email,password) - # if status_code != 200: raise ValueError(f"ERREUR 4 sur MM: {email} : {res}, on arrête tout ") - # - # # et on affecte à l'équipe kaz - # res, status_code = self.mattermost_user_team_resource.post(email,"kaz") - # if status_code != 200: raise ValueError(f"ERREUR 5 sur MM: {email} : {res}, on arrête tout ") - # - # #et aux 2 canaux de base - # res, status_code = self.mattermost_user_channel_resource.post(email,"kaz","une-question--un-soucis") - # if status_code != 200: raise ValueError(f"ERREUR 6 sur MM: {email} : {res}, on arrête tout ") - # res, status_code = self.mattermost_user_channel_resource.post(email,"kaz","cafe-du-commerce--ouvert-2424h") - # if status_code != 200: raise ValueError(f"ERREUR 7 sur MM: {email} : {res}, on arrête tout ") - # - # #on créé une nouvelle équipe ds MM si besoin - # if tab['admin_orga'] == 1: - # res, status_code = self.mattermost_team_resource.post(tab['nom_orga'],email) - # if status_code != 200: raise ValueError(f"ERREUR 8 sur MM: {email} : {res}, on arrête tout ") - # #BUG: créer la nouvelle équipe n'a pas rendu l'email admin, on le rajoute comme membre simple - # res, status_code = self.mattermost_user_team_resource.post(email,tab['nom_orga']) - # if status_code != 200: raise ValueError(f"ERREUR 8.1 sur MM: {email} : {res}, on arrête tout ") - # - # #on créé dans le cloud genéral - # #inutile car tous les user du ldap sont user du cloud général. - # - # #on inscrit email et email_secours à la nl sympa_liste_info - # res, status_code = self.sympa_user_resource.post(email,sympa_liste_info) - # if status_code != 200: raise ValueError(f"ERREUR 9 sur Sympa: {email} : {res}, on arrête tout ") - # res, status_code = self.sympa_user_resource.post(email_secours,sympa_liste_info) - # if status_code != 200: raise ValueError(f"ERREUR 10 sur Sympa: {email_secours} : {res}, on arrête tout ") - # - # #on construit/envoie le mail - # context = { - # 'ADMIN_ORGA': tab['admin_orga'], - # 'NOM': tab['nom'], - # 'EMAIL_SOUHAITE': email, - # 'PASSWORD': password, - # 'QUOTA': tab['quota_disque'], - # 'URL_WEBMAIL': webmail_url, - # 'URL_AGORA': mattermost_url, - # 'URL_MDP': mdp_url, - # 'URL_LISTE': sympa_url, - # 'URL_SITE': site_url, - # 'URL_CLOUD': cloud_url - # } - # subject="KAZ: confirmation d'inscription !" - # sender=app.config['MAIL_USERNAME'] - # reply_to = app.config['MAIL_REPLY_TO'] - # msg = Message(subject=subject, sender=sender, reply_to=reply_to, recipients=[email,email_secours]) - # msg.html = render_template('email_inscription.html', **context) - # mail.send(msg) - # - # #on met le flag paheko action à Aucune - # res, status_code = self.paheko_user_resource.put(email,"action_auto","Aucune") - # if status_code != 200: raise ValueError(f"ERREUR 12 sur paheko: {email} : {res}, on arrête tout ") - # - # #on post sur MM pour dire ok - # msg=f"**POST AUTO** Inscription réussie pour {email} avec le secours {email_secours} Bisou!" - # self.mattermost_message_resource.post(message=msg) + with Mattermost() as mm: + #on créé dans MM + user = email.split('@')[0] + mm.create_user(user, email, password) + mm.add_user_to_team(email, "kaz") + + #et aux 2 canaux de base + mm.add_user_to_channel(email, "kaz", "une-question--un-soucis") + mm.add_user_to_channel(email, "kaz", "cafe-du-commerce--ouvert-2424h") + + #on créé une nouvelle équipe ds MM si besoin + if admin_orga == 1: + mm.create_team(nom_orga, email) + #BUG: créer la nouvelle équipe n'a pas rendu l'email admin, on le rajoute comme membre simple + mm.add_user_to_team(email, nom_orga) + + sympa = Sympa() + # #on inscrit email et email_secours à la nl sympa_liste_info + sympa.add_email_to_list(email) + sympa.add_email_to_list(email_secours) + + #on construit/envoie le mail + # context = { + # 'ADMIN_ORGA': admin_orga, + # 'NOM': nom, + # 'EMAIL_SOUHAITE': email, + # 'PASSWORD': password, + # 'QUOTA': quota_disque, + # 'URL_WEBMAIL': webmail_url, + # 'URL_AGORA': mattermost_url, + # 'URL_MDP': mdp_url, + # 'URL_LISTE': sympa_url, + # 'URL_SITE': site_url, + # 'URL_CLOUD': cloud_url + # } + # subject = "KAZ: confirmation d'inscription !" + # sender = "contact@kaz.bzh" + # reply_to = "contact@kaz.bzh" + # msg = Message(subject=subject, sender=sender, reply_to=reply_to, recipients=[email,email_secours]) + # msg.html = render_template('email_inscription.html', **context) + # mail.send(msg) + + #on met le flag paheko action à Aucune + paheko = Paheko() + paheko.set_user(email, "action_auto", "Aucune") + + #on post sur MM pour dire ok + with Mattermost() as mm: + msg=f"**POST AUTO** Inscription réussie pour {email} avec le secours {email_secours} Bisou!" + mm.post_message(message=msg) def create_waiting_users(): diff --git a/bin/lib/utils.py b/bin/lib/utils.py deleted file mode 100644 index 80260ee..0000000 --- a/bin/lib/utils.py +++ /dev/null @@ -1,5 +0,0 @@ -def generate_password(self): - cmd="apg -n 1 -m 10 -M NCL -d" - output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) - new_password="_"+output.decode("utf-8")+"_" - return new_password