WebFM/src/core/routes/Routes.py

280 lines
11 KiB
Python

# 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)