Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(twenty-server): add trusted domain - backend crud #10290

Merged
merged 21 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
104f316
feat(workspace): add support for trusted domains
AMoreaux Feb 18, 2025
bdd1535
feat(workspace-trusted-domain): implement trusted domain management
AMoreaux Feb 18, 2025
4d42841
Merge branch 'main' into feat/add-allowed-domains
AMoreaux Feb 18, 2025
9f7c0f7
refactor(workspace-trusted-domain): improve validation flow
AMoreaux Feb 18, 2025
123f647
feat(workspace-trusted-domain): enhance module with new features
AMoreaux Feb 18, 2025
fbdb663
refactor(migration): update workspace trusted domain migration
AMoreaux Feb 19, 2025
fbcecce
Merge branch 'main' into feat/add-allowed-domains
AMoreaux Feb 19, 2025
2703282
feat(workspace-trusted-domain): add validation flow
AMoreaux Feb 19, 2025
11c45aa
feat(graphql): add support for workspace trusted domains
AMoreaux Feb 19, 2025
c820e96
feat(workspace-trusted-domain): enhance validation logic
AMoreaux Feb 19, 2025
94b64cc
Merge remote-tracking branch 'refs/remotes/origin/main' into feat/add…
AMoreaux Feb 19, 2025
444003a
feat(graphql): add support for workspace trusted domains
AMoreaux Feb 19, 2025
0ac2f23
Merge branch 'main' into feat/add-allowed-domains
AMoreaux Feb 20, 2025
49d71d1
Merge remote-tracking branch 'origin/main' into feat/add-allowed-domains
AMoreaux Feb 20, 2025
15fcb96
refactor(workspace-trusted-domain): improve validation flow
AMoreaux Feb 20, 2025
846d95e
refactor(tests): streamline workspace trusted domain spec
AMoreaux Feb 20, 2025
90ae412
refactor(database): rename WorkspaceTrustedDomain to ApprovedAccessDo…
AMoreaux Feb 20, 2025
2c60e66
feat(graphql): rename and restructure domain management types
AMoreaux Feb 20, 2025
21e4e12
chore: remove insecure TLS bypass configuration
AMoreaux Feb 20, 2025
70ec628
refactor(database): adjust migration formatting for clarity
AMoreaux Feb 20, 2025
605073b
feat(trusted-domain): add frontend management (without ui) (#10337)
AMoreaux Feb 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { t } from '@lingui/core/macro';
import { Trans } from '@lingui/react/macro';
import { Img } from '@react-email/components';
import { emailTheme } from 'src/common-style';

import { BaseEmail } from 'src/components/BaseEmail';
import { CallToAction } from 'src/components/CallToAction';
import { HighlightedContainer } from 'src/components/HighlightedContainer';
import { HighlightedText } from 'src/components/HighlightedText';
import { Link } from 'src/components/Link';
import { MainText } from 'src/components/MainText';
import { Title } from 'src/components/Title';
import { WhatIsTwenty } from 'src/components/WhatIsTwenty';
import { capitalize } from 'src/utils/capitalize';
import { APP_LOCALES, getImageAbsoluteURI } from 'twenty-shared';

type SendApprovedAccessDomainValidationProps = {
link: string;
domain: string;
workspace: { name: string | undefined; logo: string | undefined };
sender: {
email: string;
firstName: string;
lastName: string;
};
serverUrl: string;
locale: keyof typeof APP_LOCALES;
};

export const SendApprovedAccessDomainValidation = ({
link,
domain,
workspace,
sender,
serverUrl,
locale,
}: SendApprovedAccessDomainValidationProps) => {
const workspaceLogo = workspace.logo
? getImageAbsoluteURI({ imageUrl: workspace.logo, baseUrl: serverUrl })
: null;

return (
<BaseEmail width={333} locale={locale}>
<Title value={t`Validate domain`} />
<MainText>
{capitalize(sender.firstName)} (
<Link
href={`mailto:${sender.email}`}
value={sender.email}
color={emailTheme.font.colors.blue}
/>
)
<Trans>
Please validate this domain to allow users with <b>@{domain}</b> email
addresses to join your workspace without requiring an invitation.
</Trans>
<br />
</MainText>
<HighlightedContainer>
{workspaceLogo && <Img src={workspaceLogo} width={40} height={40} />}
{workspace.name && <HighlightedText value={workspace.name} />}
<CallToAction href={link} value={t`Validate domain`} />
</HighlightedContainer>
<WhatIsTwenty />
</BaseEmail>
);
};
1 change: 1 addition & 0 deletions packages/twenty-emails/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './emails/password-update-notify.email';
export * from './emails/send-email-verification-link.email';
export * from './emails/send-invite-link.email';
export * from './emails/warn-suspended-workspace.email';
export * from './emails/validate-approved-access-domain.email';
42 changes: 42 additions & 0 deletions packages/twenty-front/src/generated-metadata/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ export type AppTokenEdge = {
node: AppToken;
};

export type ApprovedAccessDomain = {
__typename?: 'ApprovedAccessDomain';
createdAt: Scalars['DateTime']['output'];
domain: Scalars['String']['output'];
id: Scalars['UUID']['output'];
isValidated: Scalars['Boolean']['output'];
};

export type AuthProviders = {
__typename?: 'AuthProviders';
google: Scalars['Boolean']['output'];
Expand Down Expand Up @@ -305,6 +313,11 @@ export type CreateAppTokenInput = {
expiresAt: Scalars['DateTime']['input'];
};

export type CreateApprovedAccessDomainInput = {
domain: Scalars['String']['input'];
email: Scalars['String']['input'];
};

export type CreateDraftFromWorkflowVersionInput = {
/** Workflow ID */
workflowId: Scalars['String']['input'];
Expand Down Expand Up @@ -428,6 +441,10 @@ export type CustomDomainValidRecords = {
records: Array<CustomDomainRecord>;
};

export type DeleteApprovedAccessDomainInput = {
id: Scalars['String']['input'];
};

export type DeleteOneFieldInput = {
/** The id of the field to delete. */
id: Scalars['UUID']['input'];
Expand Down Expand Up @@ -550,6 +567,7 @@ export enum FeatureFlagKey {
IsAdvancedFiltersEnabled = 'IsAdvancedFiltersEnabled',
IsAirtableIntegrationEnabled = 'IsAirtableIntegrationEnabled',
IsAnalyticsV2Enabled = 'IsAnalyticsV2Enabled',
IsApprovedAccessDomainsEnabled = 'IsApprovedAccessDomainsEnabled',
IsBillingPlansEnabled = 'IsBillingPlansEnabled',
IsCommandMenuV2Enabled = 'IsCommandMenuV2Enabled',
IsCopilotEnabled = 'IsCopilotEnabled',
Expand Down Expand Up @@ -839,6 +857,7 @@ export type Mutation = {
checkCustomDomainValidRecords?: Maybe<CustomDomainValidRecords>;
checkoutSession: BillingSessionOutput;
computeStepOutputSchema: Scalars['JSON']['output'];
createApprovedAccessDomain: ApprovedAccessDomain;
createDraftFromWorkflowVersion: WorkflowVersion;
createOIDCIdentityProvider: SetupSsoOutput;
createOneAppToken: AppToken;
Expand All @@ -850,6 +869,7 @@ export type Mutation = {
createSAMLIdentityProvider: SetupSsoOutput;
createWorkflowVersionStep: WorkflowAction;
deactivateWorkflowVersion: Scalars['Boolean']['output'];
deleteApprovedAccessDomain: Scalars['Boolean']['output'];
deleteCurrentWorkspace: Workspace;
deleteOneField: Field;
deleteOneObject: Object;
Expand Down Expand Up @@ -900,6 +920,7 @@ export type Mutation = {
uploadProfilePicture: Scalars['String']['output'];
uploadWorkspaceLogo: Scalars['String']['output'];
userLookupAdminPanel: UserLookup;
validateApprovedAccessDomain: ApprovedAccessDomain;
};


Expand Down Expand Up @@ -938,6 +959,11 @@ export type MutationComputeStepOutputSchemaArgs = {
};


export type MutationCreateApprovedAccessDomainArgs = {
input: CreateApprovedAccessDomainInput;
};


export type MutationCreateDraftFromWorkflowVersionArgs = {
input: CreateDraftFromWorkflowVersionInput;
};
Expand Down Expand Up @@ -993,6 +1019,11 @@ export type MutationDeactivateWorkflowVersionArgs = {
};


export type MutationDeleteApprovedAccessDomainArgs = {
input: DeleteApprovedAccessDomainInput;
};


export type MutationDeleteOneFieldArgs = {
input: DeleteOneFieldInput;
};
Expand Down Expand Up @@ -1225,6 +1256,11 @@ export type MutationUserLookupAdminPanelArgs = {
userIdentifier: Scalars['String']['input'];
};


export type MutationValidateApprovedAccessDomainArgs = {
input: ValidateApprovedAccessDomainInput;
};

export type Object = {
__typename?: 'Object';
createdAt: Scalars['DateTime']['output'];
Expand Down Expand Up @@ -1393,6 +1429,7 @@ export type Query = {
findOneServerlessFunction: ServerlessFunction;
findWorkspaceFromInviteHash: Workspace;
findWorkspaceInvitations: Array<WorkspaceInvitation>;
getApprovedAccessDomains: Array<ApprovedAccessDomain>;
getAvailablePackages: Scalars['JSON']['output'];
getEnvironmentVariablesGrouped: EnvironmentVariablesOutput;
getIndicatorHealthStatus: AdminPanelHealthServiceData;
Expand Down Expand Up @@ -2112,6 +2149,11 @@ export type UserWorkspace = {
workspaceId: Scalars['String']['output'];
};

export type ValidateApprovedAccessDomainInput = {
approvedAccessDomainId: Scalars['String']['input'];
validationToken: Scalars['String']['input'];
};

export type ValidatePasswordResetToken = {
__typename?: 'ValidatePasswordResetToken';
email: Scalars['String']['output'];
Expand Down
Loading
Loading