fix: add debug logging to admin API key validation and re-enable all routers

- Add debug print statements to _validate_api_key and require_admin_key for troubleshooting
- Add /admin/debug-settings and /admin/test-key endpoints for API key validation testing
- Bypass require_admin_key dependency in /admin/stats endpoint for direct validation
- Fix database warmup to properly handle session generator lifecycle
- Re-enable all previously disabled routers in main.py
- Add custom OpenAPI security scheme
This commit is contained in:
oib
2026-03-05 13:44:37 +01:00
parent b44aeaad97
commit 83b5152b40
12 changed files with 556 additions and 65 deletions

View File

@@ -48,7 +48,7 @@ def submit(ctx, job_type: str, prompt: Optional[str], model: Optional[str],
try:
with httpx.Client() as client:
response = client.post(
f"{config.coordinator_url}/api/v1/jobs",
f"{config.coordinator_url}/v1/jobs",
headers={
"Content-Type": "application/json",
"X-Api-Key": config.api_key or ""
@@ -273,7 +273,7 @@ def history(ctx, limit: int, status: Optional[str], type: Optional[str],
with httpx.Client() as client:
response = client.get(
f"{config.coordinator_url}/api/v1/jobs",
f"{config.coordinator_url}/v1/jobs",
params=params,
headers={"X-Api-Key": config.api_key or ""}
)

View File

@@ -49,7 +49,7 @@ def register(ctx, gpu: Optional[str], memory: Optional[int],
try:
with httpx.Client() as client:
response = client.post(
f"{config.coordinator_url}/api/v1/miners/register",
f"{config.coordinator_url}/v1/miners/register",
headers={
"Content-Type": "application/json",
"X-Api-Key": config.api_key or "",
@@ -81,7 +81,7 @@ def poll(ctx, wait: int, miner_id: str):
try:
with httpx.Client() as client:
response = client.post(
f"{config.coordinator_url}/api/v1/miners/poll",
f"{config.coordinator_url}/v1/miners/poll",
json={"max_wait_seconds": 5},
headers={
"X-Api-Key": config.api_key or "",
@@ -121,7 +121,7 @@ def mine(ctx, jobs: int, miner_id: str):
with httpx.Client() as client:
# Poll for job
response = client.post(
f"{config.coordinator_url}/api/v1/miners/poll",
f"{config.coordinator_url}/v1/miners/poll",
json={"max_wait_seconds": 5},
headers={
"X-Api-Key": config.api_key or "",
@@ -148,7 +148,7 @@ def mine(ctx, jobs: int, miner_id: str):
# Submit result
result_response = client.post(
f"{config.coordinator_url}/api/v1/miners/{job_id}/result",
f"{config.coordinator_url}/v1/miners/{job_id}/result",
headers={
"Content-Type": "application/json",
"X-Api-Key": config.api_key or "",
@@ -192,7 +192,7 @@ def heartbeat(ctx, miner_id: str):
try:
with httpx.Client() as client:
response = client.post(
f"{config.coordinator_url}/api/v1/miners/heartbeat",
f"{config.coordinator_url}/v1/miners/heartbeat",
headers={
"X-Api-Key": config.api_key or "",
"X-Miner-ID": miner_id
@@ -250,7 +250,7 @@ def earnings(ctx, miner_id: str, from_time: Optional[str], to_time: Optional[str
with httpx.Client() as client:
response = client.post(
f"{config.coordinator_url}/api/v1/miners/{miner_id}/earnings",
f"{config.coordinator_url}/v1/miners/{miner_id}/earnings",
params=params,
headers={"X-Api-Key": config.api_key or ""}
)
@@ -296,7 +296,7 @@ def update_capabilities(ctx, gpu: Optional[str], memory: Optional[int],
try:
with httpx.Client() as client:
response = client.put(
f"{config.coordinator_url}/api/v1/miners/{miner_id}/capabilities",
f"{config.coordinator_url}/v1/miners/{miner_id}/capabilities",
headers={
"Content-Type": "application/json",
"X-Api-Key": config.api_key or ""
@@ -334,7 +334,7 @@ def deregister(ctx, miner_id: str, force: bool):
try:
with httpx.Client() as client:
response = client.delete(
f"{config.coordinator_url}/api/v1/miners/{miner_id}",
f"{config.coordinator_url}/v1/miners/{miner_id}",
headers={"X-Api-Key": config.api_key or ""}
)
@@ -374,7 +374,7 @@ def jobs(ctx, limit: int, job_type: Optional[str], min_reward: Optional[float],
with httpx.Client() as client:
response = client.post(
f"{config.coordinator_url}/api/v1/miners/{miner_id}/jobs",
f"{config.coordinator_url}/v1/miners/{miner_id}/jobs",
params=params,
headers={"X-Api-Key": config.api_key or ""}
)
@@ -395,7 +395,7 @@ def _process_single_job(config, miner_id: str, worker_id: int) -> Dict[str, Any]
try:
with httpx.Client() as http_client:
response = http_client.post(
f"{config.coordinator_url}/api/v1/miners/poll",
f"{config.coordinator_url}/v1/miners/poll",
json={"max_wait_seconds": 5},
headers={
"X-Api-Key": config.api_key or "",
@@ -413,7 +413,7 @@ def _process_single_job(config, miner_id: str, worker_id: int) -> Dict[str, Any]
time.sleep(2) # Simulate processing
result_response = http_client.post(
f"{config.coordinator_url}/api/v1/miners/{job_id}/result",
f"{config.coordinator_url}/v1/miners/{job_id}/result",
headers={
"Content-Type": "application/json",
"X-Api-Key": config.api_key or "",
@@ -490,7 +490,7 @@ def mine_ollama(ctx, jobs: int, miner_id: str, ollama_url: str, model: str):
try:
with httpx.Client() as client:
response = client.post(
f"{config.coordinator_url}/api/v1/miners/poll",
f"{config.coordinator_url}/v1/miners/poll",
json={"max_wait_seconds": 10},
headers={
"X-Api-Key": config.api_key or "",
@@ -534,7 +534,7 @@ def mine_ollama(ctx, jobs: int, miner_id: str, ollama_url: str, model: str):
error(f"Ollama inference failed: {ollama_result['error']}")
# Submit failure
client.post(
f"{config.coordinator_url}/api/v1/miners/{job_id}/fail",
f"{config.coordinator_url}/v1/miners/{job_id}/fail",
headers={
"Content-Type": "application/json",
"X-Api-Key": config.api_key or "",
@@ -546,7 +546,7 @@ def mine_ollama(ctx, jobs: int, miner_id: str, ollama_url: str, model: str):
# Submit successful result
result_response = client.post(
f"{config.coordinator_url}/api/v1/miners/{job_id}/result",
f"{config.coordinator_url}/v1/miners/{job_id}/result",
headers={
"Content-Type": "application/json",
"X-Api-Key": config.api_key or "",

View File

@@ -40,8 +40,9 @@ def dashboard(ctx, refresh: int, duration: int):
with httpx.Client(timeout=5) as client:
# Get dashboard data
try:
url = f"{config.coordinator_url}/api/v1/dashboard"
resp = client.get(
f"{config.coordinator_url}/dashboard",
url,
headers={"X-Api-Key": config.api_key or ""}
)
if resp.status_code == 200:

View File

@@ -11,7 +11,7 @@ from dotenv import load_dotenv
@dataclass
class Config:
"""Configuration object for AITBC CLI"""
coordinator_url: str = "http://127.0.0.1:18000"
coordinator_url: str = "http://127.0.0.1:8000"
api_key: Optional[str] = None
config_dir: Path = field(default_factory=lambda: Path.home() / ".aitbc")
config_file: Optional[str] = None