mirror of
https://github.com/naruxde/revpipyload.git
synced 2025-11-08 15:13:52 +01:00
IpAclManager.valid_acl_string entfernt SaveXMLRPCServer übernimmt ACL Level bei Funktionsregistrierung SaveXMLRPCServer _dispatch werte ACL Level der Methode aus Konfigdatei mit neuen Sektionen PLCSLAVE und XMLRPC versehen Parameter autoreloaddelay für PLC-Neustart integriert ACL Vergabe für alle register_function Aufrufe
134 lines
4.0 KiB
Python
134 lines
4.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# RevPiPyLoad
|
|
#
|
|
# Webpage: https://revpimodio.org/revpipyplc/
|
|
# (c) Sven Sager, License: LGPLv3
|
|
#
|
|
"""XML-RPC Server anpassungen fuer Absicherung."""
|
|
import proginit
|
|
from helper import IpAclManager
|
|
from concurrent import futures
|
|
from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
|
|
|
|
|
|
class SaveXMLRPCServer(SimpleXMLRPCServer):
|
|
|
|
"""Erstellt einen erweiterten XMLRPCServer."""
|
|
|
|
def __init__(
|
|
self, addr, logRequests=True, allow_none=False,
|
|
use_builtin_types=False, ipacl=IpAclManager()):
|
|
"""Init SaveXMLRPCServer class."""
|
|
proginit.logger.debug("enter SaveXMLRPCServer.__init__()")
|
|
|
|
# Vererbte Klasse instantiieren
|
|
super().__init__(
|
|
addr=addr,
|
|
requestHandler=SaveXMLRPCRequestHandler,
|
|
logRequests=logRequests,
|
|
allow_none=allow_none,
|
|
encoding="utf-8",
|
|
bind_and_activate=False,
|
|
use_builtin_types=use_builtin_types
|
|
)
|
|
|
|
# Klassenvariablen
|
|
self.aclmgr = ipacl
|
|
self.funcacls = {}
|
|
self.requestacl = -1
|
|
self.tpe = futures.ThreadPoolExecutor(max_workers=1)
|
|
self.fut = None
|
|
|
|
proginit.logger.debug("leave SaveXMLRPCServer.__init__()")
|
|
|
|
def _dispatch(self, method, params):
|
|
"""Prueft ACL Level fuer angeforderte Methode.
|
|
|
|
@param method Angeforderte Methode
|
|
@param params Argumente fuer Methode
|
|
@return Dispatched data
|
|
|
|
"""
|
|
# ACL Level für angeforderte Methode prüfen
|
|
if self.requestacl < self.funcacls.get(method, -1):
|
|
raise RuntimeError("function call not allowed")
|
|
|
|
# ACL Mode abfragen (Gibt ACL Level als Parameter)
|
|
if method == "xmlmodus":
|
|
params = (self.requestacl, )
|
|
|
|
return super()._dispatch(method, params)
|
|
|
|
def isAlive(self):
|
|
"""Prueft ob der XML RPC Server laeuft.
|
|
@return True, wenn Server noch laeuft"""
|
|
return False if self.fut is None else self.fut.running()
|
|
|
|
def register_function(self, acl_level, function, name=None):
|
|
"""Override register_function to add acl_level.
|
|
|
|
@param acl_level ACL level to call this function
|
|
@param function Function to register
|
|
@param name Alternative name to use
|
|
|
|
"""
|
|
if type(acl_level) != int:
|
|
raise ValueError("parameter acl_level must be <class 'int'>")
|
|
|
|
if name is None:
|
|
name = function.__name__
|
|
self.funcs[name] = function
|
|
self.funcacls[name] = acl_level
|
|
|
|
def start(self):
|
|
"""Startet den XML-RPC Server."""
|
|
proginit.logger.debug("enter SaveXMLRPCServer.start()")
|
|
|
|
if self.fut is None:
|
|
self.server_bind()
|
|
self.server_activate()
|
|
self.fut = self.tpe.submit(self.serve_forever)
|
|
else:
|
|
raise RuntimeError("savexmlrpcservers can only be started once")
|
|
|
|
proginit.logger.debug("leave SaveXMLRPCServer.start()")
|
|
|
|
def stop(self):
|
|
"""Stoppt den XML-RPC Server."""
|
|
proginit.logger.debug("enter SaveXMLRPCServer.stop()")
|
|
|
|
if self.fut is not None:
|
|
self.shutdown()
|
|
self.tpe.shutdown()
|
|
self.server_close()
|
|
else:
|
|
raise RuntimeError("save xml rpc server was not started")
|
|
|
|
proginit.logger.debug("leave SaveXMLRPCServer.stop()")
|
|
|
|
|
|
class SaveXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
|
|
|
|
"""Verwaltet die XML-Requests und prueft Berechtigungen."""
|
|
|
|
def parse_request(self):
|
|
"""Berechtigungen pruefen.
|
|
@return True, wenn Parsen erfolgreich war"""
|
|
# Request parsen und ggf. schon abbrechen
|
|
if not super().parse_request():
|
|
return False
|
|
|
|
# ACL für IP-Adresse übernehmen
|
|
self.server.requestacl = \
|
|
self.server.aclmgr.get_acllevel(self.address_string())
|
|
|
|
if self.server.requestacl >= 0:
|
|
return True
|
|
else:
|
|
self.send_error(
|
|
401, "IP '{}' not allowed".format(self.address_string())
|
|
)
|
|
|
|
return False
|