From 1561c578f55cb96eb794788f005b82c64b74553d Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Mon, 7 Feb 2022 18:39:34 +0300 Subject: [PATCH] Process fix, WebRequest is optional now --- .vscode/settings.json | 5 ++ .../Orchestrator/Managers/Process.py | 2 +- Sources/pyOpenRPA/Orchestrator/Server.py | 12 +++- .../pyOpenRPA/Orchestrator/ServerSettings.py | 2 +- .../Orchestrator/__Orchestrator__.py | 71 ++++++++++++------- 5 files changed, 64 insertions(+), 28 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b7056e74..23c94a0f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,4 +3,9 @@ "editor.fontSize": 16, "editor.fontWeight": "700", "autoDocstring.docstringFormat": "sphinx" + "python.analysis.extraPaths": [ + "${workspaceFolder}/Sources" + + + ] } \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/Managers/Process.py b/Sources/pyOpenRPA/Orchestrator/Managers/Process.py index 5297296a..862a53c2 100644 --- a/Sources/pyOpenRPA/Orchestrator/Managers/Process.py +++ b/Sources/pyOpenRPA/Orchestrator/Managers/Process.py @@ -442,7 +442,7 @@ def ProcessInitSafe(inAgentHostNameStr, inAgentUserNameStr, inProcessNameWOExeSt :return: Process instance """ lProcess = ProcessGet(inAgentHostNameStr = inAgentHostNameStr, inAgentUserNameStr = inAgentUserNameStr, inProcessNameWOExeStr=inProcessNameWOExeStr) - if lProcess is not None: return lProcess.mStatusStr + if lProcess is not None: return lProcess else: return Process(inAgentHostNameStr=inAgentHostNameStr,inAgentUserNameStr=inAgentUserNameStr,inProcessNameWOExeStr=inProcessNameWOExeStr, inStartPathStr=inStartPathStr,inStartCMDStr=inStartCMDStr,inStopSafeTimeoutSecFloat=inStopSafeTimeoutSecFloat) diff --git a/Sources/pyOpenRPA/Orchestrator/Server.py b/Sources/pyOpenRPA/Orchestrator/Server.py index 1b6b95a9..d39ab81a 100644 --- a/Sources/pyOpenRPA/Orchestrator/Server.py +++ b/Sources/pyOpenRPA/Orchestrator/Server.py @@ -11,6 +11,7 @@ from socketserver import ThreadingMixIn import threading import json from threading import Thread +import inspect from . import Processor # Add new processor from . import ProcessorOld # Support old processor - deprecated defs only for backward compatibility import urllib.parse # decode URL in string @@ -280,7 +281,14 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): lFileObject.close() #If function is set if "ResponseDefRequestGlobal" in inURLItem: - inURLItem["ResponseDefRequestGlobal"](inRequest, inGlobalDict) + lDef = inURLItem["ResponseDefRequestGlobal"] + lDefSignature = inspect.signature(lDef) + if len(lDefSignature.parameters) == 2: + inURLItem["ResponseDefRequestGlobal"](inRequest, inGlobalDict) + elif len(lDefSignature.parameters) == 1: + inURLItem["ResponseDefRequestGlobal"](inRequest) + else: + inURLItem["ResponseDefRequestGlobal"]() if "ResponseFolderPath" in inURLItem: #lRequestPath = inRequest.path lRequestPath = urllib.parse.unquote(inRequest.path) @@ -360,6 +368,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): def do_GET(self): try: + threading.current_thread().request = self self.OpenRPA = {} self.OpenRPA["AuthToken"] = None self.OpenRPA["Domain"] = None @@ -433,6 +442,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): # POST def do_POST(self): try: + threading.current_thread().request = self lL = gSettingsDict["Logger"] self.OpenRPA = {} self.OpenRPA["AuthToken"] = None diff --git a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py index 473e0ce1..12112d6b 100644 --- a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py +++ b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py @@ -425,7 +425,7 @@ def pyOpenRPA_Agent_A2O(inRequest, inGSettings): lActivityReturnItemValue = lInput["ActivityReturnDict"][lActivityReturnItemKeyStr] # Create item in gSettings inGSettings["AgentActivityReturnDict"][lActivityReturnItemKeyStr]=SettingsTemplate.__AgentActivityReturnDictItemCreate__(inReturn=lActivityReturnItemValue) - if lL: lL.debug(f"SERVER: pyOpenRPA_Agent_A2O:: Has recieved result of the activity items from agent! ActivityItem GUID Str: {lActivityReturnItemKeyStr}; Return value: {lActivityReturnItemValue}") + if lL: lL.debug(f"SERVER: pyOpenRPA_Agent_A2O:: Has recieved result of the activity items from agent! ActivityItem GUID Str: {lActivityReturnItemKeyStr}; Return value len: {len(lActivityReturnItemValue)}") # Delete the source activity item from AgentDict if lAgentDictItemKeyTurple in inGSettings["AgentDict"]: lAgentDictActivityListNew = [] diff --git a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py index 75d80d7d..61d0a9f9 100644 --- a/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py +++ b/Sources/pyOpenRPA/Orchestrator/__Orchestrator__.py @@ -779,11 +779,11 @@ def WebURLConnectDef(inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentType "inDef": None #Function with str result :param inGSettings: Global settings dict (singleton) - :param inMethodStr: - :param inURLStr: - :param inMatchTypeStr: - :param inDef: - :param inContentTypeStr: + :param inMethodStr: "GET|POST", + :param inURLStr: example "/index", #URL of the request + :param inMatchTypeStr: #"BeginWith|Contains|Equal|EqualCase", + :param inDef: def arg allowed list: 2:[inRequest, inGSettings], 1: [inRequest], 0: [] + :param inContentTypeStr: default: "application/octet-stream" """ inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lURLItemDict = { @@ -897,7 +897,7 @@ def WebCPUpdate(inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSI if inJSInitGeneratorDef is not None: lCPManager.mBackwardCompatibilityJSDef = inJSInitGeneratorDef -def WebAuditMessageCreate(inRequest, inOperationCodeStr="-", inMessageStr="-"): +def WebAuditMessageCreate(inRequest=None, inOperationCodeStr="-", inMessageStr="-"): """ Create message string with request user details (IP, Login etc...). Very actual for IT security in big company. @@ -914,12 +914,13 @@ def WebAuditMessageCreate(inRequest, inOperationCodeStr="-", inMessageStr="-"): # Log the WebAudit message lLogger.info(lWebAuditMessageStr) - :param inRequest: HTTP request handler + :param inRequest: HTTP request handler. Optional if call def from request thread :param inOperationCodeStr: operation code in string format (actual for IT audit in control panels) :param inMessageStr: additional message after :return: format "WebAudit :: DOMAIN\\USER@101.121.123.12 :: operation code :: message" """ try: + if inRequest is None: inRequest = WebRequestGet() lClientIPStr = inRequest.client_address[0] lUserDict = WebUserInfoGet(inRequest=inRequest) lDomainUpperStr = lUserDict["DomainUpperStr"] @@ -930,54 +931,58 @@ def WebAuditMessageCreate(inRequest, inOperationCodeStr="-", inMessageStr="-"): lResultStr = inMessageStr return lResultStr -def WebRequestParseBodyBytes(inRequest): +def WebRequestParseBodyBytes(inRequest=None): """ Extract the body in bytes from the request - :param inRequest: inRequest from the server + :param inRequest: inRequest from the server. Optional if call def from request thread :return: Bytes or None """ + if inRequest is None: inRequest = WebRequestGet() lBodyBytes=None if inRequest.headers.get('Content-Length') is not None: lInputByteArrayLength = int(inRequest.headers.get('Content-Length')) lBodyBytes = inRequest.rfile.read(lInputByteArrayLength) return lBodyBytes -def WebRequestParseBodyStr(inRequest): +def WebRequestParseBodyStr(inRequest=None): """ Extract the body in str from the request - :param inRequest: inRequest from the server + :param inRequest: inRequest from the server. Optional if call def from request thread :return: str or None """ - + if inRequest is None: inRequest = WebRequestGet() return WebRequestParseBodyBytes(inRequest=inRequest).decode('utf-8') -def WebRequestParseBodyJSON(inRequest): +def WebRequestParseBodyJSON(inRequest=None): """ Extract the body in dict/list from the request - :param inRequest: + :param inRequest: inRequest from the server. Optional if call def from request thread :return: dict or list """ + if inRequest is None: inRequest = WebRequestGet() return json.loads(WebRequestParseBodyStr(inRequest=inRequest)) -def WebRequestParsePath(inRequest): +def WebRequestParsePath(inRequest=None): """ Parse the request - extract the url. Example: /pyOpenRPA/Debugging/DefHelper/... - :param inRequest: + :param inRequest: inRequest from the server. Optional if call def from request thread :return: Str, Example: /pyOpenRPA/Debugging/DefHelper/... """ + if inRequest is None: inRequest = WebRequestGet() return urllib.parse.unquote(inRequest.path) -def WebRequestParseFile(inRequest): +def WebRequestParseFile(inRequest=None): """ Parse the request - extract the file (name, body in bytes) - :param inRequest: + :param inRequest: inRequest from the server. Optional if call def from request thread :return: (FileNameStr, FileBodyBytes) or (None, None) """ + if inRequest is None: inRequest = WebRequestGet() lResultTurple=(None,None) if inRequest.headers.get('Content-Length') is not None: lInputByteArray = WebRequestParseBodyBytes(inRequest=inRequest) @@ -997,45 +1002,61 @@ def WebRequestParseFile(inRequest): return lResultTurple -def WebRequestResponseSend(inRequest, inResponeStr): +def WebRequestResponseSend(inResponeStr, inRequest=None): """ Send response for the request + + :param inRequest: inRequest from the server. Optional if call def from request thread :return: """ + if inRequest is None: inRequest = WebRequestGet() inRequest.OpenRPAResponseDict["Body"] = bytes(inResponeStr, "utf8") -def WebUserInfoGet(inRequest): + +def WebRequestGet(): + """ + Return the web request instance if current thread was created by web request from client. else return None + + """ + lCurrentThread = threading.current_thread() + if hasattr(lCurrentThread, "request"): + return lCurrentThread.request + +def WebUserInfoGet(inRequest=None): """ Return User info about request - :param inRequest: + :param inRequest: inRequest from the server. Optional if call def from request thread :return: {"DomainUpperStr": "", "UserNameUpperStr": ""} """ + if inRequest is None: inRequest = WebRequestGet() lDomainUpperStr = inRequest.OpenRPA["Domain"].upper() lUserUpperStr = inRequest.OpenRPA["User"].upper() return {"DomainUpperStr": lDomainUpperStr, "UserNameUpperStr": lUserUpperStr} -def WebUserIsSuperToken(inRequest, inGSettings = None): +def WebUserIsSuperToken(inRequest = None, inGSettings = None): """ Return bool if request is authentificated with supetoken (token which is never expires) - :param inRequest: + :param inRequest: inRequest from the server. Optional if call def from request thread :param inGSettings: Global settings dict (singleton) :return: bool True - is supertoken; False - is not supertoken """ + if inRequest is None: inRequest = WebRequestGet() inGSettings = GSettingsGet(inGSettings=inGSettings) # Set the global settings lIsSuperTokenBool = False # Get Flag is supertoken (True|False) lIsSuperTokenBool = inGSettings.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inRequest.OpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) return lIsSuperTokenBool -def WebUserUACHierarchyGet(inRequest): +def WebUserUACHierarchyGet(inRequest = None): """ Return User UAC Hierarchy DICT Return {...} - :param inRequest: + :param inRequest: inRequest from the server. Optional if call def from request thread :return: UAC Dict {} """ + if inRequest is None: inRequest = WebRequestGet() return inRequest.UserRoleHierarchyGet()