20/03/2024 - 22h30
parent
0389df9840
commit
15f1a24c89
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="12/03/2024 - 20h30">
|
||||
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="19/03/2024 - 17h30">
|
||||
<change afterPath="$PROJECT_DIR$/E_Sign_Document.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/GlobalVariable.py" beforeDir="false" afterPath="$PROJECT_DIR$/GlobalVariable.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Inscription_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/Inscription_mgt.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Log/log_file.log" beforeDir="false" afterPath="$PROJECT_DIR$/Log/log_file.log" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Session_Formation.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/class_mgt.py" beforeDir="false" afterPath="$PROJECT_DIR$/class_mgt.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/emargement.py" beforeDir="false" afterPath="$PROJECT_DIR$/emargement.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/crm_opportunite.py" beforeDir="false" afterPath="$PROJECT_DIR$/crm_opportunite.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
|
@ -77,13 +77,6 @@
|
|||
<option name="presentableId" value="Default" />
|
||||
<updated>1680804787304</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00195" summary="15/01/2024 - 17h00">
|
||||
<created>1705335099150</created>
|
||||
<option name="number" value="00195" />
|
||||
<option name="presentableId" value="LOCAL-00195" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1705335099151</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00196" summary="15/01/2024 - 22h">
|
||||
<created>1705352583884</created>
|
||||
<option name="number" value="00196" />
|
||||
|
@ -420,7 +413,14 @@
|
|||
<option name="project" value="LOCAL" />
|
||||
<updated>1710272089418</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="244" />
|
||||
<task id="LOCAL-00244" summary="19/03/2024 - 17h30">
|
||||
<created>1710866627531</created>
|
||||
<option name="number" value="00244" />
|
||||
<option name="presentableId" value="LOCAL-00244" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1710866627532</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="245" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="Vcs.Log.Tabs.Properties">
|
||||
|
@ -435,7 +435,6 @@
|
|||
</option>
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<MESSAGE value="sdsdqs" />
|
||||
<MESSAGE value="13/02/2024 - 11h" />
|
||||
<MESSAGE value="17/02/2024 - 11h" />
|
||||
<MESSAGE value="18/02/2024 - 14h" />
|
||||
|
@ -460,6 +459,7 @@
|
|||
<MESSAGE value="10/03/24 - 21h" />
|
||||
<MESSAGE value="11/03/2024 - 15h" />
|
||||
<MESSAGE value="12/03/2024 - 20h30" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="12/03/2024 - 20h30" />
|
||||
<MESSAGE value="19/03/2024 - 17h30" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="19/03/2024 - 17h30" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,450 @@
|
|||
"""
|
||||
Ce document permet de gerer la signature electronique des documents.
|
||||
|
||||
Process (exemple : convention) :
|
||||
A la creation d'un document, si il est soumis à signature electronique
|
||||
alors il est stocké dans la collection "e_document_signe" avec les champs :
|
||||
- related_collection
|
||||
- related_collection_id
|
||||
- document_data (le contenu du document)
|
||||
- statut :
|
||||
0 - a signer
|
||||
1 - signé
|
||||
|
||||
/!\ IMPORTANT :
|
||||
- A la creation d'un document, on lui ajoute une cle secrete avec 5 chiffre
|
||||
- On ajoute une adresse email qui doit signer le mail
|
||||
|
||||
Cette clée est utilisé pour :
|
||||
1 - Recuperer le document
|
||||
2 - Signer le document.
|
||||
|
||||
Dans le lien de signature on doit fournir :
|
||||
- _id du document
|
||||
|
||||
Pour afficher le doc, l'utilisateur doit fournir :
|
||||
- l'email de la personne
|
||||
- secret_key : la clé de X caractère
|
||||
|
||||
/!\ : Nous effectuons une signature electronique securisée de niveau 2 :
|
||||
https://www.francenum.gouv.fr/guides-et-conseils/pilotage-de-lentreprise/dematerialisation-des-documents/la-signature#:~:text=L'objectif%20majeur%20de%20la,rapporter%20la%20preuve%20du%20consentement.
|
||||
En pratique, comment fonctionne la signature électronique avancée (niveau 2) ?
|
||||
Pour signer numériquement un contrat de location ou même un achat immobilier et que cela ait une valeur légale, il faut passer par un tiers de confiance. Ces entreprises habilitées à effectuer des opérations de sécurité juridique d'authentification, de transmission et de stockage sont nombreuses. Si elles proposent chacune leur solution, plus ou moins élaborées ou faciles d’utilisation, leur fonctionnement est relativement similaire : la procédure ressemble un peu à un achat en ligne, avec une authentification par code secret via SMS. Le processus est le suivant.
|
||||
|
||||
Vous vous connectez sur le site du tiers de confiance en ligne à l’aide de vos identifiants, voire de votre clef électronique dans le cas d’une authentification qualifiée (niveau 3)
|
||||
Vous ajoutez les documents (word, PDF, etc…) que vous souhaitez faire signer.
|
||||
Vous invitez des signataires après avoir renseigné leurs coordonnées (en particulier leur numéro de téléphone portable).
|
||||
Chaque signataire reçoit par mail une notification pour signer ainsi qu’un code par SMS permettant de sécuriser la signature.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import base64
|
||||
|
||||
import bson
|
||||
import pymongo
|
||||
from pymongo import MongoClient
|
||||
import json
|
||||
from bson import ObjectId
|
||||
import re
|
||||
from datetime import datetime, time
|
||||
import prj_common as mycommon
|
||||
import secrets
|
||||
import inspect
|
||||
import sys, os
|
||||
import csv
|
||||
import pandas as pd
|
||||
from pymongo import ReturnDocument
|
||||
import GlobalVariable as MYSY_GV
|
||||
from math import isnan
|
||||
import GlobalVariable as MYSY_GV
|
||||
import ela_index_bdd_classes as eibdd
|
||||
import email_mgt as email
|
||||
import jinja2
|
||||
from flask import send_file
|
||||
from xhtml2pdf import pisa
|
||||
from email.message import EmailMessage
|
||||
from email.mime.text import MIMEText
|
||||
from email import encoders
|
||||
import smtplib
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.base import MIMEBase
|
||||
from email import encoders
|
||||
import hashlib
|
||||
from Crypto.Cipher import PKCS1_OAEP
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
|
||||
class SignedMessage:
|
||||
message: bytes = None
|
||||
digitalsignature: bytes = None
|
||||
|
||||
def __init__(self, message: bytes):
|
||||
self.message = message
|
||||
|
||||
def _hash_message(self):
|
||||
# Generate the hash of this message
|
||||
return calculateHash(self.message)
|
||||
|
||||
def encrypt(self, key):
|
||||
hash = self._hash_message()
|
||||
# Instantiating PKCS1_OAEP object with the public key for encryption
|
||||
cipher = PKCS1_OAEP.new(key=key)
|
||||
# Encrypting the message with the PKCS1_OAEP object
|
||||
self.digitalsignature = cipher.encrypt(hash)
|
||||
|
||||
"""
|
||||
Add document du signe
|
||||
"""
|
||||
def Create_E_Document(diction):
|
||||
try:
|
||||
diction = mycommon.strip_dictionary(diction)
|
||||
|
||||
"""
|
||||
Verification des input acceptés
|
||||
"""
|
||||
field_list = ['token', 'file_name', 'related_collection', 'related_collection_id',
|
||||
'email_destinataire']
|
||||
|
||||
incom_keys = diction.keys()
|
||||
for val in incom_keys:
|
||||
if val not in field_list and val.startswith('my_') is False:
|
||||
mycommon.myprint(str(
|
||||
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
|
||||
return False, " Les informations fournies sont incorrectes"
|
||||
|
||||
"""
|
||||
Verification des champs obligatoires
|
||||
"""
|
||||
field_list_obligatoire = ['token', 'file_name', 'related_collection', 'related_collection_id',
|
||||
'email_destinataire']
|
||||
|
||||
for val in field_list_obligatoire:
|
||||
if val not in diction:
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
|
||||
return False, " Les informations fournies sont incorrectes"
|
||||
|
||||
"""
|
||||
Verification de l'identité et autorisation de l'entité qui
|
||||
appelle cette API
|
||||
"""
|
||||
token = ""
|
||||
if ("token" in diction.keys()):
|
||||
if diction['token']:
|
||||
token = diction['token']
|
||||
|
||||
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
|
||||
if (local_status is not True):
|
||||
return local_status, my_partner
|
||||
|
||||
if (mycommon.isEmailValide(str(diction['email_destinataire'])) is False):
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " L'adresse email " + str(diction['email_destinataire']) + " n'est pas valide")
|
||||
return False, " L'adresse email " + str(diction['email_destinataire']) + " n'est pas valide "
|
||||
|
||||
file_name = diction['file_name']
|
||||
|
||||
basename = os.path.basename(file_name)
|
||||
basename2 = basename.split(".")
|
||||
|
||||
if (len(basename2) != 2):
|
||||
mycommon.myprint(str(inspect.stack()[0][3]) + " - : Le nom du fichier est incorrect")
|
||||
return False, "Le nom du fichier est incorrect"
|
||||
|
||||
if (str(basename2[1]).lower() not in MYSY_GV.ALLOWED_EXTENSIONS):
|
||||
mycommon.myprint(str(inspect.stack()[0][3]) + " - : le format de fichier '"+str(basename2[1])+"' n'est pas autorisé. Les extentions autorisées sont : "+str(MYSY_GV.ALLOWED_EXTENSIONS))
|
||||
return False, "le format de fichier '"+str(basename2[1])+"' n'est pas autorisé. Les extentions autorisées sont : "+str(MYSY_GV.ALLOWED_EXTENSIONS)
|
||||
|
||||
encoded_pdf_to_string = ""
|
||||
with open(file_name, "rb") as f:
|
||||
encoded_pdf_to_string = base64.b64encode(f.read())
|
||||
|
||||
|
||||
secret_key = secrets.token_urlsafe(5)
|
||||
new_diction = {}
|
||||
new_diction['document_data'] = encoded_pdf_to_string
|
||||
new_diction['related_collection'] = "aaaa"
|
||||
new_diction['related_collection_id'] = 'bbbb'
|
||||
new_diction['partner_owner_recid'] = my_partner['recid']
|
||||
new_diction['statut'] = '0'
|
||||
new_diction['valide'] = '1'
|
||||
new_diction['locked'] = "0"
|
||||
new_diction['secret_key'] = str(secret_key)
|
||||
new_diction['email_destinataire'] = str(diction['email_destinataire'])
|
||||
new_diction['date_update'] = str(datetime.now())
|
||||
new_diction['update_by'] = str(my_partner['_id'])
|
||||
|
||||
val = MYSY_GV.dbname['e_document_signe'].insert_one(new_diction)
|
||||
if (val is None):
|
||||
mycommon.myprint(
|
||||
" Impossible de créer le E-Document (2) ")
|
||||
return False, " Impossible de créer le E-Document (2) "
|
||||
|
||||
return True, str(val['id'])
|
||||
|
||||
|
||||
except Exception as e:
|
||||
exc_type, exc_obj, exc_tb = sys.exc_info()
|
||||
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
|
||||
return False, " Impossible de créer le E-Document "
|
||||
|
||||
|
||||
|
||||
"""
|
||||
Recuperation document à signer, sans connexion token
|
||||
"""
|
||||
def Get_Given_E_Document_Not_Signed_No_Token(diction):
|
||||
try:
|
||||
diction = mycommon.strip_dictionary(diction)
|
||||
|
||||
"""
|
||||
Verification des input acceptés
|
||||
"""
|
||||
field_list = ['token', 'e_doc_id', 'secret_key', 'user_email' ]
|
||||
|
||||
incom_keys = diction.keys()
|
||||
for val in incom_keys:
|
||||
if val not in field_list and val.startswith('my_') is False:
|
||||
mycommon.myprint(str(
|
||||
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
|
||||
return False, " Les informations fournies sont incorrectes"
|
||||
|
||||
"""
|
||||
Verification des champs obligatoires
|
||||
"""
|
||||
field_list_obligatoire = ['token', 'e_doc_id', 'secret_key', 'user_email' ]
|
||||
|
||||
for val in field_list_obligatoire:
|
||||
if val not in diction:
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
|
||||
return False, " Les informations fournies sont incorrectes"
|
||||
|
||||
"""
|
||||
Verification de l'identité et autorisation de l'entité qui
|
||||
appelle cette API
|
||||
"""
|
||||
token = ""
|
||||
if ("token" in diction.keys()):
|
||||
if diction['token']:
|
||||
token = diction['token']
|
||||
"""
|
||||
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
|
||||
if (local_status is not True):
|
||||
return local_status, my_partner
|
||||
"""
|
||||
|
||||
if( mycommon.isEmailValide(str(diction['user_email'])) is False ):
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " - La valeur '" + str(diction['user_email']) + "' n'est pas un email valide ")
|
||||
return False, " Les informations fournies sont incorrectes"
|
||||
|
||||
|
||||
RetObject = []
|
||||
val_tmp = 0
|
||||
|
||||
RetObject = []
|
||||
val_tmp = 0
|
||||
|
||||
qry = { 'valide': '1', 'locked': '0',
|
||||
'_id': ObjectId(str(diction['e_doc_id'])),
|
||||
'secret_key':str(diction['secret_key']),
|
||||
'statut':'0'}
|
||||
|
||||
for New_retVal in MYSY_GV.dbname['e_document_signe'].find(qry).sort([("_id", pymongo.DESCENDING), ]):
|
||||
if( "email_destinataire" in New_retVal.keys() and New_retVal['email_destinataire']):
|
||||
list_email = str(New_retVal['email_destinataire']).replace(",",";")
|
||||
tab_list_email = list_email.split(";")
|
||||
|
||||
if( str(diction['user_email']) in tab_list_email ) :
|
||||
user = New_retVal
|
||||
user['id'] = str(val_tmp)
|
||||
if( "signature_digitale" in New_retVal.keys() ):
|
||||
del New_retVal['signature_digitale']
|
||||
|
||||
val_tmp = val_tmp + 1
|
||||
decode_data = user['document_data'].decode()
|
||||
user['document_data'] = decode_data
|
||||
RetObject.append(mycommon.JSONEncoder().encode(user))
|
||||
|
||||
|
||||
if(len(RetObject) <= 0 ):
|
||||
mycommon.myprint(str(
|
||||
inspect.stack()[0][3]) + " Aucun E-document trouvé ")
|
||||
return False, " Aucun E-document trouvé "
|
||||
|
||||
return True, RetObject
|
||||
|
||||
except Exception as e:
|
||||
exc_type, exc_obj, exc_tb = sys.exc_info()
|
||||
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
|
||||
return False, " Impossible de récupérer le document électronique "
|
||||
|
||||
|
||||
|
||||
|
||||
def calculateHash(message):
|
||||
m = hashlib.sha256()
|
||||
m.update(message)
|
||||
return m.digest()
|
||||
|
||||
def checkIntegrity(calculated_hash, decrypted_hash):
|
||||
if calculated_hash == decrypted_hash:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
"""
|
||||
Signature du document
|
||||
"""
|
||||
def Create_E_Signature_For_E_Document(diction):
|
||||
try:
|
||||
diction = mycommon.strip_dictionary(diction)
|
||||
|
||||
"""
|
||||
Verification des input acceptés
|
||||
"""
|
||||
field_list = ['token', 'e_doc_id', 'secret_key', 'email_destinataire', 'user_ip' ]
|
||||
|
||||
incom_keys = diction.keys()
|
||||
for val in incom_keys:
|
||||
if val not in field_list and val.startswith('my_') is False:
|
||||
mycommon.myprint(str(
|
||||
inspect.stack()[0][3]) + " Le champ '" + val + "' n'est pas autorisé")
|
||||
return False, " Les informations fournies sont incorrectes"
|
||||
|
||||
"""
|
||||
Verification des champs obligatoires
|
||||
"""
|
||||
field_list_obligatoire = ['token', 'e_doc_id', 'secret_key', 'email_destinataire' ]
|
||||
|
||||
for val in field_list_obligatoire:
|
||||
if val not in diction:
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " - La valeur '" + val + "' n'est pas presente dans liste ")
|
||||
return False, " Les informations fournies sont incorrectes"
|
||||
|
||||
"""
|
||||
Verification de l'identité et autorisation de l'entité qui
|
||||
appelle cette API
|
||||
"""
|
||||
token = ""
|
||||
if ("token" in diction.keys()):
|
||||
if diction['token']:
|
||||
token = diction['token']
|
||||
|
||||
"""
|
||||
local_status, my_partner = mycommon.Check_Connexion_And_Return_Partner_Data(diction)
|
||||
if (local_status is not True):
|
||||
return local_status, my_partner
|
||||
"""
|
||||
if (mycommon.isEmailValide(str(diction['email_destinataire'])) is False):
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " - La valeur '" + str(
|
||||
diction['user_email']) + "' n'est pas un email valide ")
|
||||
return False, " Les informations fournies sont incorrectes"
|
||||
|
||||
|
||||
RetObject = []
|
||||
val_tmp = 0
|
||||
|
||||
# Verifier la validité du document
|
||||
qry = { 'valide': '1', 'locked': '0',
|
||||
'_id': ObjectId(str(diction['e_doc_id'])),
|
||||
'secret_key':str(diction['secret_key']),
|
||||
}
|
||||
|
||||
|
||||
is_valide_e_document = MYSY_GV.dbname['e_document_signe'].count_documents(qry)
|
||||
if( is_valide_e_document <= 0 ):
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " L'idientifiant du E-Document est invalide ")
|
||||
return False, " L'idientifiant du E-Document est invalide "
|
||||
|
||||
e_document_data = MYSY_GV.dbname['e_document_signe'].find_one(qry)
|
||||
|
||||
if ("email_destinataire" in e_document_data.keys() and e_document_data['email_destinataire']):
|
||||
list_email = str(e_document_data['email_destinataire']).replace(",", ";")
|
||||
tab_list_email = list_email.split(";")
|
||||
|
||||
if (str(diction['email_destinataire']) in tab_list_email):
|
||||
my_str = str(e_document_data['document_data'])
|
||||
document_data_as_bytes = str.encode(my_str)
|
||||
print(type(document_data_as_bytes)) # ensure it is byte representation
|
||||
|
||||
message = document_data_as_bytes
|
||||
msg = SignedMessage(message=message)
|
||||
|
||||
# Generating private key (RsaKey object) of key length of 1024 bits
|
||||
private_key = RSA.generate(1024)
|
||||
# Generating the public key (RsaKey object) from the private key
|
||||
public_key = private_key.publickey()
|
||||
|
||||
# Calculating the digital signature
|
||||
msg.encrypt(key=public_key)
|
||||
print(f"Digital Signature: {msg.digitalsignature}")
|
||||
|
||||
# The message is still clear
|
||||
#print(f"Message: {msg.message}")
|
||||
|
||||
# Instantiating PKCS1_OAEP object with the private key for decryption
|
||||
decrypt = PKCS1_OAEP.new(key=private_key)
|
||||
# Decrypting the message with the PKCS1_OAEP object
|
||||
decrypted_message = decrypt.decrypt(msg.digitalsignature)
|
||||
print(f"decrypted_message: {decrypted_message}")
|
||||
|
||||
# We recalculate the hash of the message using the same hash function
|
||||
calcHash = calculateHash(msg.message)
|
||||
#print(f"decrypted_message: {msg.message}")
|
||||
|
||||
is_signed_valide = checkIntegrity(calcHash, decrypted_message)
|
||||
if( is_signed_valide is False):
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " L'intégrité du document signé n'est pas valide ")
|
||||
return False, " Impossible de signer le document(3) "
|
||||
|
||||
|
||||
"""
|
||||
Apresent que le message est signé, on va mettre à jour le doc
|
||||
"""
|
||||
encoded_signed_pdf_to_string = base64.b64encode(decrypted_message)
|
||||
new_data = {}
|
||||
new_data['signature_digitale'] = msg.digitalsignature
|
||||
new_data['signed_date'] = str(datetime.now())
|
||||
new_data['signed_email'] = str(diction['email_destinataire'])
|
||||
new_data['signed_ip_adress'] = str(diction['user_ip'])
|
||||
new_data['statut'] = "1"
|
||||
|
||||
|
||||
qry_key = {'valide': '1', 'locked': '0',
|
||||
'_id': ObjectId(str(diction['e_doc_id'])),
|
||||
'secret_key': str(diction['secret_key']),
|
||||
'email_destinataire': str(diction['email_destinataire'])}
|
||||
|
||||
|
||||
result = MYSY_GV.dbname['e_document_signe'].find_one_and_update(
|
||||
qry_key,
|
||||
{"$set": new_data},
|
||||
upsert=False,
|
||||
return_document=ReturnDocument.AFTER
|
||||
)
|
||||
if ("_id" not in result.keys()):
|
||||
mycommon.myprint(
|
||||
" Impossible de signer le document (2) ")
|
||||
return False, " Impossible de signer le document (2) "
|
||||
|
||||
else:
|
||||
mycommon.myprint(
|
||||
str(inspect.stack()[0][3]) + " L'idientifiant du E-Document est invalide ")
|
||||
return False, " L'idientifiant du E-Document est invalide "
|
||||
|
||||
return True, " Le document a été correction signé. Vous allez recevoir le document par email"
|
||||
|
||||
except Exception as e:
|
||||
exc_type, exc_obj, exc_tb = sys.exc_info()
|
||||
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
|
||||
return False, " Impossible de signer le document "
|
||||
|
|
@ -41,7 +41,7 @@ from email.message import EmailMessage
|
|||
import attached_file_mgt as attached_file_mgt
|
||||
from zipfile import ZipFile
|
||||
import partner_client as partner_client
|
||||
|
||||
import E_Sign_Document as E_Sign_Document
|
||||
"""
|
||||
Enregistrement d'un stagiaire
|
||||
|
||||
|
@ -9465,6 +9465,22 @@ def Sent_Convention_Stagiaire_By_Email_By_Partner_client(tab_files_name_full_pat
|
|||
if (local_status is not True):
|
||||
return local_status, my_partner
|
||||
|
||||
"""
|
||||
20/03/2024 : Creation du E-Document à signer
|
||||
On verifier si le partenaire dispose de l'option "signature_digital" dans la collection base_partner_setup
|
||||
"""
|
||||
is_partner_digital_signature = ""
|
||||
is_signature_digital_count = MYSY_GV.dbname['base_partner_setup'].count_documents(
|
||||
{'partner_owner_recid': str(my_partner['recid']),
|
||||
'config_name': 'signature_digital',
|
||||
'valide': '1',
|
||||
'locked': '0',
|
||||
'config_value': '1'})
|
||||
if (is_signature_digital_count == 1):
|
||||
is_partner_digital_signature = "1"
|
||||
|
||||
|
||||
|
||||
# Verifier que la session est valide
|
||||
is_session_id_valide = MYSY_GV.dbname['session_formation'].count_documents(
|
||||
{'_id': ObjectId(str(diction['session_id'])),
|
||||
|
@ -9742,6 +9758,26 @@ def Sent_Convention_Stagiaire_By_Email_By_Partner_client(tab_files_name_full_pat
|
|||
# Creation de l'email à enoyer
|
||||
msg = MIMEMultipart("alternative")
|
||||
|
||||
"""
|
||||
20/03/2024 : la convention pdf a été créée.
|
||||
Si le partenaire a l'option de signature digitale, alors on créé le e-document
|
||||
"""
|
||||
if( is_partner_digital_signature == "1"):
|
||||
new_e_document_diction = {}
|
||||
new_e_document_diction['token'] = diction['token']
|
||||
new_e_document_diction['file_name'] = outputFilename
|
||||
toaddrs = ", ".join(tab_emails_destinataire)
|
||||
new_e_document_diction['email_destinataire'] = str(toaddrs)
|
||||
#new_e_document_diction['email_destinataire'] = "cbalde@mysy-training.com"
|
||||
|
||||
new_e_document_diction['related_collection'] = ""
|
||||
new_e_document_diction['related_collection_id'] = ""
|
||||
local_status_e_doc, local_retval_e_doc = E_Sign_Document.Create_E_Document(new_e_document_diction)
|
||||
|
||||
if(local_status_e_doc is False ):
|
||||
return local_status_e_doc, local_retval_e_doc
|
||||
|
||||
|
||||
else:
|
||||
# Il s'agit d'une simple email
|
||||
|
||||
|
@ -9855,6 +9891,7 @@ def Sent_Convention_Stagiaire_By_Email_By_Partner_client(tab_files_name_full_pat
|
|||
smtpserver.close()
|
||||
print(" Email envoyé " + str(val))
|
||||
|
||||
|
||||
"""
|
||||
25/01/2024 : pour loger une action dans la collection ==> courrier_template_tracking_history
|
||||
"""
|
||||
|
|
3132
Log/log_file.log
3132
Log/log_file.log
File diff suppressed because one or more lines are too long
|
@ -710,6 +710,7 @@ def Get_List_CRM_Opportunite_no_filter(diction):
|
|||
"""
|
||||
Recuperer données d'une opportunité données
|
||||
"""
|
||||
|
||||
def Get_Given_CRM_Opportunite(diction):
|
||||
try:
|
||||
diction = mycommon.strip_dictionary(diction)
|
||||
|
|
54
main.py
54
main.py
|
@ -77,6 +77,7 @@ import attestation_formation as attestation_formation
|
|||
import crm_opportunite as crm_opportunite
|
||||
import site_formation as site_formation
|
||||
import paiement_condition as paiement_condition
|
||||
import E_Sign_Document as E_Sign_Document
|
||||
|
||||
|
||||
|
||||
|
@ -7971,6 +7972,59 @@ def Configure_Partner_Init_Setup_No_Token():
|
|||
|
||||
|
||||
|
||||
"""
|
||||
API pour ajouter un document electronique à signer
|
||||
"""
|
||||
@app.route('/myclass/api/Create_E_Document/', methods=['POST','GET'])
|
||||
@crossdomain(origin='*')
|
||||
def Create_E_Document():
|
||||
# On recupere le corps (payload) de la requete
|
||||
payload = mycommon.strip_dictionary (request.form.to_dict())
|
||||
print(" ### Create_E_Document payload = ",payload)
|
||||
status, retval = E_Sign_Document.Create_E_Document(payload)
|
||||
return jsonify(status=status, message=retval)
|
||||
|
||||
|
||||
"""
|
||||
API Pour recuperer un documen électronique
|
||||
"""
|
||||
"""
|
||||
API pour ajouter un document electronique à signer
|
||||
"""
|
||||
@app.route('/myclass/api/Get_Given_E_Document_Not_Signed_No_Token/', methods=['POST','GET'])
|
||||
@crossdomain(origin='*')
|
||||
def Get_Given_E_Document_Not_Signed_No_Token():
|
||||
# On recupere le corps (payload) de la requete
|
||||
payload = mycommon.strip_dictionary (request.form.to_dict())
|
||||
print(" ### Get_Given_E_Document_Not_Signed_No_Token payload = ",payload)
|
||||
status, retval = E_Sign_Document.Get_Given_E_Document_Not_Signed_No_Token(payload)
|
||||
return jsonify(status=status, message=retval)
|
||||
|
||||
|
||||
|
||||
"""
|
||||
API pour signer electroniquement un document
|
||||
"""
|
||||
@app.route('/myclass/api/Create_E_Signature_For_E_Document/', methods=['POST','GET'])
|
||||
@crossdomain(origin='*')
|
||||
def Create_E_Signature_For_E_Document():
|
||||
# On recupere le corps (payload) de la requete
|
||||
|
||||
payload = mycommon.strip_dictionary (request.form.to_dict())
|
||||
print(" ### Create_E_Signature_For_E_Document payload = ",payload)
|
||||
|
||||
user_ip = ""
|
||||
headers_list = request.headers.getlist("X-Forwarded-For")
|
||||
user_ip = headers_list[0] if headers_list else request.remote_addr
|
||||
|
||||
payload['user_ip'] = user_ip
|
||||
|
||||
status, retval = E_Sign_Document.Create_E_Signature_For_E_Document(payload)
|
||||
return jsonify(status=status, message=retval)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(" debut api")
|
||||
context = SSL.Context(SSL.SSLv23_METHOD)
|
||||
|
|
Loading…
Reference in New Issue