Fix jwt-token
This commit is contained in:
@@ -17,10 +17,61 @@ warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
|||||||
API_BASE_URL = os.getenv('API_BASE_URL', 'http://localhost:3002/api')
|
API_BASE_URL = os.getenv('API_BASE_URL', 'http://localhost:3002/api')
|
||||||
BASE_PATH = os.getenv('VITE_BASE_PATH', '').rstrip('/')
|
BASE_PATH = os.getenv('VITE_BASE_PATH', '').rstrip('/')
|
||||||
|
|
||||||
|
# Authentication configuration
|
||||||
|
USERNAME = os.getenv('TEST_USERNAME', 'admin')
|
||||||
|
PASSWORD = os.getenv('TEST_PASSWORD', 'admin123')
|
||||||
|
SKIP_AUTH = os.getenv('SKIP_AUTH', 'false').lower() == 'true'
|
||||||
|
|
||||||
if BASE_PATH and not API_BASE_URL.endswith('/api'):
|
if BASE_PATH and not API_BASE_URL.endswith('/api'):
|
||||||
domain = API_BASE_URL.replace('/api', '').replace('/drones/api', '').replace('/uggla/api', '')
|
domain = API_BASE_URL.replace('/api', '').replace('/drones/api', '').replace('/uggla/api', '')
|
||||||
API_BASE_URL = f"{domain}{BASE_PATH}/api"
|
API_BASE_URL = f"{domain}{BASE_PATH}/api"
|
||||||
|
|
||||||
|
# Global variable to store authentication token
|
||||||
|
AUTH_TOKEN = None
|
||||||
|
|
||||||
|
def authenticate():
|
||||||
|
"""Authenticate with the API and get access token"""
|
||||||
|
global AUTH_TOKEN
|
||||||
|
|
||||||
|
if SKIP_AUTH:
|
||||||
|
print("🔓 Authentication skipped (SKIP_AUTH=true)")
|
||||||
|
return True
|
||||||
|
|
||||||
|
try:
|
||||||
|
login_data = {
|
||||||
|
"username": USERNAME,
|
||||||
|
"password": PASSWORD
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(f"{API_BASE_URL}/users/login", json=login_data, verify=False, timeout=10)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
if data.get('success') and 'data' in data and 'token' in data['data']:
|
||||||
|
AUTH_TOKEN = data['data']['token']
|
||||||
|
print(f"✅ Authentication successful")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"❌ Invalid login response: {data}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print(f"❌ Authentication failed: HTTP {response.status_code}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Authentication error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_auth_headers():
|
||||||
|
"""Get headers with authentication token"""
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
if not SKIP_AUTH and AUTH_TOKEN:
|
||||||
|
headers['Authorization'] = f'Bearer {AUTH_TOKEN}'
|
||||||
|
|
||||||
|
return headers
|
||||||
|
|
||||||
def debug_device_status():
|
def debug_device_status():
|
||||||
"""Debug device status calculation"""
|
"""Debug device status calculation"""
|
||||||
print("🔍 DEVICE STATUS DEBUG")
|
print("🔍 DEVICE STATUS DEBUG")
|
||||||
@@ -28,7 +79,7 @@ def debug_device_status():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Get all devices
|
# Get all devices
|
||||||
response = requests.get(f"{API_BASE_URL}/devices", verify=False, timeout=10)
|
response = requests.get(f"{API_BASE_URL}/devices", headers=get_auth_headers(), verify=False, timeout=10)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
data = response.json()
|
data = response.json()
|
||||||
@@ -107,6 +158,7 @@ def send_test_heartbeat():
|
|||||||
response = requests.post(
|
response = requests.post(
|
||||||
f"{API_BASE_URL}/detectors",
|
f"{API_BASE_URL}/detectors",
|
||||||
json=payload,
|
json=payload,
|
||||||
|
headers=get_auth_headers(),
|
||||||
verify=False,
|
verify=False,
|
||||||
timeout=10
|
timeout=10
|
||||||
)
|
)
|
||||||
@@ -126,6 +178,12 @@ def main():
|
|||||||
print(f"⏰ Test Time: {datetime.now()}")
|
print(f"⏰ Test Time: {datetime.now()}")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
# Authenticate first
|
||||||
|
print("🔐 Authenticating...")
|
||||||
|
if not authenticate():
|
||||||
|
print("❌ Authentication failed, tests may not work")
|
||||||
|
return
|
||||||
|
|
||||||
debug_device_status()
|
debug_device_status()
|
||||||
send_test_heartbeat()
|
send_test_heartbeat()
|
||||||
|
|
||||||
|
|||||||
217
fix_stockholm_device.py
Normal file
217
fix_stockholm_device.py
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Fix Stockholm Device Script
|
||||||
|
Ensures the Stockholm device is properly configured for heartbeat monitoring
|
||||||
|
"""
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Disable SSL warnings for self-signed certificates
|
||||||
|
import warnings
|
||||||
|
warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
API_BASE_URL = os.getenv('API_BASE_URL', 'http://localhost:3002/api')
|
||||||
|
BASE_PATH = os.getenv('VITE_BASE_PATH', '').rstrip('/')
|
||||||
|
|
||||||
|
# Authentication configuration
|
||||||
|
USERNAME = os.getenv('TEST_USERNAME', 'admin')
|
||||||
|
PASSWORD = os.getenv('TEST_PASSWORD', 'admin123')
|
||||||
|
SKIP_AUTH = os.getenv('SKIP_AUTH', 'false').lower() == 'true'
|
||||||
|
|
||||||
|
if BASE_PATH and not API_BASE_URL.endswith('/api'):
|
||||||
|
domain = API_BASE_URL.replace('/api', '').replace('/drones/api', '').replace('/uggla/api', '')
|
||||||
|
API_BASE_URL = f"{domain}{BASE_PATH}/api"
|
||||||
|
|
||||||
|
# Global variable to store authentication token
|
||||||
|
AUTH_TOKEN = None
|
||||||
|
|
||||||
|
def authenticate():
|
||||||
|
"""Authenticate with the API and get access token"""
|
||||||
|
global AUTH_TOKEN
|
||||||
|
|
||||||
|
if SKIP_AUTH:
|
||||||
|
print("🔓 Authentication skipped (SKIP_AUTH=true)")
|
||||||
|
return True
|
||||||
|
|
||||||
|
try:
|
||||||
|
login_data = {
|
||||||
|
"username": USERNAME,
|
||||||
|
"password": PASSWORD
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(f"{API_BASE_URL}/users/login", json=login_data, verify=False, timeout=10)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
if data.get('success') and 'data' in data and 'token' in data['data']:
|
||||||
|
AUTH_TOKEN = data['data']['token']
|
||||||
|
print(f"✅ Authentication successful")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"❌ Invalid login response: {data}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print(f"❌ Authentication failed: HTTP {response.status_code}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Authentication error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_auth_headers():
|
||||||
|
"""Get headers with authentication token"""
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
if not SKIP_AUTH and AUTH_TOKEN:
|
||||||
|
headers['Authorization'] = f'Bearer {AUTH_TOKEN}'
|
||||||
|
|
||||||
|
return headers
|
||||||
|
|
||||||
|
def fix_stockholm_device():
|
||||||
|
"""Check and fix Stockholm device configuration"""
|
||||||
|
print("🔧 FIXING STOCKHOLM DEVICE CONFIGURATION")
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Get all devices
|
||||||
|
response = requests.get(f"{API_BASE_URL}/devices", headers=get_auth_headers(), verify=False, timeout=10)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
if data.get('success') and data.get('data'):
|
||||||
|
devices = data['data']
|
||||||
|
|
||||||
|
# Find Stockholm device
|
||||||
|
stockholm_device = None
|
||||||
|
for device in devices:
|
||||||
|
if device.get('id') == 1001 or 'Stockholm' in device.get('name', ''):
|
||||||
|
stockholm_device = device
|
||||||
|
break
|
||||||
|
|
||||||
|
if stockholm_device:
|
||||||
|
device_id = stockholm_device['id']
|
||||||
|
print(f"📱 Found Stockholm Device (ID: {device_id})")
|
||||||
|
print(f" Name: {stockholm_device.get('name', 'N/A')}")
|
||||||
|
print(f" Active: {stockholm_device.get('is_active', False)}")
|
||||||
|
print(f" Approved: {stockholm_device.get('is_approved', False)}")
|
||||||
|
print(f" Heartbeat Interval: {stockholm_device.get('heartbeat_interval', 'Not set')} seconds")
|
||||||
|
|
||||||
|
# Check if device needs fixing
|
||||||
|
needs_fix = False
|
||||||
|
updates = {}
|
||||||
|
|
||||||
|
if not stockholm_device.get('is_active'):
|
||||||
|
print("❌ Device is not active")
|
||||||
|
updates['is_active'] = True
|
||||||
|
needs_fix = True
|
||||||
|
|
||||||
|
if not stockholm_device.get('is_approved'):
|
||||||
|
print("❌ Device is not approved")
|
||||||
|
updates['is_approved'] = True
|
||||||
|
needs_fix = True
|
||||||
|
|
||||||
|
# Ensure heartbeat interval is set to 60 seconds (matching health probe simulator)
|
||||||
|
if stockholm_device.get('heartbeat_interval') != 60:
|
||||||
|
print(f"⚠️ Heartbeat interval is {stockholm_device.get('heartbeat_interval')}, should be 60 seconds")
|
||||||
|
updates['heartbeat_interval'] = 60
|
||||||
|
needs_fix = True
|
||||||
|
|
||||||
|
if needs_fix:
|
||||||
|
print(f"\n🔧 Applying fixes: {updates}")
|
||||||
|
|
||||||
|
# Update device
|
||||||
|
response = requests.put(
|
||||||
|
f"{API_BASE_URL}/devices/{device_id}",
|
||||||
|
json=updates,
|
||||||
|
headers=get_auth_headers(),
|
||||||
|
verify=False,
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
print("✅ Device configuration updated successfully")
|
||||||
|
|
||||||
|
# Get updated device info
|
||||||
|
response = requests.get(f"{API_BASE_URL}/devices", headers=get_auth_headers(), verify=False, timeout=10)
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
devices = data['data']
|
||||||
|
for device in devices:
|
||||||
|
if device.get('id') == device_id:
|
||||||
|
print(f"\n📊 Updated device configuration:")
|
||||||
|
print(f" Active: {device.get('is_active', False)}")
|
||||||
|
print(f" Approved: {device.get('is_approved', False)}")
|
||||||
|
print(f" Heartbeat Interval: {device.get('heartbeat_interval', 'Not set')} seconds")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print(f"❌ Failed to update device: HTTP {response.status_code}")
|
||||||
|
print(f" Response: {response.text}")
|
||||||
|
else:
|
||||||
|
print("✅ Device configuration is correct")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("❌ Stockholm device not found")
|
||||||
|
print("Available devices:")
|
||||||
|
for device in devices:
|
||||||
|
print(f" - ID {device['id']}: {device.get('name', 'Unnamed')}")
|
||||||
|
else:
|
||||||
|
print(f"❌ No devices found")
|
||||||
|
else:
|
||||||
|
print(f"❌ HTTP Error: {response.status_code}")
|
||||||
|
print(f" Response: {response.text}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error: {e}")
|
||||||
|
|
||||||
|
def send_test_heartbeat():
|
||||||
|
"""Send a test heartbeat after fixing the device"""
|
||||||
|
print(f"\n💓 Sending Test Heartbeat")
|
||||||
|
print("-" * 30)
|
||||||
|
|
||||||
|
try:
|
||||||
|
payload = {
|
||||||
|
'type': 'heartbeat',
|
||||||
|
'key': '1001' # Stockholm device key
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(
|
||||||
|
f"{API_BASE_URL}/detectors",
|
||||||
|
json=payload,
|
||||||
|
headers=get_auth_headers(),
|
||||||
|
verify=False,
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f"📊 Response: {response.status_code}")
|
||||||
|
if response.status_code in [200, 201]:
|
||||||
|
data = response.json()
|
||||||
|
print(f"✅ Heartbeat sent successfully: {data.get('message', 'OK')}")
|
||||||
|
else:
|
||||||
|
print(f"❌ Error: {response.text}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Error sending heartbeat: {e}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print(f"🔗 API URL: {API_BASE_URL}")
|
||||||
|
print(f"⏰ Time: {datetime.now()}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Authenticate first
|
||||||
|
print("🔐 Authenticating...")
|
||||||
|
if not authenticate():
|
||||||
|
print("❌ Authentication failed")
|
||||||
|
return
|
||||||
|
|
||||||
|
fix_stockholm_device()
|
||||||
|
send_test_heartbeat()
|
||||||
|
|
||||||
|
print(f"\n✅ Stockholm device fix complete")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -89,6 +89,19 @@ router.get('/', authenticateToken, async (req, res) => {
|
|||||||
const expectedInterval = device.heartbeat_interval || 300;
|
const expectedInterval = device.heartbeat_interval || 300;
|
||||||
const isOnline = timeSinceLastHeartbeat && timeSinceLastHeartbeat < (expectedInterval * 2);
|
const isOnline = timeSinceLastHeartbeat && timeSinceLastHeartbeat < (expectedInterval * 2);
|
||||||
|
|
||||||
|
// Debug logging for device status calculation
|
||||||
|
if (device.id === 1001) { // Stockholm device
|
||||||
|
console.log(`🔍 DEBUG Device ${device.id} status calculation:`);
|
||||||
|
console.log(` Now: ${now.toISOString()}`);
|
||||||
|
console.log(` Last heartbeat: ${device.last_heartbeat}`);
|
||||||
|
console.log(` Time since last: ${timeSinceLastHeartbeat} seconds`);
|
||||||
|
console.log(` Expected interval: ${expectedInterval} seconds`);
|
||||||
|
console.log(` Threshold: ${expectedInterval * 2} seconds`);
|
||||||
|
console.log(` Is online: ${isOnline}`);
|
||||||
|
console.log(` Is active: ${device.is_active}`);
|
||||||
|
console.log(` Final status: ${device.is_active ? (isOnline ? 'online' : 'offline') : 'inactive'}`);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...device.toJSON(),
|
...device.toJSON(),
|
||||||
stats: {
|
stats: {
|
||||||
|
|||||||
@@ -18,11 +18,63 @@ warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
|||||||
API_BASE_URL = os.getenv('API_BASE_URL', 'http://localhost:3002/api')
|
API_BASE_URL = os.getenv('API_BASE_URL', 'http://localhost:3002/api')
|
||||||
BASE_PATH = os.getenv('VITE_BASE_PATH', '').rstrip('/')
|
BASE_PATH = os.getenv('VITE_BASE_PATH', '').rstrip('/')
|
||||||
|
|
||||||
|
# Authentication configuration - Optional for local testing
|
||||||
|
USERNAME = os.getenv('TEST_USERNAME', 'admin')
|
||||||
|
PASSWORD = os.getenv('TEST_PASSWORD', 'admin123')
|
||||||
|
SKIP_AUTH = os.getenv('SKIP_AUTH', 'false').lower() == 'true'
|
||||||
|
|
||||||
# If BASE_PATH is set, construct the full URL
|
# If BASE_PATH is set, construct the full URL
|
||||||
if BASE_PATH and not API_BASE_URL.endswith('/api'):
|
if BASE_PATH and not API_BASE_URL.endswith('/api'):
|
||||||
domain = API_BASE_URL.replace('/api', '').replace('/drones/api', '').replace('/uggla/api', '')
|
domain = API_BASE_URL.replace('/api', '').replace('/drones/api', '').replace('/uggla/api', '')
|
||||||
API_BASE_URL = f"{domain}{BASE_PATH}/api"
|
API_BASE_URL = f"{domain}{BASE_PATH}/api"
|
||||||
|
|
||||||
|
# Global variable to store authentication token
|
||||||
|
AUTH_TOKEN = None
|
||||||
|
|
||||||
|
def authenticate():
|
||||||
|
"""Authenticate with the API and get access token"""
|
||||||
|
global AUTH_TOKEN
|
||||||
|
|
||||||
|
if SKIP_AUTH:
|
||||||
|
print("🔓 Authentication skipped (SKIP_AUTH=true)")
|
||||||
|
return True
|
||||||
|
|
||||||
|
try:
|
||||||
|
login_data = {
|
||||||
|
"username": USERNAME,
|
||||||
|
"password": PASSWORD
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(f"{API_BASE_URL}/users/login", json=login_data, verify=False, timeout=10)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
if data.get('success') and 'data' in data and 'token' in data['data']:
|
||||||
|
AUTH_TOKEN = data['data']['token']
|
||||||
|
print(f"✅ Authentication successful")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"❌ Invalid login response: {data}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print(f"❌ Authentication failed: HTTP {response.status_code}")
|
||||||
|
print(f" Response: {response.text}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Authentication error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_auth_headers():
|
||||||
|
"""Get headers with authentication token"""
|
||||||
|
headers = {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
|
||||||
|
if not SKIP_AUTH and AUTH_TOKEN:
|
||||||
|
headers['Authorization'] = f'Bearer {AUTH_TOKEN}'
|
||||||
|
|
||||||
|
return headers
|
||||||
|
|
||||||
def test_device_health_status():
|
def test_device_health_status():
|
||||||
"""Test device health monitoring status"""
|
"""Test device health monitoring status"""
|
||||||
print("🔍 Testing Device Health Monitoring System")
|
print("🔍 Testing Device Health Monitoring System")
|
||||||
@@ -91,7 +143,7 @@ def test_device_list():
|
|||||||
print("-" * 40)
|
print("-" * 40)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.get(f"{API_BASE_URL}/devices", verify=False, timeout=10)
|
response = requests.get(f"{API_BASE_URL}/devices", headers=get_auth_headers(), verify=False, timeout=10)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
data = response.json()
|
data = response.json()
|
||||||
@@ -137,7 +189,7 @@ def test_alert_rules():
|
|||||||
print("-" * 40)
|
print("-" * 40)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.get(f"{API_BASE_URL}/alerts/rules", verify=False, timeout=10)
|
response = requests.get(f"{API_BASE_URL}/alerts/rules", headers=get_auth_headers(), verify=False, timeout=10)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
data = response.json()
|
data = response.json()
|
||||||
@@ -181,6 +233,12 @@ def main():
|
|||||||
print(f"⏰ Test Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
print(f"⏰ Test Time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
# Authenticate first
|
||||||
|
print("🔐 Authenticating...")
|
||||||
|
if not authenticate():
|
||||||
|
print("❌ Authentication failed, some tests may not work")
|
||||||
|
print()
|
||||||
|
|
||||||
# Run all tests
|
# Run all tests
|
||||||
test_device_health_status()
|
test_device_health_status()
|
||||||
test_device_list()
|
test_device_list()
|
||||||
|
|||||||
Reference in New Issue
Block a user