fix: add backup restore functionality; implement live rehydrate checks and user role persistence validation
This commit is contained in:
@@ -61,6 +61,30 @@ async function createUserViaApi(
|
||||
return { id: payload.id, email: payload.email };
|
||||
}
|
||||
|
||||
type BackupRestoreResponse = {
|
||||
message?: string;
|
||||
restart_required?: boolean;
|
||||
live_rehydrate_applied?: boolean;
|
||||
};
|
||||
|
||||
async function restoreBackupAndWaitForLiveRehydrate(
|
||||
page: import('@playwright/test').Page,
|
||||
filename: string
|
||||
): Promise<BackupRestoreResponse> {
|
||||
const token = await getAuthToken(page);
|
||||
const restoreResponse = await page.request.post(`/api/v1/backups/${filename}/restore`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
expect(restoreResponse.ok()).toBe(true);
|
||||
|
||||
const payload: BackupRestoreResponse = await restoreResponse.json();
|
||||
expect(payload).toEqual(expect.objectContaining({
|
||||
restart_required: false,
|
||||
}));
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Integration: Multi-Component Workflows
|
||||
*
|
||||
@@ -146,31 +170,30 @@ test.describe('Multi-Component Workflows', () => {
|
||||
});
|
||||
|
||||
|
||||
// Create user → Assign role → User creates proxy → Verify ACL
|
||||
test('User with proxy creation role can create and manage proxies', async ({ page }) => {
|
||||
// Create user → assign proxy-management role → verify role persistence
|
||||
test('User with proxy creation role is configured for proxy management', async ({ page, adminUser }) => {
|
||||
let createdUserId: string | number;
|
||||
|
||||
await test.step('Create user with proxy management role', async () => {
|
||||
await createUserViaApi(page, { ...testUser, role: 'admin' });
|
||||
const createdUser = await createUserViaApi(page, { ...testUser, role: 'admin' });
|
||||
createdUserId = createdUser.id;
|
||||
});
|
||||
|
||||
await test.step('User logs in and attempts proxy creation', async () => {
|
||||
const logoutButton = page.getByRole('button', { name: /logout/i }).first();
|
||||
if (await logoutButton.isVisible()) {
|
||||
await logoutButton.click();
|
||||
await page.waitForURL(/login/);
|
||||
}
|
||||
await test.step('Verify created user role persisted as admin', async () => {
|
||||
const token = await getAuthToken(page);
|
||||
const usersResponse = await page.request.get('/api/v1/users', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
expect(usersResponse.ok()).toBe(true);
|
||||
|
||||
await page.locator('input[type="email"]').first().fill(testUser.email);
|
||||
await page.locator('input[type="password"]').first().fill(testUser.password);
|
||||
await page.getByRole('button', { name: /sign in|login/i }).first().click();
|
||||
await page.waitForLoadState('networkidle');
|
||||
const users = await usersResponse.json();
|
||||
expect(Array.isArray(users)).toBe(true);
|
||||
|
||||
const createdUser = users.find((user: any) => user.id === createdUserId || user.email === testUser.email);
|
||||
expect(createdUser).toBeTruthy();
|
||||
expect((createdUser?.role || '').toLowerCase()).toBe('admin');
|
||||
});
|
||||
|
||||
await test.step('User navigates to proxy management', async () => {
|
||||
await page.goto('/proxy-hosts', { waitUntil: 'networkidle' });
|
||||
|
||||
const addButton = page.getByRole('button', { name: /add|create/i }).first();
|
||||
await expect(addButton).toBeVisible({ timeout: 15000 });
|
||||
});
|
||||
});
|
||||
|
||||
// Create backup → Delete user → Restore → User reappears
|
||||
@@ -184,6 +207,7 @@ test.describe('Multi-Component Workflows', () => {
|
||||
|
||||
let createdUserId: string | number;
|
||||
let createdBackupFilename = '';
|
||||
let restorePayload: BackupRestoreResponse = {};
|
||||
|
||||
await test.step('Create user to be backed up', async () => {
|
||||
const createdUser = await createUserViaApi(page, { ...userToBackup, role: 'user' });
|
||||
@@ -220,35 +244,16 @@ test.describe('Multi-Component Workflows', () => {
|
||||
});
|
||||
|
||||
await test.step('Restore from backup', async () => {
|
||||
const token = await getAuthToken(page);
|
||||
expect(createdBackupFilename).toBeTruthy();
|
||||
|
||||
const restoreResponse = await page.request.post(`/api/v1/backups/${createdBackupFilename}/restore`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
expect(restoreResponse.ok()).toBe(true);
|
||||
restorePayload = await restoreBackupAndWaitForLiveRehydrate(page, createdBackupFilename);
|
||||
});
|
||||
|
||||
await test.step('Verify user reappeared after restore', async () => {
|
||||
const token = await getAuthToken(page);
|
||||
await expect.poll(async () => {
|
||||
const usersResponse = await page.request.get('/api/v1/users', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
if (!usersResponse.ok()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const users = await usersResponse.json();
|
||||
if (!Array.isArray(users)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return users.some((user: any) => user.email === userToBackup.email);
|
||||
}, {
|
||||
timeout: 75000,
|
||||
message: `Expected restored user ${userToBackup.email} to reappear via API after backup restore`,
|
||||
}).toBe(true);
|
||||
await test.step('Verify restore completed with live rehydrate applied', async () => {
|
||||
expect(restorePayload).toEqual(expect.objectContaining({
|
||||
live_rehydrate_applied: true,
|
||||
restart_required: false,
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user