Merge pull request #188 from hummingbot/feat/backend_api_security_and_minor_fixes

Feat/backend api security and minor fixes
This commit is contained in:
rapcmia
2024-11-01 23:15:39 +08:00
committed by GitHub
9 changed files with 56 additions and 79 deletions

View File

@@ -21,3 +21,5 @@ AUTH_SYSTEM_ENABLED = os.getenv("AUTH_SYSTEM_ENABLED", "False").lower() in ("tru
BACKEND_API_HOST = os.getenv("BACKEND_API_HOST", "127.0.0.1")
BACKEND_API_PORT = os.getenv("BACKEND_API_PORT", 8000)
BACKEND_API_USERNAME = os.getenv("BACKEND_API_USERNAME", "admin")
BACKEND_API_PASSWORD = os.getenv("BACKEND_API_PASSWORD", "admin")

View File

@@ -4,6 +4,7 @@ import pandas as pd
import requests
import streamlit as st
from hummingbot.strategy_v2.models.executors_info import ExecutorInfo
from requests.auth import HTTPBasicAuth
class BackendAPIClient:
@@ -20,10 +21,11 @@ class BackendAPIClient:
cls._shared_instance = BackendAPIClient(*args, **kwargs)
return cls._shared_instance
def __init__(self, host: str = "localhost", port: int = 8000):
def __init__(self, host: str = "localhost", port: int = 8000, username: str = "admin", password: str = "admin"):
self.host = host
self.port = port
self.base_url = f"http://{self.host}:{self.port}"
self.auth = HTTPBasicAuth(username, password)
def post(self, endpoint: str, payload: Optional[Dict] = None, params: Optional[Dict] = None):
"""
@@ -34,7 +36,7 @@ class BackendAPIClient:
:return:
"""
url = f"{self.base_url}/{endpoint}"
response = requests.post(url, json=payload, params=params)
response = requests.post(url, json=payload, params=params, auth=self.auth)
return self._process_response(response)
def get(self, endpoint: str):
@@ -44,12 +46,15 @@ class BackendAPIClient:
:return:
"""
url = f"{self.base_url}/{endpoint}"
response = requests.get(url)
response = requests.get(url, auth=self.auth)
return self._process_response(response)
@staticmethod
def _process_response(response):
if response.status_code == 400:
if response.status_code == 401:
st.error("You are not authorized to access Backend API. Please check your credentials.")
return
elif response.status_code == 400:
st.error(response.json()["detail"])
return
return response.json()

View File

@@ -19,13 +19,10 @@ dependencies:
- statsmodels
- pandas_ta==0.3.14b
- pyyaml
- jupyter
- optuna
- optuna-dashboard
- pathlib
- st-pages
- st_pages
- streamlit-elements==0.1.*
- streamlit-authenticator
- streamlit-authenticator==0.3.2
- pydantic==1.10.4
- flake8
- isort

View File

@@ -49,35 +49,41 @@ class LaunchStrategyV2(Dashboard.Item):
self._controller_config_selected = [param + ".yml" for param in params]
def launch_new_bot(self):
if self._bot_name and self._image_name and len(self._controller_config_selected) > 0:
start_time_str = time.strftime("%Y.%m.%d_%H.%M")
bot_name = f"{self._bot_name}-{start_time_str}"
script_config = {
"name": bot_name,
"content": {
"markets": {},
"candles_config": [],
"controllers_config": self._controller_config_selected,
"config_update_interval": 10,
"script_file_name": "v2_with_controllers.py",
"time_to_cash_out": None,
}
if not self._bot_name:
st.warning("You need to define the bot name.")
return
if not self._image_name:
st.warning("You need to select the hummingbot image.")
return
if not self._controller_config_selected or len(self._controller_config_selected) == 0:
st.warning("You need to select the controllers configs. Please select at least one controller "
"config by clicking on the checkbox.")
return
start_time_str = time.strftime("%Y.%m.%d_%H.%M")
bot_name = f"{self._bot_name}-{start_time_str}"
script_config = {
"name": bot_name,
"content": {
"markets": {},
"candles_config": [],
"controllers_config": self._controller_config_selected,
"config_update_interval": 10,
"script_file_name": "v2_with_controllers.py",
"time_to_cash_out": None,
}
}
self._backend_api_client.add_script_config(script_config)
deploy_config = {
"instance_name": bot_name,
"script": "v2_with_controllers.py",
"script_config": bot_name + ".yml",
"image": self._image_name,
"credentials_profile": self._credentials,
}
self._backend_api_client.create_hummingbot_instance(deploy_config)
with st.spinner('Starting Bot... This process may take a few seconds'):
time.sleep(3)
else:
st.warning("You need to define the bot name and select the controllers configs "
"that you want to deploy.")
self._backend_api_client.add_script_config(script_config)
deploy_config = {
"instance_name": bot_name,
"script": "v2_with_controllers.py",
"script_config": bot_name + ".yml",
"image": self._image_name,
"credentials_profile": self._credentials,
}
self._backend_api_client.create_hummingbot_instance(deploy_config)
with st.spinner('Starting Bot... This process may take a few seconds'):
time.sleep(3)
def delete_selected_configs(self):
if self._controller_config_selected:

View File

@@ -3,8 +3,7 @@ import datetime
import pandas as pd
import streamlit as st
from backend.services.backend_api_client import BackendAPIClient
from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT
from frontend.st_utils import get_backend_api_client
def get_max_records(days_to_download: int, interval: str) -> int:
@@ -16,7 +15,7 @@ def get_max_records(days_to_download: int, interval: str) -> int:
@st.cache_data
def get_candles(connector_name="binance", trading_pair="BTC-USDT", interval="1m", days=7):
backend_client = BackendAPIClient(BACKEND_API_HOST, BACKEND_API_PORT)
backend_client = get_backend_api_client()
end_time = datetime.datetime.now() - datetime.timedelta(minutes=15)
start_time = end_time - datetime.timedelta(days=days)

View File

@@ -1,19 +0,0 @@
### Description
This page helps you deploy and manage Hummingbot instances:
- Starting and stopping Hummingbot Broker
- Creating, starting and stopping bot instances
- Managing strategy and script files that instances run
- Fetching status of running instances
### Maintainers
This page is maintained by Hummingbot Foundation as a template other pages:
* [cardosfede](https://github.com/cardosfede)
* [fengtality](https://github.com/fengtality)
### Wiki
See the [wiki](https://github.com/hummingbot/dashboard/wiki/%F0%9F%90%99-Bot-Orchestration) for more information.

View File

@@ -1,8 +0,0 @@
from frontend.components.deploy_v2_with_controllers import LaunchV2WithControllers
from frontend.st_utils import initialize_st_page
initialize_st_page(title="Launch Bot ST", icon="🙌")
launcher = LaunchV2WithControllers()
launcher()

View File

@@ -73,20 +73,16 @@ def style_metric_cards(
def get_backend_api_client():
from backend.services.backend_api_client import BackendAPIClient
from CONFIG import BACKEND_API_HOST, BACKEND_API_PORT
is_docker_running = False
from CONFIG import BACKEND_API_HOST, BACKEND_API_PASSWORD, BACKEND_API_PORT, BACKEND_API_USERNAME
try:
backend_api_client = BackendAPIClient.get_instance(host=BACKEND_API_HOST, port=BACKEND_API_PORT)
is_docker_running = backend_api_client.is_docker_running()
except Exception as e:
st.error(
f"There was an error trying to connect to the Backend API. Please make sure the Backend API is running.\n\n"
f"Error: \n\n{str(e)}")
backend_api_client = BackendAPIClient.get_instance(host=BACKEND_API_HOST, port=BACKEND_API_PORT,
username=BACKEND_API_USERNAME, password=BACKEND_API_PASSWORD)
if not backend_api_client.is_docker_running():
st.error("Docker is not running. Please make sure Docker is running.")
st.stop()
return backend_api_client
except Exception:
st.stop()
if not is_docker_running:
st.error("Docker is not running. Please make sure Docker is running.")
st.stop()
return backend_api_client
def auth_system():
@@ -102,7 +98,6 @@ def auth_system():
config['cookie']['name'],
config['cookie']['key'],
config['cookie']['expiry_days'],
config['pre-authorized']
)
show_pages(main_page() + public_pages())
st.session_state.authenticator.login()