From 8830d6eba3b897a25b3e317c37722219c6292d4d Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Tue, 6 Sep 2022 00:16:43 +0300 Subject: [PATCH] orc: API goes to FASTAPI --- Sources/pyOpenRPA/Orchestrator/Server.py | 75 +---------- .../pyOpenRPA/Orchestrator/ServerSettings.py | 120 +++++++++++++++--- 2 files changed, 107 insertions(+), 88 deletions(-) diff --git a/Sources/pyOpenRPA/Orchestrator/Server.py b/Sources/pyOpenRPA/Orchestrator/Server.py index 9a19382a..85ab3b15 100755 --- a/Sources/pyOpenRPA/Orchestrator/Server.py +++ b/Sources/pyOpenRPA/Orchestrator/Server.py @@ -11,9 +11,7 @@ import threading from pyOpenRPA.Tools import CrossOS -import base64 -import uuid -import datetime + from http import cookies from . import ServerBC @@ -40,71 +38,6 @@ app = FastAPI( swagger_ui_oauth2_redirect_url = "/orpa/fastapi/docs/oauth2-redirect", ) -def IdentifyAuthorize(inRequest:Request, inResponse:Response, - inCookiesStr: Union[str, None] = Header(default=None,alias="Cookie"), - inAuthorizationStr: Union[str, None] = Header(default="",alias="Authorization")): - lResult={"Domain": "", "User": ""} - #print("IdentifyAuthorize") - ###################################### - #Way 1 - try to find AuthToken - lCookies = cookies.SimpleCookie(inCookiesStr) # inRequest.headers.get("Cookie", "") - __Orchestrator__.GSettingsGet() - lHeaderAuthorization = inAuthorizationStr.split(" ") - if "AuthToken" in lCookies: - lCookieAuthToken = lCookies.get("AuthToken", "").value - if lCookieAuthToken: - #Find AuthToken in GlobalDict - if lCookieAuthToken in __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): - #Auth Token Has Been Founded - lResult["Domain"] = __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] - lResult["User"] = __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] - #Set auth token - mOpenRPA={} - mOpenRPA["AuthToken"] = lCookieAuthToken - mOpenRPA["Domain"] = lResult["Domain"] - mOpenRPA["User"] = lResult["User"] - mOpenRPA["IsSuperToken"] = __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) - return lAuthToken - ###################################### - #Way 2 - try to logon - if len(lHeaderAuthorization) == 2: - llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split( - ":") - lUser = llHeaderAuthorizationDecodedUserPasswordList[0] - lPassword = llHeaderAuthorizationDecodedUserPasswordList[1] - lDomain = "" - if "\\" in lUser: - lDomain = lUser.split("\\")[0] - lUser = lUser.split("\\")[1] - lLogonBool = __Orchestrator__.OSCredentialsVerify(inUserStr=lUser, inPasswordStr=lPassword, inDomainStr=lDomain) - #Check result - if lLogonBool: - lResult["Domain"] = lDomain - lResult["User"] = lUser - #Create token - lAuthToken=str(uuid.uuid1()) - __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} - __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] - __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] - __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False - __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() - #Set-cookie - inResponse.set_cookie(key="AuthToken",value=lAuthToken) - mOpenRPA={} - mOpenRPA["AuthToken"] = lAuthToken - mOpenRPA["Domain"] = lResult["Domain"] - mOpenRPA["User"] = lResult["User"] - mOpenRPA["IsSuperToken"] = __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) - return lAuthToken - #inRequest.OpenRPASetCookie = {} - #New engine of server - #inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken - else: - raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (неверная пара логин / пароль)", headers={}) - ###################################### - else: - raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (неполная пара логин / пароль)", headers={'Content-type':'text/html', 'WWW-Authenticate':'Basic'}) - lRouteList =[] for lItem in app.router.routes: lRouteList.append(lItem) @@ -114,7 +47,7 @@ for lItem in lRouteList: path=lItem.path, endpoint=lItem.endpoint, methods=["GET"], - dependencies=[Depends(IdentifyAuthorize)], + dependencies=[Depends(ServerSettings.IdentifyAuthorize)], tags=["FastAPI"] ) @@ -132,12 +65,12 @@ def BackwardCompatibility(inRequest:Request, inResponse:Response, inBodyStr:str #WRAPPERS! def BackwardCompatibityWrapperAuth(inRequest:Request, inResponse:Response, inBodyStr:str = Body(""), - inAuthTokenStr:str=Depends(IdentifyAuthorize)): # Old from v1.3.1 (updated to FastAPI) + inAuthTokenStr:str=Depends(ServerSettings.IdentifyAuthorize)): # Old from v1.3.1 (updated to FastAPI) return BackwardCompatibility(inRequest = inRequest, inResponse = inResponse, inBodyStr = inBodyStr, inAuthTokenStr=inAuthTokenStr) def BackwardCompatibityWrapperNoAuth(inRequest:Request, inResponse:Response, inBodyStr:str = Body("")): # Old from v1.3.1 (updated to FastAPI) return BackwardCompatibility(inRequest = inRequest, inResponse = inResponse, inBodyStr = inBodyStr, inAuthDict=None) def BackwardCompatibityBeginWrapperAuth(inBeginTokenStr, inRequest:Request, inResponse:Response, inBodyStr:str = Body(""), - inAuthTokenStr:str=Depends(IdentifyAuthorize)): # Old from v1.3.1 (updated to FastAPI) + inAuthTokenStr:str=Depends(ServerSettings.IdentifyAuthorize)): # Old from v1.3.1 (updated to FastAPI) return BackwardCompatibility(inRequest = inRequest, inResponse = inResponse, inBodyStr = inBodyStr, inAuthTokenStr=inAuthTokenStr) def BackwardCompatibityBeginWrapperNoAuth(inBeginTokenStr, inRequest:Request, inResponse:Response, inBodyStr:str = Body("")): # Old from v1.3.1 (updated to FastAPI) return BackwardCompatibility(inRequest = inRequest, inResponse = inResponse, inBodyStr = inBodyStr, inAuthDict=None) diff --git a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py index baf89745..4d69bf20 100755 --- a/Sources/pyOpenRPA/Orchestrator/ServerSettings.py +++ b/Sources/pyOpenRPA/Orchestrator/ServerSettings.py @@ -30,6 +30,76 @@ import io from starlette.responses import StreamingResponse from typing import Union from fastapi.responses import JSONResponse +import base64 +import uuid +import datetime + +def IdentifyAuthorize(inRequest:Request, inResponse:Response, + inCookiesStr: Union[str, None] = Header(default=None,alias="Cookie"), + inAuthorizationStr: Union[str, None] = Header(default="",alias="Authorization")): + if __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("FlagCredentialsAsk", False): + lResult={"Domain": "", "User": ""} + #print("IdentifyAuthorize") + ###################################### + #Way 1 - try to find AuthToken + lCookies = cookies.SimpleCookie(inCookiesStr) # inRequest.headers.get("Cookie", "") + __Orchestrator__.GSettingsGet() + lHeaderAuthorization = inAuthorizationStr.split(" ") + if "AuthToken" in lCookies: + lCookieAuthToken = lCookies.get("AuthToken", "").value + if lCookieAuthToken: + #Find AuthToken in GlobalDict + if lCookieAuthToken in __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}): + #Auth Token Has Been Founded + lResult["Domain"] = __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] + lResult["User"] = __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] + #Set auth token + mOpenRPA={} + mOpenRPA["AuthToken"] = lCookieAuthToken + mOpenRPA["Domain"] = lResult["Domain"] + mOpenRPA["User"] = lResult["User"] + mOpenRPA["IsSuperToken"] = __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) + return lAuthToken + ###################################### + #Way 2 - try to logon + if len(lHeaderAuthorization) == 2: + llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split( + ":") + lUser = llHeaderAuthorizationDecodedUserPasswordList[0] + lPassword = llHeaderAuthorizationDecodedUserPasswordList[1] + lDomain = "" + if "\\" in lUser: + lDomain = lUser.split("\\")[0] + lUser = lUser.split("\\")[1] + lLogonBool = __Orchestrator__.OSCredentialsVerify(inUserStr=lUser, inPasswordStr=lPassword, inDomainStr=lDomain) + #Check result + if lLogonBool: + lResult["Domain"] = lDomain + lResult["User"] = lUser + #Create token + lAuthToken=str(uuid.uuid1()) + __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken] = {} + __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["Domain"] = lResult["Domain"] + __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["User"] = lResult["User"] + __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["FlagDoNotExpire"] = False + __Orchestrator__.GSettingsGet()["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() + #Set-cookie + inResponse.set_cookie(key="AuthToken",value=lAuthToken) + mOpenRPA={} + mOpenRPA["AuthToken"] = lAuthToken + mOpenRPA["Domain"] = lResult["Domain"] + mOpenRPA["User"] = lResult["User"] + mOpenRPA["IsSuperToken"] = __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) + return lAuthToken + #inRequest.OpenRPASetCookie = {} + #New engine of server + #inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken + else: + raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (неверная пара логин / пароль)", headers={}) + ###################################### + else: + raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (неполная пара логин / пароль)", headers={'Content-type':'text/html', 'WWW-Authenticate':'Basic'}) + else: return None # Credentials are not required - return none # # # # # # # # # # # # @@ -219,28 +289,34 @@ def pyOpenRPA_Screenshot(): # Add activity item or activity list to the processor queue # Body is Activity item or Activity List -def pyOpenRPA_Processor(inRequest, inGSettings): - lL = inGSettings["Logger"] +# body inauthtoken JSON +@app.post(path="/orpa/api/processor-queue-add",response_class=JSONResponse,tags=["API"]) +def pyOpenRPA_Processor(inRequest:Request, inAuthTokenStr:str = Depends(IdentifyAuthorize), inBodyStr:str = Body("")): + inGSettings = __Orchestrator__.GSettingsGet() + lL = __Orchestrator__.OrchestratorLoggerGet() # Recieve the data - lValueStr = inRequest.body + lValueStr = inBodyStr # Превращение массива байт в объект lInput = json.loads(lValueStr) + lResult=[] # If list - operator plus if type(lInput) is list: # Logging info about processor activity if not SuperToken () - if not __Orchestrator__.WebUserIsSuperToken(inRequest=inRequest, inGSettings=inGSettings): + if not __Orchestrator__.WebUserIsSuperToken(inAuthTokenStr=inAuthTokenStr): lActivityTypeListStr = "" try: for lActivityItem in lInput: lActivityTypeListStr += f"{lActivityItem['Def']}; " except Exception as e: lActivityTypeListStr = "Ошибка чтения типа активности" - lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor") + lHostStr = __Orchestrator__.WebRequestHostGet(inRequest=inRequest) + lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inAuthTokenStr=inAuthTokenStr, inHostStr = lHostStr,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor") if lL: lL.info(lWebAuditMessageStr) # Separate into 2 lists - sync and async lSyncActvityList = [] lAsyncActivityList = [] for lActivityItem in lInput: + lResult.append(__Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lActivityItem)) if lInput.get("ThreadBool", False) == False: lSyncActvityList.append(lActivityItem) else: @@ -254,14 +330,16 @@ def pyOpenRPA_Processor(inRequest, inGSettings): lThread = threading.Thread(target=Processor.ActivityListExecute, kwargs=lActivityItemArgsDict) lThread.start() else: + lResult=__Orchestrator__.ProcessorActivityItemAppend(inActivityItemDict=lInput) # Logging info about processor activity if not SuperToken () - if not __Orchestrator__.WebUserIsSuperToken(inRequest=inRequest, inGSettings=inGSettings): + if not __Orchestrator__.WebUserIsSuperToken(inAuthTokenStr=inAuthTokenStr): lActivityTypeListStr = "" try: lActivityTypeListStr = lInput['Def'] except Exception as e: lActivityTypeListStr = "Ошибка чтения типа активности" - lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor") + lHostStr = __Orchestrator__.WebRequestHostGet(inRequest=inRequest) + lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest, inHostStr = lHostStr, inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_Processor") if lL: lL.info(lWebAuditMessageStr) if lInput.get("ThreadBool",False) == False: # Append in list @@ -270,43 +348,51 @@ def pyOpenRPA_Processor(inRequest, inGSettings): lActivityItemArgsDict = {"inGSettings": inGSettings, "inActivityList": [lInput]} lThread = threading.Thread(target=Processor.ActivityListExecute, kwargs=lActivityItemArgsDict) lThread.start() + return lResult + # Execute activity list -def pyOpenRPA_ActivityListExecute(inRequest, inGSettings): +@app.post(path="/orpa/api/activity-list-execute",response_class=JSONResponse,tags=["API"]) +def pyOpenRPA_ActivityListExecute(inRequest:Request, inAuthTokenStr:str = Depends(IdentifyAuthorize), inBodyStr:str = Body("")): # Recieve the data - lL = inGSettings["Logger"] + inGSettings = __Orchestrator__.GSettingsGet() + lL = __Orchestrator__.OrchestratorLoggerGet() lValueStr = inRequest.body # Превращение массива байт в объект lInput = json.loads(lValueStr) # If list - operator plus if type(lInput) is list: # Logging info about processor activity if not SuperToken () - if not __Orchestrator__.WebUserIsSuperToken(inRequest=inRequest, inGSettings=inGSettings): + if not __Orchestrator__.WebUserIsSuperToken(inAuthTokenStr=inAuthTokenStr): lActivityTypeListStr = "" try: for lActivityItem in lInput: lActivityTypeListStr += f"{lActivityItem['Def']}; " except Exception as e: lActivityTypeListStr = "Ошибка чтения типа активности" - lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute") + lHostStr = __Orchestrator__.WebRequestHostGet(inRequest=inRequest) + lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest, inHostStr = lHostStr,inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute") if lL: lL.info(lWebAuditMessageStr) # Execution lResultList = Processor.ActivityListExecute(inGSettings = inGSettings, inActivityList = lInput) - inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lResultList), "utf8") + return lResultList + #inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lResultList), "utf8") else: # Logging info about processor activity if not SuperToken () - if not __Orchestrator__.WebUserIsSuperToken(inRequest=inRequest, inGSettings=inGSettings): + if not __Orchestrator__.WebUserIsSuperToken(inAuthTokenStr=inAuthTokenStr): lActivityTypeListStr = "" try: lActivityTypeListStr = lInput['Def'] except Exception as e: lActivityTypeListStr = "Ошибка чтения типа активности" - lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest, + lHostStr = __Orchestrator__.WebRequestHostGet(inRequest=inRequest) + lWebAuditMessageStr = __Orchestrator__.WebAuditMessageCreate(inRequest=inRequest, inHostStr = lHostStr, inOperationCodeStr=lActivityTypeListStr, inMessageStr="pyOpenRPA_ActivityListExecute") if lL: lL.info(lWebAuditMessageStr) # Execution lResultList = Processor.ActivityListExecute(inGSettings = inGSettings, inActivityList = [lInput]) - inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lResultList[0]), "utf8") + return lResultList + #inRequest.OpenRPAResponseDict["Body"] = bytes(json.dumps(lResultList[0]), "utf8") # See docs in Agent (pyOpenRPA.Agent.O2A) def pyOpenRPA_Agent_O2A(inRequest, inGSettings): @@ -495,8 +581,8 @@ def SettingsUpdate(): {"Method": "POST", "URL": "/orpa/client/server-log", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerLog, "ResponseContentType": "application/json"}, #{"Method": "GET", "URL": "/orpa/client/screenshot-get", "MatchType": "Equal", "ResponseDefRequestGlobal": pyOpenRPA_Screenshot, "ResponseContentType": "image/png"}, # API - {"Method": "POST", "URL": "/orpa/api/processor-queue-add", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Processor, "ResponseContentType": "application/json"}, - {"Method": "POST", "URL": "/orpa/api/activity-list-execute", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ActivityListExecute, "ResponseContentType": "application/json"}, + #{"Method": "POST", "URL": "/orpa/api/processor-queue-add", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_Processor, "ResponseContentType": "application/json"}, + #{"Method": "POST", "URL": "/orpa/api/activity-list-execute", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ActivityListExecute, "ResponseContentType": "application/json"}, {"Method": "GET", "URL": "/orpa/api/helper-def-list/", "MatchType": "BeginWith","ResponseDefRequestGlobal": pyOpenRPA_Debugging_HelperDefList, "ResponseContentType": "application/json"}, {"Method": "GET", "URL": "/orpa/api/helper-autofill/", "MatchType": "BeginWith","ResponseDefRequestGlobal": pyOpenRPA_Debugging_HelperDefAutofill, "ResponseContentType": "application/json"}, # AGENT