diff --git a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py index 36198815..4e8eb416 100644 --- a/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py +++ b/Sources/pyOpenRPA/Orchestrator/BackwardCompatibility.py @@ -398,9 +398,17 @@ def Update(inGSettings): if "ActivityTimeCheckLoopSeconds" in inGSettings["Scheduler"]: inGSettings["SchedulerDict"]["CheckIntervalSecFloat"] = inGSettings["Scheduler"]["ActivityTimeCheckLoopSeconds"] for lItemDict in inGSettings["Scheduler"]["ActivityTimeList"]: - lItemDict["ActivityList"]=[v1_2_0_ProcessorOld2NewActivityDict(inActivityOld=lItemDict["Activity"])] - del lItemDict["Activity"] - inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict) + # Append to the new struct if this is not periodic ("TimeHH:MMStart"and "TimeHH:MMStop") + if "TimeHH:MMStart" not in lItemDict and "TimeHH:MMStop" not in lItemDict: + lItemDict["ActivityList"]=[v1_2_0_ProcessorOld2NewActivityDict(inActivityOld=lItemDict["Activity"])] + del lItemDict["Activity"] + inGSettings["SchedulerDict"]["ActivityTimeList"].append(lItemDict) # Remove old structure Scheduler del inGSettings["Scheduler"] if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert Scheduler to SchedulerDict with new features") # Log about compatibility + # Check if Server is active > convert to ServerDict + if "Server" in inGSettings: + inGSettings["ServerDict"]=inGSettings["Server"] + # Remove old structure Scheduler + del inGSettings["Server"] + if lL: lL.warning(f"Backward compatibility (v1.1.20 to v1.2.0): Convert Server to ServerDict") # Log about compatibility diff --git a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py index 7130e478..e338f268 100644 --- a/Sources/pyOpenRPA/Orchestrator/Orchestrator.py +++ b/Sources/pyOpenRPA/Orchestrator/Orchestrator.py @@ -170,8 +170,8 @@ def UACKeyListCheck(inRequest, inRoleKeyList): # Update user access def UACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inURLList=[], inCPAllowKeyList=[], inRoleHierarchyAllowedDict={}): - lUserTurple = (inADStr.upper(),inADLoginStr.upper()) # Create turple key for inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"] - if inURLList==[] and lUserTurple not in inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"]: # Backward compatibility if user is not exist + lUserTurple = (inADStr.upper(),inADLoginStr.upper()) # Create turple key for inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"] + if inURLList==[] and lUserTurple not in inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"]: # Backward compatibility if user is not exist inURLList=[ { "Method": "GET", @@ -189,8 +189,8 @@ def UACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inU } ] # Check RoleHierarchyAllowedDict in gSettings for the old role hierarchy - include in result. - if lUserTurple in inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"] and "RoleHierarchyAllowedDict" in inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][lUserTurple]: - lRoleHierarchyAllowedOLDDict = inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"][lUserTurple]["RoleHierarchyAllowedDict"] + if lUserTurple in inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"] and "RoleHierarchyAllowedDict" in inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lUserTurple]: + lRoleHierarchyAllowedOLDDict = inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"][lUserTurple]["RoleHierarchyAllowedDict"] Server.__ComplexDictMerge2to1__(in1Dict=inRoleHierarchyAllowedDict, in2Dict=lRoleHierarchyAllowedOLDDict) # Merge dict 2 into dict 1 # Create Access item @@ -199,16 +199,16 @@ def UACUpdate(inGSettings, inADLoginStr, inADStr="", inADIsDefaultBool=True, inU "RoleHierarchyAllowedDict": inRoleHierarchyAllowedDict } # Case add domain + user - inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"].update({(inADStr.upper(),inADLoginStr.upper()):lRuleDomainUserDict}) + inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"].update({(inADStr.upper(),inADLoginStr.upper()):lRuleDomainUserDict}) if inADIsDefaultBool: # Case add default domain + user - inGSettings["Server"]["AccessUsers"]["RuleDomainUserDict"].update({("",inADLoginStr.upper()):lRuleDomainUserDict}) + inGSettings["ServerDict"]["AccessUsers"]["RuleDomainUserDict"].update({("",inADLoginStr.upper()):lRuleDomainUserDict}) # Add supertoken for the all access (it is need for the robot communication without human) def UACSuperTokenUpdate(inGSettings, inSuperTokenStr): lLoginStr = "SUPERTOKEN" UACUpdate(inGSettings=inGSettings, inADLoginStr=lLoginStr) - inGSettings["Server"]["AccessUsers"]["AuthTokensDict"].update( + inGSettings["ServerDict"]["AccessUsers"]["AuthTokensDict"].update( {inSuperTokenStr:{"User":lLoginStr, "Domain":"", "TokenDatetime": datetime.datetime.now(), "FlagDoNotExpire":True}} ) @@ -216,6 +216,63 @@ def UACSuperTokenUpdate(inGSettings, inSuperTokenStr): # OrchestratorWeb defs # # # # # # # # # # # # # # # # # # # # # # # +# Connect URL to DEF +# "inMethodStr":"GET|POST", +# "inURLStr": "/index", #URL of the request +# "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", +# "inContentTypeStr": "", #HTTP Content-type +# "inDef": None #Function with str result +def WebURLConnectDef(inGSettings, inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentTypeStr="application/octet-stream"): + lURLItemDict = { + "Method": inMethodStr.upper(), + "URL": inURLStr, # URL of the request + "MatchType": inMatchTypeStr, # "BeginWith|Contains|Equal|EqualCase", + # "ResponseFilePath": "", #Absolute or relative path + #"ResponseFolderPath": "C:\Abs\Archive\scopeSrcUL\OpenRPA\Orchestrator\Settings", + # Absolute or relative path + "ResponseContentType": inContentTypeStr, #HTTP Content-type + "ResponseDefRequestGlobal": inDef #Function with str result + } + inGSettings["ServerDict"]["URLList"].append(lURLItemDict) + +# Connect URL to Folder +# "inMethodStr":"GET|POST", +# "inURLStr": "/Folder/", #URL of the request +# "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", +# "inFolderPathStr": "", #Absolute or relative path +def WebURLConnectFolder(inGSettings, inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr): + # Check if last symbol is "/" - append if not exist + lFolderPathStr = os.path.abspath(inFolderPathStr) + if lFolderPathStr[-1]!="/":lFolderPathStr+="/" + # Prepare URLItem + lURLItemDict = { + "Method": inMethodStr.upper(), + "URL": inURLStr, # URL of the request + "MatchType": inMatchTypeStr, # "BeginWith|Contains|Equal|EqualCase", + # "ResponseFilePath": "", #Absolute or relative path + "ResponseFolderPath": lFolderPathStr, # Absolute or relative path + "ResponseContentType": "application/octet-stream", #HTTP Content-type + #"ResponseDefRequestGlobal": inDef #Function with str result + } + inGSettings["ServerDict"]["URLList"].append(lURLItemDict) + +# Connect URL to File +# "inMethodStr":"GET|POST", +# "inURLStr": "/index", #URL of the request +# "inMatchTypeStr": "", #"BeginWith|Contains|Equal|EqualCase", +# "inFolderPathStr": "", #Absolute or relative path +def WebURLConnectFile(inGSettings, inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inContentTypeStr="application/octet-stream"): + lURLItemDict = { + "Method": inMethodStr.upper(), + "URL": inURLStr, # URL of the request + "MatchType": inMatchTypeStr, # "BeginWith|Contains|Equal|EqualCase", + "ResponseFilePath": os.path.abspath(inFilePathStr), #Absolute or relative path + #"ResponseFolderPath": os.path.abspath(inFilePathStr), # Absolute or relative path + "ResponseContentType": inContentTypeStr, #HTTP Content-type + #"ResponseDefRequestGlobal": inDef #Function with str result + } + inGSettings["ServerDict"]["URLList"].append(lURLItemDict) + # Add control panel HTML, JSON generator or JS when page init def WebCPUpdate(inGSettings, inCPKeyStr, inHTMLRenderDef=None, inJSONGeneratorDef=None, inJSInitGeneratorDef=None): # Create Struct if the re is current key @@ -409,45 +466,71 @@ def SchedulerActivityTimeAddWeekly(inGSettings, inTimeHHMMStr="23:55:", inWeekda # RDPSession # # # # # # # # # # # # # # # # # # # # # # # -# Create new RDPSession in RobotRDPActive -def RDPSessionConnect(inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr): +# Create some RDP template dict to use it when connect/reconnect +def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortInt = 3389, inWidthPXInt = 1680, inHeightPXInt = 1050, + inUseBothMonitorBool = False, inDepthBitInt = 32, inSharedDriveList=["c"]): + lRDPTemplateDict= { # Init the configuration item + "Host": inHostStr, # Host address, example "77.77.22.22" + "Port": str(inPortInt), # RDP Port, example "3389" + "Login": inLoginStr, # Login, example "test" + "Password": inPasswordStr, # Password, example "test" + "Screen": { + "Width": inWidthPXInt, # Width of the remote desktop in pixels, example 1680 + "Height": inHeightPXInt, # Height of the remote desktop in pixels, example 1050 + # "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen, example + "FlagUseAllMonitors": inUseBothMonitorBool, # True or False, example False + "DepthBit": str(inDepthBitInt) # "32" or "24" or "16" or "15", example "32" + }, + "SharedDriveList": inSharedDriveList, # List of the Root sesion hard drives, example ["c"] + ###### Will updated in program ############ + "SessionHex": "77777sdfsdf77777dsfdfsf77777777", # Hex is created when robot runs, example "" + "SessionIsWindowExistBool": False, + # Flag if the RDP window is exist, old name "FlagSessionIsActive". Check every n seconds , example False + "SessionIsWindowResponsibleBool": False, + # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False + "SessionIsIgnoredBool": False # Flag to ignore RDP window False - dont ignore, True - ignore, example False + } + return lRDPTemplateDict + +# Search dublicates in GSettings RDPlist TODO! +# Return list if dublicates +def RDPSessionDublicatesResolve(inGSettings): + pass + #for lItemKeyStr in inGSettings["RobotRDPActive"]["RDPList"]: + # lItemDict = inGSettings["RobotRDPActive"]["RDPList"][lItemKeyStr] + + +# Create new RDPSession in RobotRDPActive. Attention - activity will be ignored if key is exists +# 2 way of the use +# Var 1: inGSettings, inRDPSessionKeyStr, inRDPTemplateDict +# Var 2 (Backward compatibility): inGSettings, inRDPSessionKeyStr, inHostStr, inPortStr, inLoginStr, inPasswordStr +def RDPSessionConnect(inGSettings, inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None, inPortStr=None, inLoginStr=None, inPasswordStr=None): # Check thread if not Core.IsProcessorThread(inGSettings=inGSettings): if inGSettings["Logger"]: inGSettings["Logger"].warning(f"RDP def was called not from processor queue - activity will be append in the processor queue.") lResult = { "Def": RDPSessionConnect, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) "ArgList": [], # Args list - "ArgDict": {"inRDPSessionKeyStr": inRDPSessionKeyStr, "inHostStr": inHostStr, "inPortStr": inPortStr, - "inLoginStr": inLoginStr, "inPasswordStr": inPasswordStr, }, # Args dictionary + "ArgDict": {"inRDPSessionKeyStr": inRDPSessionKeyStr, "inRDPTemplateDict":inRDPTemplateDict, "inHostStr": inHostStr, "inPortStr": inPortStr, + "inLoginStr": inLoginStr, "inPasswordStr": inPasswordStr}, # Args dictionary "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) } inGSettings["ProcessorDict"]["ActivityList"].append(lResult) else: # In processor - do execution - # ATTENTION - dont connect if RDP session is exist + # Var 1 - if RDPTemplateDict is input + lRDPConfigurationItem=inRDPTemplateDict + # Var 2 - backward compatibility + if lRDPConfigurationItem is None: + lRDPConfigurationItem = RDPTemplateCreate(inLoginStr=inLoginStr, inPasswordStr=inPasswordStr, + inHostStr=inHostStr, inPortInt = int(inPortStr)) # ATTENTION - dont connect if RDP session is exist + # Start the connect if inRDPSessionKeyStr not in inGSettings["RobotRDPActive"]["RDPList"]: - lRDPConfigurationItem = { # Init the configuration item - "Host": inHostStr, # Host address, example "77.77.22.22" - "Port": inPortStr, # RDP Port, example "3389" - "Login": inLoginStr, # Login, example "test" - "Password": inPasswordStr, # Password, example "test" - "Screen": { - "Width": 1680, # Width of the remote desktop in pixels, example 1680 - "Height": 1050, # Height of the remote desktop in pixels, example 1050 - # "640x480" or "1680x1050" or "FullScreen". If Resolution not exists set full screen, example - "FlagUseAllMonitors": False, # True or False, example False - "DepthBit": "32" # "32" or "24" or "16" or "15", example "32" - }, - "SharedDriveList": ["c"], # List of the Root sesion hard drives, example ["c"] - ###### Will updated in program ############ - "SessionHex": "77777sdfsdf77777dsfdfsf77777777", # Hex is created when robot runs, example "" - "SessionIsWindowExistBool": False, # Flag if the RDP window is exist, old name "FlagSessionIsActive". Check every n seconds , example False - "SessionIsWindowResponsibleBool": False, # Flag if RDP window is responsible (recieve commands). Check every nn seconds. If window is Responsible - window is Exist too , example False - "SessionIsIgnoredBool": False # Flag to ignore RDP window False - dont ignore, True - ignore, example False - } inGSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] = lRDPConfigurationItem # Add item in RDPList Connector.Session(lRDPConfigurationItem) # Create the RDP session Connector.SystemRDPWarningClickOk() # Click all warning messages + else: + if inGSettings["Logger"]: inGSettings["Logger"].warning(f"RDP session was not created because it is alredy exists in the RDPList. Use RDPSessionReconnect if you want to update RDP configuration.") return True # Disconnect the RDP session @@ -476,14 +559,14 @@ def RDPSessionDisconnect(inGSettings, inRDPSessionKeyStr, inBreakTriggerProcessW return True # RDP Session reconnect -def RDPSessionReconnect(inGSettings, inRDPSessionKeyStr): +def RDPSessionReconnect(inGSettings, inRDPSessionKeyStr, inRDPTemplateDict=None): # Check thread if not Core.IsProcessorThread(inGSettings=inGSettings): if inGSettings["Logger"]: inGSettings["Logger"].warning(f"RDP def was called not from processor queue - activity will be append in the processor queue.") lResult = { "Def": RDPSessionReconnect, # def link or def alias (look gSettings["Processor"]["AliasDefDict"]) "ArgList": [], # Args list - "ArgDict": {"inRDPSessionKeyStr": inRDPSessionKeyStr }, # Args dictionary + "ArgDict": {"inRDPSessionKeyStr": inRDPSessionKeyStr, "inRDPTemplateDict":inRDPTemplateDict }, # Args dictionary "ArgGSettings": "inGSettings", # Name of GSettings attribute: str (ArgDict) or index (for ArgList) "ArgLogger": None # Name of GSettings attribute: str (ArgDict) or index (for ArgList) } @@ -491,6 +574,8 @@ def RDPSessionReconnect(inGSettings, inRDPSessionKeyStr): else: lRDPConfigurationItem = inGSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] RDPSessionDisconnect(inRDPSessionKeyStr=inRDPSessionKeyStr) # Disconnect the RDP + # Replace Configuration item if inRDPTemplateDict exists + if inRDPTemplateDict is not None: lRDPConfigurationItem=inRDPTemplateDict # Add item in RDPList inGSettings["RobotRDPActive"]["RDPList"][inRDPSessionKeyStr] = lRDPConfigurationItem # Create the RDP session @@ -748,7 +833,7 @@ def Orchestrator(inGSettings): lDaemonLoopSeconds=gSettingsDict["SchedulerDict"]["CheckIntervalSecFloat"] lDaemonActivityLogDict={} #Словарь отработанных активностей, ключ - кортеж (, , , ) lDaemonLastDateTime=datetime.datetime.now() - gSettingsDict["Server"]["WorkingDirectoryPathStr"] = os.getcwd() # Set working directory in g settings + gSettingsDict["ServerDict"]["WorkingDirectoryPathStr"] = os.getcwd() # Set working directory in g settings # Init SettingsUpdate defs from file list (after RDP restore) lSettingsUpdateFilePathList = gSettingsDict.get("OrchestratorStart", {}).get("DefSettingsUpdatePathList",[]) @@ -858,25 +943,6 @@ def Orchestrator(inGSettings): lThread = threading.Thread(target=Processor.ActivityListExecute, kwargs={"inGSettings": inGSettings, "inActivityList":lItem["ActivityList"]}) lThread.start() lIterationLastDateTime = datetime.datetime.now() # Set the new datetime for the new processor activity - ####################################################################### - #Branch 2 - if TimeHH:MMStart, TimeHH:MMStop, ActivityIntervalSeconds - ####################################################################### - if "TimeHH:MMStart" in lItem and "TimeHH:MMStop" in lItem and "ActivityIntervalSeconds" in lItem: - #Сформировать временной штамп, относительно которого надо будет проверять время - #часовой пояс пока не учитываем - lActivityDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStart"],"%H:%M") - lActivityDateTime=lActivityDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - lActivityTimeEndDateTime=datetime.datetime.strptime(lItem["TimeHH:MMStop"],"%H:%M") - lActivityTimeEndDateTime=lActivityTimeEndDateTime.replace(year=lCurrentDateTime.year,month=lCurrentDateTime.month,day=lCurrentDateTime.day) - #Убедиться в том, что время наступило - if ( - lCurrentDateTime=lActivityDateTime and - (lGUID,lActivityDateTime) not in lDaemonActivityLogDict): - #Запись в массив отработанных активностей - lDaemonActivityLogDict[(lGUID,lActivityDateTime)]={"ActivityStartDateTime":lCurrentDateTime, "ActivityEndDateTime":lActivityTimeEndDateTime} - #Запуск циклической процедуры - Timer.activityLoopStart(lItem["ActivityIntervalSeconds"], lActivityTimeEndDateTime, lItem["Activity"]) except Exception as e: if lL: lL.exception(f"Scheduler: Exception has been catched in Scheduler module when activity time item was initialising. ActivityTimeItem is {lItem}") lDaemonLastDateTime = lIterationLastDateTime # Set the new datetime for the new processor activity diff --git a/Sources/pyOpenRPA/Orchestrator/Server.py b/Sources/pyOpenRPA/Orchestrator/Server.py index 81f9785b..a158a70b 100644 --- a/Sources/pyOpenRPA/Orchestrator/Server.py +++ b/Sources/pyOpenRPA/Orchestrator/Server.py @@ -58,10 +58,10 @@ def AuthenticateVerify(inRequest): lCookieAuthToken = lCookies.get("AuthToken", "").value if lCookieAuthToken: #Find AuthToken in GlobalDict - if lCookieAuthToken in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): + if lCookieAuthToken in gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): #Auth Token Has Been Founded - lResult["Domain"] = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] - lResult["User"] = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] + lResult["Domain"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] + lResult["User"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] #Set auth token inRequest.OpenRPA["AuthToken"] = lCookieAuthToken inRequest.OpenRPA["Domain"] = lResult["Domain"] @@ -95,11 +95,11 @@ def AuthenticateVerify(inRequest): lResult["User"] = lLogonResult["User"] #Create token lAuthToken=str(uuid.uuid1()) - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False - gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False + gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() #Set-cookie inRequest.OpenRPA["AuthToken"] = lAuthToken inRequest.OpenRPA["Domain"] = lResult["Domain"] @@ -140,13 +140,13 @@ def UserAccessCheckBefore(inMethod, inRequest): #go next if user is identified lUserDict = None if lAuthToken: - lUserDict = gSettingsDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] + lUserDict = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken] #pdb.set_trace() ######################################## ######################################## #Check general before rule (without User domain) #Check rules - for lAccessRuleItem in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []): + for lAccessRuleItem in gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleMethodMatchURLBeforeList", []): #Go next execution if flag is false if not lResult: #Check if Method is identical @@ -178,7 +178,7 @@ def UserAccessCheckBefore(inMethod, inRequest): #Check access by User Domain #Check rules to find first appicable #Check rules - for lAccessRuleItem in gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []): + for lAccessRuleItem in gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lUserDict["Domain"].upper(), lUserDict["User"].upper()), {}).get("MethodMatchURLBeforeList", []): #Go next execution if flag is false if not lResult: #Check if Method is identical @@ -237,7 +237,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): def UserRoleHierarchyGet(self): lDomainUpperStr = self.OpenRPA["Domain"].upper() lUserUpperStr = self.OpenRPA["User"].upper() - return gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {}) + return gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {}) #Tech def #return {"headers":[],"body":"","statuscode":111} @@ -350,7 +350,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): ##################################### lFlagAccessUserBlock=False lAuthenticateDict = {"Domain": "", "User": ""} - if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + if gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): lAuthenticateDict = AuthenticateVerify(self) if not lAuthenticateDict["User"]: lFlagAccessUserBlock=True @@ -364,7 +364,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): #################################### lFlagUserAccess = True #If need user authentication - if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + if gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): lFlagUserAccess = UserAccessCheckBefore("GET", self) ###################################### if lFlagUserAccess: @@ -372,7 +372,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): ############################ #New server engine (url from global dict (URLList)) ############################ - for lURLItem in gSettingsDict["Server"]["URLList"]: + for lURLItem in gSettingsDict["ServerDict"]["URLList"]: #Check if all condition are applied lFlagURLIsApplied=False lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET") @@ -422,10 +422,10 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): lFlagAccessUserBlock=False lAuthenticateDict = {"Domain": "", "User": ""} lIsSuperToken = False # Is supertoken - if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + if gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): lAuthenticateDict = AuthenticateVerify(self) # Get Flag is supertoken (True|False) - lIsSuperToken = gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get( + lIsSuperToken = gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get( self.OpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) if not lAuthenticateDict["User"]: lFlagAccessUserBlock=True @@ -437,7 +437,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): #################################### lFlagUserAccess = True #If need user authentication - if gSettingsDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + if gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): lFlagUserAccess = UserAccessCheckBefore("POST", self) ###################################### if lFlagUserAccess: @@ -445,7 +445,7 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): ############################ #New server engine (url from global dict (URLList)) ############################ - for lURLItem in gSettingsDict["Server"]["URLList"]: + for lURLItem in gSettingsDict["ServerDict"]["URLList"]: #Check if all condition are applied lFlagURLIsApplied=False lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST") @@ -489,7 +489,7 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer): daemon_threads = True """Handle requests in a separate thread.""" def finish_request(self, request, client_address): - request.settimeout(gSettingsDict["Server"]["RequestTimeoutSecFloat"]) + request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]) # "super" can not be used because BaseServer is not created from object HTTPServer.finish_request(self, request, client_address) #inGlobalDict @@ -502,7 +502,7 @@ class RobotDaemonServer(Thread): ServerSettings.SettingsUpdate(inGlobalDict) def run(self): inServerAddress=""; - inPort = gSettingsDict["Server"]["ListenPort"]; + inPort = gSettingsDict["ServerDict"]["ListenPort"]; # Server settings # Choose port 8080, for port 80, which is normally used for a http server, you need root access server_address = (inServerAddress, inPort) diff --git a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py index e6c1b4ed..4f702ac5 100644 --- a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py +++ b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py @@ -386,5 +386,5 @@ def SettingsUpdate(inGlobalConfiguration): {"Method": "POST", "URL": "/pyOpenRPA/Agent/O2A", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Agent_O2A, "ResponseContentType": "application/json"}, {"Method": "POST", "URL": "/pyOpenRPA/Agent/A2O", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Agent_A2O, "ResponseContentType": "application/json"}, ] - inGlobalConfiguration["Server"]["URLList"]=inGlobalConfiguration["Server"]["URLList"]+lURLList + inGlobalConfiguration["ServerDict"]["URLList"]=inGlobalConfiguration["ServerDict"]["URLList"]+lURLList return inGlobalConfiguration \ No newline at end of file diff --git a/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py b/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py index e0584b76..9a35c437 100644 --- a/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py +++ b/Sources/pyOpenRPA/Orchestrator/SettingsTemplate.py @@ -37,7 +37,7 @@ def __Create__(): "DumpLogListHashStr": None, # Will be filled automatically # # # # # # # # # # # # # # # # # # }, - "Server": { + "ServerDict": { "WorkingDirectoryPathStr": None, # Will be filled automatically "RequestTimeoutSecFloat": 300, # Time to handle request in seconds "ListenPort_": "Порт, по которому можно подключиться к демону", diff --git a/changelog.md b/changelog.md index c2c82f6d..57d7177f 100644 --- a/changelog.md +++ b/changelog.md @@ -92,6 +92,17 @@ - Scheduler now listen SchedulerDict - def ProcessorActivityItemAppend(inGSettings, inDef, inArgList=[], inArgDict={}, inArgGSettingsStr=None, inArgLoggerStr=None): # Add Activity item in Processor list +! Scheduler period activity was suppressed ("TimeHH:MMStart" in lItem and "TimeHH:MMStop") +- WEB Connect defs +- def WebURLConnectDef(inGSettings, inMethodStr, inURLStr, inMatchTypeStr, inDef, inContentTypeStr="application/octet-stream"): # Connect URL to DEF +- def WebURLConnectFolder(inGSettings, inMethodStr, inURLStr, inMatchTypeStr, inFolderPathStr): # Connect URL to Folder +- def WebURLConnectFile(inGSettings, inMethodStr, inURLStr, inMatchTypeStr, inFilePathStr, inContentTypeStr="application/octet-stream"): # Connect URL to File + +- def RDPTemplateCreate(inLoginStr, inPasswordStr, inHostStr="127.0.0.1", inPortInt = 3389, inWidthPXInt = 1680, inHeightPXInt = 1050, inUseBothMonitorBool = False, inDepthBitInt = 32, inSharedDriveList=["c"]): # Create some RDP template dict to use it when connect/reconnect +- Update def RDPSessionConnect(inGSettings, inRDPSessionKeyStr, inRDPTemplateDict=None, inHostStr=None, inPortStr=None, inLoginStr=None, inPasswordStr=None): # Create new RDPSession in RobotRDPActive. Attention - activity will be ignored if key is exists +- Update def RDPSessionReconnect(inGSettings, inRDPSessionKeyStr, inRDPTemplateDict=None): # RDP Session reconnect + +- Add alg which find dublicates in RDPList if connection lost was appeared - important to catch 2+ RDP to one RDP configs [1.1.0] After 2 month test prefinal with new improovements (+RobotRDPActive in Orchestrator + Easy ControlPanelTemplate) Beta before 1.1.0 (new way of OpenRPA with improvements. Sorry, but no backward compatibility)/ Backward compatibility will start from 1.0.1