Files
nosys_libs/api/api.py
2026-01-25 13:55:46 +10:00

110 lines
4.3 KiB
Python

import os
from pathlib import Path
from flask import Flask, Blueprint, request, send_from_directory, jsonify
from flask_cors import CORS, cross_origin
from flask_socketio import SocketIO, Namespace
from libs.app.common.logging import get_logger
from libs.app.common.paths import ROOT_DIR
from libs.fspn.utils.wrapper_util import threaded
from .apiBlueprint import ApiBlueprint
from .eventsSocketio import EventsSocketio
from libs.noSys.noSysModule import NoSysModule
from .certs import generate_ca_and_cert, add_ca_os
logger = get_logger()
class Api(NoSysModule):
def __init__(self, nosys_core):
super().__init__(nosys_core)
self.dist_dir = os.path.join(ROOT_DIR, "libs/vueNoSys/dist")
self.assets_dir = os.path.join(self.dist_dir, "assets")
self.app = Flask(__name__, static_folder=self.assets_dir, template_folder=self.dist_dir)
CORS(self.app, resources={r"/*": {"origins": "*"}}, supports_credentials=True)
self.socketio = SocketIO(self.app, cors_allowed_origins="*")
self.server = None
self.host = self.config["server"]["host"]
self.port = self.config["server"]["port"]
self.register_blueprint(BasicBlueprint(self).blueprint)
self.register_socketio(BasicEventSocketIo(self))
def setup(self):
self.nosys_core.modules.api = self
certs_path = os.path.join(ROOT_DIR, "libs", "api", "certs")
self.ca_path = os.path.join(certs_path , "ca.pem")
self.ca_key_path = os.path.join(certs_path, "ca_key.pem")
self.cert_path = os.path.join(certs_path, "cert.pem")
self.key_path = os.path.join(certs_path, "key.pem")
if not os.path.exists(self.cert_path) or not os.path.exists(self.key_path) or not os.path.exists(self.ca_path) or not os.path.exists(self.ca_key_path):
Path(certs_path).mkdir(parents=True, exist_ok=True)
logger.debug("Generating certs")
ca, cert, key = generate_ca_and_cert(self.ca_path, self.ca_key_path, self.cert_path, self.key_path)
logger.debug("Adding ca to operational system")
add_ca_os(self.ca_path)
logger.debug("Cert installed")
else:
logger.debug("Certs already exists")
def register_blueprint(self, blueprint:Blueprint):
try:
self.app.register_blueprint(blueprint)
logger.debug(f"Registered blueprint {blueprint.url_prefix}")
except Exception:
logger.exception(f"Failed registering blueprint {blueprint.url_prefix}")
def register_socketio(self, handler:EventsSocketio):
try:
handler.register_events(self.socketio)
logger.debug(f"Registered socketio {handler.namespace}")
except Exception:
logger.exception(f"Failed registering socketio {handler.namespace}")
def on_nosys_ready(self, event):
self.run()
@threaded
def run(self):
self.routes()
logger.debug(f'Running Flask API ({self.host}:{self.port}) with urls: {self.app.url_map}')
try:
self.socketio.run(app=self.app, host=self.host, port=self.port, allow_unsafe_werkzeug=True, ssl_context=(self.cert_path, self.key_path))
except Exception as e:
logger.error(e)
def routes(self):
@self.app.route("/", defaults={"path": ""})
@self.app.route("/<path:path>")
def index(path):
if path != "" and os.path.exists(os.path.join(self.dist_dir, path)):
return send_from_directory(self.dist_dir, path)
return send_from_directory(self.dist_dir, "index.html")
class BasicBlueprint(ApiBlueprint):
def routes(self):
self.api:Api = self.module
@self.blueprint.route('/')
def show():
return "API"
class BasicEventSocketIo(EventsSocketio):
def events(self):
@self.on("connect")
def on_connect(*args, **kwargs):
print('API connected',args, kwargs, request.sid)
self.emit("welcome", {"msg": f"Your id {request.sid}"})
@self.on("disconnect")
def on_disconnect(*args, **kwargs):
print('API disconnected',args, kwargs, request.sid)
@self.on("message")
def on_message(*args, **kwargs):
print('API Message',args, kwargs)
self.emit("message", f"Message received {args[0]}")