2024-08-20 01:53:17 +02:00
|
|
|
from resources.common_imports import *
|
|
|
|
|
|
|
|
#les variables globales minimum
|
|
|
|
from resources.config import ldap_admin, ldap_pass, ldap_root, ldap_host
|
|
|
|
|
|
|
|
class Ldap_user(Resource):
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
global ldap_admin, ldap_pass, ldap_root, ldap_host
|
|
|
|
self.ldap_admin = ldap_admin
|
|
|
|
self.ldap_pass = ldap_pass
|
|
|
|
self.ldap_root = ldap_root
|
|
|
|
self.ldap_host = f"ldap://{ldap_host}"
|
|
|
|
|
|
|
|
def _connect_ldap(self):
|
|
|
|
ldap_connection = ldap.initialize(self.ldap_host)
|
|
|
|
ldap_connection.simple_bind_s("cn={},{}".format(self.ldap_admin, self.ldap_root), self.ldap_pass)
|
|
|
|
return ldap_connection
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def is_valid_field(cls, field):
|
|
|
|
allowed_fields = ['mailDeSecours', 'mailEnabled', 'nextcloudEnabled', 'mobilizonEnabled', 'agoraEnabled', 'userPassword', 'identifiantKaz', 'mailAlias', 'quota']
|
|
|
|
return field in allowed_fields
|
|
|
|
|
|
|
|
@jwt_required()
|
|
|
|
def get(self, email):
|
|
|
|
"""
|
|
|
|
Vérifier si un utilisateur avec cet email existe dans le LDAP soit comme mail principal soit comme alias
|
|
|
|
---
|
|
|
|
tags:
|
|
|
|
- Ldap
|
|
|
|
security:
|
|
|
|
- Bearer: []
|
|
|
|
parameters:
|
|
|
|
- in: path
|
|
|
|
name: email
|
|
|
|
type: string
|
|
|
|
required: true
|
|
|
|
responses:
|
|
|
|
200:
|
|
|
|
description: Existe
|
|
|
|
400:
|
|
|
|
description: N'existe pas
|
|
|
|
401:
|
|
|
|
description: oops, email invalide
|
|
|
|
402:
|
|
|
|
description: oops, autre erreur
|
|
|
|
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
|
|
|
|
if not validate_email(email):
|
|
|
|
return "Adresse e-mail non valide", 400
|
|
|
|
|
|
|
|
ldap_connection = self._connect_ldap()
|
|
|
|
|
|
|
|
#result = ldap_connection.search_s("ou=users,{}".format(self.ldap_root), ldap.SCOPE_SUBTREE, "(cn={})".format(email))
|
|
|
|
|
|
|
|
# Créer une chaîne de filtre pour rechercher dans les champs "cn" et "mailAlias"
|
|
|
|
filter_str = "(|(cn={})(mailAlias={}))".format(email, email)
|
|
|
|
result = ldap_connection.search_s("ou=users,{}".format(self.ldap_root), ldap.SCOPE_SUBTREE, filter_str)
|
|
|
|
|
|
|
|
ldap_connection.unbind_s()
|
|
|
|
|
|
|
|
if result:
|
|
|
|
return True, 200
|
|
|
|
else:
|
|
|
|
return False, 400
|
|
|
|
|
|
|
|
except EmailNotValidError as e:
|
|
|
|
return str(e), 401
|
|
|
|
|
|
|
|
except ldap.LDAPError as e:
|
|
|
|
return str(e), 402
|
|
|
|
|
|
|
|
|
|
|
|
#*************************************************
|
|
|
|
@jwt_required()
|
|
|
|
def delete(self, email):
|
|
|
|
"""
|
|
|
|
Supprimer un utilisateur du LDAP par son adresse e-mail
|
|
|
|
---
|
|
|
|
tags:
|
|
|
|
- Ldap
|
|
|
|
security:
|
|
|
|
- Bearer: []
|
|
|
|
parameters:
|
|
|
|
- in: path
|
|
|
|
name: email
|
|
|
|
type: string
|
|
|
|
required: true
|
|
|
|
responses:
|
|
|
|
200:
|
|
|
|
description: Utilisateur supprimé avec succès
|
|
|
|
404:
|
|
|
|
description: Utilisateur non trouvé dans le LDAP
|
|
|
|
400:
|
|
|
|
description: Erreur lors de la suppression de l'utilisateur
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
if not validate_email(email):
|
|
|
|
return "Adresse e-mail non valide", 400
|
|
|
|
|
|
|
|
ldap_connection = self._connect_ldap()
|
|
|
|
|
|
|
|
# Recherche de l'utilisateur
|
|
|
|
result = ldap_connection.search_s("ou=users,{}".format(self.ldap_root), ldap.SCOPE_SUBTREE, "(cn={})".format(email))
|
|
|
|
|
|
|
|
if not result:
|
|
|
|
return False, 404 # Utilisateur non trouvé
|
|
|
|
|
|
|
|
# Récupération du DN de l'utilisateur
|
|
|
|
dn = result[0][0]
|
|
|
|
|
|
|
|
# Suppression de l'utilisateur
|
|
|
|
ldap_connection.delete_s(dn)
|
|
|
|
ldap_connection.unbind_s()
|
|
|
|
|
|
|
|
return True, 200 # Utilisateur supprimé avec succès
|
|
|
|
|
|
|
|
except ldap.NO_SUCH_OBJECT:
|
|
|
|
return False, 404 # Utilisateur non trouvé
|
|
|
|
except ldap.LDAPError as e:
|
|
|
|
return str(e), 400 # Erreur lors de la suppression
|
|
|
|
except EmailNotValidError as e:
|
|
|
|
return str(e), 400
|
|
|
|
|
|
|
|
|
|
|
|
#*************************************************
|
|
|
|
@jwt_required()
|
|
|
|
def post(self, email):
|
|
|
|
"""
|
|
|
|
Ajouter, supprimer ou modifier un champ pour l'utilisateur LDAP
|
|
|
|
---
|
|
|
|
tags:
|
|
|
|
- Ldap
|
|
|
|
security:
|
|
|
|
- Bearer: []
|
|
|
|
parameters:
|
|
|
|
- in: path
|
|
|
|
name: email
|
|
|
|
type: string
|
|
|
|
required: true
|
|
|
|
- in: query
|
|
|
|
name: action
|
|
|
|
type: string
|
|
|
|
required: true
|
|
|
|
enum: ['add', 'delete', 'modify']
|
|
|
|
- in: body
|
|
|
|
name: data
|
|
|
|
required: true
|
|
|
|
schema:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
field:
|
|
|
|
type: string
|
2024-08-30 23:36:02 +02:00
|
|
|
enum: ['mailDeSecours', 'mailEnabled', 'nextcloudEnabled', 'mobilizonEnabled', 'agoraEnabled', 'userPassword', 'identifiantKaz', 'mailAlias', 'quota', 'numeroMembre']
|
2024-08-20 01:53:17 +02:00
|
|
|
description: Le champ à ajouter, supprimer ou modifier (par exemple, mailDeSecours, mailAlias, etc.)
|
|
|
|
value:
|
|
|
|
type: string
|
|
|
|
description: La valeur à ajouter, supprimer ou modifier pour le champ spécifié
|
|
|
|
responses:
|
|
|
|
200:
|
|
|
|
description: Opération réussie
|
|
|
|
404:
|
|
|
|
description: Utilisateur non trouvé dans le LDAP
|
|
|
|
400:
|
|
|
|
description: Erreur lors de l'opération
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
if not validate_email(email):
|
|
|
|
return "Adresse e-mail non valide", 400
|
|
|
|
|
|
|
|
action = request.args.get('action')
|
|
|
|
field = request.json.get('field')
|
|
|
|
value = request.json.get('value')
|
|
|
|
|
|
|
|
if not action or not field or not value:
|
|
|
|
return "Action, champ ou valeur manquant", 400
|
|
|
|
|
|
|
|
if not self.is_valid_field(field):
|
|
|
|
return "Champ non autorisé", 400
|
|
|
|
|
|
|
|
ldap_connection = self._connect_ldap()
|
|
|
|
result = ldap_connection.search_s("ou=users,{}".format(self.ldap_root), ldap.SCOPE_SUBTREE, "(cn={})".format(email))
|
|
|
|
|
|
|
|
if not result:
|
|
|
|
return False, 404
|
|
|
|
|
|
|
|
dn = result[0][0]
|
|
|
|
|
|
|
|
if field == 'userPassword' and (action == 'add' or action == 'modify'):
|
|
|
|
password_chiffre = sha512_crypt.hash(value)
|
|
|
|
value = "{{CRYPT}}{}".format(password_chiffre)
|
|
|
|
|
|
|
|
if action == 'add':
|
|
|
|
mod_attrs = [(ldap.MOD_ADD, field, value.encode('utf-8'))]
|
|
|
|
|
|
|
|
elif action == 'delete':
|
|
|
|
mod_attrs = [(ldap.MOD_DELETE, field, value.encode('utf-8'))]
|
|
|
|
|
|
|
|
elif action == 'modify':
|
|
|
|
|
|
|
|
if field == 'quota':
|
|
|
|
mail_quota_value = value + 'G'
|
|
|
|
nextcloud_quota_value = value + " GB"
|
|
|
|
mod_attrs = [
|
|
|
|
(ldap.MOD_REPLACE, 'quota', value.encode('utf-8')),
|
|
|
|
(ldap.MOD_REPLACE, 'mailQuota', mail_quota_value.encode('utf-8')),
|
|
|
|
(ldap.MOD_REPLACE, 'nextcloudQuota', nextcloud_quota_value.encode('utf-8'))
|
|
|
|
]
|
|
|
|
else:
|
|
|
|
mod_attrs = [(ldap.MOD_REPLACE, field, value.encode('utf-8'))]
|
|
|
|
|
|
|
|
else:
|
|
|
|
return "Action non valide", 400
|
|
|
|
|
|
|
|
ldap_connection.modify_s(dn, mod_attrs)
|
|
|
|
ldap_connection.unbind_s()
|
|
|
|
|
|
|
|
return True, 200
|
|
|
|
|
|
|
|
except ldap.NO_SUCH_OBJECT:
|
|
|
|
return False, 404
|
|
|
|
except ldap.LDAPError as e:
|
|
|
|
return str(e), 400
|
|
|
|
except EmailNotValidError as e:
|
|
|
|
return str(e), 400
|
|
|
|
|
|
|
|
#*************************************************
|
|
|
|
@jwt_required()
|
|
|
|
def put(self, email, **kwargs):
|
|
|
|
"""
|
|
|
|
Créer une nouvelle entrée dans le LDAP pour un nouvel utilisateur. QUESTION: A QUOI SERVENT PRENOM/NOM/IDENT_KAZ DANS LE LDAP ? POURQUOI 3 QUOTA ?
|
|
|
|
---
|
|
|
|
tags:
|
|
|
|
- Ldap
|
|
|
|
security:
|
|
|
|
- Bearer: []
|
|
|
|
parameters:
|
|
|
|
- in: path
|
|
|
|
name: email
|
|
|
|
type: string
|
|
|
|
required: true
|
|
|
|
- in: body
|
|
|
|
name: data
|
|
|
|
required: true
|
|
|
|
schema:
|
|
|
|
type: object
|
|
|
|
properties:
|
|
|
|
prenom:
|
|
|
|
type: string
|
|
|
|
description: Prénom de l'utilisateur
|
|
|
|
nom:
|
|
|
|
type: string
|
|
|
|
description: Nom de l'utilisateur
|
|
|
|
password:
|
|
|
|
type: string
|
|
|
|
description: Mot de passe de l'utilisateur
|
|
|
|
email_secours:
|
|
|
|
type: string
|
|
|
|
description: Adresse e-mail de secours
|
|
|
|
quota:
|
|
|
|
type: string
|
|
|
|
description: Quota de l'utilisateur
|
|
|
|
responses:
|
|
|
|
200:
|
|
|
|
description: Utilisateur ajouté avec succès
|
|
|
|
400:
|
|
|
|
description: Erreur lors de l'ajout de l'utilisateur
|
|
|
|
406:
|
|
|
|
description: Erreur utilisateur déjà existant
|
|
|
|
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
|
|
|
|
if kwargs: # appel depuis une autre api
|
|
|
|
email_secours = kwargs.get('email_secours')
|
|
|
|
prenom = kwargs.get('prenom')
|
|
|
|
nom = kwargs.get('nom')
|
|
|
|
password = kwargs.get('password')
|
|
|
|
quota = kwargs.get('quota')
|
|
|
|
|
|
|
|
else: # appel depuis swagger
|
|
|
|
email_secours = request.json.get('email_secours')
|
|
|
|
nom = request.json.get('nom')
|
|
|
|
prenom = request.json.get('prenom')
|
|
|
|
password = request.json.get('password')
|
|
|
|
quota = request.json.get('quota')
|
|
|
|
|
|
|
|
password_chiffre = sha512_crypt.hash(password)
|
|
|
|
|
|
|
|
if not validate_email(email) or not validate_email(email_secours):
|
|
|
|
return "Adresse e-mail ou secours non valide", 400
|
|
|
|
|
|
|
|
#le user existe t-il déjà ?
|
|
|
|
ldap_connection = self._connect_ldap()
|
|
|
|
result = ldap_connection.search_s("ou=users,{}".format(self.ldap_root), ldap.SCOPE_SUBTREE, "(cn={})".format(email))
|
|
|
|
|
|
|
|
if result:
|
|
|
|
return "User déjà existant", 406
|
|
|
|
|
|
|
|
# Construire le DN
|
|
|
|
dn = f"cn={email},ou=users,{ldap_root}"
|
|
|
|
|
|
|
|
mod_attrs = [
|
|
|
|
('objectClass', [b'inetOrgPerson', b'PostfixBookMailAccount', b'nextcloudAccount', b'kaznaute']),
|
|
|
|
('sn', f'{prenom} {nom}'.encode('utf-8')),
|
|
|
|
('mail', email.encode('utf-8')),
|
|
|
|
('mailEnabled', b'TRUE'),
|
|
|
|
('mailGidNumber', b'5000'),
|
|
|
|
('mailHomeDirectory', f"/var/mail/{email.split('@')[1]}/{email.split('@')[0]}/".encode('utf-8')),
|
|
|
|
('mailQuota', f'{quota}G'.encode('utf-8')),
|
|
|
|
('mailStorageDirectory', f"maildir:/var/mail/{email.split('@')[1]}/{email.split('@')[0]}/".encode('utf-8')),
|
|
|
|
('mailUidNumber', b'5000'),
|
|
|
|
('mailDeSecours', email_secours.encode('utf-8')),
|
|
|
|
('identifiantKaz', f'{prenom.lower()}.{nom.lower()}'.encode('utf-8')),
|
|
|
|
('quota', str(quota).encode('utf-8')),
|
|
|
|
('nextcloudEnabled', b'TRUE'),
|
|
|
|
('nextcloudQuota', f'{quota} GB'.encode('utf-8')),
|
|
|
|
('mobilizonEnabled', b'TRUE'),
|
|
|
|
('agoraEnabled', b'TRUE'),
|
|
|
|
('userPassword', f'{{CRYPT}}{password_chiffre}'.encode('utf-8')),
|
|
|
|
('cn', email.encode('utf-8'))
|
|
|
|
]
|
|
|
|
|
|
|
|
ldap_connection.add_s(dn, mod_attrs)
|
|
|
|
ldap_connection.unbind_s()
|
|
|
|
|
2024-08-30 23:36:02 +02:00
|
|
|
return "Utilisateur créé dans le ldap", 200
|
2024-08-20 01:53:17 +02:00
|
|
|
|
|
|
|
except ldap.LDAPError as e:
|
|
|
|
return str(e), 400
|
|
|
|
except EmailNotValidError as e:
|
|
|
|
return str(e), 400
|
|
|
|
|
|
|
|
#*************************************************
|
|
|
|
|
|
|
|
|
|
|
|
|