fastapi inprogress

merge-requests/1/merge
Ivan Maslov 2 years ago
parent 2b06170730
commit a12de50131

@ -14,6 +14,8 @@ import json
from threading import Thread from threading import Thread
import inspect import inspect
from requests import request
from pyOpenRPA.Tools import CrossOS from pyOpenRPA.Tools import CrossOS
from . import Processor # Add new processor from . import Processor # Add new processor
from . import ProcessorOld # Support old processor - deprecated defs only for backward compatibility from . import ProcessorOld # Support old processor - deprecated defs only for backward compatibility
@ -82,7 +84,7 @@ def AuthenticateBlock(inRequest):
def UserAccessCheckBefore(inMethod, inRequest): def UserAccessCheckBefore(inMethod, inRequest):
# Help def - Get access flag from dict # Help def - Get access flag from dict
#pdb.set_trace() #pdb.set_trace()
global gSettingsDict gSettingsDict = __Orchestrator__.GSettingsGet()
def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict): def HelpGetFlag(inAccessRuleItem, inRequest, inGlobalDict, inAuthenticateDict):
if "FlagAccess" in inAccessRuleItem: if "FlagAccess" in inAccessRuleItem:
return inAccessRuleItem["FlagAccess"] return inAccessRuleItem["FlagAccess"]
@ -171,6 +173,21 @@ def UserAccessCheckBefore(inMethod, inRequest):
return lResult return lResult
class HTTPRequestOld(): class HTTPRequestOld():
mRequest:Request = None
mResponse:Response = None
OpenRPA: dict = {}
def __init__(self,inRequest,inResponse,inAuthDict):
self.mRequest = inRequest
self.mResponse = inResponse
if inAuthDict is None:
self.OpenRPA = {}
self.OpenRPA["IsSuperToken"] = False
self.OpenRPA["AuthToken"] = None
self.OpenRPA["Domain"] = None
self.OpenRPA["User"] = None
else: self.OpenRPA = inAuthDict
# Def to check User Role access grants # Def to check User Role access grants
def UACClientCheck(self, inRoleKeyList): # Alias def UACClientCheck(self, inRoleKeyList): # Alias
return self.UserRoleAccessAsk(inRoleKeyList=inRoleKeyList) return self.UserRoleAccessAsk(inRoleKeyList=inRoleKeyList)
@ -205,7 +222,7 @@ class HTTPRequestOld():
#Tech def #Tech def
#return {"headers":[],"body":"","statuscode":111} #return {"headers":[],"body":"","statuscode":111}
def URLItemCheckDo(self, inURLItem, inMethod, inOnlyFlagUACBool = False): def URLItemCheckDo(self, inURLItem, inMethod, inOnlyFlagUACBool = False):
global gSettingsDict gSettingsDict = __Orchestrator__.GSettingsGet()
############################### ###############################
#Tech sub def - do item #Tech sub def - do item
################################ ################################
@ -256,7 +273,6 @@ class HTTPRequestOld():
else: else:
inURLItem["ResponseDefRequestGlobal"]() inURLItem["ResponseDefRequestGlobal"]()
if "ResponseFolderPath" in inURLItem: if "ResponseFolderPath" in inURLItem:
#lRequestPath = inRequest.path #lRequestPath = inRequest.path
lRequestPath = urllib.parse.unquote(inRequest.path) lRequestPath = urllib.parse.unquote(inRequest.path)
if inURLItem["URL"][-1]!="/": inURLItem["URL"]+= "/" # Fix for settings if inURLItem["URL"][-1]!="/": inURLItem["URL"]+= "/" # Fix for settings
@ -329,49 +345,35 @@ class HTTPRequestOld():
return False return False
#ResponseContentTypeFile #ResponseContentTypeFile
def SendResponseContentTypeFile(self, inContentType, inFilePath): def SendResponseContentTypeFile(self, inContentType, inFilePath):
# Send response status code inResponseDict = self.OpenRPAResponseDict
self.send_response(200) self.mResponse.status_code = 200
# Send headers # Send headers
self.send_header('Content-type', inContentType) self.mResponse.headers["Content-type"]=inContentType
#Check if var exist #Check if var exist
if hasattr(self, "OpenRPASetCookie"): if hasattr(self, "OpenRPASetCookie"):
self.send_header("Set-Cookie", f"AuthToken={self.OpenRPA['AuthToken']}") self.mResponse.set_cookie(key='AuthToken',value=self.OpenRPA['AuthToken'])
self.end_headers()
lFileObject = open(inFilePath, "rb") lFileObject = open(inFilePath, "rb")
# Write content as utf-8 data # Write content as utf-8 data
self.wfile.write(lFileObject.read()) lFileBytes = lFileObject.read()
#Закрыть файловый объект #Закрыть файловый объект
lFileObject.close() lFileObject.close()
return lFileBytes
# ResponseContentTypeFile # ResponseContentTypeFile
def ResponseDictSend(self): def ResponseDictSend(self):
lL = gSettingsDict["Logger"]
inResponseDict = self.OpenRPAResponseDict inResponseDict = self.OpenRPAResponseDict
# Send response status code self.mResponse.status_code = inResponseDict["StatusCode"]
self.send_response(inResponseDict["StatusCode"])
# Send headers # Send headers
for lItemKey, lItemValue in inResponseDict["Headers"].items(): for lItemKey, lItemValue in inResponseDict["Headers"].items():
self.send_header(lItemKey, lItemValue) self.mResponse.headers[lItemKey]=lItemValue
# Send headers: Set-Cookie # Send headers: Set-Cookie
for lItemKey, lItemValue in inResponseDict["SetCookies"].items(): for lItemKey, lItemValue in inResponseDict["SetCookies"].items():
self.mResponse.set_cookie(key=lItemKey,value=lItemValue)
self.send_header("Set-Cookie", f"{lItemKey}={lItemValue}") self.send_header("Set-Cookie", f"{lItemKey}={lItemValue}")
#Close headers section in response return inResponseDict["Body"]
try:
self.end_headers()
# Write content as utf-8 data
self.wfile.write(inResponseDict["Body"])
except (ConnectionResetError, ConnectionAbortedError) as e:
if lL: lL.warning(f"SERVER: Connection was forcibly closed by the client side - OK for the network interactions (ConnectionResetError: [WinError 10054] or ConnectionAbortedError: [WinError 10053])")
def do_GET(self): def do_GET(self, inBodyStr):
try: try:
global gSettingsDict gSettingsDict = __Orchestrator__.GSettingsGet()
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self
self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None
self.OpenRPA["Domain"] = None
self.OpenRPA["User"] = None
self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def
self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def
# Prepare result dict # Prepare result dict
@ -395,49 +397,27 @@ class HTTPRequestOld():
lFlagURLIsApplied=False lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET") lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "GET")
if lFlagURLIsApplied: if lFlagURLIsApplied:
self.ResponseDictSend() return self.ResponseDictSend()
return
#Monitor #Monitor
if self.path == '/Monitor/JSONDaemonListGet': if self.path == '/Monitor/JSONDaemonListGet':
# Send response status code lResponseDict = {"Headers": {'Content-type':'application/json'}, "SetCookies": {}, "Body": bytes(json.dumps(gSettingsDict), "utf8"), "StatusCode": 200}
self.send_response(200) return self.ResponseDictSend()
# Send headers
self.send_header('Content-type','application/json')
self.end_headers()
# Send message back to client
message = json.dumps(gSettingsDict)
# Write content as utf-8 data
self.wfile.write(bytes(message, "utf8"))
#Filemanager function #Filemanager function
if self.path.lower().startswith('/filemanager/'): if self.path.lower().startswith('/filemanager/'):
lFileURL=self.path[13:] lFileURL=self.path[13:]
# check if file in FileURL - File Path Mapping Dict # check if file in FileURL - File Path Mapping Dict
if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]: if lFileURL.lower() in gSettingsDict["FileManager"]["FileURLFilePathDict"]:
self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL]) return self.SendResponseContentTypeFile('application/octet-stream', gSettingsDict["FileManager"]["FileURLFilePathDict"][lFileURL])
else: else:
#Set access denied code raise HTTPException(status_code=403, detail="here is the details", headers={})
# Send response status code
self.send_response(403)
# Send headers
self.end_headers()
except BrokenPipeError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер (do_GET): Возникла ошибка сети - BrokenPipeError: [Errno 32] Broken pipe. Сервер продолжает работу")
except Exception as e: except Exception as e:
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
if lL: lL.exception(f"Сервер (do_GET): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу") if lL: lL.exception(f"Сервер (do_GET): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу")
# POST # POST
def do_POST(self): def do_POST(self, inBodyStr):
try: try:
global gSettingsDict gSettingsDict = __Orchestrator__.GSettingsGet()
#self.timeout=gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"]
self.request.settimeout(gSettingsDict["ServerDict"]["RequestTimeoutSecFloat"])
threading.current_thread().request = self
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
self.OpenRPA = {}
self.OpenRPA["AuthToken"] = None
self.OpenRPA["Domain"] = None
self.OpenRPA["User"] = None
self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def self.OpenRPA["DefUserRoleAccessAsk"]=self.UserRoleAccessAsk # Alias for def
self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def self.OpenRPA["DefUserRoleHierarchyGet"]=self.UserRoleHierarchyGet # Alias for def
# Prepare result dict # Prepare result dict
@ -461,24 +441,13 @@ class HTTPRequestOld():
lFlagURLIsApplied=False lFlagURLIsApplied=False
lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST") lFlagURLIsApplied=self.URLItemCheckDo(lURLItem, "POST")
if lFlagURLIsApplied: if lFlagURLIsApplied:
self.ResponseDictSend() return self.ResponseDictSend()
return
#Централизованная функция получения запросов/отправки #Централизованная функция получения запросов/отправки
if self.path == '/Utils/Processor': if self.path == '/Utils/Processor':
#ReadRequest #Превращение массива байт в объект
lInputObject={} lInputObject=json.loads(inBodyStr)
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()
# Logging info about processor activity if not SuperToken () # Logging info about processor activity if not SuperToken ()
if not lIsSuperToken: if not self.mOpenRPA['IsSuperToken']:
lActivityTypeListStr = "" lActivityTypeListStr = ""
try: try:
if type(lInputObject) is list: if type(lInputObject) is list:
@ -487,22 +456,12 @@ class HTTPRequestOld():
else: else:
lActivityTypeListStr += f"{lInputObject['Type']}" lActivityTypeListStr += f"{lInputObject['Type']}"
except Exception as e: except Exception as e:
lActivityTypeListStr = "Has some error with Activity Type read" lActivityTypeListStr = "Обнаружена ошибка при чтении Activity Type"
if lL: lL.info(f"Сервер:: !ВНИМАНИЕ! /Utils/Processor через некоторое время перестанет поддерживаться. Используйте /pyOpenRPA/Processor или /pyOpenRPA/ActivityListExecute. Активность поступила от пользователя. Домен: {self.OpenRPA['Domain']}, Логин: {self.OpenRPA['User']}, Тип активности: {lActivityTypeListStr}") if lL: lL.info(f"Сервер:: !ВНИМАНИЕ! /Utils/Processor через некоторое время перестанет поддерживаться. Используйте /pyOpenRPA/Processor или /pyOpenRPA/ActivityListExecute. Активность поступила от пользователя. Домен: {self.OpenRPA['Domain']}, Логин: {self.OpenRPA['User']}, Тип активности: {lActivityTypeListStr}")
# Send message back to client lResponseDict = {"Headers": {'Content-type':'application/json'}, "SetCookies": {}, "Body": bytes(json.dumps(ProcessorOld.ActivityListOrDict(lInputObject)), "utf8"), "StatusCode": 200}
message = json.dumps(ProcessorOld.ActivityListOrDict(lInputObject)) return self.ResponseDictSend()
# Write content as utf-8 data
self.wfile.write(bytes(message, "utf8"))
return
else: else:
# Send response status code raise HTTPException(status_code=403, detail="here is the details", headers={})
self.send_response(403)
# Send headers
self.end_headers()
return
except BrokenPipeError as e:
lL = gSettingsDict["Logger"]
if lL: lL.warning(f"Сервер, обратная совместимость (do_POST): Возникла ошибка сети - BrokenPipeError: [Errno 32] Broken pipe. Сервер продолжает работу")
except Exception as e: except Exception as e:
lL = gSettingsDict["Logger"] lL = gSettingsDict["Logger"]
if lL: lL.exception(f"Сервер, обратная совместимость (do_POST): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу") if lL: lL.exception(f"Сервер, обратная совместимость (do_POST): Неопознанная ошибка сети - см. текст ошибки. Сервер продолжает работу")
@ -511,7 +470,7 @@ class HTTPRequestOld():
from typing import Union from typing import Union
# объявление import # объявление import
from fastapi import FastAPI, Form, Request, HTTPException, Depends, Header, Response from fastapi import FastAPI, Form, Request, HTTPException, Depends, Header, Response, Body
from fastapi.responses import PlainTextResponse, HTMLResponse, FileResponse from fastapi.responses import PlainTextResponse, HTMLResponse, FileResponse
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
@ -548,12 +507,12 @@ def IdentifyAuthorize(inRequest:Request, inResponse:Response,
lResult["Domain"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"] lResult["Domain"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["Domain"]
lResult["User"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"] lResult["User"] = gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lCookieAuthToken]["User"]
#Set auth token #Set auth token
inRequest.OpenRPA={} mOpenRPA={}
inRequest.OpenRPA["AuthToken"] = lCookieAuthToken mOpenRPA["AuthToken"] = lAuthToken
inRequest.OpenRPA["Domain"] = lResult["Domain"] mOpenRPA["Domain"] = lResult["Domain"]
inRequest.OpenRPA["User"] = lResult["User"] mOpenRPA["User"] = lResult["User"]
#Exit earlier mOpenRPA["IsSuperToken"] = gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False)
return lResult return mOpenRPA
###################################### ######################################
#Way 2 - try to logon #Way 2 - try to logon
elif len(lHeaderAuthorization) == 2: elif len(lHeaderAuthorization) == 2:
@ -579,10 +538,12 @@ def IdentifyAuthorize(inRequest:Request, inResponse:Response,
gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now() gSettingsDict["ServerDict"]["AccessUsers"]["AuthTokensDict"][lAuthToken]["TokenDatetime"] = datetime.datetime.now()
#Set-cookie #Set-cookie
inResponse.set_cookie(key="AuthToken",value=lAuthToken) inResponse.set_cookie(key="AuthToken",value=lAuthToken)
inRequest.OpenRPA={} mOpenRPA={}
inRequest.OpenRPA["AuthToken"] = lAuthToken mOpenRPA["AuthToken"] = lAuthToken
inRequest.OpenRPA["Domain"] = lResult["Domain"] mOpenRPA["Domain"] = lResult["Domain"]
inRequest.OpenRPA["User"] = lResult["User"] mOpenRPA["User"] = lResult["User"]
mOpenRPA["IsSuperToken"] = gSettingsDict.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False)
return mOpenRPA
#inRequest.OpenRPASetCookie = {} #inRequest.OpenRPASetCookie = {}
#New engine of server #New engine of server
#inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken #inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken
@ -594,38 +555,47 @@ def IdentifyAuthorize(inRequest:Request, inResponse:Response,
return True return True
def BackwardCompatibityWrapper(): # Old from v1.3.1 (updated to FastAPI) def BackwardCompatibityWrapperAuth(inRequest:Request, inResponse:Response, inBodyStr:str = Body(...),
lHTTPRequest = HTTPRequestOld() inAuthDict:bool=Depends(IdentifyAuthorize)): # Old from v1.3.1 (updated to FastAPI)
lHTTPRequest.do_GET lHTTPRequest = HTTPRequestOld(inRequest=inRequest, inResponse=inResponse, inAuthDict=inAuthDict)
lHTTPRequest.do_POST threading.current_thread().request = lHTTPRequest
lResult = lHTTPRequest.do_GET(inBodyStr=inBodyStr)
@app.get(path="/", response_class=PlainTextResponse) if lResult is None:
def Hi(t:bool=Depends(IdentifyAuthorize)): lResult = lHTTPRequest.do_POST(inBodyStr=inBodyStr)
return "Hello world" return lResult
def BackwardCompatibityWrapperNoAuth(inRequest:Request, inResponse:Response, inBodyStr:str = Body(...)): # Old from v1.3.1 (updated to FastAPI)
lHTTPRequest = HTTPRequestOld(inRequest=inRequest, inResponse=inResponse, inAuthDict=None)
threading.current_thread().request = lHTTPRequest
lResult = lHTTPRequest.do_GET(inBodyStr=inBodyStr)
if lResult is None:
lResult = lHTTPRequest.do_POST(inBodyStr=inBodyStr)
return lResult.decode("utf8")
def FastAPI(): def InitFastAPI():
global gSettingsDict global gSettingsDict
global app global app
lL = gSettingsDict.get("Logger",None) lL = gSettingsDict.get("Logger",None)
#lThreadServer = Server.RobotDaemonServer(lItemKeyStr, gSettingsDict)
#lThreadServer.start()
gSettingsDict["ServerDict"]["ServerThread"] = app gSettingsDict["ServerDict"]["ServerThread"] = app
app.add_api_route( for lConnectItemDict in gSettingsDict["ServerDict"]["URLList"]:
path="/", if lConnectItemDict.get("UACBool",True):
endpoint=ServerSettings.pyOpenRPA_Index, app.add_api_route(
response_class=PlainTextResponse path=lConnectItemDict["URL"],
endpoint=BackwardCompatibityWrapperAuth,
response_class=PlainTextResponse,
methods=[lConnectItemDict["Method"]]
)
else:
app.add_api_route(
path=lConnectItemDict["URL"],
endpoint=BackwardCompatibityWrapperNoAuth,
response_class=PlainTextResponse,
methods=[lConnectItemDict["Method"]]
) )
#app.get("/", ServerSettings.pyOpenRPA_Index, response_class=PlainTextResponse)
uvicorn.run('pyOpenRPA.Orchestrator.Server:app', host='0.0.0.0', port=1024) uvicorn.run('pyOpenRPA.Orchestrator.Server:app', host='0.0.0.0', port=1024)
if lL: lL.info(f"Сервер инициализирован успешно (с поддержкой SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}, Путь к файлу сертификата (.pem): {lCertFilePathStr}") #if lL: lL.info(f"Сервер инициализирован успешно (с поддержкой SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}, Путь к файлу сертификата (.pem): {lCertFilePathStr}")
if lL: lL.info(f"Сервер инициализирован успешно (без поддержки SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}") #if lL: lL.info(f"Сервер инициализирован успешно (без поддержки SSL):: Наименование: {self.name}, Слушает URL: {lAddressStr}, Слушает порт: {lPortInt}")
if lL: lL.info("Модуль сервера FASTAPI") #Logging if lL: lL.info("Модуль сервера (FastAPI) инициализирован!") #Logging
Loading…
Cancel
Save