# Python imports import os, json, secrets, re, shutil # Lib imports from flask import request, session, render_template, send_from_directory, redirect from flask_uploads import UploadSet, configure_uploads, ALL from flask_login import current_user # App imports from core import app, logger, oidc, db, Favorites # Get from __init__ from core.utils import MessageHandler # Get simple message processor from core.utils.shellfm import WindowController # Get file manager controller msgHandler = MessageHandler() window_controllers = {} # valid_fname_pat = re.compile(r"/^[a-zA-Z0-9-_\[\]\(\)| ]+$/") valid_fname_pat = re.compile(r"[a-z0-9A-Z-_\[\]\(\)\| ]{4,20}") def get_window_controller(): controller = None try: controller = window_controllers[ session["win_controller_id"] ] except Exception as e: id = secrets.token_hex(16) controller = WindowController() view = controller.get_window(1).get_view(0) view.ABS_THUMBS_PTH = app.config['ABS_THUMBS_PTH'] view.REMUX_FOLDER = app.config['REMUX_FOLDER'] view.FFMPG_THUMBNLR = app.config['FFMPG_THUMBNLR'] view.logger = logger session['win_controller_id'] = id window_controllers.update( {id: controller } ) controller = window_controllers[ session["win_controller_id"] ] return controller @app.route('/', methods=['GET', 'POST']) def home(): if request.method == 'GET': view = get_window_controller().get_window(1).get_view(0) _dot_dots = view.get_dot_dots() _current_directory = view.get_current_directory() return render_template('pages/index.html', current_directory = _current_directory, dot_dots = _dot_dots) return render_template('error.html', title = 'Error!', message = 'Must use GET request type...') @app.route('/api/list-files/<_hash>', methods=['GET', 'POST']) def listFiles(_hash = None): if request.method == 'POST': view = get_window_controller().get_window(1).get_view(0) dot_dots = view.get_dot_dots() if dot_dots[0][1] == _hash: # Refresh view.load_directory() elif dot_dots[1][1] == _hash: # Pop from dir view.pop_from_path() msg = "Log in with an Admin privlidged user to view the requested path!" is_locked = view.is_folder_locked(_hash) if is_locked and not oidc.user_loggedin: return msgHandler.createMessageJSON("danger", msg) elif is_locked and oidc.user_loggedin: isAdmin = oidc.user_getfield("isAdmin") if isAdmin != "yes" : return msgHandler.createMessageJSON("danger", msg) if dot_dots[0][1] != _hash and dot_dots[1][1] != _hash: path = view.get_path_part_from_hash(_hash) view.push_to_path(path) error_msg = view.get_error_message() if error_msg != None: view.unset_error_message() return msgHandler.createMessageJSON("danger", error_msg) sub_path = view.get_current_sub_path() files = view.get_files_formatted() fave = db.session.query(Favorites).filter_by(link = sub_path).first() in_fave = "true" if fave else "false" files.update({'in_fave': in_fave}) return files else: msg = "Can't manage the request type..." return msgHandler.createMessageJSON("danger", msg) @app.route('/api/file-manager-action/<_type>/<_hash>', methods=['GET', 'POST']) def fileManagerAction(_type, _hash = None): view = get_window_controller().get_window(1).get_view(0) if _type == "reset-path" and _hash == "None": view.set_to_home() msg = "Returning to home directory..." return msgHandler.createMessageJSON("success", msg) folder = view.get_current_directory() file = view.get_path_part_from_hash(_hash) fpath = os.path.join(folder, file) logger.debug(fpath) if _type == "files": return send_from_directory(folder, file) if _type == "remux": # NOTE: Need to actually implimint a websocket to communicate back to client that remux has completed. # As is, the remux thread hangs until completion and client tries waiting until server reaches connection timeout. # I.E....this is stupid but for now works better than nothing good_result = view.remuxVideo(_hash, fpath) if good_result: return '{"path":"static/remuxs/' + _hash + '.mp4"}' else: msg = "Remuxing: Remux failed or took too long; please, refresh the page and try again..." return msgHandler.createMessageJSON("success", msg) if _type == "run-locally": msg = "Opened media..." view.openFilelocally(fpath) return msgHandler.createMessageJSON("success", msg) # NOTE: Positionally protecting actions further down that are privlidged # Be aware of ordering! msg = "Log in with an Admin privlidged user to do this action!" if not oidc.user_loggedin: return msgHandler.createMessageJSON("danger", msg) elif oidc.user_loggedin: isAdmin = oidc.user_getfield("isAdmin") if isAdmin != "yes" : return msgHandler.createMessageJSON("danger", msg) if _type == "delete": try: msg = f"[Success] Deleted the file/folder -->: {file} !" if os.path.isfile(fpath): os.unlink(fpath) else: shutil.rmtree(fpath) return msgHandler.createMessageJSON("success", msg) except Exception as e: msg = "[Error] Unable to delete the file/folder...." return msgHandler.createMessageJSON("danger", msg) @app.route('/api/list-favorites', methods=['GET', 'POST']) def listFavorites(): if request.method == 'POST': list = db.session.query(Favorites).all() faves = [] for fave in list: faves.append([fave.link, fave.id]) return '{"faves_list":' + json.dumps(faves) + '}' else: msg = "Can't manage the request type..." return msgHandler.createMessageJSON("danger", msg) @app.route('/api/load-favorite/<_id>', methods=['GET', 'POST']) def loadFavorite(_id): if request.method == 'POST': try: ID = int(_id) fave = db.session.query(Favorites).filter_by(id = ID).first() view = get_window_controller().get_window(1).get_view(0) view.set_path_with_sub_path(fave.link) return '{"refresh": "true"}' except Exception as e: print(repr(e)) msg = "Incorrect Favorites ID..." return msgHandler.createMessageJSON("danger", msg) else: msg = "Can't manage the request type..." return msgHandler.createMessageJSON("danger", msg) @app.route('/api/manage-favorites/<_action>', methods=['GET', 'POST']) def manageFavorites(_action): if request.method == 'POST': ACTION = _action.strip() view = get_window_controller().get_window(1).get_view(0) sub_path = view.get_current_sub_path() if ACTION == "add": fave = Favorites(link = sub_path) db.session.add(fave) msg = "Added to Favorites successfully..." elif ACTION == "delete": fave = db.session.query(Favorites).filter_by(link = sub_path).first() db.session.delete(fave) msg = "Deleted from Favorites successfully..." else: msg = "Couldn't handle action for favorites item..." return msgHandler.createMessageJSON("danger", msg) db.session.commit() return msgHandler.createMessageJSON("success", msg) else: msg = "Can't manage the request type..." return msgHandler.createMessageJSON("danger", msg) @app.route('/api/create/<_type>', methods=['GET', 'POST']) def create_item(_type = None): if request.method == 'POST': msg = "Log in with an Admin privlidged user to upload files!" if not oidc.user_loggedin: return msgHandler.createMessageJSON("danger", msg) elif oidc.user_loggedin: isAdmin = oidc.user_getfield("isAdmin") if isAdmin != "yes" : return msgHandler.createMessageJSON("danger", msg) TYPE = _type.strip() FNAME = str(request.values['fname']).strip() if not re.fullmatch(valid_fname_pat, FNAME): msg = "A new item name can only contain alphanumeric, -, _, |, [], (), or spaces and must be minimum of 4 and max of 20 characters..." return msgHandler.createMessageJSON("danger", msg) view = get_window_controller().get_window(1).get_view(0) folder = view.get_current_directory() new_item = folder + '/' + FNAME try: if TYPE == "dir": os.mkdir(new_item) elif TYPE == "file": open(new_item + ".txt", 'a').close() else: msg = "Couldn't handle action type for api create..." return msgHandler.createMessageJSON("danger", msg) except Exception as e: print(repr(e)) msg = "Couldn't create file/folder. An unexpected error occured..." return msgHandler.createMessageJSON("danger", msg) msg = "[Success] created the file/dir..." return msgHandler.createMessageJSON("success", msg) else: msg = "Can't manage the request type..." return msgHandler.createMessageJSON("danger", msg) @app.route('/upload', methods=['GET', 'POST']) def upload(): if request.method == 'POST' and len(request.files) > 0: msg = "Log in with an Admin privlidged user to upload files!" if not oidc.user_loggedin: return msgHandler.createMessageJSON("danger", msg) elif oidc.user_loggedin: isAdmin = oidc.user_getfield("isAdmin") if isAdmin != "yes" : return msgHandler.createMessageJSON("danger", msg) view = get_window_controller().get_window(1).get_view(0) folder = view.get_current_directory() UPLOADS_PTH = folder + '/' files = UploadSet('files', ALL, default_dest=lambda x: UPLOADS_PTH) configure_uploads(app, files) for file in request.files: try: files.save(request.files[file]) except Exception as e: print(repr(e)) msg = "[Error] Failed to upload some or all of the file(s)..." return msgHandler.createMessageJSON("danger", msg) msg = "[Success] Uploaded file(s)..." return msgHandler.createMessageJSON("success", msg) else: msg = "Can't manage the request type..." return msgHandler.createMessageJSON("danger", msg)