summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDebulois <quentin@debulois.fr>2022-04-15 16:09:55 +0200
committerDebulois <quentin@debulois.fr>2022-04-15 16:09:55 +0200
commit5ca5b78cef1359ca29295992c61042d6ea5375d2 (patch)
treedbfdbb73aa87e3dba9a9ba2f4b024e69cb9eede9
Initial commit, traduction des fichiers databases de PHP et système de vérification des mots de passe sur la bdd en local
-rw-r--r--app_alphajob/database/__init__.py1
-rw-r--r--app_alphajob/database/__pycache__/__init__.cpython-310.pycbin0 -> 164 bytes
-rw-r--r--app_alphajob/database/__pycache__/dbmain.cpython-310.pycbin0 -> 6816 bytes
-rw-r--r--app_alphajob/database/__pycache__/dbsearch.cpython-310.pycbin0 -> 3661 bytes
-rw-r--r--app_alphajob/database/__pycache__/dbuser.cpython-310.pycbin0 -> 3674 bytes
-rw-r--r--app_alphajob/database/dbadmin.py177
-rw-r--r--app_alphajob/database/dbmain.py217
-rw-r--r--app_alphajob/database/dbmission.py160
-rw-r--r--app_alphajob/database/dbsearch.py140
-rw-r--r--app_alphajob/database/dbuser.py171
-rw-r--r--app_alphajob/main.py119
-rw-r--r--app_alphajob/ressources/icon.icobin0 -> 41662 bytes
-rw-r--r--requierments.txtbin0 -> 342 bytes
13 files changed, 985 insertions, 0 deletions
diff --git a/app_alphajob/database/__init__.py b/app_alphajob/database/__init__.py
new file mode 100644
index 0000000..03b0cc7
--- /dev/null
+++ b/app_alphajob/database/__init__.py
@@ -0,0 +1 @@
+# https://realpython.com/python-import/#basic-python-import \ No newline at end of file
diff --git a/app_alphajob/database/__pycache__/__init__.cpython-310.pyc b/app_alphajob/database/__pycache__/__init__.cpython-310.pyc
new file mode 100644
index 0000000..d1a6aa3
--- /dev/null
+++ b/app_alphajob/database/__pycache__/__init__.cpython-310.pyc
Binary files differ
diff --git a/app_alphajob/database/__pycache__/dbmain.cpython-310.pyc b/app_alphajob/database/__pycache__/dbmain.cpython-310.pyc
new file mode 100644
index 0000000..91f77db
--- /dev/null
+++ b/app_alphajob/database/__pycache__/dbmain.cpython-310.pyc
Binary files differ
diff --git a/app_alphajob/database/__pycache__/dbsearch.cpython-310.pyc b/app_alphajob/database/__pycache__/dbsearch.cpython-310.pyc
new file mode 100644
index 0000000..48e2dc6
--- /dev/null
+++ b/app_alphajob/database/__pycache__/dbsearch.cpython-310.pyc
Binary files differ
diff --git a/app_alphajob/database/__pycache__/dbuser.cpython-310.pyc b/app_alphajob/database/__pycache__/dbuser.cpython-310.pyc
new file mode 100644
index 0000000..7442540
--- /dev/null
+++ b/app_alphajob/database/__pycache__/dbuser.cpython-310.pyc
Binary files differ
diff --git a/app_alphajob/database/dbadmin.py b/app_alphajob/database/dbadmin.py
new file mode 100644
index 0000000..dd6b4d0
--- /dev/null
+++ b/app_alphajob/database/dbadmin.py
@@ -0,0 +1,177 @@
+
+############################################################################
+# #
+# Description: Ensemble de méthodes pour étendre dbmain #
+# afin de gérer l'administration du site #
+# #
+############################################################################
+
+# Import de dbmain
+from . import dbmain
+
+# Extension de cette classe avec dbmain
+class DbAdmin(dbmain.DbMain):
+
+ # ****************************************************************************
+ # GESTION DES UTILISATEURS DANS L'ADMIN
+ # ****************************************************************************
+ # Récupérer toutes les infos de la table userAccount
+ def get_all_users_account(self):
+ reqGetAll = """
+ SELECT
+ *
+ FROM
+ """ + self.TABLEUSERACCOUNT
+ # https:#www.php.net/manual/fr/pdostatement.fetch.php
+ # "PDO::FETCH_ASSOC: retourne un tableau indexé
+ # par le nom de la colonne comme retourné dans le jeu de résultats"
+ self.exec_cmd(reqGetAll)
+ result = self.cur.fetchall()
+ return result
+
+ # https:#stackoverflow.com/questions/1361340/how-can-i-do-insert-if-not-exists-in-mysql
+ # Suppresion d'un utilisateur
+ def del_user_by_userid(self, userId):
+ # Préparation de la requète pour voir si l'utilisateur existe
+ # https:#stackoverflow.com/questions/1676551/best-way-to-test-if-a-row-exists-in-a-mysql-table
+ reqCheckExistId = """
+ SELECT EXISTS(
+ SELECT 1 FROM
+ """ + self.TABLEUSERACCOUNT + """
+ WHERE
+ userId = ?
+ LIMIT 1
+ )"""
+ # Exécution de la requète, fetchall pour avoir le résultat
+ # https:#www.php.net/manual/fr/pdostatement.fetch.php
+ # struct par défaut req et index (fetch_both) = arr([0] => arr("req" => BOOL, [0] => BOOL])
+ # PDO::FETCH_NUM : retourne un tableau indexé par le numéro de la colonne comme elle
+ # est retourné dans votre jeu de résultat, commençant à 0
+ self.exec_cmd(reqCheckExistId, [userId])
+ reqResult = self.cur.fetchall()
+ # Si il existe
+ if (reqResult[0][0]):
+ # Préparation de la requète pour suppression
+ reqDelUser = """DELETE FROM """ + self.TABLEUSERACCOUNT + """ WHERE userId = ?"""
+ # Exécution de la requète
+ self.exec_cmd(reqDelUser, [userId])
+ # Retourne 1 pour réussite
+ return 1
+ else:
+ # Retourne 0 pour échec
+ return 0
+
+
+ # ****************************************************************************
+ # GESTION DES EMPLOIS DANS L'ADMIN
+ # ****************************************************************************
+ # Ajout d'une categorie
+ def register_job_category(self, jobNameEn, jobNameFr):
+ # Préparation et execution de la requète pour voir si la categorie existe en anglais
+ reqCheckjobCategoryNameEn = """
+ SELECT EXISTS(
+ SELECT 1 FROM
+ """ + self.TABLEJOBCATEGORY + """
+ WHERE
+ jobCategoryNameEn = ?
+ LIMIT 1
+ )"""
+ self.exec_cmd(reqCheckjobCategoryNameEn, [jobNameEn])
+ reqResultEn = self.cur.fetchall()
+ # Si il n'existe pas en anglais
+ if not reqResultEn[0][0]:
+ # Préparation et execution de la requète pour voir si la categorie existe en Français
+ reqCheckjobCategoryNameFr = """
+ SELECT EXISTS(
+ SELECT 1 FROM
+ """ + self.TABLEJOBCATEGORY + """
+ WHERE
+ jobCategoryNameFr = ?
+ LIMIT 1
+ )"""
+ self.exec_cmd(reqCheckjobCategoryNameFr, [jobNameFr])
+ reqResultFr = self.cur.fetchall()
+ # Si il n'existe pas en Français non plus
+ if not reqResultFr[0][0]:
+ # Préparation de la requète pour l'ajout
+ reqjobCategoryNameAdd = """
+ INSERT INTO
+ """ + self.TABLEJOBCATEGORY + """
+ (jobCategoryNameEn, jobCategoryNameFr)
+ VALUES
+ (? ,?)"""
+ # Exécution de la requète
+ self.exec_cmd(reqjobCategoryNameAdd, [jobNameEn, jobNameFr])
+ # Retourne 1 pour réussite
+ return 1
+ else:
+ # Retourne 0 pour échec
+ return 0
+ else:
+ # Retourne 0 pour échec
+ return 0
+
+ # Suppresion d'un utilisateur
+ def del_job_category_by_jobid(self, jobId):
+ # Préparation de la requète pour voir si l'utilisateur existe
+ reqCheckExistId = """
+ SELECT EXISTS(
+ SELECT 1 FROM
+ """ + self.TABLEJOBCATEGORY + """
+ WHERE
+ jobCategoryId = ?
+ LIMIT 1
+ )"""
+ # Exécution de la requète, fetchall pour avoir le résultat
+ # struct par défaut req et index (fetch_both) = arr([0] => arr("req" => BOOL, [0] => BOOL])
+ # fetch_num pour casser l'index "req" en chiffre, dict -> list
+ self.exec_cmd(reqCheckExistId, [jobId])
+ reqResult = self.cur.fetchall()
+ # Si il existe
+ if (reqResult[0][0]):
+ # Préparation de la requète pour suppression
+ reqDelJobCategory = """
+ DELETE FROM
+ """ + self.TABLEJOBCATEGORY + """
+ WHERE
+ jobCategoryId = ?"""
+ # Exécution de la requète
+ self.exec_cmd(reqDelJobCategory, [jobId])
+ # Retourne 1 pour réussite
+ return 1
+ else:
+ # Retourne 0 pour échec
+ return 0
+
+ # ****************************************************************************
+ # GESTION DES MISSIONS DANS L'ADMIN
+ # ****************************************************************************
+ # Suppresion d'une mission
+ def del_mission_by_missionid(self, missionId):
+ # Préparation de la requète pour voir si l'utilisateur existe
+ reqCheckExistId = """
+ SELECT EXISTS(
+ SELECT 1 FROM
+ """ + self.TABLEMISSION + """
+ WHERE
+ missionId = ?
+ LIMIT 1
+ )"""
+ # Exécution de la requète
+ self.exec_cmd(reqCheckExistId, [missionId])
+ reqResult = self.cur.fetchall()
+ # Si il existe
+ if (reqResult[0][0]):
+ # Préparation de la requète pour suppression
+ reqDelMission = """
+ DELETE FROM
+ """ + self.TABLEMISSION + """
+ WHERE
+ missionId = ?"""
+ # Exécution de la requète
+ self.exec_cmd(reqDelMission, [missionId])
+ # Retourne 1 pour réussite
+ return 1
+ else:
+ # Retourne 0 pour échec
+ return 0
diff --git a/app_alphajob/database/dbmain.py b/app_alphajob/database/dbmain.py
new file mode 100644
index 0000000..602cec6
--- /dev/null
+++ b/app_alphajob/database/dbmain.py
@@ -0,0 +1,217 @@
+
+############################################################################
+# #
+# Description: Partie commune des deux ensembles de méthodes #
+# pour la gestion de la BDD #
+# #
+############################################################################
+
+import mysql.connector
+from passlib.hash import sha512_crypt
+
+# const si CAPS
+# https://www.w3schools.com/python/python_mysql_getstarted.asp
+# https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html
+# https://stackoverflow.com/questions/11565487/python-equivalent-of-php-mysql-fetch-array
+
+
+class DbMain():
+ # ****************************************************************************
+ # INFOS GLOBAL ET DE CONNEXION
+ # ****************************************************************************
+ # Pour gérer si "en production"
+ DEBUG = False
+ # Configuration du serveur MYSQL / MARIADB
+ HOST = "127.0.0.1"
+ USER = "root"
+ PASSWORD = ""
+ DATABASE = "alphajob"
+
+ # ****************************************************************************
+ # DECLARATION DES TABLES
+ # ****************************************************************************
+ # UserAccount, infos du compte nécessaire à la connection
+ CREATETABLEUSERACCOUNT = """CREATE TABLE IF NOT EXISTS `alphajob`.`userAccount` (
+ `userId` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `email` VARCHAR(128) NOT NULL,
+ `password` VARCHAR(128) NOT NULL,
+ `tokenAutoLogin` VARCHAR(128) NULL DEFAULT NULL,
+ `inscriptionDate` TIMESTAMP NOT NULL,
+ `userStatus` TINYINT(1) UNSIGNED NOT NULL,
+ PRIMARY KEY (`userId`)
+ )
+ ENGINE = InnoDB
+ DEFAULT CHARACTER SET = utf8;"""
+
+ # Infos complémentaires des utilisateur, liée à userAccount par userId
+ CREATETABLEUSERINFO = """CREATE TABLE IF NOT EXISTS `alphajob`.`userInfo` (
+ `lastname` VARCHAR(128) NOT NULL,
+ `firstname` VARCHAR(128) NOT NULL,
+ `phoneNumber` VARCHAR(10) NOT NULL,
+ `adress` VARCHAR(128) NOT NULL,
+ `zipCode` VARCHAR(6) NOT NULL,
+ `city` VARCHAR(128) NOT NULL,
+ `degree` VARCHAR(128) NULL DEFAULT NULL,
+ `capability` VARCHAR(256) NULL DEFAULT NULL,
+ `description` VARCHAR(256) NULL DEFAULT NULL,
+ `userId` INT UNSIGNED NOT NULL,
+ PRIMARY KEY (`userId`),
+ INDEX `fk_userinfo_userId_idx` (`userId` ASC) VISIBLE,
+ CONSTRAINT `fk_userinfo_userId`
+ FOREIGN KEY (`userId`)
+ REFERENCES `alphajob`.`userAccount` (`userId`)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE
+ )
+ ENGINE = InnoDB
+ DEFAULT CHARACTER SET = utf8;"""
+
+ # Liste des categories d'emploie possible
+ CREATETABLEJOBCATEGORY = """CREATE TABLE IF NOT EXISTS `alphajob`.`jobCategory` (
+ `jobCategoryId` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `jobCategoryNameEn` VARCHAR(128) NOT NULL,
+ `jobCategoryNameFr` VARCHAR(128) NOT NULL,
+ PRIMARY KEY (`jobCategoryId`)
+ )
+ ENGINE = InnoDB
+ DEFAULT CHARACTER SET = utf8;"""
+
+ # Assosications des emploies à un utilisateur
+ CREATETABLEUSERJOB = """CREATE TABLE IF NOT EXISTS `alphajob`.`userJob` (
+ `userId` INT UNSIGNED NOT NULL,
+ `jobCategoryId` INT UNSIGNED NOT NULL,
+ INDEX `fk_userInfo_userId_idx` (`userId` ASC) VISIBLE,
+ INDEX `fk_jobCategory_jobCategoryId_idx` (`jobCategoryId` ASC) VISIBLE,
+ CONSTRAINT `fk_userJob_userId`
+ FOREIGN KEY (`userId`)
+ REFERENCES `alphajob`.`userAccount` (`userId`)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE,
+ CONSTRAINT `fk_userJob_jobCategoryId`
+ FOREIGN KEY (`jobCategoryId`)
+ REFERENCES `alphajob`.`jobCategory` (`jobCategoryId`)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE
+ )
+ ENGINE = InnoDB
+ DEFAULT CHARACTER SET = utf8;"""
+
+ # Infos sur les missions effectuées, liée à userAccount par userId et consultantId
+ CREATETABLEMISSION = """CREATE TABLE IF NOT EXISTS `alphajob`.`mission` (
+ `missionId` INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ `date` TIMESTAMP NOT NULL,
+ `subject` VARCHAR(128) NULL DEFAULT NULL,
+ `note` TINYINT(1) UNSIGNED NULL DEFAULT NULL,
+ `review` VARCHAR(256) NULL DEFAULT NULL,
+ `acceptedByPro` TIMESTAMP NULL DEFAULT NULL,
+ `validatedByClient` TIMESTAMP NULL DEFAULT NULL,
+ `validatedByPro` TIMESTAMP NULL DEFAULT NULL,
+ `clientId` INT UNSIGNED NOT NULL,
+ `proId` INT UNSIGNED NOT NULL,
+ `jobCategoryId` INT UNSIGNED NOT NULL,
+ PRIMARY KEY (`missionId`),
+ INDEX `fk_mission_clientId_idx` (`clientId` ASC) VISIBLE,
+ INDEX `fk_mission_proId_idx` (`proId` ASC) VISIBLE,
+ INDEX `fk_mission_jobCategoryId_idx` (`jobCategoryId` ASC) VISIBLE,
+ CONSTRAINT `fk_mission_clientId`
+ FOREIGN KEY (`clientId`)
+ REFERENCES `alphajob`.`userAccount` (`userId`)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE,
+ CONSTRAINT `fk_mission_proId`
+ FOREIGN KEY (`proId`)
+ REFERENCES `alphajob`.`userAccount` (`userId`)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE,
+ CONSTRAINT `fk_mission_jobCategoryId`
+ FOREIGN KEY (`jobCategoryId`)
+ REFERENCES `alphajob`.`jobCategory` (`jobCategoryId`)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE
+ )
+ ENGINE = InnoDB
+ DEFAULT CHARACTER SET = utf8"""
+
+ # Noms des tables
+ TABLEUSERACCOUNT = "userAccount"
+ TABLEUSERINFO = "userInfo"
+ TABLEJOBCATEGORY = "jobCategory"
+ TABLEUSERJOB = "userJob"
+ TABLEMISSION = "mission"
+
+ # ****************************************************************************
+ # FONCTIONS PRINCIPALES
+ # ****************************************************************************
+ # Constructeur, fonction "auto" déclenchée à l'instanciation
+ def __init__(self):
+ if self.DEBUG:
+ self.conn = mysql.connector.connect(
+ host=self.HOST,
+ user=self.USER,
+ password=self.PASSWORD,
+ database=self.DATABASE,
+ raise_on_warnings=self.DEBUG
+ )
+ else:
+ self.conn = mysql.connector.connect(
+ host=self.HOST,
+ user=self.USER,
+ password=self.PASSWORD,
+ database=self.DATABASE
+ )
+ self.cur = self.conn.cursor()
+
+ # Création de la DB si elle n'existe pas
+ def create_db(self):
+ reqInitDb = "CREATE DATABASE IF NOT EXISTS " + self.DATABASE
+ self.cur.execute(reqInitDb)
+
+ # Sélection de la DB
+ def select_db(self):
+ reqSelectDb = "USE " + self.DATABASE
+ self.cur.execute(reqSelectDb)
+
+ # Création des tables si elles n'existent pas
+ def create_table(self):
+ # userAccount
+ reqInitUserAccount = self.CREATETABLEUSERACCOUNT
+ self.cur.execute(reqInitUserAccount)
+ # userInfo
+ reqInitUserInfo = self.CREATETABLEUSERINFO
+ self.cur.execute(reqInitUserAccount)
+ # jobCategory
+ reqInitJobCategory = self.CREATETABLEJOBCATEGORY
+ self.cur.execute(reqInitJobCategory)
+ # userJob
+ reqInitUserJob = self.CREATETABLEUSERJOB
+ self.cur.execute(reqInitUserJob)
+ # mission
+ reqInitMission = self.CREATETABLEMISSION
+ self.cur.execute(reqInitMission)
+
+ # Déclenche les méthodes pour créer la BDD
+ def init(self):
+ self.create_db()
+ self.select_db()
+ self.create_table()
+
+ # Chiffre la data reçue
+ def crypt_pass(self, password):
+ return sha512_crypt.hash(password, rounds=10000)
+
+ # Prépare la requète pour mitiger (se protéger) les injections SQL et
+ # initialise si nécessaire la BDD à chaque requète
+ def exec_cmd(self, req, arg=None):
+ self.init()
+ if arg:
+ self.cur.execute(req, arg)
+ else:
+ self.cur.execute(req)
+
+ # Vérifie si l'email existe dans la table userAccount de la BDD
+ def check_exist_email(self, email):
+ reqCheckEmailExist = "SELECT EXISTS(SELECT * FROM " + \
+ self.TABLEUSERACCOUNT + " WHERE email = %s)"
+ self.exec_cmd(reqCheckEmailExist, [email])
+ # Retourne 1 si existe, sinon 0
+ return self.cur.fetchall()[0][0]
diff --git a/app_alphajob/database/dbmission.py b/app_alphajob/database/dbmission.py
new file mode 100644
index 0000000..0a33a12
--- /dev/null
+++ b/app_alphajob/database/dbmission.py
@@ -0,0 +1,160 @@
+
+# ############################################################################
+# # #
+# # Description: Ensemble de méthodes pour étendre dbmain afin #
+# # d'effectuer des recherches dans la bdd #
+# # #
+# ############################################################################
+
+# Infos pour les "join":
+# https:#www.freecodecamp.org/news/sql-joins-tutorial/
+
+# Import de dbmain
+from . import dbmain
+from datetime import datetime
+
+
+# Extension de cette classe avec dbmain
+class DbMission(dbmain.DbMain):
+
+ # ****************************************************************************
+ # ENREGISTREMENT ET VALIDATION DES MISSIONS
+ # ****************************************************************************
+ # Enregistrement d'une mission
+ def register_mission(self, subject, clientId, proId, jobId):
+ # Préparation de la requète pour enregistrement de la mission
+ reqAddMission = """
+ INSERT INTO """ + self.TABLEMISSION + """
+ (date, subject, clientId, proId, jobCategoryId)
+ VALUES
+ (?, ?, ?, ?, ?)"""
+ # Exécution de la requète
+ self.exec_cmd(reqAddMission,
+ [datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
+ subject,
+ clientId,
+ proId,
+ jobId
+ ]
+ )
+ return 1
+
+ # Enregistrement d'une mission
+ def accept_mission_by_missionid(self, missionId):
+ # Préparation de la requète pour enregistrement de la mission
+ reqAddMission = """
+ UPDATE
+ """ + self.TABLEMISSION + """
+ SET
+ acceptedByPro = ?
+ WHERE
+ missionId = ?"""
+ # Exécution de la requète
+ self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId])
+ return 1
+
+ def validate_mission_pro_by_missionid(self, missionId):
+ # Préparation de la requète pour enregistrement de la mission
+ reqAddMission = """
+ UPDATE
+ """ + self.TABLEMISSION + """
+ SET
+ validatedByPro = ?
+ WHERE
+ missionId = ?"""
+ # Exécution de la requète
+ self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId])
+ return 1
+
+ def validate_mission_client_by_missionid(self, missionId):
+ # Préparation de la requète pour enregistrement de la mission
+ reqAddMission = """
+ UPDATE
+ """ + self.TABLEMISSION + """
+ SET
+ validatedByClient = ?
+ WHERE
+ missionId = ?"""
+ # Exécution de la requète
+ self.exec_cmd(reqAddMission, [datetime.now().strftime("%Y-%m-%d %H:%M:%S"), missionId])
+ return 1
+
+ def review_mission(self, missionId, review, note):
+ # Préparation de la requète pour enregistrement de la mission
+ reqAddMission = """
+ UPDATE
+ """ + self.TABLEMISSION + """
+ SET
+ review = ?, note = ?
+ WHERE
+ missionId = ?"""
+ # Exécution de la requète
+ self.exec_cmd(reqAddMission, [review, note, missionId])
+ return 1
+
+ # ****************************************************************************
+ # RECUPERATION DES INFORMATIONS RELATIVES AUX MISSIONS
+ # ****************************************************************************
+ # Récupérations des missions d'un pro par son id
+ def get_mission_by_proid(self, proId):
+ reqGetMissionsProId = """
+ SELECT
+ missionId, date, subject, note, review,
+ acceptedByPro, validatedByClient,
+ validatedByPro, jobCategoryId, proId, lastname
+ FROM
+ """ + self.TABLEMISSION + """
+ LEFT JOIN
+ """ + self.TABLEUSERINFO + """
+ ON
+ """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId
+ WHERE
+ proId = ?"""
+ self.exec_cmd(reqGetMissionsProId, [proId])
+ result = self.cur.fetchall()
+ return result
+
+ # Récupérations des missions d'un client par son id
+ def get_mission_by_clientid(self, clientId):
+ reqGetMissionsClientId = """
+ SELECT
+ missionId, date, subject, note, review,
+ acceptedByPro, validatedByClient,
+ validatedByPro, jobCategoryId, proId, lastname
+ FROM
+ """ + self.TABLEMISSION + """
+ LEFT JOIN
+ """ + self.TABLEUSERINFO + """
+ ON
+ """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId
+ WHERE
+ clientId = ?"""
+ self.exec_cmd(reqGetMissionsClientId, [clientId])
+ result = self.cur.fetchall()
+ return result
+
+ # Récupérations des missions d'un client par son id
+ def get_all_missions(self):
+ reqGetAllMission = """
+ SELECT
+ *
+ FROM
+ """ + self.TABLEMISSION
+ self.exec_cmd(reqGetAllMission)
+ result = self.cur.fetchall()
+ return result
+
+ # Compte le nombre de mission d'un consultant par son nom
+ def count_pro_missions_by_proid(self, proId):
+ reqCountMission = """
+ SELECT COUNT(*) FROM
+ """ + self.TABLEMISSION + """
+ INNER JOIN
+ """ + self.TABLEUSERINFO + """
+ ON
+ """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId
+ WHERE
+ proId = ?"""
+ self.exec_cmd(reqCountMission, [proId])
+ result = self.cur.fetchall()
+ return result
diff --git a/app_alphajob/database/dbsearch.py b/app_alphajob/database/dbsearch.py
new file mode 100644
index 0000000..15d4a24
--- /dev/null
+++ b/app_alphajob/database/dbsearch.py
@@ -0,0 +1,140 @@
+############################################################################
+# #
+# Description: Ensemble de méthodes pour étendre dbmain afin #
+# d'effectuer des recherches dans la bdd #
+# #
+############################################################################
+
+# Infos pour les """join""":
+# https:#www.freecodecamp.org/news/sql-joins-tutorial/
+
+# Import de dbmain
+from . import dbmain
+
+
+# Extension de cette classe avec dbmain
+class DbSearch(dbmain.DbMain):
+ # ****************************************************************************
+ # RECUPERATION DES INFORMATIONS RELATIVES AUX UTILISATEURS
+ # ****************************************************************************
+ # Récupération des infos d'un compte par son id
+ def get_user_account_by_userid(self, userId):
+ reqSearchUser = """
+ SELECT
+ userId, email, inscriptionDate, userStatus
+ FROM
+ """ + self.TABLEUSERACCOUNT + """
+ WHERE
+ userId = %s"""
+ self.exec_cmd(reqSearchUser, [userId])
+ return self.cur.fetchall()
+
+ # Récupération des infos d'un utilisateur par son id
+ def get_user_info_by_userid(self, userId):
+ reqGetUserInfo = """
+ SELECT
+ userId, lastname, firstname, degree,
+ capability, description, phoneNumber,
+ adress, zipCode, city
+ FROM
+ """ + self.TABLEUSERINFO + """
+ WHERE
+ userId = %s"""
+ self.exec_cmd(reqGetUserInfo, [userId])
+ return self.cur.fetchall()
+
+ # ****************************************************************************
+ # RECUPERATION DES INFORMATIONS RELATIVES AUX PROS
+ # ****************************************************************************
+ def get_all_pro_by_jobid(self, jobId):
+ reqSearchConsultant = """
+ SELECT
+ """ + self.TABLEUSERINFO + """.userId,
+ lastname, firstname, capability
+ FROM
+ """ + self.TABLEUSERINFO + """
+ INNER JOIN
+ """ + self.TABLEUSERJOB + """
+ ON
+ """ + self.TABLEUSERINFO + """.userId = """ + self.TABLEUSERJOB + """.userId
+ WHERE
+ jobCategoryId = %s"""
+ self.exec_cmd(reqSearchConsultant, [jobId])
+ return self.cur.fetchall()
+
+ # Récupération des infos d'un pro par son nom
+ def get_pro_info_by_lastname(self, lastname):
+ reqSearchConsultant = """
+ SELECT
+ """ + self.TABLEUSERINFO + """.userId,
+ lastname, firstname, capability
+ FROM
+ """ + self.TABLEUSERINFO + """
+ INNER JOIN
+ """ + self.TABLEUSERACCOUNT + """
+ ON
+ """ + self.TABLEUSERINFO + """.userId = """ + self.TABLEUSERACCOUNT + """.userId
+ WHERE
+ userStatus = '1'
+ AND
+ lastname LIKE CONCAT('%', %s, '%')"""
+ self.exec_cmd(reqSearchConsultant, [lastname])
+ return self.cur.fetchall()
+
+ # Récupération des emploies associés à un pro
+ def get_pro_job_by_proid(self, proId):
+ reqGetAll = """
+ SELECT
+ """ + self.TABLEUSERJOB + """.jobCategoryId,
+ jobCategoryNameEn, jobCategoryNameFr
+ FROM
+ """ + self.TABLEUSERJOB + """
+ INNER JOIN
+ """ + self.TABLEJOBCATEGORY + """
+ ON
+ """ + self.TABLEUSERJOB + """.jobCategoryId = """ + self.TABLEJOBCATEGORY + """.jobCategoryId
+ WHERE
+ userId = %s"""
+ self.exec_cmd(reqGetAll, [proId])
+ return self.cur.fetchall()
+
+ # Récupération des notes d'un consultant par son nom
+ def get_pro_note_by_proid(self, proId):
+ reqCountMission = """
+ SELECT
+ note
+ FROM
+ """ + self.TABLEMISSION + """
+ INNER JOIN
+ """ + self.TABLEUSERINFO + """
+ ON
+ """ + self.TABLEMISSION + """.proId = """ + self.TABLEUSERINFO + """.userId
+ WHERE
+ proId = %s"""
+ self.exec_cmd(reqCountMission, [proId])
+ return self.cur.fetchall()
+
+ # ****************************************************************************
+ # RECUPERATION DES INFORMATIONS RELATIVES AUX EMPLOIS
+ # ****************************************************************************
+ # Récupérer toutes les infos de la table jobCategory
+ def get_job_all(self):
+ reqGetAllJobs = """
+ SELECT
+ *
+ FROM
+ """ + self.TABLEJOBCATEGORY
+ self.exec_cmd(reqGetAllJobs)
+ return self.cur.fetchall()
+
+ # Récupérer toutes les infos de la table jobCategory
+ def get_job_by_jobid(self, jobId):
+ reqGetJobinfo = """
+ SELECT
+ *
+ FROM
+ """ + self.TABLEJOBCATEGORY + """
+ WHERE
+ jobCategoryId = %s"""
+ self.exec_cmd(reqGetJobinfo, [jobId])
+ return self.cur.fetchall()
diff --git a/app_alphajob/database/dbuser.py b/app_alphajob/database/dbuser.py
new file mode 100644
index 0000000..e0a62fb
--- /dev/null
+++ b/app_alphajob/database/dbuser.py
@@ -0,0 +1,171 @@
+
+
+############################################################################
+# #
+# Description: Ensemble de méthodes pour étendre dbmain #
+# afin de gérer les utilisateurs #
+# #
+############################################################################
+
+from datetime import datetime
+from passlib.hash import sha512_crypt
+# Import de dbmain
+from . import dbmain
+
+# Extension de cette classe avec dbmain
+class DbUser(dbmain.DbMain):
+
+ # ****************************************************************************
+ # GESTION DES UTILISATEURS
+ # ****************************************************************************
+ # Enregistrement d'un nouvel utilisateur
+ def register_user(self, email, password, userStatus):
+ # On vérifie si l'email existe deja dans la bdd
+ exist = self.check_exist_email(email)
+ # Si non
+ if not exist:
+ # Chiffrement du pass
+ hash = self.crypt_pass(password)
+ # Préparation de la requète
+ reqAddUser = """""
+ INSERT INTO
+ """ + self.TABLEUSERACCOUNT + """
+ (email, password, inscriptionDate, userStatus)
+ VALUES
+ (%s, %s, %s, %s)"""
+ # Execution de la requète
+ self.exec_cmd(reqAddUser,
+ [email,
+ hash,
+ datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
+ userStatus
+ ]
+ )
+ # Retourne 1 pour réussite
+ return 1
+ else:
+ # Retourne 0 pour échec
+ return 0
+
+ # Vérification de la combinaison email - pass pour authentification
+ def check_user_credential(self, email, password):
+ # Préparation de la requète pour récupérer les infos ou l'email est présent
+ reqCheckCredential = """
+ SELECT
+ userId, password
+ FROM
+ """ + self.TABLEUSERACCOUNT + """
+ WHERE
+ email = %s """
+ # Execution de la requète
+ self.exec_cmd(reqCheckCredential, [email])
+ result = self.cur.fetchone()
+ # Vérifiaction de correspondance email & pass
+ if result and sha512_crypt.verify(password, result[1]):
+ return result[0]
+
+ # Mise à jour des infos d'un utilisateur
+ def update_user_infos(self, userInfos, userId, isPro, userJobs=None):
+ # Préparation de la requète pour mise à jour des infos
+ # J'ai préféré faire deux requètes distinctes et ne pas utiliser des valeurs
+ # passées par POST (key => value) pour gérer les noms des colonnes
+ # car je préfère les passer en "dur" dans mes requêtes (risque d'injection SQL%s).
+ reqAddInfoClient = """
+ REPLACE INTO
+ """ + self.TABLEUSERINFO + """
+ (lastname, firstname, phoneNumber,
+ adress, zipCode, city, userId)
+ VALUES
+ (%s, %s, %s, %s, %s, %s, %s)"""
+ reqAddInfoPro = """
+ REPLACE INTO
+ """ + self.TABLEUSERINFO + """
+ (lastname, firstname, phoneNumber,
+ adress, zipCode, city, degree,
+ capability, description, userId)
+ VALUES
+ (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"""
+ reqAddInfoProJobs = """
+ INSERT INTO
+ """ + self.TABLEUSERJOB + """
+ (jobCategoryId, userId)
+ VALUES
+ (%s, %s)"""
+ reqRemoveInfoProJobs = """
+ DELETE FROM
+ """ + self.tableUserJob + """
+ WHERE
+ jobCategoryId = %s
+ AND
+ userId = %s"""
+ # if not isPro:
+ # # Exécution de la requète
+ # # https:#www.php.net/manual/fr/function.array-values.php
+ # # Pour passer de "dict" a "list" -> array_values()
+ # args = [i for i in userInfos]
+ # args.push(userId)
+ # self.exec_cmd(reqAddInfoClient, args)
+ # else:
+ # # https:#stackoverflow.com/questions/15986235/how-to-use-json-stringify-and-json-decode-properly
+ # # Récupération des emplois dans le JSON et supression de ces derniers de la liste
+ # selectedJobs = json_decode(html_entity_decode(userInfos["jobs"]))
+ # unset(userInfos["jobs"])
+ # # array_value -> Qu'est ce qui est présent dans 1 mais pas dans 2 %s
+ # # Comparaison des jobs anciennement présent avec ceux sélectionnés, donc ajoutés.
+ # jobsAdded = array_values(array_diff(selectedJobs, userJobs))
+ # # Comparaison des jobs deja présent avec ceux sélectionnés, donc ajoutés.
+ # jobsRemoved = array_values(array_diff(userJobs, selectedJobs))
+ # # on continue classiquement avec les autres éléments
+ # args = array_values(userInfos)
+ # array_push(args, userId)
+ # self.exec_cmd(reqAddInfoPro, args)
+ # for i in jobsAdded:
+ # self.exec_cmd(reqAddInfoProJobs, array(jobsAdded[i], userId))
+ # for i in jobsRemoved:
+ # self.exec_cmd(reqRemoveInfoProJobs, array(jobsRemoved[i], userId))
+
+ # ****************************************************************************
+ # GESTION DU TOKEN AUTOLOGIN
+ # ****************************************************************************
+ # Vérification de la combinaison email - jeton d'auto-login pour authentification
+ def check_token_autologin(self, email, token):
+ # Préparation de la requète pour récupérer les infos ou l'email est présent
+ reqCheckToken = """
+ SELECT
+ userId, tokenAutoLogin
+ FROM
+ """ + self.TABLEUSERACCOUNT + """
+ WHERE
+ email = %s"""
+ # Exécution de la requète
+ self.exec_cmd(reqCheckToken, [email])
+ result = self.cur.fetchone()
+ # Vérifiaction de correspondance email & jeton d'auto-connection
+ if result and result[1] == token:
+ return result[0]
+
+ # Mise à jour du jeton d'auto-login
+ def update_token_autologin(self, email, token):
+ # Préparation de la requète pour mise à jour du jeton d'auto-connection
+ reqUpdateToken = """
+ UPDATE
+ """ + self.TABLEUSERACCOUNT + """
+ SET
+ tokenAutoLogin = %s
+ WHERE
+ email = %s"""
+ # Execution de la requète
+ self.exec_cmd(reqUpdateToken, [token, email])
+
+ # Supression du jeton d'auto-login
+ def del_token_autologin(self, email):
+ # Préparation de la requète pour supression du jeton d'auto-connection
+ reqDeleteToken = """
+ UPDATE
+ """ + self.TABLEUSERACCOUNT + """
+ SET
+ tokenAutoLogin = NULL
+ WHERE
+ email = %s"""
+ # Execution de la requète
+ self.exec_cmd(reqDeleteToken, [email])
diff --git a/app_alphajob/main.py b/app_alphajob/main.py
new file mode 100644
index 0000000..11f4cc1
--- /dev/null
+++ b/app_alphajob/main.py
@@ -0,0 +1,119 @@
+
+
+import sys
+from os.path import join
+from PyQt5 import QtWidgets, QtGui
+from database import dbuser
+
+class mainWindow(QtWidgets.QMainWindow):
+
+ VERSION = 0.1
+
+ def __init__(self):
+ super(mainWindow, self).__init__()
+ logo = join("./ressources", "icon.ico")
+ self.setWindowIcon(QtGui.QIcon(logo))
+ menu = self.menuBar()
+ menu_options = menu.addMenu("Options")
+ btn_apropos = QtWidgets.QAction("A propos", self)
+ btn_apropos.triggered.connect(self.a_propos)
+ menu_options.addAction(btn_apropos)
+ self.setWindowTitle("Alphajob")
+ self.home()
+
+ def home(self):
+ self.label1 = QtWidgets.QLabel("Home page")
+ btn1 = QtWidgets.QPushButton("Aller à la page de connexion")
+ btn1.clicked.connect(self.page_login)
+
+ self.layoutMain = QtWidgets.QVBoxLayout()
+
+ self.layoutMain.addWidget(self.label1)
+ self.layoutMain.addWidget(btn1)
+
+ if hasattr(self, "mainWidget"):
+ self.mainWidget.deleteLater()
+ self.mainWidget = QtWidgets.QWidget()
+ self.mainWidget.setLayout(self.layoutMain)
+ self.setCentralWidget(self.mainWidget)
+ self.show()
+
+ def page_login(self):
+ btnAccueil = QtWidgets.QPushButton("Accueil")
+ btnAccueil.clicked.connect(self.home)
+ self.emailConnexion = QtWidgets.QLineEdit("Email")
+ self.passwordConnexion = QtWidgets.QLineEdit("Password")
+ btnConnexion = QtWidgets.QPushButton("Connexion")
+ btnConnexion.clicked.connect(self.login)
+
+ self.layoutMain = QtWidgets.QVBoxLayout()
+ self.layoutNavigation = QtWidgets.QHBoxLayout()
+ self.layoutPassword = QtWidgets.QHBoxLayout()
+ self.layoutPasswordWidgets = QtWidgets.QVBoxLayout()
+
+ self.layoutMain.addLayout(self.layoutNavigation)
+ self.layoutNavigation.addWidget(btnAccueil)
+ self.layoutNavigation.addStretch()
+
+ self.layoutMain.addLayout(self.layoutPassword)
+ self.layoutPassword.addStretch()
+ self.layoutPassword.addLayout(self.layoutPasswordWidgets)
+ self.layoutPassword.addStretch()
+
+ self.layoutPasswordWidgets.addWidget(self.emailConnexion)
+ self.layoutPasswordWidgets.addWidget(self.passwordConnexion)
+ self.layoutPasswordWidgets.addWidget(btnConnexion)
+
+ self.mainWidget.deleteLater()
+ self.mainWidget = QtWidgets.QWidget()
+ self.mainWidget.setLayout(self.layoutMain)
+ self.setCentralWidget(self.mainWidget)
+
+ def login(self):
+ user = dbuser.DbUser()
+ if user.check_exist_email(self.emailConnexion.text()):
+ res = user.check_user_credential(
+ self.emailConnexion.text(),
+ self.passwordConnexion.text()
+ )
+ if res:
+ QtWidgets.QMessageBox.information(
+ self,
+ "Connexion",
+ "Vous êtes connecté"
+ )
+ else:
+ QtWidgets.QMessageBox.warning(
+ self,
+ "Connexion",
+ "Mauvaise combinaison mail & mot de passe"
+ )
+ else:
+ QtWidgets.QMessageBox.warning(
+ self,
+ "Connexion",
+ "Mauvais email"
+ )
+
+
+ def a_propos(self):
+ QtWidgets.QMessageBox.information(
+ self,
+ "A propos",
+ "Logiciel pour mon dossier professionnel.\
+ <br>Version: %s\
+ <br>Auteur: Debulois Quentin\
+ <br>Code source: \
+ <a href='https://git.debulois.fr/'>git.debulois.fr/</a>" % self.VERSION
+ )
+
+
+if __name__ == "__main__":
+ def main():
+ """Démarrage de l'app
+ """
+ app = QtWidgets.QApplication(sys.argv)
+ GUI = mainWindow()
+ sys.exit(app.exec_())
+
+ main() \ No newline at end of file
diff --git a/app_alphajob/ressources/icon.ico b/app_alphajob/ressources/icon.ico
new file mode 100644
index 0000000..7c550a3
--- /dev/null
+++ b/app_alphajob/ressources/icon.ico
Binary files differ
diff --git a/requierments.txt b/requierments.txt
new file mode 100644
index 0000000..a7e7164
--- /dev/null
+++ b/requierments.txt
Binary files differ