mirror of
https://github.com/logto-io/logto.git
synced 2025-01-27 21:39:16 -05:00
feat(core): sync site configs and oidc metadata for custom domain (#5260)
This commit is contained in:
parent
43ce51ce2a
commit
fa89d33252
4 changed files with 83 additions and 12 deletions
|
@ -109,6 +109,33 @@ describe('syncAppConfigsToRemote()', () => {
|
|||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should sync custom domains configs to remote', async () => {
|
||||
findApplicationById.mockResolvedValueOnce({
|
||||
...mockProtectedApplication,
|
||||
protectedAppMetadata: {
|
||||
...mockProtectedApplication.protectedAppMetadata,
|
||||
customDomains: [mockCustomDomain],
|
||||
},
|
||||
});
|
||||
await expect(syncAppConfigsToRemote(mockProtectedApplication.id)).resolves.not.toThrow();
|
||||
const { protectedAppMetadata, id, secret } = mockProtectedApplication;
|
||||
expect(updateProtectedAppSiteConfigs).toHaveBeenLastCalledWith(
|
||||
protectedAppConfigProviderConfig,
|
||||
mockCustomDomain.domain,
|
||||
{
|
||||
...protectedAppMetadata,
|
||||
host: mockCustomDomain.domain,
|
||||
sdkConfig: {
|
||||
appId: id,
|
||||
appSecret: secret,
|
||||
// Avoid mocking envset
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
endpoint: expect.anything(),
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkAndBuildProtectedAppData()', () => {
|
||||
|
|
|
@ -113,18 +113,35 @@ export const createProtectedAppLibrary = (queries: Queries) => {
|
|||
return;
|
||||
}
|
||||
|
||||
await updateProtectedAppSiteConfigs(
|
||||
protectedAppConfigProviderConfig,
|
||||
protectedAppMetadata.host,
|
||||
{
|
||||
...protectedAppMetadata,
|
||||
const { customDomains, ...rest } = protectedAppMetadata;
|
||||
|
||||
const siteConfigs = {
|
||||
...rest,
|
||||
sdkConfig: {
|
||||
appId: id,
|
||||
appSecret: secret,
|
||||
endpoint: EnvSet.values.endpoint.href,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
// Update default host (subdomain of the default domain)
|
||||
await updateProtectedAppSiteConfigs(
|
||||
protectedAppConfigProviderConfig,
|
||||
protectedAppMetadata.host,
|
||||
siteConfigs
|
||||
);
|
||||
|
||||
// Update custom domains sites
|
||||
if (customDomains && customDomains.length > 0) {
|
||||
await Promise.all(
|
||||
customDomains.map(async ({ domain }) => {
|
||||
await updateProtectedAppSiteConfigs(protectedAppConfigProviderConfig, domain, {
|
||||
...siteConfigs,
|
||||
host: domain,
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,6 +37,7 @@ const syncAppCustomDomainStatus = jest.fn(async () => ({
|
|||
customDomains: [mockDomainResponse],
|
||||
},
|
||||
}));
|
||||
const syncAppConfigsToRemote = jest.fn();
|
||||
|
||||
await mockIdGenerators();
|
||||
|
||||
|
@ -51,7 +52,7 @@ const tenantContext = new MockTenant(
|
|||
},
|
||||
undefined,
|
||||
{
|
||||
protectedApps: { addDomainToRemote, syncAppCustomDomainStatus },
|
||||
protectedApps: { addDomainToRemote, syncAppCustomDomainStatus, syncAppConfigsToRemote },
|
||||
applications: { validateProtectedApplicationById: jest.fn() },
|
||||
}
|
||||
);
|
||||
|
@ -78,7 +79,7 @@ describe('application protected app metadata routes', () => {
|
|||
});
|
||||
|
||||
describe('POST /applications/:applicationId/protected-app-metadata/custom-domains', () => {
|
||||
it('should return 201', async () => {
|
||||
it('should return 201 and update OIDC metadata and sync site configs', async () => {
|
||||
const response = await requester
|
||||
.post(`/applications/${mockProtectedApplication.id}/protected-app-metadata/custom-domains`)
|
||||
.send({
|
||||
|
@ -90,7 +91,18 @@ describe('application protected app metadata routes', () => {
|
|||
...mockProtectedApplication.protectedAppMetadata,
|
||||
customDomains: [mockDomainResponse],
|
||||
},
|
||||
oidcClientMetadata: {
|
||||
postLogoutRedirectUris: [
|
||||
`https://${mockProtectedApplication.protectedAppMetadata.host}`,
|
||||
`https://${mockDomain}`,
|
||||
],
|
||||
redirectUris: [
|
||||
`https://${mockProtectedApplication.protectedAppMetadata.host}/callback`,
|
||||
`https://${mockDomain}/callback`,
|
||||
],
|
||||
},
|
||||
});
|
||||
expect(syncAppConfigsToRemote).toHaveBeenCalledWith(mockProtectedApplication.id);
|
||||
});
|
||||
|
||||
it('throw when domain exists', async () => {
|
||||
|
|
|
@ -20,7 +20,7 @@ export default function applicationProtectedAppMetadataRoutes<T extends AuthedRo
|
|||
},
|
||||
libraries: {
|
||||
applications: { validateProtectedApplicationById },
|
||||
protectedApps: { addDomainToRemote, syncAppCustomDomainStatus },
|
||||
protectedApps: { addDomainToRemote, syncAppCustomDomainStatus, syncAppConfigsToRemote },
|
||||
},
|
||||
},
|
||||
]: RouterInitArgs<T>
|
||||
|
@ -68,7 +68,7 @@ export default function applicationProtectedAppMetadataRoutes<T extends AuthedRo
|
|||
const { id } = ctx.guard.params;
|
||||
const { domain } = ctx.guard.body;
|
||||
|
||||
const { protectedAppMetadata } = await findApplicationById(id);
|
||||
const { protectedAppMetadata, oidcClientMetadata } = await findApplicationById(id);
|
||||
assertThat(protectedAppMetadata, 'application.protected_app_not_configured');
|
||||
|
||||
assertThat(
|
||||
|
@ -87,8 +87,23 @@ export default function applicationProtectedAppMetadataRoutes<T extends AuthedRo
|
|||
const customDomain = await addDomainToRemote(domain);
|
||||
await updateApplicationById(id, {
|
||||
protectedAppMetadata: { ...protectedAppMetadata, customDomains: [customDomain] },
|
||||
oidcClientMetadata: {
|
||||
redirectUris: [...oidcClientMetadata.redirectUris, `https://${domain}/callback`],
|
||||
postLogoutRedirectUris: [
|
||||
...oidcClientMetadata.postLogoutRedirectUris,
|
||||
`https://${domain}`,
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await syncAppConfigsToRemote(id);
|
||||
} catch (error: unknown) {
|
||||
// Revert changes
|
||||
await updateApplicationById(id, { protectedAppMetadata, oidcClientMetadata });
|
||||
throw error;
|
||||
}
|
||||
|
||||
ctx.status = 201;
|
||||
return next();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue