hmdooris/hmdooris/__main__.py
Stefan Bethke 6d3e550914
Some checks failed
docker-image / docker (push) Has been cancelled
Pretty up
2025-05-27 19:28:37 +02:00

111 lines
3.2 KiB
Python

"""
FastAPI main entry point
"""
import json
import logging
from typing import Callable
from BottleOIDC import BottleOIDC
from BottleOIDC.bottle_utils import UnauthorizedError
from BottleSessions import BottleSessions
from bottle import route, run, Bottle, static_file, TEMPLATE_PATH, jinja2_view, post, get, request
from bottle_log import LoggingPlugin
from bottle_websocket import websocket, GeventWebSocketServer
from geventwebsocket.websocket import WebSocket
from hmdooris.AppConfig import AppConfig
from hmdooris.ccujack import CCUJack
from hmdooris.updatepoller import UpdatePoller
from hmdooris.websocketcomm import WebSocketClients
config = AppConfig()
if config.debug:
logging.basicConfig(level=logging.DEBUG)
ccujack = CCUJack(config.ccujack_url, config.ccujack_username, config.ccujack_password, config.ccujack_locks)
app = Bottle()
if config.debug:
app.config.update({"logging.level": "DEBUG"})
app.install(LoggingPlugin(app.config))
TEMPLATE_PATH.insert(0, config.templatepath)
app.install(BottleSessions())
auth = BottleOIDC(app, config={
"discovery_url": config.discovery_url,
"client_id": config.client_id,
"client_secret": config.client_secret,
"client_scope": config.oidc_scope,
"user_attr": config.oidc_user_attr,
})
websocket_clients = WebSocketClients()
update_poller = UpdatePoller(websocket_clients, ccujack, 1 if config.debug else 0.1)
def require_login(func: Callable) -> Callable:
if config.requires_group is not None:
return auth.require_login(auth.require_attribute('groups', config.requires_group)(func))
else:
return auth.require_login(func)
def require_authz(func: Callable) -> Callable:
if config.requires_group is not None:
return auth.require_attribute('groups', config.requires_group)(func)
else:
def _outer_wrapper(f):
def _wrapper(*args, **kwargs):
if auth.my_username is not None:
return f(*args, **kwargs)
return UnauthorizedError('Not Authorized')
_wrapper.__name__ = f.__name__
return _wrapper
return _outer_wrapper(func)
@app.route("/static/<filepath>")
def server_static(filepath):
return static_file(filepath, root=config.staticpath)
@app.get("/")
@jinja2_view("home.html.j2")
def root():
return {}
@app.get("/operate")
@require_login
@jinja2_view("operate.html.j2")
def root():
return {}
@app.get('/ws', apply=[websocket])
def websocket_endpoint(ws: WebSocket):
try:
websocket_clients.add(ws)
ws.send(json.dumps(update_poller.get_locks(True)))
while True:
m = ws.receive()
except Exception as e:
logging.debug("error in websocket", exc_info=e)
pass
finally:
websocket_clients.remove(ws)
@app.get('/api/lock')
def get_api_lock():
return update_poller.get_locks(True)
@app.get('/api/lock/<id>')
def get_api_lock(id):
return update_poller.get_lock(id)
@app.post('/api/lock/<id>')
@require_authz
def post_api_lock(id):
return ccujack.lock_unlock(id, request.json["locking"])
if __name__ == '__main__':
app.run(host='localhost', port=3000, server=GeventWebSocketServer, debug=config.debug, quiet=not config.debug)