def JSONify(): """ Méthode : conversion en JSON du fichier """ logger.info("HTTP : Début conversion") if True: try: return_json = toJSON(request.files["data_file"], bucket_perso) # Conversion du fichier return send_file(return_json["file"], as_attachment=True, attachment_filename=return_json["name"]) except Exception as err: logger.error("HTTP : Erreur dans la conversion | " + str(err)) return redirect(url_for('convert')) else: logger.info("Déconnexion automatique") flash("Déconnexion automatique") return redirect(url_for('logout'))
def main(): while True: # Время начала работы цикла. start_time = time.time() # Институты processing_institutes() # Группы и курсы processing_groups_and_courses() # Преподаватели processing_teachers() # Расписание processing_schedule() # Обновление базы экзаменов exam_update() # Время окончания работы цикла. end_time = time.time() logger.info(f'Total operating time --- {end_time - start_time} seconds ---') # Задержка работы цикла (в часах). logger.info(f'Waiting for the next cycle. The waiting time: {GETTING_SCHEDULE_TIME_HOURS / 60 / 60} hours...\n') time.sleep(GETTING_SCHEDULE_TIME_HOURS)
def meta_pdf(cheminSauvegarde, metadonnees): """ Traitement des métadonnées des fichiers PDF :param cheminSauvegarde: fichier à traiter :type cheminSauvegarde: string :param metadonnees: métadonnées du fichier :type metadonnees: dict :return: métadonnées du fichier :rtype: dict """ logger.info("Métadonnées PDF") try: pdf = PyPDF2.PdfFileReader(cheminSauvegarde) metadonnees["metaPyPDFxmp"] = pdf.getXmpMetadata() metadonnees["metaPyPDFdoc"] = pdf.getDocumentInfo() metadonnees["metaPyPDFnumpage"] = pdf.getNumPages() metadonnees["metaPyPDFfields"] = pdf.getFields() logger.info("Retour des métadonnées PDF") return metadonnees except Exception as err: logger.warning("Erreur dans les métadonnées PDF | " + str(err)) metadonnees[ "metaPDF"] = "Erreur, vérifier présence de métadonnées ou extension" return metadonnees
def list_bucket(): """ Méthode : retourner des fichiers présents sur le bucket """ if session.get('logged_in'): try: with open('./tmp', 'w') as tmp: for file in files_bucket(bucket_perso): tmp.write(str(file) + '\n') logger.info(session['name'] + " | Retour de la liste des fichiers du bucket") return send_file('../tmp', as_attachment=True, attachment_filename='liste_fichiers.txt') except Exception as err: logger.error(session['name'] + " | Erreur dans le retour du bucket") return redirect(url_for('home')) else: logger.info("Déconnexion automatique") flash("Déconnexion automatique") return redirect(url_for('logout'))
def delete_file(bucket, s3_file): """ Supprimer un fichier du bucket S3 :param bucket: nom du bucket ciblé :type bucket: string :param s3_file: nom du fichier à supprimer :type s3_file: string :return: réussite ou non :rtype: bool """ logger.info("Début de suppression du fichier du bucket") try: s3 = boto3.client('s3') s3.delete_object(Bucket=bucket, Key=s3_file) logger.info("Suppression du fichier du bucket validé") return True except Exception as err: logger.error("Erreur dans la suppression du fichier du bucket | " + str(err)) return False
def del_file(): """ Méthode : supprimer le fichier du bucket """ if session.get('logged_in') and session['admin']: if delete_file(bucket_perso, 'StockageJSON/' + str(request.form["file_del"])): logger.info("Suppression du fichier") flash("Suppression du fichier") return redirect(url_for('home')) else: logger.warning("Erreur dans la suppression du fichier") flash("Erreur dans la suppression du fichier") return redirect(url_for('home')) else: logger.warning("Pas les autorisations") flash("Vous n'avez pas les droits pour cette fonction") return redirect(url_for('home'))
def files_bucket(bucket): """ Liste des objets sur le bucket :param bucket: nom du bucket ciblé :type bucket: string :return: liste des fichiers présents sur le bucket :rtype: [string] """ logger.info("Début de chargement du bucket") try: s3 = boto3.client('s3') list_files = [] for file in s3.list_objects(Bucket=bucket)['Contents']: if file['Key'][:len('StockageJSON/')] == 'StockageJSON/': list_files.append(file['Key'][len('StockageJSON/'):]) logger.info("Liste des fichiers du bucket validé") return list_files except Exception as err: logger.error("Erreur dans le chargement du bucket | " + str(err)) return False
def detect_labels(image): """ Appel de l'API rekognition :param image: image à envoyer à l'API :type image: string :return: les labels déterminés par l'API :rtype: [string] """ logger.info("Début de transfert vers API Rekognition ") try: reko = boto3.client('rekognition', 'eu-west-1') imgfile = open(image, 'rb') imgbytes = imgfile.read() imgfile.close() response = reko.detect_labels(Image={'Bytes': imgbytes}) response_return = [] for k in response["Labels"]: response_return.append(k["Name"]) logger.info("Appel de l'API Rekognition validé ") return response_return except Exception as err: logger.error("Erreur dans l'appel de l'API Rekognition | " + str(err)) return False
def upload_file(local_file, bucket, s3_file): """ Téléchargement sur le bucket S3 :param local_file: nom de sauvegarde en local du fichier à télécharger :type local_file: string :param bucket: nom du bucket ciblé :type bucket: string :param s3_file: nom du fichier à télécharger :type s3_file: string :return: réussite ou non :rtype: bool """ logger.info("Début de transfert vers le bucket ") try: s3 = boto3.client('s3') s3.upload_file(local_file, bucket, s3_file) logger.info("Transfert du fichier vers le bucket validé ") return True except Exception as err: logger.error("Erreur dans le transfert du fichier vers le bucket | " + str(err)) return False
def add_user(): """ Gestion d'un nouvel utilisateur """ logger.info("Début enregistrement d'un nouvel utilisateur") retour_test = test_new_users(request.form['new_username'], request.form['new_password'], request.form['new_email']) if retour_test[0]: new_user(request.form['new_username'], request.form['new_password']) session['logged_in'] = True session['admin'] = False session['name'] = request.form['new_username'] message = 'Un nouvel utilisateur : ' + request.form[ 'new_username'] + ' souhaite accéder au service. Son mail : ' + request.form[ 'new_email'] send_mail(str(message)) logger.info(session['name'] + " | Nouvel utilisateur enregistré") flash("Nouvel utilisateur enregistré") return redirect(url_for('home')) else: logger.error("Erreur dans l'enregistrement du nouvel utilisateur | " + str(retour_test[1])) flash(retour_test[1]) return render_template('enregistrer.html') DPP_from_png_to_JSON__1584647357.json
def new_user(user, password): """ Gestion du nouvel utilisateur :param user: nom d'utilisateur à ajouter :type user: string :param password: mot de passe à ajouter :type password: string :return: réussite ou non :rtype: bool """ try: couple = {} couple['user'] = user couple['mdp'] = hash_mdp( password) # On hashe directement le mot de passe. with open('./users.txt', 'a') as tmp: tmp.write(str(couple['user']) + "," + str(couple['mdp']) + "\n") logger.info("Ajout du nouvel utilisateur ") return True except Exception as err: logger.error("Erreur dans l'ajout d'un nouvel utilisateur | " + str(err)) return False
def test_identification(categorie, identifiant, length_max, length_min): """ Vérification de la taille du nom utilisateur ou du mot de passe :param categorie: type de la variable à tester :type categorie: string :param identifiant: variable à tester :type identifiant: string :param length_max: taille max de la variable :type length_max: int :param length_min: taille min de la variable :type length_min: int :return: réussite ou non :rtype: bool """ try: if len(identifiant) < length_min: logger.warning(str(categorie) + " trop court") return False elif len(identifiant) > length_max: logger.warning(str(categorie) + " trop long") return False else: logger.info(str(categorie) + " accepté") return True except Exception as err: logger.error("Erreur dans le traitement du" + str(categorie) + " | " + str(err)) return False
def send_mail(message): """ Fonction permettant d'avertir de l'ajout d'un utilisateur :param message: message à envoyer :type message: string :return: réussite ou non :rtype: bool """ try: msg = MIMEMultipart() msg['From'] = '*****@*****.**' msg['To'] = '*****@*****.**' msg['Subject'] = "Ajout d'un utilisateur" msg.attach(MIMEText(message)) mailserver = smtplib.SMTP('smtp.gmail.com', 587) mailserver.ehlo() mailserver.starttls() mailserver.ehlo() mailserver.login('*****@*****.**', 'promo2019') mailserver.sendmail('*****@*****.**', '*****@*****.**', msg.as_string()) mailserver.quit() logger.info("Mail envoyé ") return True except Exception as err: logger.error("Erreur dans l'envoi du mail | " + str(err)) return False
def logout(): """ Gestion de la déconnexion. """ session['logged_in'] = False logger.info(session['name'] + " | Déconnexion réussie") flash("Déconnexion réussie") return redirect(url_for('login'))
def meta_image(cheminSauvegarde, metadonnees): """ Traitement des métadonnées des fichiers IMG :param cheminSauvegarde: fichier à traiter :type cheminSauvegarde: string :param metadonnees: métadonnées du fichier :type metadonnees: dict :return: métadonnées du fichier :rtype: dict """ logger.info("Métadonnées IMG") try: image = PIL.Image.open(cheminSauvegarde) try: for k, v in image._getexif().items(): if k in PIL.ExifTags.TAGS: metadonnees["metaExifIMG"] = {PIL.ExifTags.TAGS[k]: v} except Exception as err: logger.error("Erreur dans les métadonnées EXIF | " + str(err)) metadonnees[ "metaExifIMG"] = "Erreur, vérifier présence de métadonnées ou extension" return metadonnees try: if metadonnees["taille"] < 5242880 and metadonnees[ "extension"] in ['.jpeg', '.jpg', '.png']: metadonnees["metaRekoIMG"] = detect_labels(cheminSauvegarde) else: logger.warning("Fichier non valide pour API Rekognition") metadonnees[ "metaRekoIMG"] = "Fichier non valide pour API Rekognition" except Exception as err: logger.error("Erreur dans les métadonnées REKO | " + str(err)) metadonnees["metaRekoIMG"] = "Erreur dans les métadonnées REKO" return metadonnees logger.info("Retour des métadonnées IMG") return metadonnees except Exception as err: logger.warning("Erreur dans les métadonnées IMG | " + str(err)) return metadonnees
def exam_update(): logger.info('Start processing_exams_schedule...') JSON_EXAMS = os.environ.get('EXAMS_API') try: response = requests.get(JSON_EXAMS) json_data = json.loads(response.text) schedule_exams = [{'group': a, 'exams': d} for a, d in json_data.items()] mongo_storage.save_schedule_exam(schedule_exams) logger.info('End processing_exams_schedule...') except requests.exceptions.ConnectionError: logger.error("Error processing_exams_schedule: Connection refused")
def processing_groups_and_courses(): """Обработка групп и курсов""" logger.info('Start processing_groups...') start_time_groups = time.time() try: # Группы pg_groups = postgre_storage.get_groups() mongo_groups = sorted(data_conversion.convert_groups(pg_groups), key=lambda x: x['name']) mongo_storage.save_groups(mongo_groups) # Сохраняем группы end_time_groups = time.time() logger.info(f'Processing_groups successful. Operation time: {end_time_groups - start_time_groups} seconds.') logger.info('Start processing_courses...') start_time_courses = time.time() try: # Курсы mongo_courses = sorted(data_conversion.convert_courses(mongo_groups), key=lambda x: x['name']) mongo_storage.save_courses(mongo_courses) # Сохраняем курсы except PyMongoError as e: logger.error(f'Mongo error:\n{e}') except Exception as e: logger.error(f'convert_courses error:\n{e}') end_time_courses = time.time() logger.info(f'Processing_courses successful. Operation time: {end_time_courses - start_time_courses} seconds.') except PyMongoError as e: logger.error(f'Mongo error:\n{e}') except psycopg2.OperationalError as e: logger.error(f'Postgre error:\n{e}') except Exception as e: logger.error(f'convert_groups error:\n{e}')
def check_login(): """ Gestion des utilisateurs enregistrés avec différenciation admin / other """ logger.info("Début identification") usr = load_users() psw = hash_mdp(request.form['password']) try: if request.form['username'] not in usr: logger.warning("Identifiant incorrect") flash("Identifiant incorrect") return redirect(url_for('login')) else: if usr[request.form['username']] == psw: session['logged_in'] = True if request.form['username'] == 'admin': session['admin'] = True else: session['admin'] = False session['name'] = request.form['username'] logger.info(session['name'] + " | Identification réussie") return redirect(url_for('home')) else: logger.warning("Mot de passe incorrect") flash("Mot de passe incorrect") return redirect(url_for('login')) except Exception as err: logger.error("Erreur dans l'identification | " + str(err)) flash("Erreur dans l'identification") return redirect(url_for('login'))
def processing_teachers(): """Обработка преподавателей""" logger.info('Start processing_teachers...') start_time = time.time() try: pg_teachers = postgre_storage.get_teachers() mongo_teachers = sorted(data_conversion.convert_teachers(pg_teachers), key=lambda x: x['prep']) # Сортируем массив mongo_storage.save_teachers(mongo_teachers) end_time = time.time() logger.info(f'Processing_teachers successful. Operation time: {end_time - start_time} seconds.') except PyMongoError as e: logger.error(f'Mongo error:\n{e}') except psycopg2.OperationalError as e: logger.error(f'Postgre error:\n{e}') except Exception as e: logger.error(f'convert_teachers error:\n{e}')
def get_file(): """ Méthode : récupérer le fichier sur le bucket """ try: if session.get('logged_in') and session['admin']: return_file = download_file( request.form["file_get"], bucket_perso, 'StockageJSON/' + str(request.form["file_get"])) if return_file["success"]: with open('./tmp', 'w') as tmp: json.dump(return_file["file"], tmp, indent=4) return send_file('../tmp', as_attachment=True, attachment_filename=request.form["file_get"]) else: logger.error("Erreur dans le téléchargement | " + str(return_file["file"])) flash("Erreur dans le téléchargement") return redirect(url_for('home')) else: logger.info("Pas les autorisations") flash("Vous n'avez pas les droits pour cette fonction") return redirect(url_for('home')) except Exception as err: logger.error("Erreur dans le téléchargement depuis le bucket | " + str(err)) flash("Erreur dans le téléchargement depuis le bucket") return redirect(url_for('home'))
def load_users(): """ Liste des utilisateurs enregistrés :return: liste des utilisateurs enregistrés :rtype: [string] """ try: users = {} with open("./users.txt") as file: for log in file: usr, psw = log.split(',') users[usr] = psw[:-1] logger.info("Chargement des utilisateurs ") return users except Exception as err: logger.error("Erreur dans le chargement des utilisateurs | " + str(err)) return None
def convert(): """ Page de conversion """ try: if True: logger.info("HTTP : Page convertisseur") return render_template('convertisseur_http.html') else: logger.info("Déconnexion automatique") flash("Déconnexion automatique") return redirect(url_for('logout')) except Exception as err: logger.error("HTTP : Erreur dans l'afficage du convertisseur | " + str(err)) flash("Erreur dans l'affichage du convertisseur") return redirect(url_for('logout'))
def processing_institutes(): """Обработка институтов""" logger.info('Start processing_institutes...') start_time = time.time() try: # Получаем данные. pg_institutes = postgre_storage.get_institutes() # Преобразуем данные в нужный формат. mongo_institutes = sorted(data_conversion.convert_institutes(pg_institutes), key=lambda x: x['name']) # Сортируем массив # Сохраняем данные. mongo_storage.save_institutes(mongo_institutes) end_time = time.time() logger.info(f'Processing_institutes successful. Operation time: {end_time - start_time} seconds.') except PyMongoError as e: logger.error(f'Mongo error:\n{e}') except psycopg2.OperationalError as e: logger.error(f'Postgre error:\n{e}') except Exception as e: logger.error(f'convert_institutes error:\n{e}')
def convert(): """ Page de conversion """ try: if session.get('logged_in'): logger.info(session['name'] + " | Page convertisseur") return render_template('convertisseur.html') else: logger.info("Déconnexion automatique") flash("Déconnexion automatique") return redirect(url_for('logout')) except Exception as err: logger.error(session['name'] + " | Erreur dans l'afficage du convertisseur | " + str(err)) flash("Erreur dans l'affichage du convertisseur") return redirect(url_for('logout'))
def download_file(local_file, bucket, s3_file): """ Téléchargement depuis le bucket S3 :param local_file: nom de sauvegarde en local du fichier à télécharger :type local_file: string :param bucket: nom du bucket ciblé :type bucket: string :param s3_file: nom du fichier à télécharger :type s3_file: string :return: le fichier à télécharger deuis le bucket :rtype: [bool, file] """ logger.info("Début de téléchargement du fichier JSON") try: s3 = boto3.client('s3') s3.download_file(bucket, s3_file, local_file) file = (str(open(local_file, 'r').read())) logger.info("Transfert du fichier depuis le bucket validé ") return_file = {} return_file["success"] = True return_file["file"] = file return return_file except Exception as err: logger.error( "Erreur dans le transfert du fichier depuis le bucket | " + str(err)) return_file = {} return_file["success"] = False return_file["file"] = err return return_file
def JSONify(): """ Méthode : conversion en JSON du fichier """ logger.info(session['name'] + " | Début conversion") if session.get('logged_in'): try: if request.files["data_file"].content_type == "text/plain": try: logger.info(session['name'] + " | Début conversion via CURL") return_json = viaCurl( request.files["data_file"], request.files["data_file"].content_type ) # Envoi pour conversion par une autre API except Exception as err: logger.warning(session['name'] + " | Erreur dans la gestion du Curl | " + str(err)) return_json = toJSON(request.files["data_file"], bucket_perso) # Conversion du fichier else: return_json = toJSON(request.files["data_file"], bucket_perso) # Conversion du fichier return send_file(return_json["file"], as_attachment=True, attachment_filename=return_json["name"]) except Exception as err: logger.error(session['name'] + " | Erreur dans la conversion | " + str(err)) flash("Erreur dans la conversion") return redirect(url_for('convert')) else: logger.info("Déconnexion automatique") flash("Déconnexion automatique") return redirect(url_for('logout'))
def test_extension(fichierNom, listeExtensions): """ Vérification de la prise en compte de l'extension :param fichierNom: nom du fichier à tester :type fichierNom: string :param listeExtensions: liste des extensions prises en compte :type listeExtensions: [string] :return: réussite ou non et extension du fichier :rtype: [bool, string] """ logger.info("Etude de l'extension") try: retour = {} extension = "".join( reversed("".join(reversed(fichierNom)) [0:"".join(reversed(fichierNom)).find('.')].lower() + ".")) logger.info("Test du l'extension") if extension not in listeExtensions: retour["resultat"] = False logger.warning("Extension non prise en compte") return retour else: retour["resultat"] = True retour["extension"] = extension logger.info("Extension prise en compte") return retour except Exception as err: retour["resultat"] = False logger.error("Erreur dans le test de l'extension | " + str(err)) return retour
def home(): """ Page principale du service """ if session.get('logged_in'): if session.get('admin'): logger.info(session['name'] + " | Page admin") else: logger.info(session['name'] + " | Page utilisateur") return render_template('menu.html') else: logger.info("Déconnexion automatique") flash("Déconnexion automatique") return redirect(url_for('logout'))
def home(): """ Page principale du service """ if True: if True: logger.info("HTTP : Page principale") else: logger.info("HTTP : Page utilisateur") return render_template('menu_http.html') else: logger.info("Déconnexion automatique") flash("Déconnexion automatique") return redirect(url_for('logout'))
def toJSON(fichier, bucket_perso): """ Fonction de convertisseur : Etape 1.0 : récupérer le fichier et déterminer son extension Etape 1.1 : tester l'extension Etape 2 : sauvegarde du fichier REQUEST en local de l'instance Etape 3.0 : récupération des métadonnées générales Etape 3.1 : si possible, récupérations des métadonnées particuliètes Etape 3.2 : stockage des métadonnées et du fichier en binaire dans un fichier JSON Etape 4.0 : sauvegarde du fichier JSONify en local de l'instance Etude 4.1 : envoi sur S3 du fichier REQUEST et JSONify Etade 5.0 : retour du fichier JSONify à l'utilisateur :param fichier: nom du fichier à traiter :type fichier: string :param bucket_perso: nom du bucket support :type bucket_perso: string :return: fichier traité :rtype: {string, string} """ logger.info("Initialisation des extensions prises en compte") listePDF = ['.pdf'] listeIMG = ['.jpeg', '.png', '.jpg', '.gif', '.bmp'] listeAutre = [ '.txt', '.csv', '.py', '.ods', '.odt', '.odg', '.ipynb', '.json', '.docx', '.doc', '.xls', '.tex' ] listeExtensions = listePDF + listeIMG + listeAutre logger.info("Récupération du fichier source") fichierType = fichier.content_type fichierNom = str(fichier.filename.replace(" ", "")) extension = test_extension(fichierNom, listeExtensions) if not extension["resultat"]: logger.warning("Extension non prise en compte") return "Extension non prise en compte" else: logger.info("Stockage en local du fichier source") nomSauvegarde = str(datetime.now()) + '__' + fichierNom fichier.save(os.path.join('./Sauvegarde', nomSauvegarde)) cheminSauvegarde = './Sauvegarde/' + nomSauvegarde try: logger.info("Initialisation des variables JSON de travail") donneesJSON = {} metadonnees = {} donneesJSON["META"] = metadonnees donneesJSON["fichier_bytes"] = {} logger.info("Métadonnées générales") metadonnees["fichiernom"] = fichierNom metadonnees["type"] = fichierType metadonnees["taille"] = os.stat(cheminSauvegarde).st_size metadonnees["extension"] = extension["extension"] logger.info("Métadonnées particulières") if extension["extension"] in listeIMG: metadonnees = meta_image(cheminSauvegarde, metadonnees) elif extension["extension"] in listePDF: metadonnees = meta_pdf(cheminSauvegarde, metadonnees) logger.info("Remplissage des variables JSON") objet = open(cheminSauvegarde, 'rb') donneesJSON["fichier_bytes"] = str(objet.read()) Nomfichier = fichierNom[ 0:fichierNom.find('.')] + '_from_' + extension["extension"][1:] fichierNomJSON = Nomfichier + '_to_JSON__' + str( int(os.stat(cheminSauvegarde).st_birthtime)) + '.json' fichierJSON = './StockageJSON/' + fichierNomJSON objet.close() logger.info("Stockage en local du fichier JSON") with open(fichierJSON, 'w') as tmp: json.dump(donneesJSON, tmp, indent=4) logger.info("Envoi du fichier source vers S3") upload_file(cheminSauvegarde, bucket_perso, 'Sauvegarde/' + nomSauvegarde) logger.info("Envoi du fichier JSON vers S3") upload_file(fichierJSON, bucket_perso, 'StockageJSON/' + str(fichierNomJSON)) logger.info("Retour du fichier JSON") # Pour restituer correctement le fichier à retourner. fichierJSON = '../StockageJSON/' + fichierNomJSON reponse = {} reponse["file"] = fichierJSON reponse["name"] = fichierNomJSON return reponse except Exception as err: logger.error("Erreur dans le traitement du fichier | " + str(err)) return False