from flask import make_response, request, current_app, Flask, jsonify from functools import update_wrapper import json import wrapper as wp import ela_user_account as eua import prj_common as pc from six import string_types from datetime import timedelta import Ela_Spacy as ls import user_message_mgt as um import user_session as us import logging import partners as pa import prj_common as mycommon import ela_index_bdd_classes as ela_index_class import class_mgt as cm import Dev_api_functions as dev_function from flask_cors import CORS, cross_origin import time DEBUG_LEVEL = logging.DEBUG LOG_FILE_NAME = "./Log/log_file.log" upload_folder = "./Data/" ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'} logging.basicConfig( level=DEBUG_LEVEL, filename=LOG_FILE_NAME) app = Flask(__name__) cors = CORS(app, resources={r"/foo": {"origins": "*"}}) app.config['CORS_HEADERS'] = 'Content-Type' app.config['UPLOAD_FOLDER'] = upload_folder def crossdomain(origin=None, methods=None, headers=None, max_age=21600, attach_to_all=True, automatic_options=True): """Decorator function that allows crossdomain requests. Courtesy of https://blog.skyred.fi/articles/better-crossdomain-snippet-for-flask.html """ if methods is not None: methods = ', '.join(sorted(x.upper() for x in methods)) # use str instead of basestring if using Python 3.x if headers is not None and not isinstance(headers, str): headers = ', '.join(x.upper() for x in headers) # use str instead of basestring if using Python 3.x if not isinstance(origin, str): origin = ', '.join(origin) if isinstance(max_age, timedelta): max_age = max_age.total_seconds() def get_methods(): """ Determines which methods are allowed """ if methods is not None: return methods options_resp = current_app.make_default_options_response() return options_resp.headers['allow'] def decorator(f): """The decorator function """ def wrapped_function(*args, **kwargs): """Caries out the actual cross domain code """ if automatic_options and request.method == 'OPTIONS': resp = current_app.make_default_options_response() else: resp = make_response(f(*args, **kwargs)) if not attach_to_all and request.method != 'OPTIONS': return resp h = resp.headers h['Access-Control-Allow-Origin'] = origin h['Access-Control-Allow-Methods'] = get_methods() h['Access-Control-Max-Age'] = str(max_age) h['Access-Control-Allow-Credentials'] = 'true' h['Access-Control-Allow-Headers'] = \ "Origin, X-Requested-With, Content-Type, Accept, Authorization" if headers is not None: h['Access-Control-Allow-Headers'] = headers return resp f.provide_automatic_options = False return update_wrapper(wrapped_function, f) return decorator @app.after_request def after_request(response): response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization') response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS') return response ''' cette API gere le login et la creation du token ''' @app.route('/myclass/api/login/', methods=['POST','GET']) @crossdomain(origin='*') def login(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = us.login(payload) return jsonify(status=status, message=retval) ''' cette API recupere les objectifs d'un utilisateur La clé est l'adresse email. si le nom de la formation est fourni, alors l'api va retourner la formation donnée ''' @app.route('/myclass/api/get_user_objectif/', methods=['POST','GET']) @crossdomain(origin='*') def get_user_objectif(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = eua.get_user_objectif(payload) return jsonify(status=status, message=retval) ''' Cette API desactive un objectif. les clés sont : - adresse email - nom de l'objectif ''' @app.route('/myclass/api/desable_user_objectif/', methods=['POST']) @crossdomain(origin='*') def desable_user_objectif(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = eua.desable_user_objectif(payload) return jsonify(status=status, message=retval) ''' Cette API ajoute un objectif à un utilisateur la clé est l'adresse email ''' @app.route('/myclass/api/add_update_user_objectif/', methods=['POST']) @crossdomain(origin='*') def add_update_user_objectif(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = eua.add_update_user_objectif(payload) return jsonify(status=status, message=retval) ''' Cette Api retourne les info d'un user accout identifié par son adresse email. ''' @app.route('/myclass/api/get_user_account/', methods=['POST','GET']) @crossdomain(origin='*') def get_user_account(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ", payload) result, message = eua.get_user_account(payload) return jsonify(status=result, message=message) ''' Cette API créer un compte utilisateur et declenche l'envoi de l'email de notification ''' @app.route('/myclass/api/add_user_account/', methods=['POST']) @crossdomain(origin='*') def add_user_account(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) mycommon.myprint(" add_user_account : info recues "+str(payload)) result, message = eua.add_user_account(payload) return jsonify(status=result, message=message) ''' Cette API valide une inscription d'un user ''' @app.route('/myclass/api/valide_user_account/', methods=['GET','POST']) @crossdomain(origin='*') def valide_user_account(value): print(" ### validation du compte = ",value) status, retval = eua.valide_user_account(value) return jsonify(status=status, message=retval) ''' Cette api met à jour un compte utilisateur ''' @app.route('/myclass/api/update_user_account/', methods=['POST','GET']) @crossdomain(origin='*') def update_user_account(): payload = request.form.to_dict() print(" ### payload = ", payload) status, retval = eua.update_user_account(payload) return jsonify(status=status, message=retval) @app.route('/myclass/api/create_class/', methods=['POST']) @crossdomain(origin='*') def create_class(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = cm.add_class(payload) return jsonify(status=status, message=retval) ''' Cette api recupete et affiche une formation. la clé d'une formation est le code externe, mais pour que l'api fonctionne, il faut lui fournir - le token du partenaire ''' @app.route('/myclass/api/get_class/', methods=['POST','GET']) @crossdomain(origin='*') def get_class(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",str(payload)+" IP requester = "+str(request.remote_addr)) status, retval = cm.get_class(payload) return jsonify(status=status, message=retval) @app.route('/myclass/api/update_class/', methods=['POST']) @crossdomain(origin='*') def update_class(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = cm.update_class(payload) return jsonify(status=status, message=retval) ''' deverrouillage d'une formation - unlock training ''' @app.route('/myclass/api/unlock_class/', methods=['POST']) @crossdomain(origin='*') def unlock_class(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = cm.unlock_class(payload) return jsonify(status=status, message=retval) ''' Verrouillage d'une formation - lock training ''' @app.route('/myclass/api/lock_class/', methods=['POST']) @crossdomain(origin='*') def lock_class(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = cm.lock_class(payload) return jsonify(status=status, message=retval) ''' Desactivé une formation - disable training ''' @app.route('/myclass/api/disable_class/', methods=['POST']) @crossdomain(origin='*') def disable_class(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = cm.disable_class(payload) return jsonify(status=status, message=retval) ''' Reactivation d'une formation - enable training ''' @app.route('/myclass/api/enable_class/', methods=['POST']) @crossdomain(origin='*') def enable_class(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = cm.enable_class(payload) return jsonify(status=status, message=retval) ''' Cette api retourne les formations dont "attribut"="valeur" ''' @app.route('/myclass/api/get_class_by_name/,', methods=['GET','POST']) @crossdomain(origin='*') def get_all_class_by_attribut(attribut, value): result = wp.get_all_class_by_attribut(attribut, value) if result: #print(" in main result = ", result) return jsonify(result) return jsonify(status="False") ''' Cette api retourne les formations dont "attribut" IN (list_valeurs) list_valeurs = val1,val2,val3,...,valn ''' @app.route('/myclass/api/get_class_by_list_attr/;', methods=['GET']) @crossdomain(origin='*') def get_class_by_list_attr(attribut, list_values): print(" ### attribut = "+attribut) result = wp.get_class_by_list_attr(attribut, list_values) if result: #print(" in main result = ", result) return jsonify(result) return jsonify(status="False") ''' fonction actuellement utilisé sur le front : Cette fonction "get_recherche_gle_class" prend en argument une phrase et retourne les formations associées ''' @app.route('/myclass/api/get_recherche_gle_class/', methods=['GET']) @crossdomain(origin='*') def get_recherche_gle_class(sentence): result = wp.get_recherche_gle_class(sentence) if result: #print(" in main result = ", result) return jsonify(result) return jsonify(status="False") ''' Fonction utilisée pour la recherche simple d'un texte. sans utilisation de critère ni de tag ''' @app.route('/myclass/api/recherche_text_simple/', methods=['GET','POST']) @crossdomain(origin='*') def recherche_text_simple(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ", payload) status, result = wp.recherche_text_simple(payload) return jsonify(status=status, message=result) # recherche globale ''' fonction NON utilisée sur le front : Cette fonction fait une recherche globale en prenant une chaine de caractère - not use on front ''' @app.route('/myclass/api/get_class_global_search/', methods=['GET','POST']) @crossdomain(origin='*') def get_class_global_search(search_string): result = cm.get_class_global_search(search_string) if result: #print(" in main result = ", result) return jsonify(result) return jsonify(status="False") @app.route('/myclass/api/get_all_class/', methods=['GET','POST']) @crossdomain(origin='*') def get_all_class(): status, result = wp.get_all_class() response = jsonify(status=status, message=result) response.headers.add("Access-Control-Allow-Origin", "*") response.headers.add("Access-Control-Allow-Headers", "*") response.headers.add("Access-Control-Allow-Methods", "*") return response @app.route('/myclass/api/update_class_by_attribut/,,', methods=['GET','POST']) def update_class_by_attribut(objId, attribut, value): print(" update_class_by_attribut ") result = wp.update_class_by_attribut(objId, attribut, value) if result: print(" in main result = ", result) return jsonify(result) return jsonify(status="False") # this function update all fields of class. # First : we retrieve all field of class and display it. # Second : the user update some fields but all fields will be returned for update # it means all field are stored in : # payload = request.form.to_dict() @app.route('/myclass/api/update_class_by_id/', methods=['GET','POST']) def update_class_by_id(id): payload = request.form.to_dict() print("on va modifier l'id (fourni en input) : ", id) for key, value in payload.items(): print(key," : ", value) result = wp.update_class(payload) #result = "1" if result: return jsonify(status='True', message='Class updated') return jsonify(status='False') ''' Cette API créer un compte patenaire / client et declenche l'envoi de l'email de notification La clé est reste l'adresse email du partenaire (pas du contact du partenaire) ''' @app.route('/myclass/api/add_partner_account/', methods=['POST','GET']) @crossdomain(origin='*') def add_partner_account(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = pa.add_partner_account(payload) return jsonify(status=status, message=retval) ''' Cette API valide une inscription d'un partenaire ''' @app.route('/myclass/api/valide_partnair_account/', methods=['GET','POST']) @crossdomain(origin='*') def valide_partnair_account(value): print(" ### validation du compte = ",value) result, token = pa.valide_partnair_account(value) if result: #return jsonify(status='True', message='Votre compte a été activé') return "Votre Compte a été activé, le token est : "+str(token) return jsonify(status='False') ''' Cette fonction modifie/MAJ un partenaire ''' @app.route('/myclass/api/update_partner_account/', methods=['POST','GET']) @crossdomain(origin='*') def update_partner_account(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = pa.update_partner_account(payload) return jsonify(status=status, message=retval) ''' Cette fonction recupere les données d'un partenaire ''' @app.route('/myclass/api/get_partner_account/', methods=['POST','GET']) @crossdomain(origin='*') def get_partner_account(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = pa.get_partner_account(payload) return jsonify(status=status, message=retval) ''' Cette API index la base donnée. La fonction "ela_index_all_classes" va aller chercher chaque cours dans la BDD et créer les mots clées qui sont ensuite enregister dans la table "elaindex" ''' @app.route('/myclass/api/ela_index_all_classes/', methods=['POST','GET']) @crossdomain(origin='*') def ela_index_all_classes(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = ela_index_class.ela_index_all_classes() return jsonify(status=status, message=retval) ''' Cette API index la base donnée en se basant sur le title. La fonction "ela_index_all_classes" va aller chercher chaque cours dans la BDD et créer les mots clées qui sont ensuite enregister dans la table "elaindex" ''' @app.route('/myclass/api/ela_index_all_classes_title/', methods=['POST','GET']) @crossdomain(origin='*') def ela_index_all_classes_title(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = ela_index_class.ela_index_all_classes_title() return jsonify(status=status, message=retval) ''' Cette API index la base donnée en se basant sur le description. La fonction "ela_index_all_classes" va aller chercher chaque cours dans la BDD et créer les mots clées qui sont ensuite enregister dans la table "elaindex" ''' @app.route('/myclass/api/ela_index_all_classes_desc/', methods=['POST','GET']) @crossdomain(origin='*') def ela_index_all_classes_desc(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = ela_index_class.ela_index_all_classes_desc() return jsonify(status=status, message=retval) ''' Cette API index la base donnée en se basant sur le objectif. La fonction "ela_index_all_classes" va aller chercher chaque cours dans la BDD et créer les mots clées qui sont ensuite enregister dans la table "elaindex" ''' @app.route('/myclass/api/ela_index_all_classes_obj/', methods=['POST','GET']) @crossdomain(origin='*') def ela_index_all_classes_obj(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = ela_index_class.ela_index_all_classes_obj() return jsonify(status=status, message=retval) ''' Cette API, utilisée dans phase de developpement est utilisé pour supprimer le token d'un user Use case : Uniquement en developpement ''' @app.route('/myclass/api/Dev_del_user_token/', methods=['POST','GET']) @crossdomain(origin='*') def Dev_del_user_token(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = dev_function.Dev_del_user_token(payload) return jsonify(status=status, message=retval) ''' Recherche en mode tips ''' @app.route('/myclass/api/recherche_tips/', methods=['POST','GET']) @crossdomain(origin='*') def recherche_tips(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = wp.recherche_tips(payload) return jsonify(status=status, message=retval) ''' Recuperation de l'historique de recherche d'un user ''' @app.route('/myclass/api/get_stored_recherche/', methods=['POST','GET']) @crossdomain(origin='*') def get_stored_recherche(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = wp.get_stored_recherche(payload) return jsonify(status=status, message=retval) ''' Cette API met à jour le password d'un user ''' ''' Recuperation de l'historique de recherche d'un user ''' @app.route('/myclass/api/change_uer_pwd/', methods=['POST','GET']) @crossdomain(origin='*') def change_uer_pwd(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = eua.change_uer_pwd(payload) return jsonify(status=status, message=retval) ''' Cette API met à jour le l'adresse email principale d'un user ''' @app.route('/myclass/api/change_uer_email/', methods=['POST','GET']) @crossdomain(origin='*') def change_uer_email(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = eua.change_uer_email(payload) return jsonify(status=status, message=retval) ''' Cette API supprime un compte utilisateur tout en gardant la cohérence des information. Cela revient à : 1 - Anonyser le compte tous les champ identifiants une personne (['adr_street', 'adr_city', 'adr_zip', 'adr_country', 'mob_phone','link_facebook', 'link_twitter', 'token']) 2 - Bloquer le compte 3 - Desactiver le compte ''' @app.route('/myclass/api/delete_user_account/', methods=['POST','GET']) @crossdomain(origin='*') def delete_user_account(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = eua.delete_user_account(payload) return jsonify(status=status, message=retval) ''' Cette API verrouille le compte d'un utilisateur Cela revient à mettre le champ : "locked" à 1 ''' @app.route('/myclass/api/lock_user_account/', methods=['POST','GET']) @crossdomain(origin='*') def lock_user_account(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = eua.lock_user_account(payload) return jsonify(status=status, message=retval) ''' Cette API desactive le compte d'un utilisateur Cela revient à mettre le champ : "active" à 0 et "locked" a 1 ''' @app.route('/myclass/api/desable_user_account/', methods=['POST','GET']) @crossdomain(origin='*') def desable_user_account(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = eua.desable_user_account(payload) return jsonify(status=status, message=retval) ''' Cette API enregistre le message d'un utilisateur Par pour la gestion des message de "contactez-nous". ''' @app.route('/myclass/api/add_user_message/', methods=['POST','GET']) @crossdomain(origin='*') def add_user_message(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) status, retval = um.add_user_message(payload) return jsonify(status=status, message=retval) ''' Cette API ajoute des formation en masse par exemple avec un fichier CSV ''' def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route('/myclass/api/add_class_mass/', methods=['POST','GET']) @crossdomain(origin='*') def add_class_mass(): # On recupere le corps (payload) de la requete payload = request.form.to_dict() print(" ### payload = ",payload) print(request.files) if request.method == 'POST': # Create variable for uploaded file f = request.files['File'] status, retval = cm.add_class_mass(f, app.config['UPLOAD_FOLDER'], payload) return jsonify(status=status, message=retval) if __name__ == '__main__': print(" debut api") #ls.init_ch() #pc.similaire() #pc.textdist() #pc.test() app.run(host='127.0.0.1', port=5000, debug=True) #app.run(host='192.168.0.21', port=5000, debug=True)