mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
fix(console): should display custom domain as alternative endpoint in app details and guides (#4501)
fix(console): should display custom domain as alternative endpoint in app guide and details
This commit is contained in:
parent
e1fac554db
commit
926da108e8
6 changed files with 35 additions and 31 deletions
|
@ -12,7 +12,6 @@ import DynamicT from '@/ds-components/DynamicT';
|
|||
import FormField from '@/ds-components/FormField';
|
||||
import useCustomDomain from '@/hooks/use-custom-domain';
|
||||
import type { ConnectorFormType } from '@/types/connector';
|
||||
import { applyDomain } from '@/utils/domain';
|
||||
import { jsonValidator } from '@/utils/validator';
|
||||
|
||||
import ConfigFormFields from './ConfigFormFields';
|
||||
|
@ -32,7 +31,7 @@ function ConfigForm({ formItems, className, connectorId, connectorType }: Props)
|
|||
formState: { errors },
|
||||
} = useFormContext<ConnectorFormType>();
|
||||
const { tenantEndpoint } = useContext(AppDataContext);
|
||||
const { data: customDomain } = useCustomDomain();
|
||||
const { data: customDomain, applyDomain: applyCustomDomain } = useCustomDomain();
|
||||
const callbackUri = new URL(`/callback/${connectorId}`, tenantEndpoint).toString();
|
||||
|
||||
return (
|
||||
|
@ -45,11 +44,7 @@ function ConfigForm({ formItems, className, connectorId, connectorType }: Props)
|
|||
<CopyToClipboard
|
||||
className={styles.copyToClipboard}
|
||||
variant="border"
|
||||
value={
|
||||
customDomain?.status === DomainStatus.Active
|
||||
? applyDomain(callbackUri, customDomain.domain)
|
||||
: callbackUri
|
||||
}
|
||||
value={applyCustomDomain(callbackUri)}
|
||||
/>
|
||||
{customDomain?.status === DomainStatus.Active && tenantEndpoint && (
|
||||
<div className={styles.description}>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { type Domain } from '@logto/schemas';
|
||||
import { DomainStatus, type Domain } from '@logto/schemas';
|
||||
import { conditional } from '@silverhand/essentials';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import useSWR from 'swr';
|
||||
|
||||
import { customDomainSyncInterval } from '@/consts/custom-domain';
|
||||
import { isCloud } from '@/consts/env';
|
||||
import { isAbsoluteUrl } from '@/utils/url';
|
||||
|
||||
import { type RequestError } from './use-api';
|
||||
|
||||
|
@ -22,18 +24,30 @@ const useCustomDomain = (autoSync = false) => {
|
|||
/**
|
||||
* Note: we can only create a custom domain, and we don't have a default id for it, so the first element of the array is the custom domain.
|
||||
*/
|
||||
const customDomain = conditional(!isLoading && data)?.[0];
|
||||
const customDomain = useMemo(() => data?.[0], [data]);
|
||||
|
||||
const mutateDomain = useCallback(
|
||||
(domain?: Domain) => {
|
||||
void mutate(domain ? [domain] : undefined);
|
||||
},
|
||||
[mutate]
|
||||
);
|
||||
|
||||
const applyDomain = useCallback(
|
||||
(url: string) => {
|
||||
if (customDomain?.status !== DomainStatus.Active || !isAbsoluteUrl(url)) {
|
||||
return url;
|
||||
}
|
||||
return url.replace(new URL(url).host, customDomain.domain);
|
||||
},
|
||||
[customDomain]
|
||||
);
|
||||
|
||||
return {
|
||||
data: customDomain,
|
||||
isLoading,
|
||||
mutate: (domain?: Domain) => {
|
||||
if (domain) {
|
||||
void mutate([domain]);
|
||||
return;
|
||||
}
|
||||
void mutate();
|
||||
},
|
||||
mutate: mutateDomain,
|
||||
applyDomain,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ import Switch from '@/ds-components/Switch';
|
|||
import TextInput from '@/ds-components/TextInput';
|
||||
import TextLink from '@/ds-components/TextLink';
|
||||
import useCustomDomain from '@/hooks/use-custom-domain';
|
||||
import { applyDomain } from '@/utils/domain';
|
||||
|
||||
import * as styles from '../index.module.scss';
|
||||
|
||||
|
@ -44,10 +43,7 @@ function AdvancedSettings({ app: { type }, oidcConfig }: Props) {
|
|||
min: minTtl,
|
||||
max: maxTtl,
|
||||
});
|
||||
const { data: customDomain } = useCustomDomain();
|
||||
|
||||
const tryApplyCustomDomain = (url: string) =>
|
||||
customDomain?.status === DomainStatus.Active ? applyDomain(url, customDomain.domain) : url;
|
||||
const { data: customDomain, applyDomain: applyCustomDomain } = useCustomDomain();
|
||||
|
||||
return (
|
||||
<FormCard
|
||||
|
@ -59,7 +55,7 @@ function AdvancedSettings({ app: { type }, oidcConfig }: Props) {
|
|||
<FormField title="application_details.config_endpoint">
|
||||
<CopyToClipboard
|
||||
className={styles.textField}
|
||||
value={tryApplyCustomDomain(appendPath(tenantEndpoint, openIdProviderConfigPath).href)}
|
||||
value={applyCustomDomain(appendPath(tenantEndpoint, openIdProviderConfigPath).href)}
|
||||
variant="border"
|
||||
/>
|
||||
</FormField>
|
||||
|
@ -84,21 +80,21 @@ function AdvancedSettings({ app: { type }, oidcConfig }: Props) {
|
|||
>
|
||||
<CopyToClipboard
|
||||
className={styles.textField}
|
||||
value={tryApplyCustomDomain(oidcConfig.authorization_endpoint)}
|
||||
value={applyCustomDomain(oidcConfig.authorization_endpoint)}
|
||||
variant="border"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField title="application_details.token_endpoint">
|
||||
<CopyToClipboard
|
||||
className={styles.textField}
|
||||
value={tryApplyCustomDomain(oidcConfig.token_endpoint)}
|
||||
value={applyCustomDomain(oidcConfig.token_endpoint)}
|
||||
variant="border"
|
||||
/>
|
||||
</FormField>
|
||||
<FormField title="application_details.user_info_endpoint">
|
||||
<CopyToClipboard
|
||||
className={styles.textField}
|
||||
value={tryApplyCustomDomain(oidcConfig.userinfo_endpoint)}
|
||||
value={applyCustomDomain(oidcConfig.userinfo_endpoint)}
|
||||
variant="border"
|
||||
/>
|
||||
</FormField>
|
||||
|
|
|
@ -21,8 +21,6 @@ function AppGuide({ className, guideId, app, isCompact, onClose }: Props) {
|
|||
const isCustomDomainActive = customDomain?.status === DomainStatus.Active;
|
||||
const guide = guides.find(({ id }) => id === guideId);
|
||||
|
||||
const GuideComponent = guide?.Component;
|
||||
|
||||
const memorizedContext = useMemo(
|
||||
() =>
|
||||
conditional(
|
||||
|
@ -32,7 +30,7 @@ function AppGuide({ className, guideId, app, isCompact, onClose }: Props) {
|
|||
Logo: guide.Logo,
|
||||
app,
|
||||
endpoint: tenantEndpoint?.toString() ?? '',
|
||||
alternativeEndpoint: conditional(isCustomDomainActive && tenantEndpoint?.toString()),
|
||||
alternativeEndpoint: conditional(isCustomDomainActive && customDomain.domain),
|
||||
redirectUris: app.oidcClientMetadata.redirectUris,
|
||||
postLogoutRedirectUris: app.oidcClientMetadata.postLogoutRedirectUris,
|
||||
isCompact: Boolean(isCompact),
|
||||
|
@ -42,7 +40,7 @@ function AppGuide({ className, guideId, app, isCompact, onClose }: Props) {
|
|||
},
|
||||
}
|
||||
) satisfies GuideContextType | undefined,
|
||||
[guide, app, tenantEndpoint, isCustomDomainActive, isCompact]
|
||||
[guide, app, tenantEndpoint, isCustomDomainActive, customDomain?.domain, isCompact]
|
||||
);
|
||||
|
||||
return memorizedContext ? (
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
} from '@/ds-components/MultiTextInput/utils';
|
||||
import TextInput from '@/ds-components/TextInput';
|
||||
import TextLink from '@/ds-components/TextLink';
|
||||
import useCustomDomain from '@/hooks/use-custom-domain';
|
||||
import useDocumentationUrl from '@/hooks/use-documentation-url';
|
||||
|
||||
import * as styles from '../index.module.scss';
|
||||
|
@ -27,6 +28,7 @@ type Props = {
|
|||
|
||||
function Settings({ data }: Props) {
|
||||
const { tenantEndpoint } = useContext(AppDataContext);
|
||||
const { applyDomain: applyCustomDomain } = useCustomDomain();
|
||||
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const { getDocumentationUrl } = useDocumentationUrl();
|
||||
|
@ -62,7 +64,7 @@ function Settings({ data }: Props) {
|
|||
{tenantEndpoint && (
|
||||
<FormField title="application_details.logto_endpoint">
|
||||
<CopyToClipboard
|
||||
value={tenantEndpoint.href}
|
||||
value={applyCustomDomain(tenantEndpoint.href)}
|
||||
variant="border"
|
||||
className={styles.textField}
|
||||
/>
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export const applyDomain = (url: string, domain: string) => url.replace(new URL(url).host, domain);
|
Loading…
Reference in a new issue