server data & log processed - need test

dev-fastapi
Иван Маслов 2 years ago
parent b6fbe1bba0
commit f96ce9ab58

@ -21,6 +21,31 @@
# Call the orchestrator main def # Call the orchestrator main def
Orchestrator.Orchestrator(inGSettings=gSettings) Orchestrator.Orchestrator(inGSettings=gSettings)
************************************************************
Шаблоны функций веб-сервера (с использованием FastAPI)
************************************************************
.. code-block:: python
# ПРИМЕР Если НЕ требуется авторизация пользователя (получить inAuthTokenStr)
from fastapi import Request
from fastapi.responses import JSONResponse, HTMLResponse
@app.post("/url/to/def",response_class=JSONResponse)
async def some_def(inRequest:Request):
l_input_dict = await inRequest.json()
if lValueStr == None or lValueStr == b"": lValueStr=""
else: lValueStr = lValueStr.decode("utf8")
# ПРИМЕР Если требуется авторизация пользователя (получить inAuthTokenStr)
from fastapi import Request
from fastapi.responses import JSONResponse, HTMLResponse
from pyOpenRPA import Orchestrator
@app.post("/url/to/def",response_class=JSONResponse)
async def some_def(inRequest:Request, inAuthTokenStr:str=Depends(Orchestrator.WebAuthDefGet())):
l_input_dict = await inRequest.json()
if lValueStr == None or lValueStr == b"": lValueStr=""
else: lValueStr = lValueStr.decode("utf8")
****************************** ******************************
Конфигурационный файл config.py Конфигурационный файл config.py

@ -30,7 +30,7 @@ import io
from starlette.responses import StreamingResponse from starlette.responses import StreamingResponse
from typing import Union from typing import Union
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
import asyncio
# # # # # # # # # # # # # # # # # # # # # # # #
# v 1.2.0 Functionallity # v 1.2.0 Functionallity
@ -132,13 +132,11 @@ def HiddenAgentDictGenerate(inAuthTokenStr):
# Client: mGlobal.pyOpenRPA.ServerDataHashStr # Client: mGlobal.pyOpenRPA.ServerDataHashStr
# Client: mGlobal.pyOpenRPA.ServerDataDict # Client: mGlobal.pyOpenRPA.ServerDataDict
import asyncio
from fastapi import Request @app.post("/orpa/client/server-data",response_class=JSONResponse, tags=["Client"])
@app.post("/orpa/client/server-data",response_class=JSONResponse)
#{"Method": "POST", "URL": "/orpa/client/server-data", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerData, "ResponseContentType": "application/json"}, #{"Method": "POST", "URL": "/orpa/client/server-data", "MatchType": "Equal","ResponseDefRequestGlobal": pyOpenRPA_ServerData, "ResponseContentType": "application/json"},
async def pyOpenRPA_ServerData(inRequest: Request): async def pyOpenRPA_ServerData(inRequest: Request, inAuthTokenStr:str=Depends(__Orchestrator__.WebAuthDefGet())):
inGSettings = __Orchestrator__.GSettingsGet() inGSettings = __Orchestrator__.GSettingsGet()
print(f"START pyOpenRPA_ServerData")
# Extract the hash value from request # Extract the hash value from request
lValueStr = await inRequest.body() lValueStr = await inRequest.body()
lValueStr= lValueStr.decode("utf8") lValueStr= lValueStr.decode("utf8")
@ -146,11 +144,11 @@ async def pyOpenRPA_ServerData(inRequest: Request):
lFlagDoGenerateBool = True lFlagDoGenerateBool = True
while lFlagDoGenerateBool: while lFlagDoGenerateBool:
lServerDataDict = { lServerDataDict = {
"CPDict": None,#HiddenCPDictGenerate(inRequest=inRequest, inGSettings=inGSettings), "CPDict": HiddenCPDictGenerate(inAuthTokenStr=inAuthTokenStr),
"RDPDict": None,#HiddenRDPDictGenerate(inRequest=inRequest, inGSettings=inGSettings), "RDPDict": HiddenRDPDictGenerate(inAuthTokenStr=inAuthTokenStr),
"AgentDict": None,#HiddenAgentDictGenerate(inRequest=inRequest, inGSettings=inGSettings), "AgentDict": HiddenAgentDictGenerate(inAuthTokenStr=inAuthTokenStr),
"UserDict": {"UACClientDict": {}, "CWDPathStr": os.getcwd(), "VersionStr": inGSettings["VersionStr"]}, "UserDict": {"UACClientDict": {}, "CWDPathStr": os.getcwd(), "VersionStr": inGSettings["VersionStr"]},
} # inRequest.OpenRPA["DefUserRoleHierarchyGet"]() }
# Create JSON # Create JSON
lServerDataDictJSONStr = json.dumps(lServerDataDict) lServerDataDictJSONStr = json.dumps(lServerDataDict)
# Generate hash # Generate hash
@ -162,12 +160,6 @@ async def pyOpenRPA_ServerData(inRequest: Request):
await asyncio.sleep(inGSettings["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"]) await asyncio.sleep(inGSettings["Client"]["Session"]["ControlPanelRefreshIntervalSecFloat"])
# Return the result if Hash is changed # Return the result if Hash is changed
lResult = {"HashStr": lServerDataHashStr, "ServerDataDict": lServerDataDict} lResult = {"HashStr": lServerDataHashStr, "ServerDataDict": lServerDataDict}
#inResponseDict = inRequest.OpenRPAResponseDict
# Send message back to client
#message = json.dumps(lResult)
# Write content as utf-8 data
#inResponseDict["Body"] = bytes(message, "utf8")
print(f"STOP pyOpenRPA_ServerData")
return lResult return lResult
# GET # GET
@ -184,9 +176,12 @@ def pyOpenRPA_ServerJSInit(inRequest,inGSettings):
# /pyOpenRPA/ServerLog return {"HashStr" , "ServerLogList": ["row 1", "row 2"]} # /pyOpenRPA/ServerLog return {"HashStr" , "ServerLogList": ["row 1", "row 2"]}
# Client: mGlobal.pyOpenRPA.ServerLogListHashStr # Client: mGlobal.pyOpenRPA.ServerLogListHashStr
# Client: mGlobal.pyOpenRPA.ServerLogList # Client: mGlobal.pyOpenRPA.ServerLogList
async def pyOpenRPA_ServerLog(inRequest,inGSDict): @app.post("/orpa/client/server-log",response_class=JSONResponse, tags=["Client"])
async def pyOpenRPA_ServerLog(inRequest: Request, inAuthTokenStr:str=Depends(__Orchestrator__.WebAuthDefGet())):
inGSDict = __Orchestrator__.GSettingsGet()
# Extract the hash value from request # Extract the hash value from request
lValueStr = inRequest.body lValueStr = await inRequest.body()
lValueStr= lValueStr.decode("utf8")
# Generate ServerDataDict # Generate ServerDataDict
lFlagDoGenerateBool = True lFlagDoGenerateBool = True
while lFlagDoGenerateBool: while lFlagDoGenerateBool:
@ -199,11 +194,6 @@ async def pyOpenRPA_ServerLog(inRequest,inGSDict):
asyncio.sleep(inGSDict["Client"]["DumpLogListRefreshIntervalSecFloat"]) asyncio.sleep(inGSDict["Client"]["DumpLogListRefreshIntervalSecFloat"])
# Return the result if Hash is changed # Return the result if Hash is changed
lResult = {"HashStr": lServerLogListHashStr, "ServerLogList": lServerLogList} lResult = {"HashStr": lServerLogListHashStr, "ServerLogList": lServerLogList}
inResponseDict = inRequest.OpenRPAResponseDict
# Send message back to client
message = json.dumps(lResult)
# Write content as utf-8 data
inResponseDict["Body"] = bytes(message, "utf8")
return lResult return lResult
# Get thread list /orpa/threads # Get thread list /orpa/threads

@ -1,5 +1,6 @@
from re import I from re import I
import subprocess, json, psutil, time, os import subprocess, json, psutil, time, os
import typing
from pyOpenRPA.Tools import CrossOS from pyOpenRPA.Tools import CrossOS
if CrossOS.IS_WINDOWS_BOOL: import win32security #CrossOS if CrossOS.IS_WINDOWS_BOOL: import win32security #CrossOS
if CrossOS.IS_LINUX_BOOL: from simplepam import authenticate #CrossOS if CrossOS.IS_LINUX_BOOL: from simplepam import authenticate #CrossOS
@ -42,7 +43,9 @@ import math
import glob # search the files import glob # search the files
import urllib import urllib
from . import ServerSettings
from fastapi import FastAPI, Depends
#Единый глобальный словарь (За основу взять из Settings.py) #Единый глобальный словарь (За основу взять из Settings.py)
gSettingsDict = None gSettingsDict = None
@ -1053,6 +1056,101 @@ def GSettingsKeyListValueOperatorPlus(inValue, inKeyList=None, inGSettings = Non
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# OrchestratorWeb defs # OrchestratorWeb defs
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
def WebUserLoginGet(inAuthTokenStr: str=None) -> str:
"""L+,W+: Получить логин авторизованного пользователя. Если авторизация не производилась - вернуть None
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен)
:type inAuthTokenStr: str, опционально
:return: Логин пользователя
:rtype: str
"""
if inAuthTokenStr is None: return None
inGS = GSettingsGet() # Get the global settings
return inGS.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("User", None)
def WebUserDomainGet(inAuthTokenStr: str=None) -> str:
"""L+,W+: Получить домен авторизованного пользователя. Если авторизация не производилась - вернуть None
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен)
:type inAuthTokenStr: str, опционально
:return: Домен пользователя
:rtype: str
"""
if inAuthTokenStr is None: return None
inGS = GSettingsGet() # Get the global settings
return inGS.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("Domain", None)
def WebUserInfoGet(inAuthTokenStr=None):
"""L+,W+: Информация о пользователе, который отправил HTTP запрос.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: Сведения в формате {"DomainUpperStr": "PYOPENRPA", "UserNameUpperStr": "IVAN.MASLOV"}
"""
try:
lResultDict = {
"DomainUpperStr": WebUserDomainGet(inAuthTokenStr=inAuthTokenStr).upper(),
"UserNameUpperStr": WebUserLoginGet(inAuthTokenStr=inAuthTokenStr).upper()
}
return lResultDict
except Exception as e:
return {"DomainUpperStr": None, "UserNameUpperStr": None}
def WebUserIsSuperToken(inAuthTokenStr: str=None):
"""L+,W+: [ИЗМЕНЕНИЕ В 1.3.1] Проверить, авторизован ли HTTP запрос с помощью супер токена (токен, который не истекает).
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен)
:type inAuthTokenStr: str, опционально
:return: True - является супертокеном; False - не является супертокеном; None - авторизация не производилась
"""
if inAuthTokenStr is None: return None
inGSettings = GSettingsGet() # Get the global settings
lIsSuperTokenBool = False
# Get Flag is supertoken (True|False)
lIsSuperTokenBool = inGSettings.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("FlagDoNotExpire", False)
return lIsSuperTokenBool
def WebUserUACHierarchyGet(inAuthTokenStr: str=None) -> dict:
"""L+,W+: [ИЗМЕНЕНИЕ В 1.3.1] Вернуть словарь доступа UAC в отношении пользователя, который выполнил HTTP запрос inRequest
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен)
:type inAuthTokenStr: str, опционально
:return: UAC словарь доступа или {}, что означает полный доступ
"""
lDomainUpperStr = WebUserDomainGet(inAuthTokenStr=inAuthTokenStr).upper()
lUserUpperStr = WebUserLoginGet(inAuthTokenStr=inAuthTokenStr).upper()
if lUserUpperStr is None: return {}
else: return GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {})
def WebUserUACCheck(inAuthTokenStr:str=None, inKeyList:list=None) -> bool:
"""L+,W+: Проверить UAC доступ списка ключей для пользователя
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен)
:type inAuthTokenStr: str, опционально
:return: True - доступ имеется, False - доступа нет
:rtype: bool
"""
if inAuthTokenStr is None: return True # Если авторизации не происходило - супердоступ
lResult = True # Init flag
lRoleHierarchyDict = WebUserUACHierarchyGet(inAuthTokenStr=inAuthTokenStr) # get the Hierarchy
# Try to get value from key list
lKeyValue = lRoleHierarchyDict # Init the base
for lItem in inKeyList:
if type(lKeyValue) is dict:
if lItem in lKeyValue: # Has key
lKeyValue = lKeyValue[lItem] # Get the value and go to the next loop iteration
else: # Else branch - true or false
if len(lKeyValue)>0: # False - if Dict has some elements
lResult = False # Set the False Flag
else:
lResult = True # Set the True flag
break # Stop the loop
else: # Has element with no detalization - return True
lResult = True # Set the flag
break # Close the loop
return lResult # Return the result
def WebURLIndexChange(inURLIndexStr:str ="/"): def WebURLIndexChange(inURLIndexStr:str ="/"):
"""L+,W+: Изменить адрес главной страницы Оркестратора. По умолчанию '/' """L+,W+: Изменить адрес главной страницы Оркестратора. По умолчанию '/'
@ -1315,107 +1413,31 @@ def WebRequestGet():
lCurrentThread = threading.current_thread() lCurrentThread = threading.current_thread()
if hasattr(lCurrentThread, "request"): if hasattr(lCurrentThread, "request"):
return lCurrentThread.request return lCurrentThread.request
from fastapi import FastAPI
def WebAppGet() -> FastAPI: def WebAppGet() -> FastAPI:
"""L+,W+: Вернуть экземпляр веб сервера fastapi.FastAPI (app). Подробнее про app см. https://fastapi.tiangolo.com/tutorial/first-steps/ """L+,W+: Вернуть экземпляр веб сервера fastapi.FastAPI (app). Подробнее про app см. https://fastapi.tiangolo.com/tutorial/first-steps/
""" """
return Server.app return Server.app
def WebUserLoginGet(inAuthTokenStr: str=None) -> str:
"""L+,W+: Получить логин авторизованного пользователя. Если авторизация не производилась - вернуть None
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен)
:type inAuthTokenStr: str, опционально
:return: Логин пользователя
:rtype: str
"""
if inAuthTokenStr is None: return None
inGS = GSettingsGet() # Get the global settings
return inGS.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("User", None)
def WebUserDomainGet(inAuthTokenStr: str=None) -> str:
"""L+,W+: Получить домен авторизованного пользователя. Если авторизация не производилась - вернуть None
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен)
:type inAuthTokenStr: str, опционально
:return: Домен пользователя
:rtype: str
"""
if inAuthTokenStr is None: return None
inGS = GSettingsGet() # Get the global settings
return inGS.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("Domain", None)
def WebUserInfoGet(inAuthTokenStr=None):
"""L+,W+: Информация о пользователе, который отправил HTTP запрос.
:param inRequest: Экземпляр HTTP request. Опционален, если сообщение фиксируется из под потока, который был инициирован запросом пользователя
:return: Сведения в формате {"DomainUpperStr": "PYOPENRPA", "UserNameUpperStr": "IVAN.MASLOV"}
"""
try:
lResultDict = {
"DomainUpperStr": WebUserDomainGet(inAuthTokenStr=inAuthTokenStr).upper(),
"UserNameUpperStr": WebUserLoginGet(inAuthTokenStr=inAuthTokenStr).upper()
}
return lResultDict
except Exception as e:
return {"DomainUpperStr": None, "UserNameUpperStr": None}
def WebUserIsSuperToken(inAuthTokenStr: str=None):
"""L+,W+: [ИЗМЕНЕНИЕ В 1.3.1] Проверить, авторизован ли HTTP запрос с помощью супер токена (токен, который не истекает).
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен)
:type inAuthTokenStr: str, опционально
:return: True - является супертокеном; False - не является супертокеном; None - авторизация не производилась
"""
if inAuthTokenStr is None: return None
inGSettings = GSettingsGet() # Get the global settings
lIsSuperTokenBool = False
# Get Flag is supertoken (True|False)
lIsSuperTokenBool = inGSettings.get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(inAuthTokenStr, {}).get("FlagDoNotExpire", False)
return lIsSuperTokenBool
def WebUserUACHierarchyGet(inAuthTokenStr: str=None) -> dict: def WebAuthDefGet():
"""L+,W+: [ИЗМЕНЕНИЕ В 1.3.1] Вернуть словарь доступа UAC в отношении пользователя, который выполнил HTTP запрос inRequest """Вернуть функцию авторизации пользователя. Функция может использоваться для доменной авторизации.
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен) .. code-block:: python
:type inAuthTokenStr: str, опционально
:return: UAC словарь доступа или {}, что означает полный доступ
"""
lDomainUpperStr = WebUserDomainGet(inAuthTokenStr=inAuthTokenStr).upper()
lUserUpperStr = WebUserLoginGet(inAuthTokenStr=inAuthTokenStr).upper()
if lUserUpperStr is None: return {}
else: return GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("RuleDomainUserDict", {}).get((lDomainUpperStr, lUserUpperStr), {}).get("RoleHierarchyAllowedDict", {})
def WebUserUACCheck(inAuthTokenStr:str=None, inKeyList:list=None) -> bool: # ПРИМЕР Если требуется авторизация пользователя (получить inAuthTokenStr)
"""L+,W+: Проверить UAC доступ списка ключей для пользователя from fastapi import Request
from fastapi.responses import JSONResponse, HTMLResponse
from pyOpenRPA import Orchestrator
@app.post("/url/to/def",response_class=JSONResponse)
async def some_def(inRequest:Request, inAuthTokenStr:str=Depends(Orchestrator.WebAuthDefGet())):
l_input_dict = await inRequest.json()
if lValueStr == None or lValueStr == b"": lValueStr=""
else: lValueStr = lValueStr.decode("utf8")
:param inAuthTokenStr: Токен авторизации пользователя / бота, по умолчанию None (не установлен) :return: Функция авторизации
:type inAuthTokenStr: str, опционально :rtype: def
:return: True - доступ имеется, False - доступа нет
:rtype: bool
""" """
if inAuthTokenStr is None: return True # Если авторизации не происходило - супердоступ return ServerSettings.IdentifyAuthorize
lResult = True # Init flag
lRoleHierarchyDict = WebUserUACHierarchyGet(inAuthTokenStr=inAuthTokenStr) # get the Hierarchy
# Try to get value from key list
lKeyValue = lRoleHierarchyDict # Init the base
for lItem in inKeyList:
if type(lKeyValue) is dict:
if lItem in lKeyValue: # Has key
lKeyValue = lKeyValue[lItem] # Get the value and go to the next loop iteration
else: # Else branch - true or false
if len(lKeyValue)>0: # False - if Dict has some elements
lResult = False # Set the False Flag
else:
lResult = True # Set the True flag
break # Stop the loop
else: # Has element with no detalization - return True
lResult = True # Set the flag
break # Close the loop
return lResult # Return the result
def StorageRobotExists(inRobotNameStr): def StorageRobotExists(inRobotNameStr):
"""L+,W+: Проверить, существует ли ключ inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict) """L+,W+: Проверить, существует ли ключ inRobotNameStr в хранилище пользовательской информации StorageDict (GSettings > StarageDict)

@ -4,6 +4,11 @@ STD - STUDIO
RBT - ROBOT RBT - ROBOT
AGT - AGENT AGT - AGENT
[1.3.2]
- ОРКЕСТРАТОР
- - Поддержка многотысячной аудитории, одновременно работающей в панели управления (async server-data server-log with fastapi)
- - Новые функции для упрощенной работы с FastAPI: Orchestrator.WebAuthDefGet Orchestrator.WebAppGet
[1.3.1] [1.3.1]
- ОРКЕСТРАТОР - ОРКЕСТРАТОР
- - минорные правки в дизайн - - минорные правки в дизайн

Loading…
Cancel
Save