Integrate htmx and dropzone for file Section

This commit is contained in:
2026-01-13 01:53:13 +01:00
parent 0e79fdcb36
commit 5abbf367ab
15 changed files with 248 additions and 225 deletions

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from flask import Blueprint, Flask, request, flash, render_template, url_for, session, redirect, abort, make_response, flash, abort, send_file, send_from_directory
from werkzeug.utils import secure_filename
from markupsafe import escape
from PIL import Image
@@ -16,15 +17,14 @@ filesupload = Blueprint('filesupload', __name__, template_folder='templates')
app = Flask( 'pywallter' )
app.config.from_pyfile('config.py')
#### Variables ##################################################################################
#### Variables ####################################################################################
DOSSIER_PERSO= app.config.get('DOSSIER_APP')
DOSSIER_PUBLIC= app.config.get('DOSSIER_PUBLIC')
DOSSIER_PERSO= app.config['DOSSIER_APP']+'/'
DOSSIER_PUBLIC= app.config['DOSSIER_PUBLIC']+'/'
extensionimg = app.config['EXT_IMG']
DATABASE = app.config['DATABASE']
BASE_URL= app.config['BASE_URL']
extensionimg = app.config.get('EXT_IMG')
DATABASE = app.config.get('DATABASE')
BASE_URL= app.config.get('BASE_URL')
##################################################################################################
@@ -46,19 +46,20 @@ def upload():
files = request.files.getlist('fic')
for f in files :
nom = secure_filename(f.filename)
check_and_create(DOSSIER_PERSO+ user + '/files')
check_and_create(DOSSIER_PERSO+ user + '/images')
if os.path.isfile(DOSSIER_PERSO + user + '/files/' + nom) or os.path.isfile(DOSSIER_PERSO + user + '/images/' + nom):
check_and_create(os.path.join(DOSSIER_PERSO, user, 'files'))
check_and_create(os.path.join(DOSSIER_PERSO, user, 'images'))
if os.path.isfile(os.path.join(DOSSIER_PERSO,user, 'files', nom) or
os.path.isfile(DOSSIER_PERSO, user, 'images', nom)):
alert = "Le fichier "+str(f.filename)+" avec le même nom existe déjà, merci de spécifier un autre nom de fichier \n"
flash(alert, 'error')
else:
file, ext = os.path.splitext(nom)
if ext in extensionimg :
f.save(DOSSIER_PERSO + user + '/images/' + nom)
image = DOSSIER_PERSO + user + '/images/' + nom
f.save(os.path.join(DOSSIER_PERSO, user, 'images', nom))
image = os.path.join(DOSSIER_PERSO, user, 'images', nom)
with Image.open(image) as img :
img.thumbnail((300,300))
img.save( DOSSIER_PERSO + user + '/images/thumbnails/' + nom )
img.save(os.path.join(DOSSIER_PERSO, user, 'images','thumbnails', nom ))
time_img_create=time.strftime("%A %d %B %Y %H:%M:%S")
IP=request.environ['REMOTE_ADDR']
client_platform=request.headers.get('User-Agent')
@@ -68,9 +69,9 @@ def upload():
log.close()
else:
f.save(DOSSIER_PERSO + user + '/files/' + nom)
f.save(os.path.join(DOSSIER_PERSO, user, 'files', nom))
time_file_upload=time.strftime("%A %d %B %Y %H:%M:%S")
IP=request.environ['REMOTE_ADDR']
IP=request.environ.get('REMOTE_ADDR')
client_platform=request.headers.get('User-Agent')
log=open("log.txt", "a") # Ouvre fichier log.txt
log.write (time_file_upload + ' - ' + IP + ' - ' + user + ' - ' + client_platform + '\n' + '---> ' + nom + '\n') # Écrit dans log
@@ -80,43 +81,101 @@ def upload():
return redirect(url_for('filesupload.list'))
@filesupload.route( '/upload-dropzone', methods=['POST'])
@login_required
def drop_upload():
user = '%s'% escape(session['username'])
file = request.files['file']
check_and_create(os.path.join(DOSSIER_PERSO, user, 'files'))
check_and_create(os.path.join(DOSSIER_PERSO, user, 'images' ))
filename = secure_filename(file.filename)
ext = os.path.splitext(filename)
is_image = False
print("nom du fichier :" +filename)
if ext in extensionimg :
save_path = os.path.join(DOSSIER_PERSO, user, 'images', filename )
is_image = True
else:
save_path = os.path.join(DOSSIER_PERSO, user, 'files', filename )
@filesupload.route('/view/')
current_chunk = int(request.form['dzchunkindex'])
print (current_chunk)
if (os.path.isfile(save_path) or os.path.isfile( os.path.join(DOSSIER_PERSO, user, 'images', filename ))) and current_chunk == 0:
return make_response(('Un fichier avec le même nom existe déjà', 400))
try:
with open(save_path, 'ab') as f:
f.seek(int(request.form['dzchunkbyteoffset']))
f.write(file.stream.read())
except OSError:
return make_response(("Une erreur est survenue,"
" Impossible d'écrire le fichier sur le disque", 500))
total_chunks = int(request.form['dztotalchunkcount'])
if current_chunk + 1 == total_chunks:
# This was the last chunk, the file should be complete and the size we expect
if os.path.getsize(save_path) != int(request.form['dztotalfilesize']):
return make_response(('La taille du fichier source est différentes', 500))
else:
time_file_upload=time.strftime("%A %d %B %Y %H:%M:%S")
IP=request.environ['REMOTE_ADDR']
client_platform=request.headers.get('User-Agent')
log=open("log.txt", "a") # Ouvre fichier log.txt
log.write (time_file_upload + ' - ' + IP + ' - ' + user + ' - ' + client_platform + '\n' + '---> ' + filename + '\n') # Écrit dans log
log.close() # Ferme log.txt
if is_image :
with Image.open(save_path) as img :
img.thumbnail((300,300))
img.save(os.path.join(DOSSIER_PERSO, user, 'images', 'thumbnails', filename ) )
return make_response(('Chunk upload succesfull', 200))
@filesupload.route('/view/', methods=['GET'])
@login_required
def list():
user = '%s'% escape(session['username'])
check_and_create(DOSSIER_PUBLIC + user + '/files/')
check_and_create(DOSSIER_PERSO + user + '/files/')
files_public = os.listdir(DOSSIER_PUBLIC + user + '/files/')
files_private = os.listdir(DOSSIER_PERSO + user + '/files/')
listFilesPublic = []
listFilesPrivate = []
nb_pv = 0
size=0
if files_private:
for fich in files_private:
nb_pv += 1
size = getFileSizeMo(DOSSIER_PERSO + user + '/files/' + fich) # size = taille des fichiers
listFilesPrivate.append([nb_pv, fich, size]) # On implémente la listeFichiers avec le num le ficier et sa taille
nb_pu = 0
if files_public:
for fich in files_public:
nb_pu += 1
size = getFileSizeMo(DOSSIER_PUBLIC + user + '/files/' + fich) # size = taille des fichiers
listFilesPublic.append([nb_pu, fich, size])
check_and_create(os.path.join(DOSSIER_PUBLIC, user, 'files'))
check_and_create(os.path.join(DOSSIER_PERSO, user, 'files'))
return render_template('files.html',
section="Files",
BASE_URL=BASE_URL,
username=user)
@filesupload.route('/files/<status>/', methods=['GET'])
@login_required
def list_files(status: str ):
user = '%s' % escape(session['username'])
listFiles = []
nb_files = 0
size=0
folder=""
if status == "public":
folder=DOSSIER_PUBLIC
else:
folder=DOSSIER_PERSO
files = os.listdir(os.path.join(folder, user, 'files'))
if files:
for fich in files:
nb_files += 1
size = getFileSizeMo(os.path.join(folder, user, 'files', fich)) # size = taille des fichiers
listFiles.append([nb_files, fich, size]) # On implémente la listeFichiers avec le num le ficier et sa taille
resp = "<h2> Bonjour " + user +" ça va bien putain ca marche ? </h2>"
return render_template('list_files.html',
BASE_URL=BASE_URL,
status=status,
size=size,
username=user,
nb_pv=nb_pv,
nb_pu=nb_pu,
listFilesPrivate=listFilesPrivate,
listFilesPublic=listFilesPublic)
nb_files=nb_files,
listFiles=listFiles)
@filesupload.route('/myfiles/<username>/<filename>')
@@ -130,11 +189,9 @@ def myfiles(username, filename):
@login_required
def move_public(filename):
user = '%s' % escape(session['username'])
check_and_create(DOSSIER_PUBLIC + user + '/files/')
check_and_create(DOSSIER_PERSO + user + '/files/')
src = os.path.join(DOSSIER_PERSO, user, 'files', filename)
dst = os.path.join(DOSSIER_PUBLIC, user, 'files/')
dst = os.path.join(DOSSIER_PUBLIC, user, 'files')
move (src, dst)
return redirect(url_for('filesupload.list', _external=True))
@@ -142,10 +199,8 @@ def move_public(filename):
@login_required
def move_private(filename):
user = '%s' % escape(session['username'])
check_and_create(DOSSIER_PUBLIC + user + '/files/')
check_and_create(DOSSIER_PERSO + user + '/files/')
src = os.path.join(DOSSIER_PUBLIC, user, 'files', filename)
dst = os.path.join(DOSSIER_PERSO, user, 'files/')
dst = os.path.join(DOSSIER_PERSO, user, 'files')
move (src, dst)
return redirect(url_for('filesupload.list', _external=True))
@@ -158,7 +213,7 @@ def remove_privateFile(filename):
user = '%s' % escape(session['username'])
filename = secure_filename(filename)
try:
os.remove(DOSSIER_PERSO + user + '/files/' + filename) # on le supprime
os.remove( os.path.join(DOSSIER_PERSO, user, 'files', filename)) # on le supprime
except FileNotFoundError:
flash(u'Fichier {filename} inexistant.'.format(filename=filename), 'error')
return redirect(url_for('filesupload.list', _external=True))
@@ -170,7 +225,7 @@ def remove_publicFile(filename):
user = '%s' % escape(session['username'])
filename = secure_filename(filename)
try:
os.remove(DOSSIER_PUBLIC + user + '/files/' + filename) # on le supprime
os.remove( os.path.join(DOSSIER_PUBLIC, user, 'files', filename)) # on le supprime
except FileNotFoundError:
flash(u'Fichier {filename} inexistant.'.format(filename=filename), 'error')
return redirect(url_for('filesupload.list', _external=True))
@@ -179,8 +234,8 @@ def remove_publicFile(filename):
@filesupload.route('/<author>/blog.css')
def blog_theme(author):
user = author
if os.path.isfile(DOSSIER_PERSO+ user +'/blog.css'):
return send_file(DOSSIER_PERSO+ user +'/blog.css', mimetype='text/css')
if os.path.isfile(os.path.join(DOSSIER_PERSO, user,'blog.css')):
return send_file(os.path.join(DOSSIER_PERSO, user, 'blog.css'), mimetype='text/css')
else:
return send_file("/static/blog.css", mimetype='text/css')
@@ -188,8 +243,8 @@ def blog_theme(author):
def theme():
if 'username' in session:
user = '%s' % escape(session['username'])
if os.path.isfile(DOSSIER_PERSO+ user +'/theme.min.css'):
return send_file(DOSSIER_PERSO+ user +'/theme.min.css', mimetype='text/css')
if os.path.isfile(os.path.join(DOSSIER_PERSO, user,'theme.min.css')):
return send_file(os.path.join(DOSSIER_PERSO, user,'theme.min.css'), mimetype='text/css')
return send_file("static/default.min.css", mimetype='text/css')

View File

@@ -9,7 +9,7 @@ import subprocess
from shutil import copy
from socket import gethostname
from flask_bcrypt import Bcrypt
from tools.utils import email_disp, append_to_log, gen_token, valid_passwd, valid_token_register, get_user_by_token, totp_is_valid, login_required
from tools.utils import email_disp, append_to_log, gen_token, valid_passwd, valid_token_register, get_user_by_token, totp_is_valid, login_required, valid_email
from pyotp import random_base32
from tools.filesutils import check_and_create
import qrcode
@@ -73,18 +73,20 @@ def profile() :
os.path.join(DOSSIER_PERSO, user ,'theme.min.css') )
if request.form['nom']:
profil_user['nom'] = request.form['nom']
profil_user['nom'] = str(request.form['nom'])
if request.form['prenom']:
profil_user['prenom'] = request.form['prenom']
profil_user['prenom'] = str(request.form['prenom'])
if request.form['age']:
profil_user['age'] = request.form['age']
if '@' in request.form['mail_rescue']:
if len(request.form['mail_rescue']) > 4:
profil_user['mail_rescue'] = request.form['mail_rescue']
profil_user['age'] = str(request.form['age'])
if request.form['mail_rescue'] :
new_mail_rescue = str(request.form['mail_rescue'])
if valid_email(new_mail_rescue):
profil_user['mail_rescue']=new_mail_rescue
else:
flash(u'Adresse de courriel invalide', 'error')
else:
flash(u'Adresse de courriel de secour invalide', 'error')
if f: # On vérifie qu'un fichier a bien été envoyé
nom = secure_filename(f.filename)
f.save(os.path.join(DOSSIER_PERSO, user, 'profile', nom))
@@ -98,7 +100,6 @@ def profile() :
cursor.execute("UPDATE users SET avatar=? WHERE name=?",
(filename, user))
conn.commit()
cursor = conn.cursor() # Création de l'objet "curseur"
conn.close()
flash(u'Image de profil mise à jour', 'success')
@@ -109,7 +110,7 @@ def profile() :
(profil_user['nom'], profil_user['prenom'], profil_user['age'], profil_user['mail_rescue'],
user))
conn.commit()
flash(u'Le profil a été mis à jour', 'succes')
flash(u'Le profil a été mis à jour', 'success')
@@ -195,7 +196,7 @@ def change_passwd() :
if not(account['totp']):
account['totp'] = random_base32()
img = qrcode.make('otpauth://totp/'+BASE_URL+'?secret='+account['totp'])
img.save(DOSSIER_PERSO + user + "/totp.png")
img.save(os.path.join(DOSSIER_PERSO, user, "totp.png"))
shared_key_validate = False
return render_template('mypassword.html',
@@ -302,7 +303,7 @@ def set_totp():
cursor.execute("""UPDATE users SET totp=? WHERE name=?""", (shared_key, user,))
conn.commit()
img = qrcode.make('otpauth://totp/'+BASE_URL+'?secret='+shared_key)
img.save(DOSSIER_PERSO + user + "/totp.png")
img.save(os.path.join(DOSSIER_PERSO, user, "totp.png"))
flash(u'Votre mot de passe à usage unique est configuré et actif.', 'success')
else:
flash(u'Le code de validation totp n\'est pas valide.', 'error')