fix: resolve stale credentials causing astrolabe background sync test failures
The revoke test failed because it only completed Step 2 (app password) but not Step 1 (OAuth authorization). In hybrid mode, Astrolabe requires both steps for $isFullyConfigured=true, which gates the "Revoke Access" button. Changes: - Use complete_astrolabe_authorization() in revoke test for full two-step flow - Add stale state cleanup (app passwords, bruteforce entries, Astrolabe prefs) to both enablement and revoke tests - Add startup cleanup of invalid app passwords in BasicAuth mode - Pre-validate credentials before entering scanner loop to fail fast - Handle 401/403/429 in scanner with proper backoff and circuit breaking - Clean up app passwords in test_users_setup fixture teardown Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2400,6 +2400,30 @@ async def test_users_setup(anyio_backend, nc_client: NextcloudClient):
|
||||
except Exception as e:
|
||||
logger.warning(f"Error deleting test user {username}: {e}")
|
||||
|
||||
# Clean up app passwords from MCP server to prevent stale scanners
|
||||
for username in created_users:
|
||||
try:
|
||||
import subprocess
|
||||
|
||||
subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"compose",
|
||||
"exec",
|
||||
"-T",
|
||||
"mcp-multi-user-basic",
|
||||
"sqlite3",
|
||||
"/app/data/tokens.db",
|
||||
f"DELETE FROM app_passwords WHERE user_id = '{username}';",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
)
|
||||
logger.info(f"Cleaned up app password for {username}")
|
||||
except Exception as e:
|
||||
logger.debug(f"App password cleanup for {username}: {e}")
|
||||
|
||||
|
||||
async def _get_oauth_token_for_user(
|
||||
browser,
|
||||
|
||||
@@ -861,6 +861,43 @@ async def test_multi_user_astrolabe_background_sync_enablement(
|
||||
This tests ADR-002 Tier 2 authentication: User-specific app passwords for background operations
|
||||
in multi-user BasicAuth deployments.
|
||||
"""
|
||||
# Clear stale state from previous test runs
|
||||
logger.info("Clearing stale app passwords and bruteforce entries...")
|
||||
subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"compose",
|
||||
"exec",
|
||||
"-T",
|
||||
"mcp-multi-user-basic",
|
||||
"sqlite3",
|
||||
"/app/data/tokens.db",
|
||||
"DELETE FROM app_passwords;",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
)
|
||||
subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"compose",
|
||||
"exec",
|
||||
"-T",
|
||||
"db",
|
||||
"mariadb",
|
||||
"-u",
|
||||
"root",
|
||||
"-ppassword",
|
||||
"nextcloud",
|
||||
"-e",
|
||||
"DELETE FROM oc_bruteforce_attempts;",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
)
|
||||
|
||||
# Configure Astrolabe to point to the mcp-multi-user-basic server
|
||||
logger.info("Configuring Astrolabe for mcp-multi-user-basic server...")
|
||||
await configure_astrolabe_for_mcp_server(
|
||||
@@ -1198,6 +1235,64 @@ async def test_revoke_background_sync_access(
|
||||
This tests the fix for the issue where POST requests to the revoke endpoint
|
||||
were returning errors due to HTTP method mismatch (was DELETE, now POST).
|
||||
"""
|
||||
# Clear stale state from previous test runs
|
||||
logger.info(
|
||||
"Clearing stale app passwords, bruteforce entries, and Astrolabe preferences..."
|
||||
)
|
||||
subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"compose",
|
||||
"exec",
|
||||
"-T",
|
||||
"mcp-multi-user-basic",
|
||||
"sqlite3",
|
||||
"/app/data/tokens.db",
|
||||
"DELETE FROM app_passwords;",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
)
|
||||
subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"compose",
|
||||
"exec",
|
||||
"-T",
|
||||
"db",
|
||||
"mariadb",
|
||||
"-u",
|
||||
"root",
|
||||
"-ppassword",
|
||||
"nextcloud",
|
||||
"-e",
|
||||
"DELETE FROM oc_bruteforce_attempts;",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
)
|
||||
subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
"compose",
|
||||
"exec",
|
||||
"-T",
|
||||
"db",
|
||||
"mariadb",
|
||||
"-u",
|
||||
"root",
|
||||
"-ppassword",
|
||||
"nextcloud",
|
||||
"-e",
|
||||
"DELETE FROM oc_preferences WHERE appid = 'astrolabe';",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=10,
|
||||
)
|
||||
|
||||
# Configure Astrolabe to point to the mcp-multi-user-basic server
|
||||
logger.info("Configuring Astrolabe for mcp-multi-user-basic server...")
|
||||
await configure_astrolabe_for_mcp_server(
|
||||
@@ -1218,9 +1313,14 @@ async def test_revoke_background_sync_access(
|
||||
# Step 1: Login to Nextcloud
|
||||
await login_to_nextcloud(page, username, password)
|
||||
|
||||
# Step 2: Generate app password and enable background sync
|
||||
app_password = await generate_app_password(page, username)
|
||||
await enable_background_sync_via_app_password(page, username, app_password)
|
||||
# Step 2: Complete full authorization (OAuth Step 1 + App Password Step 2)
|
||||
auth_result = await complete_astrolabe_authorization(page, username, password)
|
||||
assert auth_result["step1"], (
|
||||
f"OAuth authorization (Step 1) failed for {username}"
|
||||
)
|
||||
assert auth_result["step2"], (
|
||||
f"App password setup (Step 2) failed for {username}"
|
||||
)
|
||||
|
||||
# Step 3: Verify background sync is enabled
|
||||
assert await verify_app_password_created(username), (
|
||||
|
||||
Reference in New Issue
Block a user