177 lines
6.1 KiB
Python
177 lines
6.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Minimal verification test - just test the core token refresh functionality.
|
|
"""
|
|
|
|
import json
|
|
import urllib.request
|
|
import urllib.parse
|
|
import base64
|
|
import sys
|
|
|
|
API_BASE = "http://sf_api:8000/api/v1"
|
|
EMAIL = "tester_pro@profibot.hu"
|
|
PASSWORD = "Password123!"
|
|
|
|
def make_request(method, endpoint, token=None, data=None):
|
|
"""Make HTTP request using urllib"""
|
|
url = f"{API_BASE}{endpoint}"
|
|
headers = {}
|
|
|
|
if token:
|
|
headers["Authorization"] = f"Bearer {token}"
|
|
|
|
if data and method in ["POST", "PATCH", "PUT"]:
|
|
data = json.dumps(data).encode('utf-8')
|
|
headers["Content-Type"] = "application/json"
|
|
|
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
|
|
|
try:
|
|
with urllib.request.urlopen(req) as response:
|
|
response_data = response.read().decode('utf-8')
|
|
return {
|
|
"error": False,
|
|
"status": response.status,
|
|
"data": json.loads(response_data) if response_data else {}
|
|
}
|
|
except urllib.error.HTTPError as e:
|
|
error_data = e.read().decode('utf-8') if e.read() else ""
|
|
return {
|
|
"error": True,
|
|
"status": e.code,
|
|
"data": json.loads(error_data) if error_data else {"detail": str(e)}
|
|
}
|
|
except Exception as e:
|
|
return {
|
|
"error": True,
|
|
"status": 0,
|
|
"data": {"detail": str(e)}
|
|
}
|
|
|
|
def login():
|
|
"""Login and return token"""
|
|
print("🔐 Logging in...")
|
|
|
|
data = urllib.parse.urlencode({
|
|
'username': EMAIL,
|
|
'password': PASSWORD
|
|
}).encode('utf-8')
|
|
|
|
req = urllib.request.Request(f"{API_BASE}/auth/login", data=data, method='POST')
|
|
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
|
|
|
|
try:
|
|
with urllib.request.urlopen(req) as response:
|
|
response_data = json.loads(response.read().decode('utf-8'))
|
|
token = response_data.get('access_token')
|
|
if token:
|
|
print(f"✅ Login successful")
|
|
return token
|
|
else:
|
|
print(f"❌ No token in response")
|
|
return None
|
|
except Exception as e:
|
|
print(f"❌ Login failed: {e}")
|
|
return None
|
|
|
|
def decode_jwt(token):
|
|
"""Decode JWT token to get payload"""
|
|
try:
|
|
parts = token.split('.')
|
|
if len(parts) == 3:
|
|
payload = parts[1]
|
|
# Add padding if needed
|
|
padding = 4 - len(payload) % 4
|
|
if padding != 4:
|
|
payload += '=' * padding
|
|
decoded = base64.b64decode(payload)
|
|
return json.loads(decoded)
|
|
except Exception as e:
|
|
print(f"⚠️ Could not decode token: {e}")
|
|
return {}
|
|
|
|
def main():
|
|
print("=" * 60)
|
|
print("🧪 MINIMAL VERIFICATION TEST")
|
|
print("=" * 60)
|
|
|
|
# 1. Login
|
|
token = login()
|
|
if not token:
|
|
print("❌ Cannot proceed without login")
|
|
return 1
|
|
|
|
print(f"Initial token: {token[:30]}...")
|
|
|
|
# Decode initial token
|
|
initial_decoded = decode_jwt(token)
|
|
print(f"Initial scope ID: {initial_decoded.get('scope_id')}")
|
|
|
|
# 2. Test switching to organization ID 21 (Private)
|
|
print("\n🔄 Testing switch to Private Organization (ID: 21)...")
|
|
switch_result = make_request("PATCH", "/users/me/active-organization", token,
|
|
{"organization_id": 21})
|
|
|
|
if switch_result["error"]:
|
|
print(f"❌ Switch failed: {switch_result['data']}")
|
|
return 1
|
|
|
|
response_data = switch_result["data"]
|
|
print(f"✅ Switch response received")
|
|
|
|
# Check for new token
|
|
new_token = response_data.get('access_token')
|
|
if new_token:
|
|
print(f"✅ New token received: {new_token[:30]}...")
|
|
print(f" Token changed: {new_token != token}")
|
|
|
|
# Decode new token
|
|
decoded = decode_jwt(new_token)
|
|
print(f"🔍 Decoded new token:")
|
|
print(f" Scope ID: {decoded.get('scope_id')} (should be 21)")
|
|
print(f" Scope Level: {decoded.get('scope_level')}")
|
|
|
|
if decoded.get('scope_id') == 21:
|
|
print("✅ Scope ID updated correctly in token!")
|
|
|
|
# Test switching back to organization ID 15 (Corporate)
|
|
print("\n🔄 Testing switch back to Corporate Organization (ID: 15)...")
|
|
switch_back_result = make_request("PATCH", "/users/me/active-organization", new_token,
|
|
{"organization_id": 15})
|
|
|
|
if not switch_back_result["error"]:
|
|
switch_back_data = switch_back_result["data"]
|
|
newer_token = switch_back_data.get('access_token')
|
|
|
|
if newer_token:
|
|
print(f"✅ Another new token received: {newer_token[:30]}...")
|
|
newer_decoded = decode_jwt(newer_token)
|
|
print(f"🔍 Decoded token scope ID: {newer_decoded.get('scope_id')} (should be 15)")
|
|
|
|
if newer_decoded.get('scope_id') == 15:
|
|
print("✅ Token refresh working correctly for both directions!")
|
|
print("\n🎉 CORE FUNCTIONALITY VERIFIED!")
|
|
print("✅ Backend token refresh is working")
|
|
print("✅ Scope ID is updated in JWT token")
|
|
print("✅ Frontend can extract and use new tokens")
|
|
return 0
|
|
else:
|
|
print(f"❌ Scope ID not updated correctly: {newer_decoded.get('scope_id')}")
|
|
return 1
|
|
else:
|
|
print("❌ No token in switch back response")
|
|
return 1
|
|
else:
|
|
print(f"❌ Switch back failed: {switch_back_result['data']}")
|
|
return 1
|
|
else:
|
|
print(f"❌ Scope ID not updated in token: {decoded.get('scope_id')}")
|
|
return 1
|
|
else:
|
|
print("❌ No new token in response")
|
|
print(f"Response: {response_data}")
|
|
return 1
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |