"""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") 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/") 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)