diff --git a/Orchestrator/Template_Settings_AccessUser.py b/Orchestrator/Template_Settings_AccessUser.py index e11679b8..f8b8b4ae 100644 --- a/Orchestrator/Template_Settings_AccessUser.py +++ b/Orchestrator/Template_Settings_AccessUser.py @@ -40,7 +40,8 @@ def SettingsUpdate(inDict): "FlagAccess": True } ], - "ControlPanelKeyAllowedList": ["TestControlPanel", "RobotRDPActive","RobotScreenActive", "ControlPanel_Template"] # If empty - all is allowed + "ControlPanelKeyAllowedList": ["TestControlPanel", "RobotRDPActive","RobotScreenActive", "ControlPanel_Template"], # If empty - all is allowed + "RoleHierarchyAllowedDict": {"Key1":"Test"} } # Case add domain + user inDict["Server"]["AccessUsers"]["RuleDomainUserDict"].update({(gDomainNameStr.upper(),gUserNameStr.upper()):lRuleDomainUserDict}) diff --git a/Resources/WPy64-3720/settings/.jupyter/lab/workspaces/lab-a511.jupyterlab-workspace b/Resources/WPy64-3720/settings/.jupyter/lab/workspaces/lab-a511.jupyterlab-workspace new file mode 100644 index 00000000..95faf96f --- /dev/null +++ b/Resources/WPy64-3720/settings/.jupyter/lab/workspaces/lab-a511.jupyterlab-workspace @@ -0,0 +1 @@ +{"data":{"layout-restorer:data":{"main":{"dock":{"type":"tab-area","currentIndex":0,"widgets":[]},"mode":"multiple-document"},"left":{"collapsed":false,"current":"filebrowser","widgets":["filebrowser","running-sessions","command-palette","jp-property-inspector","tab-manager","extensionmanager.main-view"]},"right":{"collapsed":true,"widgets":[]}},"file-browser-filebrowser:cwd":{"path":""}},"metadata":{"id":"/lab"}} \ No newline at end of file diff --git a/Resources/WPy64-3720/settings/runtime/nbserver-4160-open.html b/Resources/WPy64-3720/settings/runtime/nbserver-4160-open.html new file mode 100644 index 00000000..88d29878 --- /dev/null +++ b/Resources/WPy64-3720/settings/runtime/nbserver-4160-open.html @@ -0,0 +1,22 @@ + + + + + + + Opening Jupyter Notebook + + + + +

+ This page should redirect you to Jupyter Notebook. If it doesn't, + click here to go to Jupyter. +

+ + + \ No newline at end of file diff --git a/Resources/WPy64-3720/settings/runtime/nbserver-4160.json b/Resources/WPy64-3720/settings/runtime/nbserver-4160.json new file mode 100644 index 00000000..0cf5c588 --- /dev/null +++ b/Resources/WPy64-3720/settings/runtime/nbserver-4160.json @@ -0,0 +1,12 @@ +{ + "base_url": "/", + "hostname": "localhost", + "notebook_dir": "C:\\Abs\\Archive\\scopeSrcUL\\OpenRPA\\Resources\\WPy64-3720\\notebooks", + "password": false, + "pid": 4160, + "port": 8888, + "secure": false, + "sock": "", + "token": "fe0a6fb1d56b2d786835fe0a5b80b7f0ddb200741a6dfb23", + "url": "http://localhost:8888/" +} \ No newline at end of file diff --git a/Resources/WPy64-3720/settings/runtime/notebook_cookie_secret b/Resources/WPy64-3720/settings/runtime/notebook_cookie_secret new file mode 100644 index 00000000..fa43d305 --- /dev/null +++ b/Resources/WPy64-3720/settings/runtime/notebook_cookie_secret @@ -0,0 +1 @@ +w7CTIp3VGJjVG12fVxVz5VEh5bRm8JIiR11mIZRakLU= diff --git a/Sources/Sandbox/.ipynb_checkpoints/OrchestratorTestInit-checkpoint.ipynb b/Sources/Sandbox/.ipynb_checkpoints/OrchestratorTestInit-checkpoint.ipynb new file mode 100644 index 00000000..dbf0aba6 --- /dev/null +++ b/Sources/Sandbox/.ipynb_checkpoints/OrchestratorTestInit-checkpoint.ipynb @@ -0,0 +1,75 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Init the configuration GSettings" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "lSettingsDirStr = r\"..\\..\\..\\OpenRPA_Creds\\Orchestrator\\Settings\" # Set Gsettings dir path str\n", + "import sys\n", + "sys.path.append(lSettingsDirStr) # Add path with settings in search dir for .py modules\n", + "sys.path.insert(0,r\"..\") # Add path to sources - to import from experimental pyOpenRPA\n", + "import SettingsOrchestratorExample\n", + "gSettings = SettingsOrchestratorExample.Settings()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run the orchestrator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pyOpenRPA.Orchestrator import Orchestrator # Import orchestrator main\n", + "Orchestrator.Orchestrator(inGSettings=gSettings) # Call the orchestrator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.2" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Sources/Sandbox/.ipynb_checkpoints/OrchestratorTestProcessorNew-checkpoint.ipynb b/Sources/Sandbox/.ipynb_checkpoints/OrchestratorTestProcessorNew-checkpoint.ipynb new file mode 100644 index 00000000..7fec5150 --- /dev/null +++ b/Sources/Sandbox/.ipynb_checkpoints/OrchestratorTestProcessorNew-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py index a60aa1f7..a648db73 100644 --- a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py +++ b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py @@ -1,8 +1,177 @@ # Def to check inGSettings and update structure to the backward compatibility # !!! ATTENTION: Backward compatibility has been started from v1.1.13 !!! # So you can use config of the orchestrator 1.1.13 in new Orchestrator versions and all will be ok :) (hope it's true) -import win32security +import win32security, json, datetime, time + +# # # # # # # # # # # # # # # # # # # +# Backward compatibility Web defs up to v1.2.0 +# # # # # # # # # # # # # # # # # # # + +# UserAccess get rights hierarchy dict in json +def v1_2_0_UserRoleHierarchyGet(inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + # Create result JSON + lResultDict = inRequest.OpenRPA["DefUserRoleHierarchyGet"]() # Get the User Role Hierarchy list + # Send message back to client + message = json.dumps(lResultDict) + # Write content as utf-8 data + inResponseDict["Body"] = bytes(message, "utf8") + +from inspect import signature # For detect count of def args +# /Orchestrator/RobotRDPActive/ControlPanelDictGet +def v1_2_0_RobotRDPActive_ControlPanelDictGet(inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + lResultDict = { + "DataList":[ + # {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} + ] + } + # Iterate throught the RDP List + for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]: + lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][lRDPSessionKeyStrItem] # Get the configuration dict + lDataItemDict = {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} # Template + lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str + lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex + lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"]["FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window + lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored + lResultDict["DataList"].append(lDataItemDict) + # Send message back to client + message = json.dumps(lResultDict) + # Write content as utf-8 data + inResponseDict["Body"] = bytes(message, "utf8") + +# def to check control panels for selected session +def v1_2_0_Monitor_ControlPanelDictGet_SessionCheckInit(inRequest,inGlobalDict): + lL = inGlobalDict["Logger"] # Alias for logger + lLifetimeSecFloat = inGlobalDict["Client"]["Session"]["LifetimeSecFloat"] + lLifetimeRequestSecFloat = inGlobalDict["Client"]["Session"]["LifetimeRequestSecFloat"] + lControlPanelRefreshIntervalSecFloat = inGlobalDict["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"] + lCookieSessionGUIDStr = None # generate the new GUID + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Technicaldef - interval check control panels + check actuality of the session by the datetime + def TechnicalCheck(): + lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] + # Lifetime is ok - check control panel + lDatasetCurrentBytes = v1_2_0_Monitor_ControlPanelDictGet(inRequest,inGlobalDict) # Call the control panel + if lDatasetCurrentBytes != lItemValue["DatasetLast"]["ControlPanel"]["Data"]: # Check if dataset is changed + lItemValue["DatasetLast"]["ControlPanel"]["Data"] = lDatasetCurrentBytes # Set new datset + lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] = True # Set flag to return the data + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + # Technicaldef - Create new session struct + def TechnicalSessionNew(inSessionGUIDStr): + lCookieSessionGUIDStr = inSessionGUIDStr # Generate the new GUID + lSessionNew = { # Session with some GUID str. On client session guid stored in cookie "SessionGUIDStr" + "InitDatetime": datetime.datetime.now(), # Datetime when session GUID was created + "DatasetLast": { + "ControlPanel": { + "Data": None, # Struct to check with new iterations. None if starts + "ReturnBool": False # flag to return, close request and return data as json + } + }, + "ClientRequestHandler": inRequest, # Last client request handler + "UserADStr": inRequest.OpenRPA["User"], # User, who connect. None if user is not exists + "DomainADStr": inRequest.OpenRPA["Domain"], # Domain of the user who connect. None if user is not exists + } + inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] = lSessionNew # Set new session in dict + inRequest.OpenRPAResponseDict["SetCookies"]["SessionGUIDStr"] = lCookieSessionGUIDStr # Set SessionGUIDStr in cookies + if lL: lL.info(f"New session GUID is created. GUID {lCookieSessionGUIDStr}") + return lCookieSessionGUIDStr + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # + lCreateNewSessionBool = False # Flag to create new session structure + # step 1 - get cookie SessionGUIDStr + lSessionGUIDStr = inRequest.headers.get("SessionGUIDStr", None) + if lSessionGUIDStr is not None: # Check if GUID session is ok + #inRequest.OpenRPAResponseDict["StatusCode"] = 301 + #inRequest.OpenRPAResponseDict["Headers"]["Location"] = "/" + #if lL: lL.info(f"GUID is detected - send HTTP 301 to refresh page") + lCookieSessionGUIDStr = lSessionGUIDStr # Get the existing GUID + if lSessionGUIDStr not in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: + lCookieSessionGUIDStr= TechnicalSessionNew(inSessionGUIDStr = lSessionGUIDStr) # Create new session + else: # Update the datetime of the request session + inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr]["InitDatetime"]=datetime.datetime.now() + else: + lCookieSessionGUIDStr = TechnicalSessionNew(inSessionGUIDStr = lSessionGUIDStr) # Create new session + # Init the RobotRDPActive in another thread + #lThreadCheckCPInterval = threading.Thread(target=TechnicalIntervalCheck) + #lThreadCheckCPInterval.daemon = True # Run the thread in daemon mode. + #lThreadCheckCPInterval.start() # Start the thread execution. + + # Step 2 - interval check if data is exist + lTimeStartSecFloat = time.time() + lDoWhileBool = True # Flag to iterate throught the lifetime of the request + while lDoWhileBool: + #print(lTechnicalSessionGUIDCache) + #print(lCookieSessionGUIDStr) + if lCookieSessionGUIDStr in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: + lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] + if (time.time() - lTimeStartSecFloat) >= lLifetimeRequestSecFloat: # Check if lifetime client request is over or has no key + if lL: lL.debug(f"Client request lifetime is over") + lDoWhileBool = False # Stop the iterations + if lDoWhileBool: + TechnicalCheck() # Calculate the CP + if lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] == True: # Return data if data flag it True + lDatasetCurrentBytes = lItemValue["DatasetLast"]["ControlPanel"]["Data"] # Set new dataset + inResponseDict = inRequest.OpenRPAResponseDict + inResponseDict["Body"] = lDatasetCurrentBytes + lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] = False # Set flag that data was returned + lDoWhileBool = False # Stop the iterations + else: + lCookieSessionGUIDStr = TechnicalSessionNew(inSessionGUIDStr = lCookieSessionGUIDStr) # Create new session + if lDoWhileBool: # Sleep if we wait hte next iteration + time.sleep(lControlPanelRefreshIntervalSecFloat) # Sleep to the next iteration + +def v1_2_0_Monitor_ControlPanelDictGet(inRequest,inGlobalDict): + inResponseDict = inRequest.OpenRPAResponseDict + lL = inGlobalDict["Logger"] # Alias for logger + # Create result JSON + lResultJSON = {"RenderRobotList": [], "RenderRDPList": []} + lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"] + for lItem in lRenderFunctionsRobotList: + lUACBool = True # Check if render function is applicable User Access Rights (UAC) + if inGlobalDict["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True: + lUserRights = inGlobalDict["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(),inRequest.OpenRPA["User"].upper())] + if len(lUserRights["ControlPanelKeyAllowedList"]) > 0 and lItem["KeyStr"] not in lUserRights["ControlPanelKeyAllowedList"]: + lUACBool = False # UAC Check is not passed - False for user + if lUACBool: # Run function if UAC is TRUE + # Выполнить вызов и записать результат + # Call def (inRequest, inGSettings) or def (inGSettings) + lItemResultDict = None + lDEFSignature = signature(lItem["RenderFunction"]) # Get signature of the def + lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args + try: + if lDEFARGLen == 1: # def (inGSettings) + lItemResultDict = lItem["RenderFunction"](inGlobalDict) + elif lDEFARGLen == 2: # def (inRequest, inGSettings) + lItemResultDict = lItem["RenderFunction"](inRequest, inGlobalDict) + elif lDEFARGLen == 0: # def () + lItemResultDict = lItem["RenderFunction"]() + # RunFunction + lResultJSON["RenderRobotList"].append(lItemResultDict) + except Exception as e: + if lL: lL.exception(f"Error in control panel. CP item {lItem}. Exception is below") + # Iterate throught the RDP list + for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]: + lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][ + lRDPSessionKeyStrItem] # Get the configuration dict + lDataItemDict = {"SessionKeyStr": "", "SessionHexStr": "", "IsFullScreenBool": False, + "IsIgnoredBool": False} # Template + lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str + lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex + lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"][ + "FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window + lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored + lResultJSON["RenderRDPList"].append(lDataItemDict) + # Send message back to client + message = json.dumps(lResultJSON) + # Write content as utf-8 data + #inResponseDict["Body"] = bytes(message, "utf8") + return bytes(message, "utf8") + + from . import Orchestrator # For user defs + + + # v1.2.0 Def for old procesor to new processor # Return new activity for the new processor def v1_2_0_ProcessorOld2NewActivityDict(inActivityOld): @@ -108,6 +277,7 @@ def v1_2_0_ProcessorOld2NewActivityDict(inActivityOld): raise Exception(f"BackwardCompatibility up to v1.2.0, old processor: No type {inActivityOld['Type']} has been found in old processor.") return lResult # return the result + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # HERE IS THE MAIN DEF WHICH IS LAUNCHES WHEN START # # # # # # # # # diff --git a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py index b18fbbff..660aa001 100644 --- a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py +++ b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py @@ -62,7 +62,7 @@ def OrchestratorSessionSave(inGSettings=None): ## Orchestrator session save f"Orchestrator has dump the RDP list before the restart. The RDP List is {inGSettings['RobotRDPActive']['RDPList']}") return True # Update user access -def OrchestratorAccessUserUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=[], inCPAllowKeyList=[]): +def OrchestratorAccessUserUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=[], inCPAllowKeyList=[], inRoleHierarchyAllowedDict={}): # Backward compatibility if inURLList==[]: inURLList=[ @@ -85,6 +85,7 @@ def OrchestratorAccessUserUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDe lRuleDomainUserDict = { "MethodMatchURLBeforeList": inURLList, "ControlPanelKeyAllowedList": inCPAllowKeyList, #["TestControlPanel", "RobotRDPActive","RobotScreenActive", "ControlPanel_Template"] # If empty - all is allowed + "RoleHierarchyAllowedDict": inRoleHierarchyAllowedDict } # Case add domain + user inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"].update({(inADStr.upper(),inADLoginStr.upper()):lRuleDomainUserDict}) diff --git a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py index 3c15dd6a..37929b88 100644 --- a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py +++ b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py @@ -10,7 +10,10 @@ import time # sleep functions import datetime # datetime functions import threading # Multi-threading from .Web import Basic - +from . import BackwardCompatibility # Support old up to 1.2.0 defs +# # # # # # # # # # # # +# v 1.2.0 Functionallity +# # # # # # # # # # # # # Generate CP # Return {"Key":{"",""}} def HiddenCPDictGenerate(inRequest, inGSettings): @@ -86,7 +89,7 @@ def pyOpenRPA_ServerData(inRequest,inGSettings): lServerDataDict = { "CPDict": HiddenCPDictGenerate(inRequest=inRequest, inGSettings=inGSettings), "RDPDict": HiddenRDPDictGenerate(inRequest=inRequest, inGSettings=inGSettings), - "UserDict": {} + "UserDict": {"RoleHierarchyDict": inRequest.OpenRPA["DefUserRoleHierarchyGet"]()} } # Create JSON lServerDataDictJSONStr = json.dumps(lServerDataDict) @@ -106,165 +109,9 @@ def pyOpenRPA_ServerData(inRequest,inGSettings): return lResult -# /Orchestrator/RobotRDPActive/ControlPanelDictGet -def RobotRDPActive_ControlPanelDictGet(inRequest,inGlobalDict): - inResponseDict = inRequest.OpenRPAResponseDict - lResultDict = { - "DataList":[ - # {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} - ] - } - # Iterate throught the RDP List - for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]: - lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][lRDPSessionKeyStrItem] # Get the configuration dict - lDataItemDict = {"SessionKeyStr":"", "SessionHexStr": "", "IsFullScreenBool": False, "IsIgnoredBool": False} # Template - lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str - lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex - lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"]["FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window - lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored - lResultDict["DataList"].append(lDataItemDict) - # Send message back to client - message = json.dumps(lResultDict) - # Write content as utf-8 data - inResponseDict["Body"] = bytes(message, "utf8") -# def to check control panels for selected session -def Monitor_ControlPanelDictGet_SessionCheckInit(inRequest,inGlobalDict): - lL = inGlobalDict["Logger"] # Alias for logger - lLifetimeSecFloat = inGlobalDict["Client"]["Session"]["LifetimeSecFloat"] - lLifetimeRequestSecFloat = inGlobalDict["Client"]["Session"]["LifetimeRequestSecFloat"] - lControlPanelRefreshIntervalSecFloat = inGlobalDict["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"] - lCookieSessionGUIDStr = None # generate the new GUID - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # Technicaldef - interval check control panels + check actuality of the session by the datetime - def TechnicalCheck(): - lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] - # Lifetime is ok - check control panel - lDatasetCurrentBytes = Monitor_ControlPanelDictGet(inRequest,inGlobalDict) # Call the control panel - if lDatasetCurrentBytes != lItemValue["DatasetLast"]["ControlPanel"]["Data"]: # Check if dataset is changed - lItemValue["DatasetLast"]["ControlPanel"]["Data"] = lDatasetCurrentBytes # Set new datset - lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] = True # Set flag to return the data - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - # Technicaldef - Create new session struct - def TechnicalSessionNew(inSessionGUIDStr): - lCookieSessionGUIDStr = inSessionGUIDStr # Generate the new GUID - lSessionNew = { # Session with some GUID str. On client session guid stored in cookie "SessionGUIDStr" - "InitDatetime": datetime.datetime.now(), # Datetime when session GUID was created - "DatasetLast": { - "ControlPanel": { - "Data": None, # Struct to check with new iterations. None if starts - "ReturnBool": False # flag to return, close request and return data as json - } - }, - "ClientRequestHandler": inRequest, # Last client request handler - "UserADStr": inRequest.OpenRPA["User"], # User, who connect. None if user is not exists - "DomainADStr": inRequest.OpenRPA["Domain"], # Domain of the user who connect. None if user is not exists - } - inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] = lSessionNew # Set new session in dict - inRequest.OpenRPAResponseDict["SetCookies"]["SessionGUIDStr"] = lCookieSessionGUIDStr # Set SessionGUIDStr in cookies - if lL: lL.info(f"New session GUID is created. GUID {lCookieSessionGUIDStr}") - return lCookieSessionGUIDStr - # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # - lCreateNewSessionBool = False # Flag to create new session structure - # step 1 - get cookie SessionGUIDStr - lSessionGUIDStr = inRequest.headers.get("SessionGUIDStr", None) - if lSessionGUIDStr is not None: # Check if GUID session is ok - #inRequest.OpenRPAResponseDict["StatusCode"] = 301 - #inRequest.OpenRPAResponseDict["Headers"]["Location"] = "/" - #if lL: lL.info(f"GUID is detected - send HTTP 301 to refresh page") - lCookieSessionGUIDStr = lSessionGUIDStr # Get the existing GUID - if lSessionGUIDStr not in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: - lCookieSessionGUIDStr= TechnicalSessionNew(inSessionGUIDStr = lSessionGUIDStr) # Create new session - else: # Update the datetime of the request session - inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr]["InitDatetime"]=datetime.datetime.now() - else: - lCookieSessionGUIDStr = TechnicalSessionNew(inSessionGUIDStr = lSessionGUIDStr) # Create new session - # Init the RobotRDPActive in another thread - #lThreadCheckCPInterval = threading.Thread(target=TechnicalIntervalCheck) - #lThreadCheckCPInterval.daemon = True # Run the thread in daemon mode. - #lThreadCheckCPInterval.start() # Start the thread execution. - - # Step 2 - interval check if data is exist - lTimeStartSecFloat = time.time() - lDoWhileBool = True # Flag to iterate throught the lifetime of the request - while lDoWhileBool: - #print(lTechnicalSessionGUIDCache) - #print(lCookieSessionGUIDStr) - if lCookieSessionGUIDStr in inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"]: - lItemValue = inGlobalDict["Client"]["Session"]["TechnicalSessionGUIDCache"][lCookieSessionGUIDStr] - if (time.time() - lTimeStartSecFloat) >= lLifetimeRequestSecFloat: # Check if lifetime client request is over or has no key - if lL: lL.debug(f"Client request lifetime is over") - lDoWhileBool = False # Stop the iterations - if lDoWhileBool: - TechnicalCheck() # Calculate the CP - if lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] == True: # Return data if data flag it True - lDatasetCurrentBytes = lItemValue["DatasetLast"]["ControlPanel"]["Data"] # Set new dataset - inResponseDict = inRequest.OpenRPAResponseDict - inResponseDict["Body"] = lDatasetCurrentBytes - lItemValue["DatasetLast"]["ControlPanel"]["ReturnBool"] = False # Set flag that data was returned - lDoWhileBool = False # Stop the iterations - else: - lCookieSessionGUIDStr = TechnicalSessionNew(inSessionGUIDStr = lCookieSessionGUIDStr) # Create new session - if lDoWhileBool: # Sleep if we wait hte next iteration - time.sleep(lControlPanelRefreshIntervalSecFloat) # Sleep to the next iteration - -def Monitor_ControlPanelDictGet(inRequest,inGlobalDict): - inResponseDict = inRequest.OpenRPAResponseDict - lL = inGlobalDict["Logger"] # Alias for logger - # Create result JSON - lResultJSON = {"RenderRobotList": [], "RenderRDPList": []} - lRenderFunctionsRobotList = inGlobalDict["ControlPanelDict"]["RobotList"] - for lItem in lRenderFunctionsRobotList: - lUACBool = True # Check if render function is applicable User Access Rights (UAC) - if inGlobalDict["Server"]["AccessUsers"]["FlagCredentialsAsk"] is True: - lUserRights = inGlobalDict["Server"]["AccessUsers"]["RuleDomainUserDict"][(inRequest.OpenRPA["Domain"].upper(),inRequest.OpenRPA["User"].upper())] - if len(lUserRights["ControlPanelKeyAllowedList"]) > 0 and lItem["KeyStr"] not in lUserRights["ControlPanelKeyAllowedList"]: - lUACBool = False # UAC Check is not passed - False for user - if lUACBool: # Run function if UAC is TRUE - # Выполнить вызов и записать результат - # Call def (inRequest, inGSettings) or def (inGSettings) - lItemResultDict = None - lDEFSignature = signature(lItem["RenderFunction"]) # Get signature of the def - lDEFARGLen = len(lDEFSignature.parameters.keys()) # get count of the def args - try: - if lDEFARGLen == 1: # def (inGSettings) - lItemResultDict = lItem["RenderFunction"](inGlobalDict) - elif lDEFARGLen == 2: # def (inRequest, inGSettings) - lItemResultDict = lItem["RenderFunction"](inRequest, inGlobalDict) - elif lDEFARGLen == 0: # def () - lItemResultDict = lItem["RenderFunction"]() - # RunFunction - lResultJSON["RenderRobotList"].append(lItemResultDict) - except Exception as e: - if lL: lL.exception(f"Error in control panel. CP item {lItem}. Exception is below") - # Iterate throught the RDP list - for lRDPSessionKeyStrItem in inGlobalDict["RobotRDPActive"]["RDPList"]: - lRDPConfiguration = inGlobalDict["RobotRDPActive"]["RDPList"][ - lRDPSessionKeyStrItem] # Get the configuration dict - lDataItemDict = {"SessionKeyStr": "", "SessionHexStr": "", "IsFullScreenBool": False, - "IsIgnoredBool": False} # Template - lDataItemDict["SessionKeyStr"] = lRDPSessionKeyStrItem # Session key str - lDataItemDict["SessionHexStr"] = lRDPConfiguration["SessionHex"] # Session Hex - lDataItemDict["IsFullScreenBool"] = True if lRDPSessionKeyStrItem == inGlobalDict["RobotRDPActive"][ - "FullScreenRDPSessionKeyStr"] else False # Check the full screen for rdp window - lDataItemDict["IsIgnoredBool"] = lRDPConfiguration["SessionIsIgnoredBool"] # Is ignored - lResultJSON["RenderRDPList"].append(lDataItemDict) - # Send message back to client - message = json.dumps(lResultJSON) - # Write content as utf-8 data - #inResponseDict["Body"] = bytes(message, "utf8") - return bytes(message, "utf8") -# UserAccess get rights hierarchy dict in json -def UserRoleHierarchyGet(inRequest,inGlobalDict): - inResponseDict = inRequest.OpenRPAResponseDict - # Create result JSON - lResultDict = inRequest.OpenRPA["DefUserRoleHierarchyGet"]() # Get the User Role Hierarchy list - # Send message back to client - message = json.dumps(lResultDict) - # Write content as utf-8 data - inResponseDict["Body"] = bytes(message, "utf8") -def GetScreenshot(inRequest,inGlobalDict): +def pyOpenRPA_Screenshot(inRequest,inGlobalDict): # Get Screenshot def SaveScreenshot(inFilePath): # grab fullscreen @@ -306,11 +153,13 @@ def SettingsUpdate(inGlobalConfiguration): {"Method":"GET", "URL": "/3rdParty/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.woff2", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\themes\\default\\assets\\fonts\\icons.woff2"), "ResponseContentType": "font/woff2"}, {"Method":"GET", "URL": "/favicon.ico", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\favicon.ico"), "ResponseContentType": "image/x-icon"}, {"Method":"GET", "URL": "/3rdParty/Handlebars/handlebars-v4.1.2.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Handlebars\\handlebars-v4.1.2.js"), "ResponseContentType": "application/javascript"}, - {"Method": "GET", "URL": "/Monitor/ControlPanelDictGet", "MatchType": "Equal", "ResponseDefRequestGlobal": Monitor_ControlPanelDictGet_SessionCheckInit, "ResponseContentType": "application/json"}, - {"Method": "GET", "URL": "/GetScreenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": GetScreenshot, "ResponseContentType": "image/png"}, + {"Method": "GET", "URL": "/Monitor/ControlPanelDictGet", "MatchType": "Equal", "ResponseDefRequestGlobal": BackwardCompatibility.v1_2_0_Monitor_ControlPanelDictGet_SessionCheckInit, "ResponseContentType": "application/json"}, + {"Method": "GET", "URL": "/GetScreenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": pyOpenRPA_Screenshot, "ResponseContentType": "image/png"}, {"Method": "GET", "URL": "/pyOpenRPA_logo.png", "MatchType": "Equal", "ResponseFilePath": os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\pyOpenRPA_logo.png"), "ResponseContentType": "image/png"}, - {"Method": "POST", "URL": "/Orchestrator/UserRoleHierarchyGet", "MatchType": "Equal","ResponseDefRequestGlobal": UserRoleHierarchyGet, "ResponseContentType": "application/json"}, - {"Method": "POST", "URL": "/pyOpenRPA/ServerData", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerData, "ResponseContentType": "application/json"} + {"Method": "POST", "URL": "/Orchestrator/UserRoleHierarchyGet", "MatchType": "Equal","ResponseDefRequestGlobal": BackwardCompatibility.v1_2_0_UserRoleHierarchyGet, "ResponseContentType": "application/json"}, + # New way of the v.1.2.0 functionallity (all defs by the URL from /pyOpenRPA/...) + {"Method": "POST", "URL": "/pyOpenRPA/ServerData", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerData, "ResponseContentType": "application/json"}, + {"Method": "GET", "URL": "/pyOpenRPA/Screenshot", "MatchType": "BeginWith", "ResponseDefRequestGlobal": pyOpenRPA_Screenshot, "ResponseContentType": "image/png"}, ] inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList return inGlobalConfiguration \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml b/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml index 672fda6c..7d948b0d 100644 --- a/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml +++ b/Sources/pyOpenRPA/Orchestrator/Web/Index.xhtml @@ -116,114 +116,81 @@
-
-

- -
- Administration -
-

- - - -
-
- + +