From f6ed0cf27aea6cee6cfa91099f73d0e9d42ffae8 Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Fri, 22 Nov 2019 22:13:26 +0300 Subject: [PATCH] #Orchestrator AccessUser for test --- Frameworks available.txt | 3 + Orchestrator/Settings/Settings.py | 17 +- Sources/pyOpenRPA/Orchestrator/Server.py | 229 ++++++++++++++--------- 3 files changed, 158 insertions(+), 91 deletions(-) create mode 100644 Frameworks available.txt diff --git a/Frameworks available.txt b/Frameworks available.txt new file mode 100644 index 00000000..8c29e488 --- /dev/null +++ b/Frameworks available.txt @@ -0,0 +1,3 @@ +iAccessible +iAccessible2 +MSAA \ No newline at end of file diff --git a/Orchestrator/Settings/Settings.py b/Orchestrator/Settings/Settings.py index 02ae51f1..4eb2b2fc 100644 --- a/Orchestrator/Settings/Settings.py +++ b/Orchestrator/Settings/Settings.py @@ -76,14 +76,19 @@ def Settings(): "URL": "http://127.0.0.1:8081" } ], - "AccessUsers": { + "AccessUsers": { #Defaul - all URL is blocked "FlagCredentialsAsk": True, #Turn on Authentication - "FlagNoRulesBlock": True, #Block request, if user has no rules for requested URL (if FlagCredentialAsk is turned on) - "UserDict": { + "RuleDict": { #("Domain", "User"): { - # "FunctionDict": { - # # ("Method|GET|POST", "Match type|BeginWith|Contains", "URL"): def function (inRequest, inGlobalDict, inAuthenticateDict) - # } + # "MethodMatchURLBeforeList": [ + # { + # "Method":"GET|POST", + # "MatchType":"BeginWith|Contains|Equal|EqualCase", + # "URL":"", + # "FlagAccessDefRequestGlobalAuthenticate": None, #Return bool + # "FlagAccess": True + # } + # ] #} }, "AuthTokensDict": { diff --git a/Sources/pyOpenRPA/Orchestrator/Server.py b/Sources/pyOpenRPA/Orchestrator/Server.py index fa7d8484..edbb9aa2 100644 --- a/Sources/pyOpenRPA/Orchestrator/Server.py +++ b/Sources/pyOpenRPA/Orchestrator/Server.py @@ -111,6 +111,50 @@ def AuthenticateBlock(inRequest): inRequest.end_headers() # Write content as utf-8 data inRequest.wfile.write(bytes("", "utf8")) +#Check access before execute the action +#return bool True - go execute, False - dont execute +def UserAccessCheckBefore(inMethod, inRequest): + # Help def - Get access flag from dict + def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict): + if "FlagAccess" in inAccessRuleItem: + return inAccessRuleItem["FlagAccess"] + elif "FlagAccessDefRequestGlobalAuthenticate" in inAccessRuleItem: + return inAccessRuleItem["FlagAccessDefRequestGlobalAuthenticate"](inRequest, inGlobalDict, + inAuthenticateDict) + ########################################## + inMethod=inMethod.upper() + #Prepare result false + lResult = False + #Check rules to find first appicable + lAuthToken = inRequest.OpenRPA["AuthToken"] + #go next if user is identified + lUserDict = None + if lAuthToken: + lUserDict = mGlobalDict["Server"]["AccessUsers"]["AuthTokensDict"][lAuthToken] + #Check rules + for lAccessRuleItem in mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("RuleDict", {}).get((lUserDict["Domain"], lUserDict["User"]), {}).get("MethodMatchURLBeforeList", []): + #Go next execution if flag is false + if not lResult: + #Check if Method is identical + if lAccessRuleItem["Method"].upper() == inMethod: + #check Match type variant: BeginWith + if lAccessRuleItem["MatchType"].upper() == "BEGINWITH": + if inRequest.path.startswith(lAccessRuleItem["URL"]): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + #check Match type variant: Contains + elif lAccessRuleItem["MatchType"].upper() == "CONTAINS": + if inRequest.path.contains(lAccessRuleItem["URL"]): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: Equal + elif lAccessRuleItem["MatchType"].upper() == "EQUAL": + if lAccessRuleItem["URL"].upper() == inRequest.path.upper(): + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + # check Match type variant: EqualCase + elif lAccessRuleItem["MatchType"].upper() == "EQUALCASE": + if lAccessRuleItem["URL"] == inRequest.path: + lResult = HelpGetFlag(lAccessRuleItem, inRequest, mGlobalDict, lUserDict) + #Return lResult + return lResult # HTTPRequestHandler class class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): #ResponseContentTypeFile @@ -144,72 +188,79 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): AuthenticateBlock(self) ##################################### else: - lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) - #Мост между файлом и http запросом (новый формат) - if self.path == "/": - self.SendResponseContentTypeFile('text/html', os.path.join(lOrchestratorFolder, "Web\\Index.xhtml")) - #Мост между файлом и http запросом (новый формат) - if self.path == '/3rdParty/Semantic-UI-CSS-master/semantic.min.css': - self.SendResponseContentTypeFile('text/css', os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.css")) - #Мост между файлом и http запросом (новый формат) - if self.path == '/3rdParty/Semantic-UI-CSS-master/semantic.min.js': - self.SendResponseContentTypeFile('application/javascript', os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.js")) - #Мост между файлом и http запросом (новый формат) - if self.path == '/3rdParty/jQuery/jquery-3.1.1.min.js': - self.SendResponseContentTypeFile('application/javascript', os.path.join(lOrchestratorFolder,"..\\Resources\\Web\\jQuery\\jquery-3.1.1.min.js")) - #Мост между файлом и http запросом (новый формат) - if self.path == '/3rdParty/Google/LatoItalic.css': - self.SendResponseContentTypeFile('font/css', os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Google\\LatoItalic.css")) - #Мост между файлом и http запросом (новый формат) - if self.path == '/3rdParty/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.woff2': - self.SendResponseContentTypeFile('font/woff2', os.path.join(lOrchestratorFolder,"..\\Resources\\Web\\Semantic-UI-CSS-master\\themes\\default\\assets\\fonts\\icons.woff2")) - #Мост между файлом и http запросом (новый формат) - if self.path == '/favicon.ico': - self.SendResponseContentTypeFile('image/x-icon', os.path.join(lOrchestratorFolder, "Web\\favicon.ico")) - #Мост между файлом и http запросом (новый формат) - if self.path == '/3rdParty/Handlebars/handlebars-v4.1.2.js': - self.SendResponseContentTypeFile('application/javascript', os.path.join(lOrchestratorFolder,"..\\Resources\\Web\\Handlebars\\handlebars-v4.1.2.js")) - #Получить скриншот - if self.path.split("?")[0] == '/GetScreenshot': - #Сохранить файл на диск - SaveScreenshot("Screenshot.png") - self.SendResponseContentTypeFile('image/png',"Screenshot.png") - #Monitor - if self.path == '/Monitor/JSONDaemonListGet': - # Send response status code - self.send_response(200) - # Send headers - self.send_header('Content-type','application/json') - self.end_headers() - # Send message back to client - message = json.dumps(mGlobalDict) - # Write content as utf-8 data - self.wfile.write(bytes(message, "utf8")) - if self.path == '/Monitor/ControlPanelDictGet': - # Send response status code - self.send_response(200) - # Send headers - self.send_header('Content-type','application/json') - self.end_headers() - #Create result JSON - lResultJSON={"RenderRobotList":[]} - lRenderFunctionsRobotList=mGlobalDict["ControlPanelDict"]["RobotList"] - for lItem in lRenderFunctionsRobotList: - #Выполнить вызов и записать результат - lItemResultDict=lItem["RenderFunction"](mGlobalDict) - #RunFunction - lResultJSON["RenderRobotList"].append(lItemResultDict) - # Send message back to client - message = json.dumps(lResultJSON) - # Write content as utf-8 data - self.wfile.write(bytes(message, "utf8")) - #Filemanager function - if self.path.lower().startswith('/filemanager/'): - lFileURL=self.path[13:] - # check if file in FileURL - File Path Mapping Dict - if lFileURL.lower() in mGlobalDict["FileManager"]["FileURLFilePathDict"]: - self.SendResponseContentTypeFile('application/octet-stream',mGlobalDict["FileManager"]["FileURLFilePathDict"][lFileURL]) - # Auth function + #Check the user access (if flag) + #################################### + lFlagUserAccess = True + #If need user authentication + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lFlagUserAccess = UserAccessCheckBefore("GET", self) + ###################################### + if lFlagUserAccess: + lOrchestratorFolder = "\\".join(__file__.split("\\")[:-1]) + #Мост между файлом и http запросом (новый формат) + if self.path == "/": + self.SendResponseContentTypeFile('text/html', os.path.join(lOrchestratorFolder, "Web\\Index.xhtml")) + #Мост между файлом и http запросом (новый формат) + if self.path == '/3rdParty/Semantic-UI-CSS-master/semantic.min.css': + self.SendResponseContentTypeFile('text/css', os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.css")) + #Мост между файлом и http запросом (новый формат) + if self.path == '/3rdParty/Semantic-UI-CSS-master/semantic.min.js': + self.SendResponseContentTypeFile('application/javascript', os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Semantic-UI-CSS-master\\semantic.min.js")) + #Мост между файлом и http запросом (новый формат) + if self.path == '/3rdParty/jQuery/jquery-3.1.1.min.js': + self.SendResponseContentTypeFile('application/javascript', os.path.join(lOrchestratorFolder,"..\\Resources\\Web\\jQuery\\jquery-3.1.1.min.js")) + #Мост между файлом и http запросом (новый формат) + if self.path == '/3rdParty/Google/LatoItalic.css': + self.SendResponseContentTypeFile('font/css', os.path.join(lOrchestratorFolder, "..\\Resources\\Web\\Google\\LatoItalic.css")) + #Мост между файлом и http запросом (новый формат) + if self.path == '/3rdParty/Semantic-UI-CSS-master/themes/default/assets/fonts/icons.woff2': + self.SendResponseContentTypeFile('font/woff2', os.path.join(lOrchestratorFolder,"..\\Resources\\Web\\Semantic-UI-CSS-master\\themes\\default\\assets\\fonts\\icons.woff2")) + #Мост между файлом и http запросом (новый формат) + if self.path == '/favicon.ico': + self.SendResponseContentTypeFile('image/x-icon', os.path.join(lOrchestratorFolder, "Web\\favicon.ico")) + #Мост между файлом и http запросом (новый формат) + if self.path == '/3rdParty/Handlebars/handlebars-v4.1.2.js': + self.SendResponseContentTypeFile('application/javascript', os.path.join(lOrchestratorFolder,"..\\Resources\\Web\\Handlebars\\handlebars-v4.1.2.js")) + #Получить скриншот + if self.path.split("?")[0] == '/GetScreenshot': + #Сохранить файл на диск + SaveScreenshot("Screenshot.png") + self.SendResponseContentTypeFile('image/png',"Screenshot.png") + #Monitor + if self.path == '/Monitor/JSONDaemonListGet': + # Send response status code + self.send_response(200) + # Send headers + self.send_header('Content-type','application/json') + self.end_headers() + # Send message back to client + message = json.dumps(mGlobalDict) + # Write content as utf-8 data + self.wfile.write(bytes(message, "utf8")) + if self.path == '/Monitor/ControlPanelDictGet': + # Send response status code + self.send_response(200) + # Send headers + self.send_header('Content-type','application/json') + self.end_headers() + #Create result JSON + lResultJSON={"RenderRobotList":[]} + lRenderFunctionsRobotList=mGlobalDict["ControlPanelDict"]["RobotList"] + for lItem in lRenderFunctionsRobotList: + #Выполнить вызов и записать результат + lItemResultDict=lItem["RenderFunction"](mGlobalDict) + #RunFunction + lResultJSON["RenderRobotList"].append(lItemResultDict) + # Send message back to client + message = json.dumps(lResultJSON) + # Write content as utf-8 data + self.wfile.write(bytes(message, "utf8")) + #Filemanager function + if self.path.lower().startswith('/filemanager/'): + lFileURL=self.path[13:] + # check if file in FileURL - File Path Mapping Dict + if lFileURL.lower() in mGlobalDict["FileManager"]["FileURLFilePathDict"]: + self.SendResponseContentTypeFile('application/octet-stream',mGlobalDict["FileManager"]["FileURLFilePathDict"][lFileURL]) # POST def do_POST(self): ##################################### @@ -226,22 +277,30 @@ class testHTTPServer_RequestHandler(BaseHTTPRequestHandler): AuthenticateBlock(self) ##################################### else: - #Централизованная функция получения запросов/отправки - if self.path == '/Utils/Processor': - #ReadRequest - lInputObject={} - if self.headers.get('Content-Length') is not None: - lInputByteArrayLength = int(self.headers.get('Content-Length')) - lInputByteArray=self.rfile.read(lInputByteArrayLength) - #Превращение массива байт в объект - lInputObject=json.loads(lInputByteArray.decode('utf8')) - # Send response status code - self.send_response(200) - # Send headers - self.send_header('Content-type','application/json') - self.end_headers() - # Send message back to client - message = json.dumps(Processor.ActivityListOrDict(lInputObject)) - # Write content as utf-8 data - self.wfile.write(bytes(message, "utf8")) - return \ No newline at end of file + #Check the user access (if flag) + #################################### + lFlagUserAccess = True + #If need user authentication + if mGlobalDict.get("Server", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lFlagUserAccess = UserAccessCheckBefore("GET", self) + ###################################### + if lFlagUserAccess: + #Централизованная функция получения запросов/отправки + if self.path == '/Utils/Processor': + #ReadRequest + lInputObject={} + if self.headers.get('Content-Length') is not None: + lInputByteArrayLength = int(self.headers.get('Content-Length')) + lInputByteArray=self.rfile.read(lInputByteArrayLength) + #Превращение массива байт в объект + lInputObject=json.loads(lInputByteArray.decode('utf8')) + # Send response status code + self.send_response(200) + # Send headers + self.send_header('Content-type','application/json') + self.end_headers() + # Send message back to client + message = json.dumps(Processor.ActivityListOrDict(lInputObject)) + # Write content as utf-8 data + self.wfile.write(bytes(message, "utf8")) + return \ No newline at end of file