feat: add CrowdSec API key status handling and warning component
- Implemented `getCrowdsecKeyStatus` API call to retrieve the current status of the CrowdSec API key. - Created `CrowdSecKeyWarning` component to display warnings when the API key is rejected. - Integrated `CrowdSecKeyWarning` into the Security page, ensuring it only shows when relevant. - Updated i18n initialization in main.tsx to prevent race conditions during rendering. - Enhanced authentication setup in tests to handle various response statuses more robustly. - Adjusted security tests to accept broader error responses for import validation.
This commit is contained in:
+75
-51
@@ -1,4 +1,5 @@
|
||||
import { test as setup, expect } from '@bgotink/playwright-coverage';
|
||||
import { test as setup } from '@bgotink/playwright-coverage';
|
||||
import type { APIRequestContext } from '@playwright/test';
|
||||
import { STORAGE_STATE } from './constants';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
@@ -23,10 +24,80 @@ const TEST_NAME = process.env.E2E_TEST_NAME || 'E2E Test User';
|
||||
// Re-export STORAGE_STATE for backwards compatibility with playwright.config.js
|
||||
export { STORAGE_STATE };
|
||||
|
||||
/**
|
||||
* Performs login and stores auth state
|
||||
*/
|
||||
async function performLoginAndSaveState(
|
||||
request: APIRequestContext,
|
||||
setupRequired: boolean,
|
||||
baseURL: string | undefined
|
||||
): Promise<void> {
|
||||
console.log('Logging in as test user...');
|
||||
const loginResponse = await request.post('/api/v1/auth/login', {
|
||||
data: {
|
||||
email: TEST_EMAIL,
|
||||
password: TEST_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
if (!loginResponse.ok()) {
|
||||
const errorBody = await loginResponse.text();
|
||||
console.log(`Login failed: ${loginResponse.status()} - ${errorBody}`);
|
||||
|
||||
if (!setupRequired) {
|
||||
console.log('Login failed - existing user may have different credentials.');
|
||||
console.log('Please set E2E_TEST_EMAIL and E2E_TEST_PASSWORD environment variables');
|
||||
console.log('to match an existing user, or clear the database for fresh setup.');
|
||||
}
|
||||
throw new Error(`Login failed: ${loginResponse.status()} - ${errorBody}`);
|
||||
}
|
||||
|
||||
console.log('Login successful');
|
||||
|
||||
// Store the authentication state
|
||||
await request.storageState({ path: STORAGE_STATE });
|
||||
console.log(`Auth state saved to ${STORAGE_STATE}`);
|
||||
|
||||
// Verify cookie domain matches expected base URL
|
||||
try {
|
||||
const savedState = JSON.parse(readFileSync(STORAGE_STATE, 'utf-8'));
|
||||
const cookies = savedState.cookies || [];
|
||||
const authCookie = cookies.find((c: { name: string }) => c.name === 'auth_token');
|
||||
|
||||
if (authCookie?.domain && baseURL) {
|
||||
const expectedHost = new URL(baseURL).hostname;
|
||||
if (authCookie.domain !== expectedHost && authCookie.domain !== `.${expectedHost}`) {
|
||||
console.warn(`⚠️ Cookie domain mismatch: cookie domain "${authCookie.domain}" does not match baseURL host "${expectedHost}"`);
|
||||
console.warn('TestDataManager API calls may fail with 401. Ensure PLAYWRIGHT_BASE_URL uses localhost.');
|
||||
} else {
|
||||
console.log(`✅ Cookie domain "${authCookie.domain}" matches baseURL host "${expectedHost}"`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('⚠️ Could not validate cookie domain:', err instanceof Error ? err.message : err);
|
||||
}
|
||||
}
|
||||
|
||||
setup('authenticate', async ({ request, baseURL }) => {
|
||||
// Step 1: Check if setup is required
|
||||
const setupStatusResponse = await request.get('/api/v1/setup');
|
||||
expect(setupStatusResponse.ok()).toBeTruthy();
|
||||
|
||||
// Accept 200 (normal) or 401 (already initialized/auth required)
|
||||
// Provide diagnostic info on unexpected status for actionable failures
|
||||
const status = setupStatusResponse.status();
|
||||
if (![200, 401].includes(status)) {
|
||||
const body = await setupStatusResponse.text();
|
||||
throw new Error(
|
||||
`GET /api/v1/setup failed with unexpected status ${status}: ${body}\n` +
|
||||
`Verify PLAYWRIGHT_BASE_URL (${baseURL}) points to a running backend.`
|
||||
);
|
||||
}
|
||||
|
||||
// If 401, setup is already complete - proceed to login
|
||||
if (status === 401) {
|
||||
console.log('Setup endpoint returned 401 - setup already complete, proceeding to login');
|
||||
return await performLoginAndSaveState(request, false, baseURL);
|
||||
}
|
||||
|
||||
const setupStatus = await setupStatusResponse.json();
|
||||
|
||||
@@ -48,53 +119,6 @@ setup('authenticate', async ({ request, baseURL }) => {
|
||||
console.log('Initial setup completed successfully');
|
||||
}
|
||||
|
||||
// Step 3: Login to get auth token
|
||||
console.log('Logging in as test user...');
|
||||
const loginResponse = await request.post('/api/v1/auth/login', {
|
||||
data: {
|
||||
email: TEST_EMAIL,
|
||||
password: TEST_PASSWORD,
|
||||
},
|
||||
});
|
||||
|
||||
if (!loginResponse.ok()) {
|
||||
const errorBody = await loginResponse.text();
|
||||
console.log(`Login failed: ${loginResponse.status()} - ${errorBody}`);
|
||||
|
||||
// If login fails and setup wasn't required, the user might already exist with different credentials
|
||||
// This can happen in dev environments
|
||||
if (!setupStatus.setupRequired) {
|
||||
console.log('Login failed - existing user may have different credentials.');
|
||||
console.log('Please set E2E_TEST_EMAIL and E2E_TEST_PASSWORD environment variables');
|
||||
console.log('to match an existing user, or clear the database for fresh setup.');
|
||||
}
|
||||
throw new Error(`Login failed: ${loginResponse.status()} - ${errorBody}`);
|
||||
}
|
||||
|
||||
const loginData = await loginResponse.json();
|
||||
console.log('Login successful');
|
||||
|
||||
// Step 4: Store the authentication state
|
||||
// The login endpoint sets an auth_token cookie, we need to save the storage state
|
||||
await request.storageState({ path: STORAGE_STATE });
|
||||
console.log(`Auth state saved to ${STORAGE_STATE}`);
|
||||
|
||||
// Step 5: Verify cookie domain matches expected base URL
|
||||
try {
|
||||
const savedState = JSON.parse(readFileSync(STORAGE_STATE, 'utf-8'));
|
||||
const cookies = savedState.cookies || [];
|
||||
const authCookie = cookies.find((c: { name: string }) => c.name === 'auth_token');
|
||||
|
||||
if (authCookie?.domain && baseURL) {
|
||||
const expectedHost = new URL(baseURL).hostname;
|
||||
if (authCookie.domain !== expectedHost && authCookie.domain !== `.${expectedHost}`) {
|
||||
console.warn(`⚠️ Cookie domain mismatch: cookie domain "${authCookie.domain}" does not match baseURL host "${expectedHost}"`);
|
||||
console.warn('TestDataManager API calls may fail with 401. Ensure PLAYWRIGHT_BASE_URL uses localhost.');
|
||||
} else {
|
||||
console.log(`✅ Cookie domain "${authCookie.domain}" matches baseURL host "${expectedHost}"`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('⚠️ Could not validate cookie domain:', err instanceof Error ? err.message : err);
|
||||
}
|
||||
// Step 3: Login and save auth state
|
||||
await performLoginAndSaveState(request, setupStatus.setupRequired, baseURL);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user