distribusi-verse/verse/start.py

218 lines
6.2 KiB
Python

"""This is the main flask distribusi page"""
import os
import zipfile
import shutil
from datetime import timedelta
from flask import (
render_template,
redirect,
request,
flash,
url_for,
session,
abort,
send_from_directory,
)
from sqlalchemy.exc import (
IntegrityError,
DataError,
DatabaseError,
InterfaceError,
InvalidRequestError,
)
from flask_login import (
login_user,
logout_user,
login_required,
current_user,
)
from werkzeug.routing import BuildError
from flask_bcrypt import generate_password_hash, check_password_hash
from flask_wtf.csrf import CSRFError
from app import create_app, db, login_manager
from usermodel import User
# Forms!
from loginform import LoginForm
from registerform import RegisterForm
from uploadform import UploadForm
from distribusiform import DistribusiForm
# Tada!
from distribusi.cli import build_argparser
from distribusi.distribusi import distribusify
APP = create_app()
@APP.before_request
def session_handler():
session.permanent = True
APP.permanent_session_lifetime = timedelta(minutes=1)
@APP.route("/")
def index():
users = User.query.filter(User.distribusiname.isnot(None)).all()
distribusinames = []
for user in users:
distribusinames.append(user.distribusiname)
return render_template("index.html", distribusinames=distribusinames)
@APP.route("/login", methods=["GET", "POST"])
def login():
loginform = LoginForm()
if loginform.validate_on_submit():
try:
user = User.query.filter_by(email=loginform.email.data).first()
if check_password_hash(user.password, loginform.password.data):
login_user(user)
flash("Logged in successfully.", "success")
next = request.args.get("next")
if next is not None and not is_safe_url(next): # noqa: F821
return abort(400)
return redirect(next or url_for("index"))
else:
flash("Invalid Username or password!", "danger")
except Exception as e:
flash(e, "danger")
return render_template("login.html", loginform=loginform)
@APP.route("/register", methods=["GET", "POST"])
def register():
registerform = RegisterForm()
if registerform.validate_on_submit():
try:
email = registerform.email.data
password = registerform.confirmpassword.data
newuser = User(
email=email,
password=generate_password_hash(password),
)
db.session.add(newuser)
db.session.commit()
flash("Account Succesfully created", "success")
login_user(newuser)
return redirect(url_for("index"))
except InvalidRequestError:
db.session.rollback()
flash("Something went wrong!", "danger")
except IntegrityError:
db.session.rollback()
flash("User already exists!.", "warning")
except DataError:
db.session.rollback()
flash("Invalid Entry", "warning")
except InterfaceError:
db.session.rollback()
flash("Error connecting to the database", "danger")
except DatabaseError:
db.session.rollback()
flash("Error connecting to the database", "danger")
except BuildError:
db.session.rollback()
flash("An error occured !", "danger")
return render_template("register.html", registerform=registerform)
@APP.route("/distribusi", methods=["GET", "POST"])
@login_required
def distribusi():
uploadform = UploadForm()
distribusiform = DistribusiForm()
user = User.query.filter_by(email=current_user.email).first()
if user.distribusiname is None:
print("nothing to deploy!")
if distribusiform.validate_on_submit():
zipfilename = "{}.zip".format(user.distribusiname)
copyzipfile = os.path.join(APP.config["UPLOAD_FOLDER"], zipfilename)
newuserfolder = os.path.join("stash", user.distribusiname)
os.mkdir(newuserfolder)
shutil.copy(copyzipfile, newuserfolder)
unzipfile = os.path.join(newuserfolder, zipfilename)
with zipfile.ZipFile(unzipfile, "r") as zip_ref:
# To do, replace extractall with inspection and extract
zip_ref.extractall(newuserfolder)
os.remove(os.path.join(APP.config["UPLOAD_FOLDER"], zipfilename))
os.remove(os.path.join(newuserfolder, zipfilename))
# Make sure nothing can be executed from the upload folder
parser = build_argparser()
args = parser.parse_args()
distribusify(args, newuserfolder)
return redirect(url_for("index"))
template = render_template(
"distribusi.html",
uploadform=uploadform,
distribusiform=distribusiform,
)
return template
@APP.route("/upload", methods=["POST"])
@login_required
def upload():
success = False
uploadform = UploadForm()
distribusiform = DistribusiForm()
if uploadform.validate_on_submit():
user = User.query.filter_by(email=current_user.email).first()
user.distribusiname = uploadform.sitename.data
db.session.commit()
zipfilename = "{}.zip".format(user.distribusiname)
zipfile = uploadform.zipfile.data
zipfile.save(os.path.join(APP.config["UPLOAD_FOLDER"], zipfilename))
success = True
template = render_template(
"distribusi.html",
uploadform=uploadform,
distribusiform=distribusiform,
success=success,
)
return template
@APP.route("/stash/<path:path>")
def distribusistash(path):
return send_from_directory("stash", path)
@APP.route("/admin")
@login_required
def admin():
return "admin"
@APP.route("/logout")
@login_required
def logout():
logout_user()
return redirect(url_for("index"))
@APP.errorhandler(CSRFError)
def handle_csrf_error(e):
return render_template("csrf_error.html", reason=e.description), 400
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
if __name__ == "__main__":
APP.debug = True
APP.run(port=5000)