mirror of
https://github.com/aljazceru/hummingbot-dashboard.git
synced 2026-02-23 14:06:56 +01:00
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:
@@ -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")
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user