feat(sso): allow to use OIDC and SAML (#7246)
## What it does ### Backend - [x] Add a mutation to create OIDC and SAML configuration - [x] Add a mutation to delete an SSO config - [x] Add a feature flag to toggle SSO - [x] Add a mutation to activate/deactivate an SSO config - [x] Add a mutation to delete an SSO config - [x] Add strategy to use OIDC or SAML - [ ] Improve error management ### Frontend - [x] Add section "security" in settings - [x] Add page to list SSO configurations - [x] Add page and forms to create OIDC or SAML configuration - [x] Add field to "connect with SSO" in the signin/signup process - [x] Trigger auth when a user switch to a workspace with SSO enable - [x] Add an option on the security page to activate/deactivate the global invitation link - [ ] Add new Icons for SSO Identity Providers (okta, Auth0, Azure, Microsoft) --------- Co-authored-by: Félix Malfait <felix@twenty.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -2,11 +2,13 @@ import { CalendarChannel } from '@/accounts/types/CalendarChannel';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { SettingsAccountsEventVisibilitySettingsCard } from '@/settings/accounts/components/SettingsAccountsCalendarVisibilitySettingsCard';
|
||||
import { SettingsAccountsToggleSettingCard } from '@/settings/accounts/components/SettingsAccountsToggleSettingCard';
|
||||
import styled from '@emotion/styled';
|
||||
import { Section } from '@react-email/components';
|
||||
import { H2Title } from 'twenty-ui';
|
||||
import { CalendarChannelVisibility } from '~/generated-metadata/graphql';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { SettingsOptionCardContent } from '@/settings/components/SettingsOptionCardContent';
|
||||
import { Toggle } from '@/ui/input/components/Toggle';
|
||||
|
||||
const StyledDetailsContainer = styled.div`
|
||||
display: flex;
|
||||
@ -21,6 +23,10 @@ type SettingsAccountsCalendarChannelDetailsProps = {
|
||||
>;
|
||||
};
|
||||
|
||||
const StyledToggle = styled(Toggle)`
|
||||
margin-left: auto;
|
||||
`;
|
||||
|
||||
export const SettingsAccountsCalendarChannelDetails = ({
|
||||
calendarChannel,
|
||||
}: SettingsAccountsCalendarChannelDetailsProps) => {
|
||||
@ -63,16 +69,21 @@ export const SettingsAccountsCalendarChannelDetails = ({
|
||||
title="Contact auto-creation"
|
||||
description="Automatically create contacts for people you've participated in an event with."
|
||||
/>
|
||||
<SettingsAccountsToggleSettingCard
|
||||
parameters={[
|
||||
{
|
||||
value: !!calendarChannel.isContactAutoCreationEnabled,
|
||||
title: 'Auto-creation',
|
||||
description: 'Automatically create contacts for people.',
|
||||
onToggle: handleContactAutoCreationToggle,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Card>
|
||||
<SettingsOptionCardContent
|
||||
title="Auto-creation"
|
||||
description="Automatically create contacts for people."
|
||||
onClick={() =>
|
||||
handleContactAutoCreationToggle(
|
||||
!calendarChannel.isContactAutoCreationEnabled,
|
||||
)
|
||||
}
|
||||
>
|
||||
<StyledToggle
|
||||
value={calendarChannel.isContactAutoCreationEnabled}
|
||||
/>
|
||||
</SettingsOptionCardContent>
|
||||
</Card>
|
||||
</Section>
|
||||
</StyledDetailsContainer>
|
||||
);
|
||||
|
||||
@ -9,9 +9,11 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { SettingsAccountsMessageAutoCreationCard } from '@/settings/accounts/components/SettingsAccountsMessageAutoCreationCard';
|
||||
import { SettingsAccountsMessageVisibilityCard } from '@/settings/accounts/components/SettingsAccountsMessageVisibilityCard';
|
||||
import { SettingsAccountsToggleSettingCard } from '@/settings/accounts/components/SettingsAccountsToggleSettingCard';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { MessageChannelVisibility } from '~/generated-metadata/graphql';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { SettingsOptionCardContent } from '@/settings/components/SettingsOptionCardContent';
|
||||
import { Toggle } from '@/ui/input/components/Toggle';
|
||||
|
||||
type SettingsAccountsMessageChannelDetailsProps = {
|
||||
messageChannel: Pick<
|
||||
@ -31,6 +33,10 @@ const StyledDetailsContainer = styled.div`
|
||||
gap: ${({ theme }) => theme.spacing(6)};
|
||||
`;
|
||||
|
||||
const StyledToggle = styled(Toggle)`
|
||||
margin-left: auto;
|
||||
`;
|
||||
|
||||
export const SettingsAccountsMessageChannelDetails = ({
|
||||
messageChannel,
|
||||
}: SettingsAccountsMessageChannelDetailsProps) => {
|
||||
@ -99,23 +105,31 @@ export const SettingsAccountsMessageChannelDetails = ({
|
||||
/>
|
||||
</Section>
|
||||
<Section>
|
||||
<SettingsAccountsToggleSettingCard
|
||||
parameters={[
|
||||
{
|
||||
title: 'Exclude non-professional emails',
|
||||
description:
|
||||
'Don’t create contacts from/to Gmail, Outlook emails',
|
||||
value: !!messageChannel.excludeNonProfessionalEmails,
|
||||
onToggle: handleIsNonProfessionalEmailExcludedToggle,
|
||||
},
|
||||
{
|
||||
title: 'Exclude group emails',
|
||||
description: 'Don’t sync emails from team@ support@ noreply@...',
|
||||
value: !!messageChannel.excludeGroupEmails,
|
||||
onToggle: handleIsGroupEmailExcludedToggle,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Card>
|
||||
<SettingsOptionCardContent
|
||||
title="Exclude non-professional emails"
|
||||
description="Don’t create contacts from/to Gmail, Outlook emails"
|
||||
divider
|
||||
onClick={() =>
|
||||
handleIsNonProfessionalEmailExcludedToggle(
|
||||
!messageChannel.excludeNonProfessionalEmails,
|
||||
)
|
||||
}
|
||||
>
|
||||
<StyledToggle value={messageChannel.excludeNonProfessionalEmails} />
|
||||
</SettingsOptionCardContent>
|
||||
<SettingsOptionCardContent
|
||||
title="Exclude group emails"
|
||||
description="Don’t sync emails from team@ support@ noreply@..."
|
||||
onClick={() =>
|
||||
handleIsGroupEmailExcludedToggle(
|
||||
!messageChannel.excludeGroupEmails,
|
||||
)
|
||||
}
|
||||
>
|
||||
<StyledToggle value={messageChannel.excludeGroupEmails} />
|
||||
</SettingsOptionCardContent>
|
||||
</Card>
|
||||
</Section>
|
||||
</StyledDetailsContainer>
|
||||
);
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { Toggle } from '@/ui/input/components/Toggle';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
|
||||
type Parameter = {
|
||||
value: boolean;
|
||||
title: string;
|
||||
description: string;
|
||||
onToggle: (value: boolean) => void;
|
||||
};
|
||||
|
||||
type SettingsAccountsToggleSettingCardProps = {
|
||||
parameters: Parameter[];
|
||||
};
|
||||
|
||||
const StyledCardContent = styled(CardContent)`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: ${({ theme }) => theme.background.transparent.lighter};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTitle = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledDescription = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
font-size: ${({ theme }) => theme.font.size.sm};
|
||||
`;
|
||||
|
||||
const StyledToggle = styled(Toggle)`
|
||||
margin-left: auto;
|
||||
`;
|
||||
|
||||
export const SettingsAccountsToggleSettingCard = ({
|
||||
parameters,
|
||||
}: SettingsAccountsToggleSettingCardProps) => (
|
||||
<Card rounded>
|
||||
{parameters.map((parameter, index) => (
|
||||
<StyledCardContent
|
||||
key={index}
|
||||
divider={index < parameters.length - 1}
|
||||
onClick={() => parameter.onToggle(!parameter.value)}
|
||||
>
|
||||
<div>
|
||||
<StyledTitle>{parameter.title}</StyledTitle>
|
||||
<StyledDescription>{parameter.description}</StyledDescription>
|
||||
</div>
|
||||
<StyledToggle value={parameter.value} onChange={parameter.onToggle} />
|
||||
</StyledCardContent>
|
||||
))}
|
||||
</Card>
|
||||
);
|
||||
Reference in New Issue
Block a user