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:
Antoine Moreaux
2024-10-21 20:07:08 +02:00
committed by GitHub
parent 11c3f1c399
commit 0f0a7966b1
132 changed files with 5245 additions and 306 deletions

View File

@ -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>
);

View File

@ -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:
'Dont create contacts from/to Gmail, Outlook emails',
value: !!messageChannel.excludeNonProfessionalEmails,
onToggle: handleIsNonProfessionalEmailExcludedToggle,
},
{
title: 'Exclude group emails',
description: 'Dont sync emails from team@ support@ noreply@...',
value: !!messageChannel.excludeGroupEmails,
onToggle: handleIsGroupEmailExcludedToggle,
},
]}
/>
<Card>
<SettingsOptionCardContent
title="Exclude non-professional emails"
description="Dont create contacts from/to Gmail, Outlook emails"
divider
onClick={() =>
handleIsNonProfessionalEmailExcludedToggle(
!messageChannel.excludeNonProfessionalEmails,
)
}
>
<StyledToggle value={messageChannel.excludeNonProfessionalEmails} />
</SettingsOptionCardContent>
<SettingsOptionCardContent
title="Exclude group emails"
description="Dont sync emails from team@ support@ noreply@..."
onClick={() =>
handleIsGroupEmailExcludedToggle(
!messageChannel.excludeGroupEmails,
)
}
>
<StyledToggle value={messageChannel.excludeGroupEmails} />
</SettingsOptionCardContent>
</Card>
</Section>
</StyledDetailsContainer>
);

View File

@ -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>
);