ajout gestion token et basic auth sur apikaz
This commit is contained in:
parent
7c52d4844b
commit
94cbbc1006
@ -14,6 +14,8 @@ from flask import Flask, jsonify, send_from_directory, request, abort, json, Res
|
||||
from flask_mail import Mail, Message
|
||||
from flasgger import Swagger
|
||||
from flask_restful import Api, Resource
|
||||
from flask_jwt_extended import JWTManager, create_access_token, jwt_required
|
||||
|
||||
from passlib.hash import sha512_crypt
|
||||
from unidecode import unidecode
|
||||
from email_validator import validate_email, EmailNotValidError
|
||||
@ -23,6 +25,7 @@ from bs4 import BeautifulSoup
|
||||
from datetime import datetime
|
||||
|
||||
app = Flask(__name__)
|
||||
jwt = JWTManager(app)
|
||||
api = Api(app)
|
||||
|
||||
app.logger.setLevel(logging.DEBUG)
|
||||
@ -33,8 +36,41 @@ swagger = Swagger(app, template={
|
||||
"title": "L'API Kaz de la mort qui tue",
|
||||
"version": "0.2.0",
|
||||
"description": "Permettre des opérations de gestion des services kaz avec des écrans Ouaib"
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
{"name": "Authentication", "description": "Auth related operations"},
|
||||
{"name": "Test", "description": "pour tester des conneries"},
|
||||
{"name": "Password", "description": "Gestion Mdp"},
|
||||
{"name": "Paheko", "description": "Gestion Paheko"},
|
||||
{"name": "Mattermost", "description": "Gestion Mattermost Authent"},
|
||||
{"name": "Mattermost User", "description": "Gestion Mattermost User"},
|
||||
{"name": "Mattermost Team", "description": "Gestion Mattermost Team"},
|
||||
{"name": "Ldap", "description": "Gestion Ldap"},
|
||||
{"name": "Cloud", "description": "Gestion Cloud Général"},
|
||||
{"name": "Sympa", "description": "Gestion Sympa"},
|
||||
{"name": "Quota", "description": "Gestion Quota"},
|
||||
{"name": "Dns", "description": "Gestion Dns"},
|
||||
{"name": "Kaz User", "description": "Gestion Kaz User"}
|
||||
],
|
||||
"securityDefinitions": {
|
||||
"basicAuth": {
|
||||
"type": "basic",
|
||||
"description": "Basic Authentication with username and password"
|
||||
},
|
||||
"Bearer": {
|
||||
"type": "apiKey",
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
"description": "JWT Authorization header using the Bearer scheme. Example: 'Bearer {token}'"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
#TODO:
|
||||
# check variables
|
||||
# fail2ban (ou alors sur traefik)
|
||||
# découper app.py en service
|
||||
# quels scripts bash garder ?
|
||||
|
||||
#*************************************************
|
||||
|
||||
@ -47,7 +83,7 @@ swagger = Swagger(app, template={
|
||||
#TODO: au lieu d'avoir les IP en dur, prendre le fichier allow_ip'
|
||||
|
||||
trusted_ips = [
|
||||
"82.64.20.246",
|
||||
"82.64.20.246",
|
||||
"31.39.14.228",
|
||||
"51.75.112.172",
|
||||
"80.11.47.59",
|
||||
@ -58,44 +94,17 @@ trusted_ips = [
|
||||
"80.67.176.91",
|
||||
"89.234.177.119",
|
||||
"78.127.1.19",
|
||||
"80.215.236.243",
|
||||
"78.117.86.68",
|
||||
"80.215.236.168"
|
||||
"80.215.236.243"
|
||||
]
|
||||
|
||||
@app.before_request
|
||||
def limit_remote_addr():
|
||||
if request.environ['HTTP_X_FORWARDED_FOR'] not in trusted_ips:
|
||||
abort(jsonify(message="Et pis quoi encore "+request.environ['HTTP_X_FORWARDED_FOR']), 400)
|
||||
|
||||
|
||||
|
||||
#*************************************************
|
||||
|
||||
@app.route('/print_env')
|
||||
def print_environment():
|
||||
# Crée une chaîne de caractères pour stocker les variables d'environnement
|
||||
env_string = ""
|
||||
|
||||
# Itère sur les variables d'environnement et les ajoute à la chaîne de caractères
|
||||
for key, value in os.environ.items():
|
||||
env_string += f"{key}: {value}\n" + "<br>"
|
||||
|
||||
# Retourne la chaîne de caractères contenant les variables d'environnement
|
||||
return env_string
|
||||
|
||||
#*************************************************
|
||||
#***** DEBUT Quelques fonctions utiles ***********
|
||||
#*************************************************
|
||||
|
||||
#pour injecter la date dans dans le contexte des template
|
||||
@app.context_processor
|
||||
def inject_now():
|
||||
return {'now': datetime.now}
|
||||
|
||||
#*************************************************
|
||||
#***** FIN Quelques fonctions utiles ***********
|
||||
#*************************************************
|
||||
|
||||
#variables globales
|
||||
#*************************************************
|
||||
|
||||
#le secret pour générer les tokens
|
||||
#app.config['JWT_SECRET_KEY'] = os.environ.get('JWT_SECRET_KEY')
|
||||
app.config['JWT_SECRET_KEY'] = os.environ.get('JWT_SECRET_KEY', 'your_jwt_secret_key')
|
||||
|
||||
#le paheko de kaz
|
||||
paheko_ident=os.environ.get('paheko_API_USER')
|
||||
@ -148,12 +157,64 @@ MAIL_USERNAME=app.config['MAIL_USERNAME']
|
||||
serveur_imap = os.environ.get('serveur_imap')
|
||||
mot_de_passe_mail=os.environ.get('mot_de_passe_mail')
|
||||
|
||||
#*************************************************
|
||||
@app.before_request
|
||||
def limit_remote_addr():
|
||||
if request.environ['HTTP_X_FORWARDED_FOR'] not in trusted_ips:
|
||||
abort(jsonify(message="Et pis quoi encore ?"), 400)
|
||||
|
||||
#*************************************************
|
||||
#authent mdp/pass basique
|
||||
def check_auth(username, password):
|
||||
return username == os.environ.get('apikaz_doc_user') and password == os.environ.get('apikaz_doc_password')
|
||||
|
||||
def authenticate():
|
||||
return Response('tssssss.\n', 401, {'WWW-Authenticate': 'Basic realm="Login Required"'})
|
||||
|
||||
@app.before_request
|
||||
def require_basic_auth():
|
||||
if request.path.startswith('/apidocs') or request.path.startswith('/print_env'):
|
||||
#if request.path.startswith('/'):
|
||||
auth = request.authorization
|
||||
if not auth or not check_auth(auth.username, auth.password):
|
||||
return authenticate()
|
||||
|
||||
|
||||
#*************************************************
|
||||
#DANGER: ne jamais mettre print_env en PROD
|
||||
@app.route('/print_env')
|
||||
def print_environment():
|
||||
# Crée une chaîne de caractères pour stocker les variables d'environnement
|
||||
env_string = ""
|
||||
|
||||
# Itère sur les variables d'environnement et les ajoute à la chaîne de caractères
|
||||
for key, value in os.environ.items():
|
||||
env_string += f"{key}: {value}\n" + "<br>"
|
||||
|
||||
# Retourne la chaîne de caractères contenant les variables d'environnement
|
||||
return env_string
|
||||
|
||||
#*************************************************
|
||||
#***** DEBUT Quelques fonctions utiles ***********
|
||||
#*************************************************
|
||||
|
||||
#pour injecter la date dans dans le contexte des template
|
||||
@app.context_processor
|
||||
def inject_now():
|
||||
return {'now': datetime.now}
|
||||
|
||||
#*************************************************
|
||||
#***** FIN Quelques fonctions utiles ***********
|
||||
#*************************************************
|
||||
|
||||
|
||||
#*************************************************
|
||||
|
||||
@app.route('/favicon.ico')
|
||||
def favicon():
|
||||
# return send_from_directory(os.path.join(app.root_path, 'static'),'favicon.ico')
|
||||
return '', 204
|
||||
|
||||
|
||||
#*************************************************
|
||||
#la page d'accueil est vide
|
||||
@ -161,16 +222,51 @@ def favicon():
|
||||
def silence():
|
||||
return ""
|
||||
|
||||
|
||||
#*************************************************
|
||||
# obtenir un token
|
||||
@app.route('/get_token', methods=['GET'])
|
||||
def get_token():
|
||||
"""
|
||||
Get JWT token with basic auth
|
||||
---
|
||||
tags:
|
||||
- Authentication
|
||||
security:
|
||||
- basicAuth: []
|
||||
responses:
|
||||
200:
|
||||
description: Token generated successfully
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
access_token:
|
||||
type: string
|
||||
description: JWT access token
|
||||
401:
|
||||
description: Unauthorized
|
||||
"""
|
||||
auth = request.authorization
|
||||
if auth and check_auth(auth.username, auth.password):
|
||||
# Créez un token JWT après une authentification réussie
|
||||
access_token = create_access_token(identity=auth.username)
|
||||
return jsonify(access_token=access_token)
|
||||
else:
|
||||
return authenticate()
|
||||
|
||||
#*************************************************
|
||||
#*******MDP***************************************
|
||||
#*************************************************
|
||||
class Password_create(Resource):
|
||||
@jwt_required()
|
||||
def get(self):
|
||||
"""
|
||||
créer un password qui colle avec les appli kaz
|
||||
---
|
||||
tags:
|
||||
- Password
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters: []
|
||||
responses:
|
||||
200:
|
||||
@ -184,7 +280,7 @@ class Password_create(Resource):
|
||||
try:
|
||||
output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
|
||||
new_password="_"+output.decode("utf-8")+"_"
|
||||
return new_password,200
|
||||
return new_password,200
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
return e.output.decode("utf-8"), 400
|
||||
@ -196,12 +292,16 @@ api.add_resource(Password_create, '/password/create')
|
||||
#*************************************************
|
||||
|
||||
class Paheko_categories(Resource):
|
||||
|
||||
@jwt_required()
|
||||
def get(self):
|
||||
"""
|
||||
Récupérer les catégories Paheko avec le compteur associé
|
||||
---
|
||||
tags:
|
||||
- Paheko
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters: []
|
||||
responses:
|
||||
200:
|
||||
@ -227,12 +327,16 @@ api.add_resource(Paheko_categories, '/paheko/user/categories')
|
||||
#*************************************************
|
||||
|
||||
class Paheko_users(Resource):
|
||||
|
||||
@jwt_required()
|
||||
def get(self,categorie):
|
||||
"""
|
||||
Afficher les membres d'une catégorie Paheko
|
||||
---
|
||||
tags:
|
||||
- Paheko
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: categorie
|
||||
@ -248,6 +352,9 @@ class Paheko_users(Resource):
|
||||
global paheko_ident, paheko_pass, paheko_url
|
||||
|
||||
auth = (paheko_ident, paheko_pass)
|
||||
if not categorie.isdigit():
|
||||
return 'Id de category non valide', 400
|
||||
|
||||
api_url = paheko_url + '/api/user/category/'+categorie+'.json'
|
||||
|
||||
response = requests.get(api_url, auth=auth)
|
||||
@ -263,19 +370,23 @@ api.add_resource(Paheko_users, '/paheko/user/category/<categorie>')
|
||||
#*************************************************
|
||||
|
||||
class Paheko_user(Resource):
|
||||
|
||||
def __init__(self):
|
||||
global paheko_ident, paheko_pass, paheko_url
|
||||
self.paheko_ident = paheko_ident
|
||||
self.paheko_pass = paheko_pass
|
||||
self.paheko_url = paheko_url
|
||||
self.auth = (self.paheko_ident, self.paheko_pass)
|
||||
|
||||
|
||||
@jwt_required()
|
||||
def get(self,ident):
|
||||
"""
|
||||
Afficher un membre de Paheko par son email kaz ou son numéro ou le non court de l'orga
|
||||
---
|
||||
tags:
|
||||
- Paheko
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: ident
|
||||
@ -289,8 +400,10 @@ class Paheko_user(Resource):
|
||||
description: N'existe pas
|
||||
"""
|
||||
|
||||
if '@' in ident:
|
||||
data = { "sql": f"select * from users where email='{ident}'" }
|
||||
emailmatchregexp = re.compile(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
|
||||
|
||||
if emailmatchregexp.match(ident):
|
||||
data = { "sql": f"select * from users where email='{ident}' or alias = '{ident}'" }
|
||||
api_url = self.paheko_url + '/api/sql/'
|
||||
response = requests.post(api_url, auth=self.auth, data=data)
|
||||
#TODO: if faut Rechercher count et vérifier que = 1 et supprimer le count=1 dans la réponse
|
||||
@ -298,26 +411,35 @@ class Paheko_user(Resource):
|
||||
api_url = self.paheko_url + '/api/user/'+ident
|
||||
response = requests.get(api_url, auth=self.auth)
|
||||
else:
|
||||
data = { "sql": f"select * from users where admin_orga=1 and nom_orga='{ident}'" }
|
||||
nomorga = re.sub(r'\W+', '', ident) # on vire les caractères non alphanumérique
|
||||
data = { "sql": f"select * from users where admin_orga=1 and nom_orga='{nomorga}'" }
|
||||
api_url = self.paheko_url + '/api/sql/'
|
||||
response = requests.post(api_url, auth=self.auth, data=data)
|
||||
#TODO:if faut Rechercher count et vérifier que = 1 et supprimer le count=1 dans la réponse
|
||||
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
return jsonify(data)
|
||||
if data["count"] == 1:
|
||||
return jsonify(data["results"][0])
|
||||
elif data["count"] == 0:
|
||||
return "pas de résultat", 400
|
||||
else:
|
||||
return "Plusieurs utilisateurs correspondent ?!", 400
|
||||
else:
|
||||
#return jsonify({'error': 'La requête a échoué'}), response.status_code
|
||||
return "pas de résultat", response.status_code
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def put(self,ident,field,new_value):
|
||||
"""
|
||||
Modifie la valeur d'un champ d'un membre paheko (ident= numéro paheko ou email kaz)
|
||||
---
|
||||
tags:
|
||||
- Paheko
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: ident
|
||||
@ -345,7 +467,8 @@ class Paheko_user(Resource):
|
||||
"""
|
||||
|
||||
#récupérer le numero paheko si on fournit un email kaz
|
||||
if '@' in ident:
|
||||
emailmatchregexp = re.compile(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
|
||||
if emailmatchregexp.match(ident):
|
||||
data = { "sql": f"select id from users where email='{ident}'" }
|
||||
api_url = self.paheko_url + '/api/sql/'
|
||||
response = requests.post(api_url, auth=self.auth, data=data)
|
||||
@ -361,16 +484,23 @@ class Paheko_user(Resource):
|
||||
ident = data['results'][0]['id']
|
||||
else:
|
||||
return "pas de résultat", response.status_code
|
||||
|
||||
elif not ident.isdigit():
|
||||
return "Identifiant utilisateur invalide", response.status_code
|
||||
|
||||
regexp = re.compile("[^a-zA-Z0-9 \\r\\n\\t" + re.escape(string.punctuation) + "]")
|
||||
valeur = regexp.sub('',new_value) # mouais, il faudrait être beaucoup plus précis ici en fonction des champs qu'on accepte...
|
||||
|
||||
champ = re.sub(r'\W+','',field) # pas de caractères non alphanumériques ici, dans l'idéal, c'est à choisir dans une liste plutot
|
||||
|
||||
api_url = self.paheko_url + '/api/user/'+str(ident)
|
||||
payload = {field: new_value}
|
||||
payload = {champ: valeur}
|
||||
response = requests.post(api_url, auth=self.auth, data=payload)
|
||||
return response.json(),response.status_code
|
||||
|
||||
#*************************************************
|
||||
|
||||
api.add_resource(Paheko_user, '/paheko/user/<ident>', endpoint='paheko_get_user', methods=['GET'])
|
||||
api.add_resource(Paheko_user, '/paheko/user/<ident>/<field>/<new_value>', endpoint='paheko_maj_user', methods=['PUT'])
|
||||
api.add_resource(Paheko_user, '/paheko/user/<ident>/<string:field>/<string:new_value>', endpoint='paheko_maj_user', methods=['PUT'])
|
||||
|
||||
#*************************************************
|
||||
|
||||
@ -382,12 +512,15 @@ class Paheko_users_action(Resource):
|
||||
self.paheko_pass = paheko_pass
|
||||
self.paheko_url = paheko_url
|
||||
|
||||
@jwt_required()
|
||||
def get(self, action):
|
||||
"""
|
||||
retourne tous les membres de paheko avec une action à mener (création du compte kaz / modification...)
|
||||
---
|
||||
tags:
|
||||
- Paheko
|
||||
- Paheko
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: action
|
||||
@ -411,7 +544,7 @@ class Paheko_users_action(Resource):
|
||||
else:
|
||||
return "pas de résultat", response.status_code
|
||||
|
||||
api.add_resource(Paheko_users_action, '/paheko/users/<string:action>')
|
||||
api.add_resource(Paheko_users_action, '/paheko/users/<string:action>')
|
||||
|
||||
#*************************************************
|
||||
#*******MATTERMOST********************************
|
||||
@ -431,12 +564,16 @@ def Mattermost_authenticate():
|
||||
#*************************************************
|
||||
|
||||
class Mattermost_message(Resource):
|
||||
|
||||
@jwt_required()
|
||||
def post(self,message,equipe="kaz",canal="creation-comptes"):
|
||||
"""
|
||||
Envoyer un message dans une Equipe/Canal de MM
|
||||
---
|
||||
tags:
|
||||
- Mattermost
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: equipe
|
||||
@ -476,12 +613,15 @@ class Mattermost_user(Resource):
|
||||
Mattermost_authenticate()
|
||||
|
||||
#*************************************************
|
||||
@jwt_required()
|
||||
def get(self,user):
|
||||
"""
|
||||
Le user existe t-il sur MM ?
|
||||
---
|
||||
tags:
|
||||
- Mattermost User
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: user
|
||||
@ -503,13 +643,15 @@ class Mattermost_user(Resource):
|
||||
return 404 # Le nom d'utilisateur n'existe pas
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def post(self,user,email,password):
|
||||
"""
|
||||
Créer un utilisateur sur MM
|
||||
---
|
||||
tags:
|
||||
- Mattermost User
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: user
|
||||
@ -541,12 +683,15 @@ class Mattermost_user(Resource):
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def delete(self,email):
|
||||
"""
|
||||
Supprimer un utilisateur sur MM
|
||||
---
|
||||
tags:
|
||||
- Mattermost User
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -568,12 +713,16 @@ class Mattermost_user(Resource):
|
||||
return e.output.decode("utf-8"), 400
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def put(self,email,new_password):
|
||||
"""
|
||||
Changer un password pour un utilisateur de MM
|
||||
---
|
||||
tags:
|
||||
- Mattermost User
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -607,12 +756,16 @@ api.add_resource(Mattermost_user, '/mattermost/user/change/password/<string:emai
|
||||
#*************************************************
|
||||
|
||||
class Mattermost_user_team(Resource):
|
||||
|
||||
@jwt_required()
|
||||
def post(self,email,equipe):
|
||||
"""
|
||||
Affecte un utilisateur à une équipe MM
|
||||
---
|
||||
tags:
|
||||
- Mattermost Team
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -643,12 +796,15 @@ api.add_resource(Mattermost_user_team, '/mattermost/user/team/<string:email>/<st
|
||||
#*************************************************
|
||||
|
||||
class Mattermost_user_channel(Resource):
|
||||
@jwt_required()
|
||||
def post(self,email,equipe,canal):
|
||||
"""
|
||||
Affecte un utilisateur à un canal MM
|
||||
---
|
||||
tags:
|
||||
- Mattermost
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -688,12 +844,16 @@ class Mattermost_team(Resource):
|
||||
Mattermost_authenticate()
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def get(self):
|
||||
"""
|
||||
Lister les équipes sur MM
|
||||
---
|
||||
tags:
|
||||
- Mattermost Team
|
||||
- Mattermost Team
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters: []
|
||||
responses:
|
||||
200:
|
||||
@ -715,12 +875,15 @@ class Mattermost_team(Resource):
|
||||
return e.output.decode("utf-8"), 400
|
||||
|
||||
#*************************************************
|
||||
@jwt_required()
|
||||
def post(self,equipe,email):
|
||||
"""
|
||||
Créer une équipe sur MM et affecter un admin si email est renseigné (set admin marche pô)
|
||||
---
|
||||
tags:
|
||||
- Mattermost Team
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: equipe
|
||||
@ -752,12 +915,15 @@ class Mattermost_team(Resource):
|
||||
return e.output.decode("utf-8"), 400
|
||||
|
||||
#*************************************************
|
||||
@jwt_required()
|
||||
def delete(self,equipe):
|
||||
"""
|
||||
Supprimer une équipe sur MM
|
||||
---
|
||||
tags:
|
||||
- Mattermost Team
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: equipe
|
||||
@ -807,12 +973,15 @@ class Ldap_user(Resource):
|
||||
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
|
||||
@ -857,13 +1026,15 @@ class Ldap_user(Resource):
|
||||
|
||||
|
||||
#*************************************************
|
||||
|
||||
@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
|
||||
@ -907,13 +1078,15 @@ class Ldap_user(Resource):
|
||||
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def post(self, email):
|
||||
"""
|
||||
Ajouter, supprimer ou modifier un champ pour l'utilisateur LDAP
|
||||
---
|
||||
tags:
|
||||
- Ldap
|
||||
- Ldap
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -1007,13 +1180,15 @@ class Ldap_user(Resource):
|
||||
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
|
||||
- Ldap
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -1126,12 +1301,16 @@ api.add_resource(Ldap_user, '/ldap/user/add/<string:email>', endpoint='ldap_user
|
||||
#TODO: pas réussi à faire une seule classe Cloud_user avec 2 méthodes get/delete
|
||||
|
||||
class Cloud_user(Resource):
|
||||
|
||||
@jwt_required()
|
||||
def get(self, email):
|
||||
"""
|
||||
Existe dans le cloud général ?
|
||||
---
|
||||
tags:
|
||||
- Cloud
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -1167,6 +1346,8 @@ api.add_resource(Cloud_user, '/cloud/user/<string:email>')
|
||||
|
||||
#*************************************************
|
||||
class Cloud_user_delete(Resource):
|
||||
|
||||
@jwt_required()
|
||||
def delete(self, email):
|
||||
"""
|
||||
Supprime le compte dans le cloud général
|
||||
@ -1174,6 +1355,8 @@ class Cloud_user_delete(Resource):
|
||||
---
|
||||
tags:
|
||||
- Cloud
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -1209,12 +1392,15 @@ api.add_resource(Cloud_user_delete, '/cloud/user/delete/<string:email>')
|
||||
|
||||
#*************************************************
|
||||
# class Cloud_user_change(Resource):
|
||||
# @jwt_required()
|
||||
# def put(self, email, new_password):
|
||||
# """
|
||||
# Modifie le mot de passe d'un Utilisateur dans le cloud général: QUESTION: A PRIORI INUTILE CAR LIE AU LDAP
|
||||
# ---
|
||||
# tags:
|
||||
# - Cloud
|
||||
# security:
|
||||
# - Bearer: []
|
||||
# parameters:
|
||||
# - in: path
|
||||
# name: email
|
||||
@ -1278,12 +1464,15 @@ class Sympa_user(Resource):
|
||||
except subprocess.CalledProcessError as e:
|
||||
return e.output.decode("utf-8"), 400 # Retourne la sortie de la commande et un code d'erreur 400
|
||||
|
||||
@jwt_required()
|
||||
def post(self, email, liste):
|
||||
"""
|
||||
Ajouter un email dans une liste sympa
|
||||
---
|
||||
tags:
|
||||
- Sympa
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -1302,12 +1491,15 @@ class Sympa_user(Resource):
|
||||
output, status_code = self._execute_sympa_command(email, liste, 'add')
|
||||
return output, status_code
|
||||
|
||||
@jwt_required()
|
||||
def delete(self, email, liste):
|
||||
"""
|
||||
Supprimer un email dans une liste sympa
|
||||
---
|
||||
tags:
|
||||
- Sympa
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -1340,13 +1532,15 @@ class Quota(Resource):
|
||||
# sur kazkouil.fr, j'ai modifié /etc/dovecot/conf.d/20-lmtp.conf
|
||||
#mail_plugins = $mail_plugins sieve quota
|
||||
|
||||
|
||||
@jwt_required()
|
||||
def get(self, email):
|
||||
"""
|
||||
Récupérer la place prise par une BAL
|
||||
Récupérer la place prise par une BAL (EN COURS)
|
||||
---
|
||||
tags:
|
||||
- Quota (EN COURS)
|
||||
- Quota
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: email
|
||||
@ -1402,12 +1596,15 @@ class Dns_serveurs(Resource):
|
||||
self.gandi_key = gandi_key
|
||||
self.gandi_url_api = gandi_url_api
|
||||
|
||||
@jwt_required()
|
||||
def get(self):
|
||||
"""
|
||||
Renvoie tous les serveurs kaz de la zone dns
|
||||
---
|
||||
tags:
|
||||
- Dns
|
||||
security:
|
||||
- Bearer: []
|
||||
responses:
|
||||
200:
|
||||
description: Succès, liste des serveurs
|
||||
@ -1440,13 +1637,15 @@ class Dns(Resource):
|
||||
self.dns_serveurs_resource = Dns_serveurs()
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def get(self,sdomaine):
|
||||
"""
|
||||
Le sous-domaine existe t-il dans la zone dns avec un enreg CNAME ?
|
||||
---
|
||||
tags:
|
||||
- Dns
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: sdomaine
|
||||
@ -1466,12 +1665,15 @@ class Dns(Resource):
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def delete(self,sdomaine):
|
||||
"""
|
||||
suppression du sdomaine
|
||||
---
|
||||
tags:
|
||||
- Dns
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: sdomaine
|
||||
@ -1490,12 +1692,15 @@ class Dns(Resource):
|
||||
|
||||
#*************************************************
|
||||
|
||||
@jwt_required()
|
||||
def post(self,sdomaine,serveur):
|
||||
"""
|
||||
Créé le sous-domaine de type CNAME qui pointe sur serveur
|
||||
---
|
||||
tags:
|
||||
- Dns
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: sdomaine
|
||||
@ -1564,12 +1769,15 @@ class Kaz_user(Resource):
|
||||
|
||||
|
||||
#********************************************************************************************
|
||||
@jwt_required()
|
||||
def delete(self):
|
||||
"""
|
||||
Utile pour les tests de createUser. Avant le POST de /kaz/create/users. Ça permet de supprimer/maj les comptes.
|
||||
---
|
||||
tags:
|
||||
- Kaz
|
||||
- Kaz User
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters: []
|
||||
responses:
|
||||
201:
|
||||
@ -1608,12 +1816,15 @@ class Kaz_user(Resource):
|
||||
|
||||
#********************************************************************************************
|
||||
|
||||
@jwt_required()
|
||||
def post(self):
|
||||
"""
|
||||
Créé un nouveau kaznaute: inscription sur MM / Cloud / email + msg sur MM + email à partir de action="a créer" sur paheko
|
||||
---
|
||||
tags:
|
||||
- Kaz
|
||||
- Kaz User
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters: []
|
||||
responses:
|
||||
201:
|
||||
@ -1770,12 +1981,15 @@ class Test(Resource):
|
||||
#global mattermost_url, sympa_url, webmail_url, mdp_url, site_url, nc_url
|
||||
|
||||
#********************************************************************************************
|
||||
@jwt_required()
|
||||
def get(self):
|
||||
"""
|
||||
Pour tester des conneries
|
||||
Pour tester des conneries: # test lançement de cmde ssh sur des serveurs distants:
|
||||
---
|
||||
tags:
|
||||
- a simple test
|
||||
- Test
|
||||
security:
|
||||
- Bearer: []
|
||||
parameters: []
|
||||
responses:
|
||||
201:
|
||||
@ -1784,6 +1998,23 @@ class Test(Resource):
|
||||
description: KO
|
||||
"""
|
||||
#********************************************************************************************
|
||||
|
||||
|
||||
# test lançcement de cmde ssh sur des serveurs distants:
|
||||
# il faut au préalable que la clé publique de root du conteneur apikaz soit dans authorized key du user fabricer de la machine 163.172.94.54
|
||||
# clé à créer dans le Dockerfile
|
||||
# risque sécu ?
|
||||
|
||||
|
||||
cmd="ssh -p 2201 fabricer@163.172.94.54 mkdir -p /tmp/toto"
|
||||
try:
|
||||
output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
|
||||
return "ok",200
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
return e.output.decode("utf-8"), 400
|
||||
|
||||
#********************************************************************************************
|
||||
# #***** test suppression de toutes les équipes de MM sauf KAZ
|
||||
# res,status=self.mattermost_team_resource=Mattermost_team().get()
|
||||
# for equipe in res:
|
||||
@ -1794,39 +2025,39 @@ class Test(Resource):
|
||||
|
||||
#**** test messagerie
|
||||
|
||||
NOM="toto"
|
||||
EMAIL_SOUHAITE='f@kaz.bzh'
|
||||
PASSWORD="toto"
|
||||
QUOTA="1"
|
||||
ADMIN_ORGA="0"
|
||||
|
||||
context = {
|
||||
'ADMIN_ORGA': ADMIN_ORGA,
|
||||
'NOM': NOM,
|
||||
'EMAIL_SOUHAITE': EMAIL_SOUHAITE,
|
||||
'PASSWORD': PASSWORD,
|
||||
'QUOTA': QUOTA,
|
||||
'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_SOUHAITE])
|
||||
msg.html = render_template('email_inscription.html', **context)
|
||||
|
||||
# Parsez le contenu HTML avec BeautifulSoup
|
||||
soup = BeautifulSoup(msg.html, 'html.parser')
|
||||
msg.body = soup.get_text()
|
||||
|
||||
mail.send(msg)
|
||||
return "Message envoyé!"
|
||||
# NOM="toto"
|
||||
# EMAIL_SOUHAITE='f@kaz.bzh'
|
||||
# PASSWORD="toto"
|
||||
# QUOTA="1"
|
||||
# ADMIN_ORGA="0"
|
||||
#
|
||||
# context = {
|
||||
# 'ADMIN_ORGA': ADMIN_ORGA,
|
||||
# 'NOM': NOM,
|
||||
# 'EMAIL_SOUHAITE': EMAIL_SOUHAITE,
|
||||
# 'PASSWORD': PASSWORD,
|
||||
# 'QUOTA': QUOTA,
|
||||
# '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_SOUHAITE])
|
||||
# msg.html = render_template('email_inscription.html', **context)
|
||||
#
|
||||
# # Parsez le contenu HTML avec BeautifulSoup
|
||||
# soup = BeautifulSoup(msg.html, 'html.parser')
|
||||
# msg.body = soup.get_text()
|
||||
#
|
||||
# mail.send(msg)
|
||||
# return "Message envoyé!"
|
||||
|
||||
#********************************************************************************************
|
||||
# #**** test ms erreur
|
||||
@ -1847,8 +2078,7 @@ class Test(Resource):
|
||||
# sleep(20)
|
||||
# return str(lock_file), 201
|
||||
|
||||
api.add_resource(Test, '/atest', endpoint='atest', methods=['GET'])
|
||||
|
||||
api.add_resource(Test, '/test', endpoint='test', methods=['GET'])
|
||||
|
||||
#*************************************************
|
||||
#*************************************************
|
||||
|
@ -7,3 +7,5 @@ passlib
|
||||
unidecode
|
||||
email-validator
|
||||
python-ldap
|
||||
flask-jwt-extended
|
||||
BeautifulSoup4
|
||||
|
Loading…
Reference in New Issue
Block a user