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