#### Imports
import jinja2 as j2
from flask import (
Flask,
render_template,
render_template_string,
request,
redirect,
flash,
send_file,
)
from markupsafe import Markup # No longer imported from Flask
# Form libraries
from flask_wtf import FlaskForm
from wtforms import (
StringField,
RadioField,
SelectField,
SubmitField,
TextAreaField,
BooleanField,
SelectMultipleField,
)
from wtforms.validators import (
DataRequired,
InputRequired,
Optional,
Regexp,
URL,
Length,
)
# Markdown to HTML - for debugging purposes
from misaka import Markdown, HtmlRenderer
# Managing zipfiles
import zipfile
from flask_cors import CORS
from urllib import parse
from secrets import token_urlsafe
#### Create FLASK and Jinja Environments
app = Flask(__name__)
app.config["SECRET_KEY"] = token_urlsafe(16) # Necessary for the form CORS
cors = CORS(app)
environment = j2.Environment(loader=j2.FileSystemLoader("templates/"))
#### Custom functions
# Define custom filter
@app.template_filter("render_markdown")
def render_markdown(text):
renderer = HtmlRenderer()
markdown = Markdown(renderer)
return markdown(text)
# Add custom filter
j2.filters.FILTERS["render_markdown"] = render_markdown
# Converting markdown to html
def markdown_file_to_html_string(file):
with open(file, "r") as file:
markdown_content = file.read()
# Convert content from Markdown to HTML
html_content = render_markdown(markdown_content)
# Return Markdown and HTML contents
return markdown_content, html_content
### Forms
## PHP forms
class Form_PHP_Config(FlaskForm):
php_config_file = SelectField(
"Type de fichier PHP :",
choices=[
(
"php-fpm.conf",
Markup(
'Fichier de configuration PHP complet (php-fpm.conf)'
),
),
(
"php_extra-fpm.conf",
Markup(
'Fichier de configuration PHP particulier (extra_php-fpm.conf)'
),
),
],
default="php_extra-fpm.conf",
validators=[DataRequired()],
)
## TODO : figure out how to include these comments/title values
# 'title': 'Remplace la configuration générée par défaut par un fichier de configuration complet. À éviter si possible.
# 'title': "Choisir un fichier permettant un paramétrage d'options complémentaires. C'est généralement recommandé."
php_config_file_content = TextAreaField(
"Saisissez le contenu du fichier de configuration PHP :",
validators=[Optional()],
render_kw={
"class": "form-control",
"style": "width: 50%;height:11em;min-height: 5.5em; max-height: 55em;flex-grow: 1;box-sizing: border-box;",
"title": "TODO",
"placeholder": "; Additional php.ini defines, specific to this pool of workers. \n\nphp_admin_value[upload_max_filesize] = 100M \nphp_admin_value[post_max_size] = 100M",
},
)
class Form_PHP(Form_PHP_Config):
use_php = BooleanField("Nécessite PHP", default=False)
## NodeJS forms
class Form_NodeJS(FlaskForm):
use_nodejs = BooleanField("Nécessite NodeJS", default=False)
use_nodejs_version = StringField(
"Version de NodeJS :",
render_kw={
"placeholder": "20",
"class": "form-control",
"title": "Saisissez la version de NodeJS à installer. Cela peut-être une version majeure (ex: 20) ou plus précise (ex: 20.1).",
},
) # TODO : this should be validated using a regex, should be only numbers and any (≥0) number of dots in between
use_nodejs_needs_yarn = BooleanField(
"Nécessite Yarn",
default=False,
render_kw={
"title": "Faut-il installer automatiquement Yarn ? Cela configurera les dépôts spécifiques à Yarn."
},
)
## Python forms
class Form_Python(FlaskForm):
use_python = BooleanField(
"Nécessite Python", default=False
) ## TODO -> python3, python3-pip, python3-ven dependencies by default
python_dependencies_type = SelectField(
"Configuration des dépendances Python :",
choices=[
("requirements.txt", Markup("Fichier requirements.txt")),
("manual_list", "Liste manuelle"),
],
default="requirements.txt",
validators=[DataRequired(), Optional()],
)
python_requirements = TextAreaField(
"La liste de dépendances inclue dans le fichier requirements.txt :",
render_kw={
"class": "form-control",
"style": "width: 50%;height:5.5em;min-height: 5.5em; max-height: 55em;flex-grow: 1;box-sizing: border-box;",
"title": "Lister les dépendances à installer, une par ligne, avec un numéro de version derrière.\nEx: 'dépendance==1.0'.",
"placeholder": "tensorflow==2.3.1 \nuvicorn==0.12.2 \nfastapi==0.63.0",
},
)
python_dependencies_list = StringField(
"Liste de dépendances python :",
render_kw={
"placeholder": "tensorflow uvicorn fastapi",
"class": "form-control",
"title": "Lister les dépendances à installer, séparées d'un espace.",
},
)
class GeneralInfos(FlaskForm):
app_id = StringField(
Markup(
"""Identifiant (id) de l'application (en minuscule et sans espaces) :"""
),
validators=[DataRequired(), Regexp("[a-z_1-9]+.*(?