from app import app from flask import render_template, url_for, request, flash, redirect, session, make_response, send_from_directory import json from markupsafe import escape from werkzeug.utils import secure_filename import os import re from app.forms import ImageForm, ImageUpload from app.models.sites import DataSite from app.models.blocs import MyBlocs from PIL import Image from flask_bcrypt import Bcrypt from copy import deepcopy from app.forms import Login from functools import wraps from app.utils import login_required from flask_wtf.csrf import CSRFProtect csrf = CSRFProtect(app) app.secret_key = 'your_secret_key' app.config.from_pyfile('config.py') THEMES_FOLDER = './templates/themes/' USERS_FOLDER = app.config['USERS_FOLDER'] bcrypt = Bcrypt(app) EXT_IMG = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' } @app.route('/login', methods=['GET', 'POST']) def login(): form = Login() if 'username' in session : resp = redirect(url_for('edit', _external=True)) else : resp = redirect(url_for('login', _external=True)) if request.method == 'POST' : login = str(request.form['login']) password = str(request.form['passwd']) if login in os.listdir(USERS_FOLDER): db = DataSite(login, USERS_FOLDER) passwd_bcrypt = db.datas['config']['passwd'] if bcrypt.check_password_hash(passwd_bcrypt, password) is True: session['username'] = login resp = redirect(url_for('edit', _external=True)) else: flash(u'Mauvais mot de passe', 'error') else: resp = render_template('/admin/login.html', form=form) return resp @app.route( '/logout/', methods=['GET'] ) @login_required def logout(): session.pop('username', None) # Supprimer username de la session s'il s'y trouve session.clear() return redirect(url_for('login')) @app.route('/', methods=['GET'], defaults={'page': ''}) @app.route('//', methods=['GET']) @login_required def edit(page): user = '%s'% escape(session['username']) page = '%s' % escape(page) db = DataSite(user, USERS_FOLDER) mypages = db.getPages() theme = db.datas['config']['theme'] menu = db.datas['menu'] myblocs = db.getBlocs(page)['blocs'] return render_template('/edit.html.tpl', blocEdit="", config=db.datas['config'], menu=menu, theme=theme, pagesList=mypages, page=page, myblocs=myblocs ) @app.route('/edit/images//', methods=['GET', 'POST'], defaults={'page': ''}) @app.route('//edit/images//', methods=['GET', 'POST']) @login_required def editPhoto(page, image, bloc): user = '%s'% escape(session['username']) page = '%s' % escape(page) image = '%s' % escape(image) bloc = '%s' % escape(bloc) db = DataSite(user, USERS_FOLDER) theme = db.datas['config']['theme'] form = ImageForm() myblocs = db.getBlocs(page)['blocs'] if form.validate_on_submit(): if request.method == 'POST': myblocs[bloc][image] = db.updateImg(image, form) db.saveBlocs(page, myblocs) form = MyBlocs.makeForm(db.datas['blocs'][bloc]) if "hx-request" in request.headers: return make_response(('Image modified', 200)) else: return redirect ('/#'+bloc) else: return render_template(THEMES_FOLDER+theme+'/blocs/edit/_image-edit'+'.html', form=form, image=myblocs[bloc][image], bloc=myblocs[bloc]) @app.route('/upload-gallery/', methods=['POST'], defaults={'page': ''}) @app.route('//upload-gallery/', methods=['POST']) @login_required def drop_upload(page, bloc): user = '%s'% escape(session['username']) page = '%s' % escape(page) db = DataSite(user, USERS_FOLDER) datas = dict() file = request.files['file'] filename = secure_filename(file.filename) myblocs = db.getBlocs(page)['blocs'] ext = os.path.splitext(filename)[-1] save_path = os.path.join(USERS_FOLDER, user, 'public', 'img' ) if ext not in EXT_IMG : return make_response(('Le fichier n\'est pas une image', 400)) current_chunk = int(request.form['dzchunkindex']) if (os.path.isfile(os.path.join(save_path, filename ))) and current_chunk == 0: return make_response(('Un fichier avec le même nom existe déjà', 400)) try: with open(os.path.join(save_path, filename ), '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(os.path.join(save_path, filename )) != int(request.form['dztotalfilesize']): return make_response(('La taille du fichier source est différentes', 500)) else: with Image.open(os.path.join(save_path, filename )) as img : img.thumbnail((640,480)) img.save(os.path.join(save_path, 'thumbnails', filename ) ) myblocs[bloc][filename] = db.addImg(filename) db.saveBlocs(page, myblocs) return make_response(('Chunk upload succesfull', 200)) @app.route('/edit/images//del/', methods=['GET'], defaults={'page': ''}) @app.route('//edit/images//del/', methods=['GET']) @login_required def delImage(page, bloc, image): user = '%s'% escape(session['username']) page = '%s' % escape(page) db = DataSite(user, USERS_FOLDER) myblocs = db.getBlocs(page)['blocs'] myblocs[bloc] = db.delImg(myblocs[bloc], image) db.saveBlocs(page, myblocs) return make_response(('Image removed', 200)) @app.route('/imgs_list/', methods=['GET'], defaults={'page': ''}) @app.route('//imgs_list/', methods=['GET']) @login_required def imagesList(page, blocname): user = '%s'% escape(session['username']) page = '%s' % escape(page) blocname = '%s' % escape(blocname) db = DataSite(user, USERS_FOLDER) theme = db.datas['config']['theme'] myblocs = db.getBlocs(page)['blocs'] bloc = myblocs[blocname] return render_template(THEMES_FOLDER+theme+'/blocs/edit/images_list.html',page=page, bloc=bloc) @app.route('/edit/', methods=['GET', 'POST'], defaults={'page': ''}) @app.route('//edit/', methods=['GET', 'POST']) @login_required def editBloc(page, blocname): user = '%s'% escape(session['username']) page = '%s' % escape(page) db = DataSite(user, USERS_FOLDER) theme = db.datas['config']['theme'] myblocs = db.getBlocs(page)['blocs'] bloc = myblocs[blocname] form = MyBlocs.makeForm(bloc) if request.method == 'POST': datas=dict() if form.validate_on_submit(): for field, value in request.form.items(): print (field) if field != 'csrf_token' and field != 'image': myblocs[blocname][field] = value if 'image' in request.files.keys(): file = request.files['image'] print ('filename: '+ file.filename) filename = secure_filename(file.filename) bg_custom = 'bg_custom_'+bloc['name']+filename print('bg_custom : '+ bg_custom) file.save(os.path.join(USERS_FOLDER, user, 'public', 'img', bg_custom )) if 'bg_img' in bloc.keys(): db.delImg(bloc, bloc['bg_img']) myblocs[blocname]['bg_img'] = bg_custom db.saveBlocs(page, myblocs) flash(u'Vos changements on été pris en compte et enregistré', 'success') else: print(form.errors) if "hx-request" in request.headers: return render_template(THEMES_FOLDER+theme+'/blocs/_'+bloc['type']+'.html', theme=theme, page=page, bloc=myblocs[blocname]) else: return redirect(url_for('edit')) else: if "hx-request" in request.headers: return render_template(THEMES_FOLDER+theme+'/blocs/edit/_'+bloc['type']+'.html', theme=theme, bloc=bloc, page=page, form=form) else: return render_template('/edit.html.tpl', config=db.datas['config'], menu=db.datas['menu'], myblocs=myblocs, page=page, theme=theme, blocEdit=bloc['name'], form=form) @app.route('/view/', methods=['GET'], defaults={'page': ''}) @app.route('//view/', methods=['GET']) @login_required def viewBloc(page, bloc): user = '%s'% escape(session['username']) page = '%s' % escape(page) db = DataSite(user, USERS_FOLDER) theme = db.datas['config']['theme'] myblocs = db.getBlocs(page)['blocs'] bloc = myblocs[bloc] return render_template(THEMES_FOLDER+theme+'/blocs/_'+bloc['type']+'.html', bloc=bloc) @app.route('/addBloc', methods=['POST'], defaults={'page': ''}) @app.route('//addBloc', methods=['POST']) @login_required def addBloc(page): user = '%s'% escape(session['username']) page = '%s' % escape(page) db = DataSite(user, USERS_FOLDER) datas = dict() myblocs = db.getBlocs(page)['blocs'] blocName = '%s' % escape(request.form['blocName']) blocType = request.form['blocType'] bloc = MyBlocs.new(blocName, blocType, db.datas['config']['theme']) test_name = "^[A-Za-z0-9_-]*$" if bloc != None: if bool(re.match(test_name, blocName)) : myblocs[blocName] = { 'name': blocName, 'type': blocType} flash (u'Bloc ajouté avec succès', 'succes'); else: return make_response(('Invalid bloc Name', 500)) db.saveBlocs(page, myblocs) if "hx-request" in request.headers: return render_template('/admin/_blocs-list.html', myblocs=db.datas['blocs']) else: return redirect(url_for('edit')) @app.route('/addPage', methods=['POST']) @login_required def addPage(): user = '%s'% escape(session['username']) db = DataSite(user, USERS_FOLDER) datas = dict() pageName = '%s' % escape(request.form['pageName']) pageType = request.form['pageType'] test_name = "^[A-Za-z0-9_-]*$" if bool(re.match(test_name, pageName)) : try : page = db.new_page(pageName, pageType) except FileExistsError: return make_response(('Page already exist', 500)) else: flash (u'Page créé avec succès', 'success'); else: return make_response(('Invalid type ', 500)) mypages = db.getPages() return redirect(url_for('edit', page=pageName)) @app.route('/rmPage/') @login_required def rmPage(pageName): pageName = '%s' % escape(pageName) user = '%s'% escape(session['username']) db = DataSite(user, USERS_FOLDER) try: db.rm_page(pageName) flash (u'Page supprimé avec succès', 'success'); except OSError as e: flash (u"La page n'a pa pu être supprimer", 'error'); return redirect(url_for('edit')) @app.route('/sortblocs', methods=['POST'], defaults={'page': ''}) @app.route('//sortblocs', methods=['POST']) @login_required def sortblocs(page): user = '%s'% escape(session['username']) page = '%s' % escape(page) db = DataSite(user, USERS_FOLDER) config = db.datas['config'] menu = db.datas['menu'] datas = dict() myblocs = dict() myblocs_orig = db.getBlocs(page)['blocs'] for bloc in request.form: if bloc != 'csrf_token': bloc_name = bloc.replace("bloc-", "", 2) myblocs[bloc_name] = myblocs_orig[bloc_name] flash (u'Les blocs ont été réagencés', 'succes'); db.saveBlocs(page, myblocs) return redirect(url_for('edit')) @app.route('/editmenu', methods=['POST']) @login_required def editMenu(): user = '%s'% escape(session['username']) db = DataSite(user, USERS_FOLDER) db.datas['menu']=dict() for menu in request.form: if '§§' in menu: submenu = menu.split("§§") if submenu[0] in db.datas['menu'].keys(): db.datas['menu'][submenu[0]] = db.datas['menu'][submenu[0]] | {submenu[1]: str(request.form[menu])} else: db.datas['menu'][submenu[0]] = {submenu[1]: str(request.form[menu])} elif menu == 'csrf_token': pass else: db.datas['menu'][menu] = str(request.form[menu]) db.saveMenu(db.datas['menu']) flash (u'Le menu a bien été modifier', 'success'); return redirect(url_for('edit')) @app.route('/img/') @login_required def myimgs(filename): user = '%s' % escape(session['username']) return send_from_directory( os.path.join(USERS_FOLDER, user, 'public', 'img'), filename ) @app.route('/img/thumbnails/') @login_required def mythumbnails(filename): user = '%s' % escape(session['username']) return send_from_directory( os.path.join(USERS_FOLDER, user, 'public', 'img', 'thumbnails'), filename ) @app.route('/favicon.ico', methods=['GET']) @app.route('/favicon.ico/', methods=['GET']) def favicon(): return make_response(('Ok! ', 200)) @app.route('/publish', methods=['POST']) @login_required def publish(): user = '%s' % escape(session['username']) db = DataSite(user, USERS_FOLDER) listPages = db.getPages() theme = db.datas['config']['theme'] menu = db.datas['menu'] test_alphanum = "^[A-Za-z0-9/_-]*$" serverAddress = str(request.form['serverAddress']) serverPort = str(request.form['serverPort']) username = str(request.form['username']) password = str(request.form['password']) folder = str(request.form['folder']) for page in listPages: myblocs = db.getBlocs(page)['blocs'] htmlExport = render_template('/index.html.tpl', config=db.datas['config'], menu=menu, theme=theme, page=page, myblocs=myblocs) db.writeHTML(theme, page, htmlExport) # Export index.html landing page myblocs = db.getBlocs('')['blocs'] htmlExport = render_template('/index.html.tpl', config=db.datas['config'], menu=menu, theme=theme, page='/', myblocs=myblocs) db.writeHTML(theme, '/', htmlExport) if serverPort == '' or serverPort.isdigit() == False : serverPort = '22' if folder == '' : folder = '/' elif(bool(re.match(test_alphanum, folder)) == False): folder = '/' if db.publish(username, password, serverAddress, serverPort, folder) == False: return make_response(('Impossible de publier le site ', 500)) return redirect(url_for('edit'))