mirror of
https://github.com/WGDashboard/WGDashboard-PRW.git
synced 2026-08-04 06:52:58 +00:00
feat: start working on Flask
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ dashboard_refresh_interval = 60000
|
|||||||
dashboard_peer_list_display = grid
|
dashboard_peer_list_display = grid
|
||||||
dashboard_sort = status
|
dashboard_sort = status
|
||||||
dashboard_theme = dark
|
dashboard_theme = dark
|
||||||
dashboard_api_key = false
|
wgdashboard_apikey = false
|
||||||
dashboard_language = en-US
|
dashboard_language = en-US
|
||||||
|
|
||||||
[Account]
|
[Account]
|
||||||
|
|||||||
+17
-2
@@ -2,20 +2,35 @@
|
|||||||
|
|
||||||
import logging as log
|
import logging as log
|
||||||
|
|
||||||
|
import flask
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
from modules.config.reader import reader
|
from modules.config.reader import reader
|
||||||
from modules.database.database import database
|
from modules.database.database import database
|
||||||
from modules.utilities.utilities import utilities as util
|
from modules.utilities.utilities import utilities as util
|
||||||
|
|
||||||
|
from modules.routes.routes import routes
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
log.basicConfig(level=log.DEBUG)
|
log.basicConfig(level=log.DEBUG)
|
||||||
|
|
||||||
config_contents = reader.read_config()
|
ok, config_contents = reader.read_config()
|
||||||
|
if not ok:
|
||||||
|
exit(1)
|
||||||
|
|
||||||
found, config_database = util.filter_config(config_contents, 'DATABASE')
|
found, config_database = util.filter_config(config_contents, 'DATABASE')
|
||||||
if not found:
|
if not found:
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
ok, engine, session = database.create_session(config_database)
|
ok, engine, session = database.create_session(config_database)
|
||||||
ok = database.verify_contents(engine)
|
ok = database.ensure_contents(engine)
|
||||||
|
|
||||||
|
app = flask.Flask("WGDashboard", template_folder=os.path.abspath("./static/dist/WGDashboardAdmin"))
|
||||||
|
app.register_blueprint(routes)
|
||||||
|
|
||||||
|
app.wgdashboard_config = config_contents
|
||||||
|
app.engine = engine
|
||||||
|
app.db_session = session
|
||||||
|
|
||||||
|
app.run(debug=True, use_reloader=False)
|
||||||
@@ -6,19 +6,19 @@ from .utilities import checks
|
|||||||
|
|
||||||
class reader():
|
class reader():
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def read_config() -> dict:
|
def read_config() -> tuple[bool, dict]:
|
||||||
'''
|
'''
|
||||||
check some basic things and then return the dict containing the config data
|
check some basic things and then return the dict containing the config data
|
||||||
'''
|
'''
|
||||||
|
|
||||||
ok, candidate_path = checks.search_known_paths()
|
ok, candidate_path = checks.search_known_paths()
|
||||||
if not ok:
|
if not ok:
|
||||||
return {}
|
return False, {}
|
||||||
ok, config_contents = checks.verify_contents(candidate_path)
|
ok, config_contents = checks.verify_contents(candidate_path)
|
||||||
if not ok:
|
if not ok:
|
||||||
return {}
|
return False, {}
|
||||||
|
|
||||||
return config_contents
|
return True, config_contents
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def refresh_config(config_contents: dict) -> dict:
|
def refresh_config(config_contents: dict) -> dict:
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class checks():
|
|||||||
log.debug(f'checking integrity of section: {section}')
|
log.debug(f'checking integrity of section: {section}')
|
||||||
|
|
||||||
if len(config.items(section)) == 0:
|
if len(config.items(section)) == 0:
|
||||||
log.warn('empty section, removing for runtime due to irrelevance')
|
log.warn(f'empty section: {section}, removing at runtime due to irrelevance')
|
||||||
config.remove_section(section)
|
config.remove_section(section)
|
||||||
|
|
||||||
config_dict = {}
|
config_dict = {}
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ class database():
|
|||||||
if not ok:
|
if not ok:
|
||||||
return False, None, None
|
return False, None, None
|
||||||
|
|
||||||
log.info(connection_string)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
engine = sqlalchemy.create_engine(connection_string, echo=False)
|
engine = sqlalchemy.create_engine(connection_string, echo=False)
|
||||||
|
|
||||||
@@ -30,7 +28,7 @@ class database():
|
|||||||
return False, None, None
|
return False, None, None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def verify_contents(engine) -> bool:
|
def ensure_contents(engine) -> bool:
|
||||||
try:
|
try:
|
||||||
log.info('checking if all tables are present, and creating them if they are not')
|
log.info('checking if all tables are present, and creating them if they are not')
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import sqlalchemy.orm
|
||||||
|
|
||||||
|
from .schema import Base
|
||||||
|
from .schema import Apikeys
|
||||||
|
|
||||||
|
class functions():
|
||||||
|
def retrieve_api_keys(session: sqlalchemy.orm.Session) -> dict:
|
||||||
|
time_now = datetime.now()
|
||||||
|
|
||||||
|
api_keys = session.query(Apikeys).all()
|
||||||
|
print(api_keys)
|
||||||
|
|
||||||
|
return {}
|
||||||
@@ -21,5 +21,90 @@ class User(Base):
|
|||||||
|
|
||||||
email = sqlalchemy.Column(sqlalchemy.String)
|
email = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
class Apikeys(Base):
|
||||||
|
__tablename__ = 'apikeys'
|
||||||
|
|
||||||
|
apikey_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, index=True)
|
||||||
|
apikey_data = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
apikey_creation = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
apikey_expiration = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
class Wireguard(Base):
|
class Wireguard(Base):
|
||||||
__tablename__ = 'wireguard_interfaces'
|
__tablename__ = 'wireguard_interfaces'
|
||||||
|
|
||||||
|
iface_status = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, index=True)
|
||||||
|
|
||||||
|
iface_name = sqlalchemy.Column(sqlalchemy.String, unique=True)
|
||||||
|
iface_notes = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
iface_privkey = sqlalchemy.Column(sqlalchemy.String, unique=True)
|
||||||
|
iface_pubkey = sqlalchemy.Column(sqlalchemy.String, unique=True)
|
||||||
|
iface_address = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_listen_port = sqlalchemy.Column(sqlalchemy.Integer, unique=True)
|
||||||
|
iface_mtu = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
|
||||||
|
iface_preup = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_predown = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_postup = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_predown = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
iface_save_config = sqlalchemy.Column(sqlalchemy.Boolean, default=True)
|
||||||
|
|
||||||
|
iface_total_rx = sqlalchemy.Column(sqlalchemy.Float)
|
||||||
|
iface_total_tx = sqlalchemy.Column(sqlalchemy.Float)
|
||||||
|
iface_total_data = sqlalchemy.Column(sqlalchemy.Float)
|
||||||
|
|
||||||
|
class Amnezia(Base):
|
||||||
|
__tablename__ = 'amnezia_interfaces'
|
||||||
|
|
||||||
|
iface_status = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, index=True)
|
||||||
|
|
||||||
|
iface_name = sqlalchemy.Column(sqlalchemy.String, unique=True)
|
||||||
|
iface_notes = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
iface_privkey = sqlalchemy.Column(sqlalchemy.String, unique=True)
|
||||||
|
iface_pubkey = sqlalchemy.Column(sqlalchemy.String, unique=True)
|
||||||
|
iface_address = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_listen_port = sqlalchemy.Column(sqlalchemy.Integer, unique=True)
|
||||||
|
iface_mtu = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
|
||||||
|
iface_preup = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_predown = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_postup = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_predown = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
iface_jc = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
iface_jmin = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
iface_jmax = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
|
||||||
|
iface_s1 = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
iface_s2 = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
iface_s3 = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
iface_s4 = sqlalchemy.Column(sqlalchemy.Integer)
|
||||||
|
|
||||||
|
iface_h1 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_h2 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_h3 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_h4 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
iface_i1 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_i2 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_i3 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_i4 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
iface_i5 = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
iface_save_config = sqlalchemy.Column(sqlalchemy.Boolean, default=True)
|
||||||
|
|
||||||
|
iface_total_rx = sqlalchemy.Column(sqlalchemy.Float)
|
||||||
|
iface_total_tx = sqlalchemy.Column(sqlalchemy.Float)
|
||||||
|
iface_total_data = sqlalchemy.Column(sqlalchemy.Float)
|
||||||
|
|
||||||
|
class Peers(Base):
|
||||||
|
__tablename__ = 'interface_peers'
|
||||||
|
|
||||||
|
peer_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, index=True)
|
||||||
|
|
||||||
|
assigned_iface = sqlalchemy.Column(sqlalchemy.String)
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import flask
|
||||||
|
|
||||||
|
def make_resp_obj(success: bool = True, message: str = "", data: dict = {}, http_code: int = 200) -> flask.wrappers.Response:
|
||||||
|
response = flask.make_response({
|
||||||
|
"status": success,
|
||||||
|
"message": message,
|
||||||
|
"data": data
|
||||||
|
}, http_code
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import flask
|
||||||
|
|
||||||
|
from .response import make_resp_obj
|
||||||
|
from ..database.functions import functions
|
||||||
|
from ..utilities.utilities import utilities
|
||||||
|
|
||||||
|
routes = flask.Blueprint("routes", __name__)
|
||||||
|
|
||||||
|
@routes.before_request
|
||||||
|
def auth_required():
|
||||||
|
if flask.request.method.lower() == "options":
|
||||||
|
return make_resp_obj(True, "", flask.jsonify({"status": True}), 200)
|
||||||
|
|
||||||
|
ok, config_server = utilities.filter_config(flask.current_app.wgdashboard_config, 'SERVER')
|
||||||
|
if not ok:
|
||||||
|
return make_resp_obj(False, "Internal Error", {}, 500)
|
||||||
|
|
||||||
|
auth_required = config_server.get('auth_req', True) # Set to true for a safe default
|
||||||
|
|
||||||
|
if not auth_required:
|
||||||
|
return
|
||||||
|
|
||||||
|
whiteList = [
|
||||||
|
'/client',
|
||||||
|
'/static/',
|
||||||
|
'/fileDownload',
|
||||||
|
'validateAuthentication',
|
||||||
|
'authenticate',
|
||||||
|
'getDashboardConfiguration',
|
||||||
|
'getDashboardTheme',
|
||||||
|
'getDashboardVersion',
|
||||||
|
'sharePeer/get',
|
||||||
|
'isTotpEnabled',
|
||||||
|
'locale'
|
||||||
|
]
|
||||||
|
|
||||||
|
request_path = flask.request.path
|
||||||
|
http_headers = flask.request.headers
|
||||||
|
api_key = http_headers.get("wgdashboard-apikey")
|
||||||
|
|
||||||
|
api_key_enabled = config_server.get("wgdashboard_apikey", False)
|
||||||
|
registered_api_keys = functions.retrieve_api_keys(flask.current_app.db_session)
|
||||||
|
|
||||||
|
if not api_key:
|
||||||
|
response = make_resp_obj()
|
||||||
|
return response
|
||||||
|
|
||||||
|
@routes.route("/")
|
||||||
|
def index():
|
||||||
|
return make_resp_obj(True, "/ Endpoint", flask.jsonify({"message": "Hello from routes file!"}), 200)
|
||||||
|
|
||||||
|
@routes.route("/health")
|
||||||
|
@routes.route("/healthz")
|
||||||
|
def health():
|
||||||
|
return make_resp_obj(True, "Health Endpoint", flask.jsonify({"status": "ok"}), 200)
|
||||||
@@ -1 +1,2 @@
|
|||||||
#!/bin/env python3
|
#!/bin/env python3
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
configparser==7.2.0
|
configparser==7.2.0
|
||||||
|
Flask==3.1.3
|
||||||
sqlalchemy==2.0.47
|
sqlalchemy==2.0.47
|
||||||
Reference in New Issue
Block a user