mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-02-04 13:21:45 +00:00
feat: add support for SCIM provisioning (#1182)
This commit is contained in:
172
tests/specs/scim.spec.ts
Normal file
172
tests/specs/scim.spec.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import test, { expect, type Page } from '@playwright/test';
|
||||
import { cleanupBackend, cleanupScimServiceProvider } from 'utils/cleanup.util';
|
||||
import { oidcClients, userGroups, users } from '../data';
|
||||
|
||||
async function configureOidcClient(page: Page) {
|
||||
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
|
||||
|
||||
await page.getByRole('button', { name: 'Expand card' }).nth(1).click();
|
||||
|
||||
await page
|
||||
.getByLabel('SCIM Endpoint')
|
||||
.fill(process.env.SCIM_SERVICE_PROVIDER_URL_INTERNAL || 'http://scim.provider/api');
|
||||
|
||||
await page.getByRole('button', { name: 'Enable' }).click();
|
||||
}
|
||||
|
||||
async function syncScimServiceProvider(page: Page) {
|
||||
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
|
||||
|
||||
await page.getByRole('button', { name: 'Sync now' }).click();
|
||||
await page.waitForSelector('[data-type="success"]');
|
||||
}
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await cleanupBackend({ skipLdapSetup: true });
|
||||
});
|
||||
|
||||
test.describe('SCIM Configuration', () => {
|
||||
test('Enable SCIM for OIDC client', async ({ page }) => {
|
||||
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
|
||||
|
||||
await page.getByRole('button', { name: 'Expand card' }).nth(1).click();
|
||||
|
||||
await page.getByLabel('SCIM Endpoint').fill('http://scim.provider/api');
|
||||
await page.getByLabel('SCIM Token').fill('supersecrettoken');
|
||||
|
||||
await page.getByRole('button', { name: 'Enable' }).click();
|
||||
|
||||
await expect(page.locator('[data-type="success"]')).toHaveText('SCIM enabled successfully.');
|
||||
|
||||
await page.reload();
|
||||
|
||||
await expect(page.getByLabel('SCIM Endpoint')).toHaveValue('http://scim.provider/api');
|
||||
await expect(page.getByLabel('SCIM Token')).toHaveValue('supersecrettoken');
|
||||
});
|
||||
|
||||
test('Update SCIM of OIDC client', async ({ page }) => {
|
||||
await configureOidcClient(page);
|
||||
|
||||
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
|
||||
|
||||
await page.getByLabel('SCIM Endpoint').fill('http://new.scim.provider/api');
|
||||
await page.getByLabel('SCIM Token').fill('evenmoresecrettoken');
|
||||
|
||||
await page.getByRole('button', { name: 'Save' }).nth(1).click();
|
||||
|
||||
await expect(page.locator('[data-type="success"]')).toHaveText(
|
||||
'SCIM configuration updated successfully.'
|
||||
);
|
||||
|
||||
await page.reload();
|
||||
|
||||
await expect(page.getByLabel('SCIM Endpoint')).toHaveValue('http://new.scim.provider/api');
|
||||
await expect(page.getByLabel('SCIM Token')).toHaveValue('evenmoresecrettoken');
|
||||
});
|
||||
|
||||
test('Disable SCIM of OIDC client', async ({ page }) => {
|
||||
await configureOidcClient(page);
|
||||
|
||||
await page.goto(`/settings/admin/oidc-clients/${oidcClients.scim.id}`);
|
||||
|
||||
await page.getByRole('button', { name: 'Disable' }).click();
|
||||
await page.getByRole('button', { name: 'Disable' }).nth(1).click();
|
||||
|
||||
await expect(page.locator('[data-type="success"]')).toHaveText('SCIM disabled successfully.');
|
||||
|
||||
await page.reload();
|
||||
|
||||
await expect(page.getByRole('button', { name: 'Enable' })).toBeVisible();
|
||||
await expect(page.getByLabel('SCIM Endpoint')).toHaveValue('');
|
||||
await expect(page.getByLabel('SCIM Token')).toHaveValue('');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('SCIM Sync', () => {
|
||||
test.skip(
|
||||
!process.env.SCIM_SERVICE_PROVIDER_URL || !process.env.SCIM_SERVICE_PROVIDER_URL_INTERNAL,
|
||||
'Skipping SCIM Sync tests because SCIM_SERVICE_PROVIDER_URL or SCIM_SERVICE_PROVIDER_URL_INTERNAL is not set'
|
||||
);
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await Promise.all([configureOidcClient(page), cleanupScimServiceProvider()]);
|
||||
});
|
||||
|
||||
test('Sync client', async ({ page }) => {
|
||||
await syncScimServiceProvider(page);
|
||||
|
||||
const scimUsers = await getScimResources('Users');
|
||||
await expect(scimUsers.length).toBe(2);
|
||||
|
||||
const groups = await getScimResources('Groups');
|
||||
await expect(groups.length).toBe(2);
|
||||
|
||||
const timUser = scimUsers.find((u: any) => u.userName === 'tim');
|
||||
await expect(timUser).toBeDefined();
|
||||
await expect(timUser).toMatchObject({
|
||||
externalId: users.tim.id,
|
||||
emails: [
|
||||
{
|
||||
value: users.tim.email,
|
||||
primary: true
|
||||
}
|
||||
],
|
||||
name: {
|
||||
givenName: users.tim.firstname,
|
||||
familyName: users.tim.lastname
|
||||
},
|
||||
displayName: users.tim.displayName,
|
||||
active: true
|
||||
});
|
||||
});
|
||||
|
||||
test('Remove allowed group and sync', async ({ page }) => {
|
||||
await syncScimServiceProvider(page);
|
||||
|
||||
await page.getByRole('button', { name: 'Expand card' }).first().click();
|
||||
|
||||
await page
|
||||
.getByRole('row', { name: userGroups.developers.name })
|
||||
.getByRole('cell')
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await page.getByRole('button', { name: 'Save' }).nth(1).click();
|
||||
|
||||
await syncScimServiceProvider(page);
|
||||
|
||||
const scimUsers = await getScimResources('Users');
|
||||
await expect(scimUsers.length).toBe(1);
|
||||
await expect(scimUsers.find((u: any) => u.userName === users.tim.username)).toBeDefined();
|
||||
|
||||
const scimGroups = await getScimResources('Groups');
|
||||
await expect(scimGroups.length).toBe(1);
|
||||
await expect(
|
||||
scimGroups.find((g: any) => g.displayName === userGroups.designers.friendlyName)
|
||||
).toBeDefined();
|
||||
});
|
||||
|
||||
test('Remove group restrictions and sync', async ({ page }) => {
|
||||
await syncScimServiceProvider(page);
|
||||
|
||||
await page.getByRole('button', { name: 'Expand card' }).first().click();
|
||||
|
||||
await page.getByRole('button', { name: 'Unrestrict' }).click();
|
||||
await page.getByRole('button', { name: 'Unrestrict' }).nth(1).click();
|
||||
|
||||
await syncScimServiceProvider(page);
|
||||
|
||||
const scimUsers = await getScimResources('Users');
|
||||
await expect(scimUsers.length).toBe(3);
|
||||
|
||||
const scimGroups = await getScimResources('Groups');
|
||||
await expect(scimGroups.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
async function getScimResources(resourceType: 'Users' | 'Groups') {
|
||||
const response = await fetch(`${process.env.SCIM_SERVICE_PROVIDER_URL}/${resourceType}`).then(
|
||||
(res) => res.json()
|
||||
);
|
||||
return response['Resources'];
|
||||
}
|
||||
Reference in New Issue
Block a user