mirror of
https://github.com/WGDashboard/WGDashboard-PRW.git
synced 2026-08-03 14:32:56 +00:00
chore: try to make a working base
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
*.db
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[codz]
|
*.py[codz]
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Alembic
|
||||||
|
|
||||||
|
Steps:
|
||||||
|
- alembic init alembic
|
||||||
|
- change alembic.ini (connection string)
|
||||||
|
- change env.py to include base
|
||||||
@@ -29,7 +29,6 @@ totp_verified = false
|
|||||||
totp_key = ZSI2Z4QHSGVAK6TFVMZXORFDWKHDN4TQ
|
totp_key = ZSI2Z4QHSGVAK6TFVMZXORFDWKHDN4TQ
|
||||||
|
|
||||||
[Other]
|
[Other]
|
||||||
welcome_session = true
|
|
||||||
|
|
||||||
[Database]
|
[Database]
|
||||||
type = sqlite
|
type = sqlite
|
||||||
+11
-4
@@ -2,13 +2,20 @@
|
|||||||
|
|
||||||
import logging as log
|
import logging as log
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
from modules.config.reader import reader
|
from modules.config.reader import reader
|
||||||
|
from modules.database.database import database
|
||||||
|
from modules.utilities.utilities import utilities as util
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
log.basicConfig(level=log.DEBUG)
|
log.basicConfig(level=log.DEBUG)
|
||||||
|
|
||||||
config_contents = reader.read_config()
|
config_contents = reader.read_config()
|
||||||
log.info(config_contents)
|
|
||||||
input()
|
found, config_database = util.filter_config(config_contents, 'DATABASE')
|
||||||
config_contents = reader.refresh_config(config_contents)
|
if not found:
|
||||||
log.info(config_contents)
|
exit(1)
|
||||||
|
|
||||||
|
ok, engine, session = database.create_session(config_database)
|
||||||
|
ok = database.verify_contents(engine)
|
||||||
@@ -2,23 +2,25 @@
|
|||||||
|
|
||||||
import logging as log
|
import logging as log
|
||||||
|
|
||||||
from .utilities import preflight_checks
|
from .utilities import checks
|
||||||
|
|
||||||
class reader():
|
class reader():
|
||||||
|
@staticmethod
|
||||||
def read_config() -> dict:
|
def read_config() -> 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 = preflight_checks.search_known_paths()
|
ok, candidate_path = checks.search_known_paths()
|
||||||
if not ok:
|
if not ok:
|
||||||
return {}
|
return {}
|
||||||
ok, config_contents = preflight_checks.verify_contents(candidate_path)
|
ok, config_contents = checks.verify_contents(candidate_path)
|
||||||
if not ok:
|
if not ok:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
return config_contents
|
return config_contents
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def refresh_config(config_contents: dict) -> dict:
|
def refresh_config(config_contents: dict) -> dict:
|
||||||
log.debug(f'refreshing config values')
|
log.debug(f'refreshing config values')
|
||||||
return reader.read_config()
|
return reader.read_config()
|
||||||
@@ -5,7 +5,8 @@ import logging as log
|
|||||||
import configparser as cp
|
import configparser as cp
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class preflight_checks():
|
class checks():
|
||||||
|
@staticmethod
|
||||||
def search_known_paths() -> tuple[bool, str]:
|
def search_known_paths() -> tuple[bool, str]:
|
||||||
'''
|
'''
|
||||||
Look at predefined paths on the filesystem for a config file
|
Look at predefined paths on the filesystem for a config file
|
||||||
@@ -34,6 +35,7 @@ class preflight_checks():
|
|||||||
log.error(f'error occured while searching for the config file: {err}')
|
log.error(f'error occured while searching for the config file: {err}')
|
||||||
return False, ''
|
return False, ''
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def verify_contents(config_path: str) -> tuple[bool, dict]:
|
def verify_contents(config_path: str) -> tuple[bool, dict]:
|
||||||
'''
|
'''
|
||||||
Check the existing config file for contents
|
Check the existing config file for contents
|
||||||
@@ -53,10 +55,15 @@ class preflight_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.error('empty section, no keys or values')
|
log.warn('empty section, removing for runtime due to irrelevance')
|
||||||
return False, {}
|
config.remove_section(section)
|
||||||
|
|
||||||
return True, dict(config.items())
|
config_dict = {}
|
||||||
|
for section in config.sections():
|
||||||
|
items = dict(config.items(section))
|
||||||
|
config_dict[section] = items
|
||||||
|
|
||||||
|
return True, config_dict
|
||||||
|
|
||||||
except cp.ParsingError as err:
|
except cp.ParsingError as err:
|
||||||
log.error(f'error parsing the ini config file: {err}')
|
log.error(f'error parsing the ini config file: {err}')
|
||||||
|
|||||||
@@ -1,2 +1,43 @@
|
|||||||
#!/bin/env python3
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import logging as log
|
||||||
|
|
||||||
|
import sqlalchemy
|
||||||
|
import sqlalchemy.orm
|
||||||
|
|
||||||
|
from .schema import Base
|
||||||
|
from .utilities import checks
|
||||||
|
|
||||||
|
class database():
|
||||||
|
@staticmethod
|
||||||
|
def create_session(database_config: dict) -> tuple[bool, sqlalchemy.engine.Engine | None, sqlalchemy.orm.Session | None]:
|
||||||
|
ok, connection_string = checks.generate_connection_string(database_config)
|
||||||
|
if not ok:
|
||||||
|
return False, None, None
|
||||||
|
|
||||||
|
log.info(connection_string)
|
||||||
|
|
||||||
|
try:
|
||||||
|
engine = sqlalchemy.create_engine(connection_string, echo=False)
|
||||||
|
|
||||||
|
local_session = sqlalchemy.orm.sessionmaker(bind=engine)
|
||||||
|
session = local_session()
|
||||||
|
|
||||||
|
return True, engine, session
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
log.critical(f'database initialization failed: {err}')
|
||||||
|
return False, None, None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def verify_contents(engine) -> bool:
|
||||||
|
try:
|
||||||
|
log.info('checking if all tables are present, and creating them if they are not')
|
||||||
|
|
||||||
|
Base.metadata.create_all(engine)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
log.error('failed to verify contents of the database')
|
||||||
|
return False
|
||||||
|
|||||||
@@ -1,2 +1,25 @@
|
|||||||
#!/bin/env python3
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import sqlalchemy
|
||||||
|
import sqlalchemy.orm
|
||||||
|
|
||||||
|
Base = sqlalchemy.orm.declarative_base()
|
||||||
|
|
||||||
|
class User(Base):
|
||||||
|
__tablename__ = 'users'
|
||||||
|
|
||||||
|
user_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, index=True)
|
||||||
|
|
||||||
|
username = sqlalchemy.Column(sqlalchemy.String, unique=True, index=True)
|
||||||
|
password = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
role = sqlalchemy.Column(sqlalchemy.String, default='user')
|
||||||
|
|
||||||
|
totp_enabled = sqlalchemy.Column(sqlalchemy.Boolean, default=False)
|
||||||
|
totp_verified = sqlalchemy.Column(sqlalchemy.Boolean, default=False)
|
||||||
|
totp_key = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
email = sqlalchemy.Column(sqlalchemy.String)
|
||||||
|
|
||||||
|
class Wireguard(Base):
|
||||||
|
__tablename__ = 'wireguard_interfaces'
|
||||||
@@ -1,9 +1,45 @@
|
|||||||
#!/bin/env python3
|
#!/bin/env python3
|
||||||
|
|
||||||
class db_setup():
|
import logging as log
|
||||||
|
|
||||||
|
import os
|
||||||
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
|
from modules.utilities.utilities import utilities as util
|
||||||
|
|
||||||
|
class checks():
|
||||||
'''
|
'''
|
||||||
This class functions as a collection of function to prepare a connection to a database.
|
This class functions as a collection of function to prepare a connection to a database.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def compile_connection_string() -> string:
|
@staticmethod
|
||||||
return "The Connection string"
|
def generate_connection_string(database_config: dict) -> tuple[bool, str]:
|
||||||
|
if not 'type' in database_config:
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
username = quote_plus(database_config.get('username', ''))
|
||||||
|
password = quote_plus(database_config.get('password', ''))
|
||||||
|
|
||||||
|
match database_config['type']:
|
||||||
|
case 'sqlite':
|
||||||
|
local_database_path = os.path.abspath("./database")
|
||||||
|
|
||||||
|
exists = util.ensure_directory(local_database_path)
|
||||||
|
if exists:
|
||||||
|
connection_string = f'sqlite:///{local_database_path}/wgdashboard.db'
|
||||||
|
else:
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
case 'postgresql' | 'postgres':
|
||||||
|
connection_string = f'postgresql+psycopg://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '5432')}'
|
||||||
|
|
||||||
|
case 'mariadb':
|
||||||
|
connection_string = f'mariadb+mariadbconnector://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '3306')}'
|
||||||
|
|
||||||
|
case 'mysql':
|
||||||
|
connection_string = f'mysql+pymysql://{username}:{password}@{database_config.get('host', 'localhost')}:{database_config.get('port', '3306')}'
|
||||||
|
|
||||||
|
case _:
|
||||||
|
return False, ''
|
||||||
|
|
||||||
|
return True, connection_string
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/env python3
|
||||||
|
|
||||||
|
import logging as log
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
class utilities():
|
||||||
|
@staticmethod
|
||||||
|
def filter_config(config_contents: dict, filter_keyword: str) -> tuple[bool, dict]:
|
||||||
|
'''
|
||||||
|
Helper function to grab a specific part of the config
|
||||||
|
'''
|
||||||
|
|
||||||
|
log.debug(f'searching for section: {filter_keyword}')
|
||||||
|
for section in config_contents:
|
||||||
|
if str(section).lower() == filter_keyword.lower():
|
||||||
|
return True, dict(config_contents[section].items())
|
||||||
|
|
||||||
|
return False, {}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def ensure_directory(path: str) -> bool:
|
||||||
|
'''
|
||||||
|
Make the directory if it does not exist yet, return only true if the directory was missing and created.
|
||||||
|
'''
|
||||||
|
|
||||||
|
log.debug(f'checking if the directory at: {path} exists')
|
||||||
|
if os.path.exists(path) and os.path.isdir(path):
|
||||||
|
return True
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.mkdir(path)
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
log.critical('failed to create directory')
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
configparser==7.2.0
|
configparser==7.2.0
|
||||||
|
sqlalchemy==2.0.47
|
||||||
Reference in New Issue
Block a user