"""This is the main flask distribusi page""" import os import zipfile import shutil from datetime import timedelta from flask import ( render_template, redirect, url_for, session, send_from_directory, ) from flask_login import ( logout_user, login_required, current_user, ) from flask_wtf.csrf import CSRFError from app import create_app, db, login_manager from usermodel import User from distribusimodel import Distribusis # Forms! from forms.uploadform import UploadForm from forms.distribusiform import DistribusiForm from forms.themeform import ThemeForm from forms.editorform import EditorForm from forms.selectorform import SelectorForm # CRUD! from selector import ( SelectNewDistribusi, SelectUpdateDistribusi, DeleteDistribusi, SelectorVisible, ) # Upload from upload import UploadNewDistribusi, UploadUpdatedFiles # UserPengguna from statuspengguna.helper import ( IsZipUploaded, IsCssSelected, CurrentDistribusi, HasDistribusi, IsDistribusiLive, ResetUserState, ) from statuspengguna.loginuser import LoginUser from statuspengguna.registeruser import RegisterUser # 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=30) @APP.route("/") def index(): ResetUserState() uploadform = UploadForm() distribusis = Distribusis.query.filter( Distribusis.visible.isnot(False) ).all() distribusies = {} for distribusi in distribusis: user = User.query.filter_by(id=distribusi.userid).first() singledistribusi = { "username": user.username, "term": distribusi.term, "course": distribusi.course, "year": distribusi.year, "tags": distribusi.tags.split(','), } distribusies[distribusi.distribusiname] = singledistribusi years = uploadform.academicyear.choices terms = uploadform.term.choices courses = uploadform.course.choices template = render_template( "index.html", distribusies=distribusies, years=years, terms=terms, courses=courses, ) return template @APP.route("/distribusi", methods=["GET", "POST"]) @login_required def distribusi(): uploadform = UploadForm() distribusiform = DistribusiForm() themeform = ThemeForm() selectorform = SelectorForm() selectorform.distribusis.choices = distribusisfields() selectorvisible = SelectorVisible() current_distribusi = CurrentDistribusi() files_uploaded = IsZipUploaded(current_distribusi) distribusi_live = IsDistribusiLive(current_distribusi) css_selected = IsCssSelected(current_distribusi) user = User.query.filter_by(email=current_user.email).first() distribusi = Distribusis.query.filter_by( distribusiname=current_distribusi ).first() if distribusiform.validate_on_submit(): zipfilename = "{}.zip".format(distribusi.distribusiname) userfolder = os.path.join("stash", distribusi.distribusiname) unzipfile = os.path.join(userfolder, zipfilename) if os.path.exists(unzipfile): with zipfile.ZipFile(unzipfile, "r") as zip_ref: # To do, replace extractall with inspection and extract zip_ref.extractall(userfolder) if os.path.exists(unzipfile): os.remove(os.path.join(userfolder, zipfilename)) # To Do: Make sure nothing can be executed from the upload folder cssfile = "" cssfolder = os.path.join("themes/userstyles", distribusi.distribusiname) for filename in os.listdir(cssfolder): if filename.endswith(".css"): cssfile = os.path.join(cssfolder, filename) parser = build_argparser() args = parser.parse_args(["-s", cssfile]) distribusify(args, userfolder) distribusi.visible = True user.currentdistribusi = None os.remove(cssfile) db.session.commit() return redirect(url_for("index")) template = render_template( "distribusi.html", uploadform=uploadform, distribusiform=distribusiform, themeform=themeform, selectorform=selectorform, files_uploaded=files_uploaded, distribusi_live=distribusi_live, css_selected=css_selected, selectorvisible=selectorvisible, ) return template @APP.route("/upload", methods=["POST"]) @login_required def upload(): distribusiform = DistribusiForm() themeform = ThemeForm() selectorform = SelectorForm() selectorform.distribusis.choices = distribusisfields() selectorvisible = SelectorVisible() current_distribusi = CurrentDistribusi() if current_distribusi == "new" or HasDistribusi() == False: uploadform = UploadNewDistribusi(APP.config["UPLOAD_FOLDER"]) else: uploadform = UploadUpdatedFiles(APP.config["UPLOAD_FOLDER"]) files_uploaded = IsZipUploaded(uploadform.sitename.data) distribusi_live = IsDistribusiLive(current_distribusi) css_selected = IsCssSelected(current_distribusi) template = render_template( "distribusi.html", uploadform=uploadform, distribusiform=distribusiform, themeform=themeform, selectorform=selectorform, files_uploaded=files_uploaded, distribusi_live=distribusi_live, css_selected=css_selected, selectorvisible=selectorvisible, ) return template @APP.route("/theme", methods=["GET", "POST"]) @login_required def theme(): uploadform = UploadForm() distribusiform = DistribusiForm() themeform = ThemeForm() selectorform = SelectorForm() selectorform.distribusis.choices = distribusisfields() selectorvisible = SelectorVisible() current_distribusi = CurrentDistribusi() print(current_distribusi) files_uploaded = IsZipUploaded(current_distribusi) distribusi_live = IsDistribusiLive(current_distribusi) css_selected = IsCssSelected(current_distribusi) if themeform.validate_on_submit(): newcssfolder = os.path.join("themes/userstyles", current_distribusi) if not os.path.exists(newcssfolder): os.mkdir(newcssfolder) copycssfile = os.path.join( "themes", "{}.css".format(themeform.theme.data), ) shutil.copy(copycssfile, newcssfolder) css_selected = IsCssSelected(current_distribusi) template = render_template( "distribusi.html", uploadform=uploadform, distribusiform=distribusiform, themeform=themeform, selectorform=selectorform, files_uploaded=files_uploaded, distribusi_live=distribusi_live, css_selected=css_selected, selectorvisible=selectorvisible, ) return template @APP.route("/editor", methods=["GET", "POST"]) @login_required def editor(): editorform = EditorForm() current_distribusi = CurrentDistribusi() files_uploaded = IsZipUploaded(current_distribusi) distribusi_live = IsDistribusiLive(current_distribusi) cssplaceholder = "Try out your CSS here" with open('themes/editor/placeholder.css') as f: cssplaceholder = f.read() editorform.css.data = cssplaceholder htmlplaceholder = "Write some test HTML here" with open('themes/editor/placeholder.html') as f: htmlplaceholder = f.read() print(htmlplaceholder) if editorform.validate_on_submit(): userfolder = os.path.join("themes/userstyles", current_distribusi) os.mkdir(newuserfolder) cssfilename = "{}.css".format(editorform.cssname.data) with open(os.path.join(userfolder, cssfilename), "w") as cssfile: cssfile.write(editorform.css.data) cssfile.close template = render_template( "editor.html", files_uploaded=files_uploaded, distribusi_live=distribusi_live, editorform=editorform, htmlplaceholder=htmlplaceholder, ) return template @APP.route("/selector", methods=["GET", "POST"]) @login_required def selector(): selectorform = SelectorForm() uploadform = UploadForm() distribusiform = DistribusiForm() themeform = ThemeForm() selectorform = SelectorForm() selectorform.distribusis.choices = distribusisfields() current_distribusi = CurrentDistribusi() if selectorform.validate_on_submit(): if selectorform.new.data: selectorform = SelectNewDistribusi() if selectorform.delete.data: selectorform = DeleteDistribusi(selectorform.distribusis.data) selectorform.distribusis.choices = distribusisfields() if selectorform.update.data: selectorform = SelectUpdateDistribusi( selectorform.distribusis.data ) current_distribusi = CurrentDistribusi() distribusi = Distribusis.query.filter_by( distribusiname=current_distribusi ).first() uploadform.sitename.data = distribusi.distribusiname uploadform.sitename.render_kw = {"readonly": True} uploadform.term.data = distribusi.term uploadform.course.data = distribusi.course uploadform.academicyear.data = distribusi.year uploadform.tags.data = distribusi.tags files_uploaded = IsZipUploaded(current_distribusi) distribusi_live = IsDistribusiLive(current_distribusi) # because the user has chosen to update his distribusi, we assume # no selected css. css_selected = False selectorvisible = SelectorVisible() template = render_template( "distribusi.html", uploadform=uploadform, distribusiform=distribusiform, themeform=themeform, selectorform=selectorform, files_uploaded=files_uploaded, distribusi_live=distribusi_live, css_selected=css_selected, selectorvisible=selectorvisible, ) 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.route("/login", methods=["GET", "POST"]) def login(): result = LoginUser() return result @APP.route("/register", methods=["GET", "POST"]) def register(): result = RegisterUser() return result @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)) def distribusisfields(): distribusinames = [] user = User.query.filter_by(email=current_user.email).first() for distribusi in Distribusis.query.filter_by(userid=user.id).all(): distribusinames.append(distribusi.distribusiname) return distribusinames if __name__ == "__main__": APP.debug = True APP.run(port=5000)