Functions for publish website by ftp or sftp

This commit is contained in:
2026-06-04 20:33:16 +02:00
parent ec1e127234
commit 43c5bb7240
5 changed files with 139 additions and 39 deletions

View File

@@ -6,6 +6,8 @@ from PIL import Image
from pathlib import Path, PurePath, PurePosixPath from pathlib import Path, PurePath, PurePosixPath
from shutil import rmtree, copytree from shutil import rmtree, copytree
import subprocess import subprocess
from flask import session
class DataSite: class DataSite:
user_folder = None user_folder = None
@@ -214,25 +216,44 @@ class DataSite:
return False return False
else: else:
return True return True
def publish(self, serverInfos=dict(), password=str()): def publish(self, serverInfos=dict(), password=str()):
userDir = Path(PurePosixPath(self.user_folder)) userDir = Path(PurePosixPath(self.user_folder))
command = "lftp -u \"{}\",\"{}\" -p {} {} -e ' mirror -R public {}; chmod -R o+rx ./; bye;'".format(serverInfos['username'], upload = "lftp -u \"{}\",\"{}\" -p {} {} -e ' mirror -R public {}; chmod -R o+rx ./; bye;'".format(serverInfos['username'],
password, password,
serverInfos['Port'], serverInfos['Port'],
serverInfos['Address'], serverInfos['Address'],
serverInfos['folder']) serverInfos['folder'])
set_permissions = "lftp -u \"{}\",\"{}\" -p {} {} -e 'chmod -R o+rx ./; bye;'".format(serverInfos['username'],
password,
serverInfos['Port'],
serverInfos['Address'],
serverInfos['folder'])
try: try:
subprocess.call(command, shell=True, cwd=str(userDir)) subprocess.call(upload, shell=True, cwd=str(userDir))
self.update_status_publish("Uploaded")
subprocess.call(set_permissions, shell=True, cwd=str(userDir))
except ChildProcessError: except ChildProcessError:
return False return False
return True return True
def update_status_publish (self, status: str):
self.datas['publication_status'] = status
self.filej.write_text(json.dumps(self.datas, indent=5))
def get_status_publish(self):
if 'publication_status' in self.datas.keys():
return self.datas['publication_status']
else:
return "";

View File

@@ -15,6 +15,8 @@ from app.forms import Login
from functools import wraps from functools import wraps
from app.utils import login_required from app.utils import login_required
from flask_wtf.csrf import CSRFProtect from flask_wtf.csrf import CSRFProtect
from datetime import datetime
csrf = CSRFProtect(app) csrf = CSRFProtect(app)
@@ -27,6 +29,7 @@ bcrypt = Bcrypt(app)
EXT_IMG = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' } EXT_IMG = {'.jpg', '.JPG', '.png', '.PNG', '.gif', '.GIF', '.bmp', '.BMP', '.jpeg', '.JPEG' }
@app.route('/login', methods=['GET', 'POST']) @app.route('/login', methods=['GET', 'POST'])
def login(): def login():
form = Login() form = Login()
@@ -44,6 +47,7 @@ def login():
if bcrypt.check_password_hash(passwd_bcrypt, password) is True: if bcrypt.check_password_hash(passwd_bcrypt, password) is True:
session['username'] = login session['username'] = login
session['upload'] = None
resp = redirect(url_for('edit', _external=True)) resp = redirect(url_for('edit', _external=True))
else: else:
flash(u'Mauvais mot de passe', 'error') flash(u'Mauvais mot de passe', 'error')
@@ -68,19 +72,17 @@ def edit(page):
user = '%s'% escape(session['username']) user = '%s'% escape(session['username'])
page = '%s' % escape(page) page = '%s' % escape(page)
db = DataSite(user, USERS_FOLDER) db = DataSite(user, USERS_FOLDER)
mypages = db.get_pages()
theme = db.datas['config']['theme']
menu = db.datas['menu']
myblocs = db.get_blocs(page)['blocs'] myblocs = db.get_blocs(page)['blocs']
print(myblocs)
return render_template('/edit.html.tpl', return render_template('/edit.html.tpl',
blocEdit="", blocEdit="",
config=db.datas['config'], config=db.datas['config'],
menu=menu, menu=db.datas['menu'],
theme=theme, theme=db.datas['config']['theme'],
pagesList=mypages, pagesList=db.get_pages(),
page=page, page=page,
myblocs=myblocs myblocs=myblocs,
serverInfos=db.datas['publish']
) )
@@ -102,7 +104,7 @@ def edit_photo(page, image, bloc):
if request.method == 'POST': if request.method == 'POST':
myblocs[bloc][image] = db.update_img(image, form) myblocs[bloc][image] = db.update_img(image, form)
db.save_blocs(page, myblocs) db.save_blocs(page, myblocs)
form = MyBlocs.makeForm(db.datas['blocs'][bloc]) form = MyBlocs.make_form(db.datas['blocs'][bloc])
if "hx-request" in request.headers: if "hx-request" in request.headers:
return make_response(('Image modified', 200)) return make_response(('Image modified', 200))
else: else:
@@ -149,7 +151,7 @@ def drop_upload(page, bloc):
img.thumbnail((640,480)) img.thumbnail((640,480))
img.save(os.path.join(save_path, 'thumbnails', filename ) ) img.save(os.path.join(save_path, 'thumbnails', filename ) )
myblocs[bloc][filename] = db.addImg(filename) myblocs[bloc][filename] = db.add_img(filename)
db.save_blocs(page, myblocs) db.save_blocs(page, myblocs)
return make_response(('Chunk upload succesfull', 200)) return make_response(('Chunk upload succesfull', 200))
@@ -209,7 +211,7 @@ def edit_bloc(page, blocname):
bg_custom = 'bg_custom_'+bloc['name']+filename bg_custom = 'bg_custom_'+bloc['name']+filename
file.save(os.path.join(USERS_FOLDER, user, 'public', 'img', bg_custom )) file.save(os.path.join(USERS_FOLDER, user, 'public', 'img', bg_custom ))
if 'bg_img' in bloc.keys(): if 'bg_img' in bloc.keys():
db.delImg(bloc, bloc['bg_img']) db.del_img(bloc, bloc['bg_img'])
myblocs[blocname]['bg_img'] = bg_custom myblocs[blocname]['bg_img'] = bg_custom
@@ -340,7 +342,7 @@ def rm_page(pageName):
def sortblocs(page): def sortblocs(page):
user = '%s'% escape(session['username']) user = '%s'% escape(session['username'])
page = '%s' % escape(page) page = '%s' % escape(page)
db = DataSite(user, USERS_FOLDER) db = DataSite(user, USERS_FOLDER)
config = db.datas['config'] config = db.datas['config']
menu = db.datas['menu'] menu = db.datas['menu']
@@ -403,6 +405,39 @@ def favicon():
return make_response(('Ok! ', 200)) return make_response(('Ok! ', 200))
@app.route('/publish_progress/', methods=['GET'])
@login_required
def publish_progress():
user = '%s' % escape(session['username'])
db = DataSite(user, USERS_FOLDER)
progress = 0
error = False
completed = False
status = db.get_status_publish()
match status:
case "Generated" :
progress = 30
case "Login Incorrect" | "Upload error" :
progress = 100
error = True
case "Identification verified":
progress = 50
status = "Upload ..."
case "Uploaded":
progress = 80
status = "Set permissions ..."
case str(x) if "Uploaded at:" in x:
progress = 100
completed = True
status = status.replace("Uploaded at:", "")
return render_template('admin/_publish-progress.html', progress=progress,
status=status,
error = error,
completed = completed)
@app.route('/publish', methods=['POST']) @app.route('/publish', methods=['POST'])
@@ -416,12 +451,13 @@ def publish():
test_alphanum = "^[A-Za-z0-9/_-]*$" 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']) password = str(request.form['password'])
folder = str(request.form['folder'])
serverInfos = dict()
serverInfos['Address'] = str(request.form['serverAddress'])
serverInfos['Port'] = str(request.form['serverPort'])
serverInfos['username'] = str(request.form['username'])
serverInfos['folder'] = str(request.form['folder'])
for page in listPages: for page in listPages:
myblocs = db.get_blocs(page)['blocs'] myblocs = db.get_blocs(page)['blocs']
@@ -433,6 +469,7 @@ def publish():
myblocs=myblocs) myblocs=myblocs)
db.writeHTML(theme, page, htmlExport) db.writeHTML(theme, page, htmlExport)
# Export index.html landing page # Export index.html landing page
myblocs = db.get_blocs('')['blocs'] myblocs = db.get_blocs('')['blocs']
htmlExport = render_template('/index.html.tpl', htmlExport = render_template('/index.html.tpl',
@@ -444,21 +481,34 @@ def publish():
db.writeHTML(theme, '/', htmlExport) db.writeHTML(theme, '/', htmlExport)
db.copy_static_files() db.copy_static_files()
db.update_status_publish("Generated")
if serverPort == '' or serverPort.isdigit() == False :
if serverInfos['Port'] == '' or serverInfos['Port'].isdigit() == False :
serverPort = '22' serverPort = '22'
if folder == '' : if serverInfos['folder'] == '' :
folder = '/'
elif(bool(re.match(test_alphanum, folder)) == False):
folder = '/' folder = '/'
elif(bool(re.match(test_alphanum, serverInfos['folder'])) == False):
serverInfos['folder'] = '/'
if db.publish(username, password, serverAddress, serverPort, folder) == False: if db.test_server_login(serverInfos, password ) == False:
return make_response(('Impossible de publier le site ', 500)) db.update_status_publish ("Identification Incorrect")
return make_response(('Login Incorrect', 500))
else:
db.update_status_publish("Identification verified")
if db.publish(serverInfos, password) == False:
db.update_status_publish ("Upload error")
return make_response('Upload Error !')
#Generate date of success upload
now = datetime.now()
date_upload = now.strftime("%d/%m/%Y, %H:%M:%S")
db.update_status_publish ("Uploaded at: "+date_upload)
db.save_server_info(serverInfos)
return redirect(url_for('edit')) return redirect(url_for('edit'))

View File

@@ -2,9 +2,6 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#options"> Options </a> <a class="nav-link" data-toggle="pill" href="#options"> Options </a>
</li> </li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#publication"> Publication </a>
</li>
</ul> </ul>
<!-- Tab panes --> <!-- Tab panes -->
@@ -13,10 +10,9 @@
<br/> <br/>
<h4> Mes réseaux sociaux </h4> <h4> Mes réseaux sociaux </h4>
</div> </div>
<div class="tab-pane container fade text-center" id="publication">
<br/>
<h4> Serveur(s) où publier mon site </h4>
</div>
</div> </div>

View File

@@ -0,0 +1,12 @@
<div class="progress" style="height: 30px;">
<div class="progress-bar {% if completed %} bg-success {% endif %} {% if error %} bg-danger {%endif%}"
style="width:{{progress}}%">
{% if completed %}
Dernière publication avec succès le : {{ status }}
{% else %}
{{ status }} {{progress}}%
{% endif %}
</div>
</div>

View File

@@ -10,10 +10,14 @@
name="serverAddress" name="serverAddress"
class="form-control" class="form-control"
id="serverAddress" id="serverAddress"
placeholder="sftp://mon_serveur.com, ou ftp://mon_serveur.com" {%if serverInfos.Address %}
value="{{ serverInfos.Address }}"
{%else%}
placeholder="sftp://mon_serveur.com, ou ftp://mon_serveur.com"
{%endif%}
required> required>
<div class="invalid-feedback"> <div class="invalid-feedback">
L'upload a rencontrer n'a pas pu se faire. La publication du site n'a pas pu se faire correctement.
</div> </div>
</div> </div>
<br/> <br/>
@@ -25,7 +29,12 @@
max="65536" max="65536"
class="form-control" class="form-control"
id="serverPort" id="serverPort"
placeholder="Si vous ne savez pas ne mettez rien"> {%if serverInfos.Port %}
value="{{ serverInfos.Port }}"
{%else%}
placeholder="1-65535"
{%endif%}>
<br/> <br/>
@@ -34,8 +43,12 @@
<input type="text" <input type="text"
name="folder" name="folder"
class="form-control" class="form-control"
id="folder" id="folder"
placeholder="Spécifier un dossier sinon ne mettez rien"> {%if serverInfos.folder %}
value="{{ serverInfos.folder }}"
{%else%}
placeholder="Spécifier un dossier sinon ne mettez rien"
{%endif%}>
<br/> <br/>
@@ -44,7 +57,13 @@
<input type="text" <input type="text"
name="username" name="username"
class="form-control" class="form-control"
id="username" id="username"
{%if serverInfos.username %}
value="{{ serverInfos.username }}"
{%else%}
placeholder="Nom d'utilisateur fourni par votre hébergeur"
{%endif%}
placeholder="Nom d'utilisateur fourni par votre hébergeur" placeholder="Nom d'utilisateur fourni par votre hébergeur"
required> required>
@@ -61,8 +80,10 @@
<br/> <br/>
<div hx-get="{{ url_for('publish_progress') }}" hx-trigger="load, every 1s">
</div>
<br/>
<button type="submit" class="btn btn-success" <button type="submit" class="btn btn-success"
onclick="valid_nameBloc()"> Publier le site </button> onclick="valid_nameBloc()"> Publier le site </button>
</form> </form>