summaryrefslogtreecommitdiff
path: root/server/web.py
diff options
context:
space:
mode:
Diffstat (limited to 'server/web.py')
-rw-r--r--server/web.py139
1 files changed, 139 insertions, 0 deletions
diff --git a/server/web.py b/server/web.py
new file mode 100644
index 0000000..2cc4c3b
--- /dev/null
+++ b/server/web.py
@@ -0,0 +1,139 @@
+'''
+ Handles everything related to the GUI,
+ exposing the necessary functionality.
+ Taking care of logging & middleware.
+
+ Verified: 2021 February 8
+ * Follows PEP8
+ * Tested Platforms
+ * Windows 10
+ * Third Party Modules
+ * eel
+'''
+
+from server.state import ServerStatic, Dynamic
+from server.helper import ServerHelper
+from server.settings import Settings
+from server.error import ServerError
+from server.console import Console
+from shared.helper import Helper
+from shared.state import Static
+
+import traceback
+import bottle
+import eel
+
+
+class Web:
+
+ @staticmethod
+ @eel.expose
+ def clients_eel():
+ return [[key, value.data] for key, value
+ in Dynamic.CLIENTS.items()]
+
+ @staticmethod
+ @eel.expose
+ def session_eel():
+ return list(Dynamic.SESSION)
+
+ @staticmethod
+ @eel.expose
+ def help_eel():
+ return ServerStatic.GUI_HELP
+
+ @staticmethod
+ @eel.expose
+ def host_eel():
+ return ServerStatic.HOST
+
+
+class Gui:
+
+ @staticmethod
+ @ServerError.thread
+ def start():
+ eel.init(ServerStatic.GUI_DIR)
+
+ if ServerStatic.WEB_GUI:
+ Gui.__execute_start(False)
+ else:
+ try:
+ Gui.__execute_start('chrome')
+ except EnvironmentError:
+ Console.log(traceback.format_exc(),
+ log_type=ServerStatic.TRACEBACK)
+
+ Console.printf(Helper.join(
+ 'Chrome browser is not installed',
+ 'Converting to web GUI instance'
+ ), Static.INFO, newline=True)
+
+ ServerStatic.WEB_GUI = True
+ Gui.__execute_start(False)
+
+ @staticmethod
+ def __execute_start(mode):
+ eel.start(ServerStatic.GUI_PAGE,
+ mode=mode,
+ host=Static.IP,
+ port=ServerStatic.GUI_PORT,
+ app=Gui.__load_middleware(),
+ size=ServerStatic.WINDOW_SIZE,
+ close_callback=lambda *_: None)
+
+ @staticmethod
+ def __load_middleware():
+ bottle_instance = bottle.default_app()
+ bottle_instance.install(Middleware.verify)
+ bottle_instance.install(bottle.auth_basic(Middleware.login))
+
+ # CONSTANT : logout path is GUI dependant
+ @bottle_instance.route('/logout')
+ def _(): bottle.abort(401, 'Access denied')
+
+ return bottle_instance
+
+
+class Middleware:
+
+ __IP_PROXY = ('REMOTE_ADDR',
+ 'HTTP_X_FORWARDED_FOR')
+
+ @staticmethod
+ def verify(callback):
+ def wrapper(*args, **kwargs):
+ if Settings.GUI_WHITELIST:
+ normal, proxy = ServerHelper.keys(bottle.request.environ,
+ Middleware.__IP_PROXY)
+ gui_whitelist = Settings.GUI_WHITELIST.split(',')
+
+ if normal in gui_whitelist or proxy in gui_whitelist:
+ return callback(*args, **kwargs)
+ else:
+ Console.log('Blocked: {} [{}/{}]\n'.format(
+ bottle.request.url, normal, proxy
+ ), Static.DANGER, ServerStatic.HTTP)
+
+ bottle.abort(401, 'Access denied')
+ else:
+ return callback(*args, **kwargs)
+
+ return wrapper
+
+ @staticmethod
+ def login(username, password):
+ if (username == Settings.GUI_USERNAME and
+ password == Settings.GUI_PASSWORD):
+ Middleware.__resource(True)
+ return True
+ else:
+ Middleware.__resource(False)
+ return False
+
+ @staticmethod
+ def __resource(success):
+ Console.log('Resource Request: {} [{}/{}]\n'.format(
+ bottle.request.url, *ServerHelper.keys(bottle.request.environ,
+ Middleware.__IP_PROXY)
+ ), Static.SUCCESS if success else Static.DANGER, ServerStatic.HTTP)