feat(): enable custom domain usage (#9911)

# Content
- Introduce the `workspaceUrls` property. It contains two
sub-properties: `customUrl, subdomainUrl`. These endpoints are used to
access the workspace. Even if the `workspaceUrls` is invalid for
multiple reasons, the `subdomainUrl` remains valid.
- Introduce `ResolveField` workspaceEndpoints to avoid unnecessary URL
computation on the frontend part.
- Add a `forceSubdomainUrl` to avoid custom URL using a query parameter
This commit is contained in:
Antoine Moreaux
2025-02-07 14:34:26 +01:00
committed by GitHub
parent 3cc66fe712
commit 68183b7c85
87 changed files with 645 additions and 373 deletions

View File

@ -1,3 +1,4 @@
import { ApolloError } from '@apollo/client';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useRecoilState } from 'recoil';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
@ -13,7 +14,6 @@ import { SettingsSubdomain } from '~/pages/settings/workspace/SettingsSubdomain'
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
import { getSettingsPath } from '~/utils/navigation/getSettingsPath';
import { ApolloError } from '@apollo/client';
import { Trans, useLingui } from '@lingui/react/macro';
import { z } from 'zod';
import { FormProvider, useForm } from 'react-hook-form';
@ -94,12 +94,18 @@ export const SettingsDomain = () => {
});
},
onCompleted: () => {
const currentUrl = new URL(window.location.href);
currentUrl.hostname = new URL(
currentWorkspace.workspaceUrls.subdomainUrl,
).hostname.replace(currentWorkspace.subdomain, values.subdomain);
setCurrentWorkspace({
...currentWorkspace,
subdomain: values.subdomain,
});
redirectToWorkspaceDomain(values.subdomain);
redirectToWorkspaceDomain(currentUrl.toString());
},
});
};

View File

@ -1,5 +1,4 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { useRedirectToWorkspaceDomain } from '@/domain-manager/hooks/useRedirectToWorkspaceDomain';
import { TextInputV2 } from '@/ui/input/components/TextInputV2';
import styled from '@emotion/styled';
import { zodResolver } from '@hookform/resolvers/zod';
@ -41,7 +40,6 @@ export const SettingsHostname = () => {
const [updateWorkspace] = useUpdateWorkspaceMutation();
const { data: getHostnameDetailsData } = useGetHostnameDetailsQuery();
const { redirectToWorkspaceDomain } = useRedirectToWorkspaceDomain();
const { t } = useLingui();
const [currentWorkspace, setCurrentWorkspace] = useRecoilState(
@ -75,8 +73,6 @@ export const SettingsHostname = () => {
},
},
});
redirectToWorkspaceDomain(currentWorkspace.subdomain);
} catch (error) {
control.setError('hostname', {
type: 'manual',
@ -106,8 +102,6 @@ export const SettingsHostname = () => {
...currentWorkspace,
hostname: values.hostname,
});
// redirectToWorkspaceDomain(values.subdomain);
} catch (error) {
control.setError('hostname', {
type: 'manual',
@ -139,12 +133,36 @@ export const SettingsHostname = () => {
{isDefined(getHostnameDetailsData?.getHostnameDetails?.hostname) && (
<pre>
{getHostnameDetailsData.getHostnameDetails.hostname} CNAME
app.twenty-main.com
twenty-main.com
</pre>
)}
{getHostnameDetailsData && (
<pre>{JSON.stringify(getHostnameDetailsData, null, 4)}</pre>
)}
{getHostnameDetailsData?.getHostnameDetails &&
getHostnameDetailsData.getHostnameDetails.ownershipVerifications.map(
(ownershipVerification) => {
if (
ownershipVerification.__typename ===
'CustomHostnameOwnershipVerificationTxt'
) {
return (
<pre>
{ownershipVerification.name} TXT {ownershipVerification.value}
</pre>
);
}
if (
ownershipVerification.__typename ===
'CustomHostnameOwnershipVerificationHttp'
) {
return (
<pre>
{ownershipVerification.url} HTTP {ownershipVerification.body}
</pre>
);
}
return <></>;
},
)}
</Section>
);
};