mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-23 12:02:10 +03:00
parent
99caab1412
commit
33e69805cb
@ -22,6 +22,7 @@ import { WorkspaceProviderEffect } from '@/workspace/components/WorkspaceProvide
|
|||||||
import { StrictMode } from 'react';
|
import { StrictMode } from 'react';
|
||||||
import { Outlet, useLocation } from 'react-router-dom';
|
import { Outlet, useLocation } from 'react-router-dom';
|
||||||
import { getPageTitleFromPath } from '~/utils/title-utils';
|
import { getPageTitleFromPath } from '~/utils/title-utils';
|
||||||
|
import { PageFavicon } from '@/ui/utilities/page-favicon/components/PageFavicon';
|
||||||
|
|
||||||
export const AppRouterProviders = () => {
|
export const AppRouterProviders = () => {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
@ -49,6 +50,7 @@ export const AppRouterProviders = () => {
|
|||||||
<PromiseRejectionEffect />
|
<PromiseRejectionEffect />
|
||||||
<GotoHotkeysEffectsProvider />
|
<GotoHotkeysEffectsProvider />
|
||||||
<PageTitle title={pageTitle} />
|
<PageTitle title={pageTitle} />
|
||||||
|
<PageFavicon />
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
</DialogManager>
|
</DialogManager>
|
||||||
|
@ -31,7 +31,7 @@ import { useReadCaptchaToken } from '@/captcha/hooks/useReadCaptchaToken';
|
|||||||
import { signInUpModeState } from '@/auth/states/signInUpModeState';
|
import { signInUpModeState } from '@/auth/states/signInUpModeState';
|
||||||
import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken';
|
import { useRequestFreshCaptchaToken } from '@/captcha/hooks/useRequestFreshCaptchaToken';
|
||||||
import { useUrlManager } from '@/url-manager/hooks/useUrlManager';
|
import { useUrlManager } from '@/url-manager/hooks/useUrlManager';
|
||||||
import { SignInUpMode } from '@/auth/types/signInUpMode.type';
|
import { SignInUpMode } from '@/auth/types/signInUpMode';
|
||||||
|
|
||||||
const StyledContentContainer = styled(motion.div)`
|
const StyledContentContainer = styled(motion.div)`
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
||||||
|
@ -5,7 +5,7 @@ import { motion } from 'framer-motion';
|
|||||||
import { StyledText } from 'twenty-ui';
|
import { StyledText } from 'twenty-ui';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import { Form } from '@/auth/sign-in-up/hooks/useSignInUpForm';
|
import { Form } from '@/auth/sign-in-up/hooks/useSignInUpForm';
|
||||||
import { SignInUpMode } from '@/auth/types/signInUpMode.type';
|
import { SignInUpMode } from '@/auth/types/signInUpMode';
|
||||||
|
|
||||||
const StyledFullWidthMotionDiv = styled(motion.div)`
|
const StyledFullWidthMotionDiv = styled(motion.div)`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -14,7 +14,7 @@ import { useState, useMemo } from 'react';
|
|||||||
import { captchaProviderState } from '@/client-config/states/captchaProviderState';
|
import { captchaProviderState } from '@/client-config/states/captchaProviderState';
|
||||||
import { isRequestingCaptchaTokenState } from '@/captcha/states/isRequestingCaptchaTokenState';
|
import { isRequestingCaptchaTokenState } from '@/captcha/states/isRequestingCaptchaTokenState';
|
||||||
import { FormProvider } from 'react-hook-form';
|
import { FormProvider } from 'react-hook-form';
|
||||||
import { SignInUpMode } from '@/auth/types/signInUpMode.type';
|
import { SignInUpMode } from '@/auth/types/signInUpMode';
|
||||||
|
|
||||||
const StyledForm = styled.form`
|
const StyledForm = styled.form`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -4,15 +4,12 @@ import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm';
|
|||||||
import { SignInUpStep } from '@/auth/states/signInUpStepState';
|
import { SignInUpStep } from '@/auth/states/signInUpStepState';
|
||||||
import { authProvidersState } from '@/client-config/states/authProvidersState';
|
import { authProvidersState } from '@/client-config/states/authProvidersState';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useCallback, useEffect } from 'react';
|
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
import { ActionLink, HorizontalSeparator } from 'twenty-ui';
|
import { ActionLink, HorizontalSeparator } from 'twenty-ui';
|
||||||
import { SignInUpWithGoogle } from '@/auth/sign-in-up/components/SignInUpWithGoogle';
|
import { SignInUpWithGoogle } from '@/auth/sign-in-up/components/SignInUpWithGoogle';
|
||||||
import { SignInUpWithMicrosoft } from '@/auth/sign-in-up/components/SignInUpWithMicrosoft';
|
import { SignInUpWithMicrosoft } from '@/auth/sign-in-up/components/SignInUpWithMicrosoft';
|
||||||
import { SignInUpWithSSO } from '@/auth/sign-in-up/components/SignInUpWithSSO';
|
import { SignInUpWithSSO } from '@/auth/sign-in-up/components/SignInUpWithSSO';
|
||||||
import { SignInUpWithCredentials } from '@/auth/sign-in-up/components/SignInUpWithCredentials';
|
import { SignInUpWithCredentials } from '@/auth/sign-in-up/components/SignInUpWithCredentials';
|
||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
import { isDefined } from '~/utils/isDefined';
|
|
||||||
|
|
||||||
const StyledContentContainer = styled.div`
|
const StyledContentContainer = styled.div`
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
||||||
@ -25,38 +22,7 @@ export const SignInUpWorkspaceScopeForm = () => {
|
|||||||
const { form } = useSignInUpForm();
|
const { form } = useSignInUpForm();
|
||||||
const { handleResetPassword } = useHandleResetPassword();
|
const { handleResetPassword } = useHandleResetPassword();
|
||||||
|
|
||||||
const { signInUpStep, continueWithEmail, continueWithCredentials } =
|
const { signInUpStep } = useSignInUp(form);
|
||||||
useSignInUp(form);
|
|
||||||
const location = useLocation();
|
|
||||||
|
|
||||||
const checkAuthProviders = useCallback(() => {
|
|
||||||
if (
|
|
||||||
signInUpStep === SignInUpStep.Init &&
|
|
||||||
!authProviders.google &&
|
|
||||||
!authProviders.microsoft &&
|
|
||||||
!authProviders.sso
|
|
||||||
) {
|
|
||||||
return continueWithEmail();
|
|
||||||
}
|
|
||||||
const searchParams = new URLSearchParams(location.search);
|
|
||||||
const email = searchParams.get('email');
|
|
||||||
if (isDefined(email) && authProviders.password) {
|
|
||||||
return continueWithCredentials();
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
continueWithCredentials,
|
|
||||||
location.search,
|
|
||||||
authProviders.google,
|
|
||||||
authProviders.microsoft,
|
|
||||||
authProviders.password,
|
|
||||||
authProviders.sso,
|
|
||||||
continueWithEmail,
|
|
||||||
signInUpStep,
|
|
||||||
]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
checkAuthProviders();
|
|
||||||
}, [checkAuthProviders]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
import { SignInUpStep } from '@/auth/states/signInUpStepState';
|
||||||
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
import { useSignInUp } from '@/auth/sign-in-up/hooks/useSignInUp';
|
||||||
|
import { authProvidersState } from '@/client-config/states/authProvidersState';
|
||||||
|
import { useSignInUpForm } from '@/auth/sign-in-up/hooks/useSignInUpForm';
|
||||||
|
import { useRecoilState } from 'recoil';
|
||||||
|
import { useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
|
const email = searchParams.get('email');
|
||||||
|
|
||||||
|
export const SignInUpWorkspaceScopeFormEffect = () => {
|
||||||
|
const [authProviders] = useRecoilState(authProvidersState);
|
||||||
|
|
||||||
|
const { form } = useSignInUpForm();
|
||||||
|
|
||||||
|
const { signInUpStep, continueWithEmail, continueWithCredentials } =
|
||||||
|
useSignInUp(form);
|
||||||
|
|
||||||
|
const checkAuthProviders = useCallback(() => {
|
||||||
|
if (
|
||||||
|
signInUpStep === SignInUpStep.Init &&
|
||||||
|
!authProviders.google &&
|
||||||
|
!authProviders.microsoft &&
|
||||||
|
!authProviders.sso
|
||||||
|
) {
|
||||||
|
return continueWithEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDefined(email) && authProviders.password) {
|
||||||
|
return continueWithCredentials();
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
signInUpStep,
|
||||||
|
authProviders.google,
|
||||||
|
authProviders.microsoft,
|
||||||
|
authProviders.sso,
|
||||||
|
authProviders.password,
|
||||||
|
continueWithEmail,
|
||||||
|
continueWithCredentials,
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkAuthProviders();
|
||||||
|
}, [checkAuthProviders]);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
@ -16,7 +16,7 @@ import {
|
|||||||
import { AppPath } from '@/types/AppPath';
|
import { AppPath } from '@/types/AppPath';
|
||||||
import { useAuth } from '../../hooks/useAuth';
|
import { useAuth } from '../../hooks/useAuth';
|
||||||
import { signInUpModeState } from '@/auth/states/signInUpModeState';
|
import { signInUpModeState } from '@/auth/states/signInUpModeState';
|
||||||
import { SignInUpMode } from '@/auth/types/signInUpMode.type';
|
import { SignInUpMode } from '@/auth/types/signInUpMode';
|
||||||
|
|
||||||
export const useSignInUp = (form: UseFormReturn<Form>) => {
|
export const useSignInUp = (form: UseFormReturn<Form>) => {
|
||||||
const { enqueueSnackBar } = useSnackBar();
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
|
@ -58,8 +58,10 @@ export const useSignInUpForm = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isDefined(prefilledEmail)) {
|
if (isDefined(prefilledEmail)) {
|
||||||
form.setValue('email', prefilledEmail);
|
form.setValue('email', prefilledEmail);
|
||||||
} else if (isDeveloperDefaultSignInPrefilled === true) {
|
}
|
||||||
form.setValue('email', 'tim@apple.dev');
|
|
||||||
|
if (isDeveloperDefaultSignInPrefilled === true) {
|
||||||
|
form.setValue('email', prefilledEmail ?? 'tim@apple.dev');
|
||||||
form.setValue('password', 'Applecar2025');
|
form.setValue('password', 'Applecar2025');
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
@ -68,5 +70,5 @@ export const useSignInUpForm = () => {
|
|||||||
prefilledEmail,
|
prefilledEmail,
|
||||||
location.search,
|
location.search,
|
||||||
]);
|
]);
|
||||||
return { form, validationSchema };
|
return { form: form, validationSchema };
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createState } from 'twenty-ui';
|
import { createState } from 'twenty-ui';
|
||||||
import { SignInUpMode } from '@/auth/types/signInUpMode.type';
|
import { SignInUpMode } from '@/auth/types/signInUpMode';
|
||||||
|
|
||||||
export const signInUpModeState = createState<SignInUpMode>({
|
export const signInUpModeState = createState<SignInUpMode>({
|
||||||
key: 'signInUpModeState',
|
key: 'signInUpModeState',
|
||||||
|
@ -14,7 +14,7 @@ import { useRecoilValue, useRecoilState } from 'recoil';
|
|||||||
import { IconKey } from 'twenty-ui';
|
import { IconKey } from 'twenty-ui';
|
||||||
import { useListSsoIdentityProvidersByWorkspaceIdQuery } from '~/generated/graphql';
|
import { useListSsoIdentityProvidersByWorkspaceIdQuery } from '~/generated/graphql';
|
||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
|
|
||||||
const StyledLink = styled(Link, {
|
const StyledLink = styled(Link, {
|
||||||
|
@ -6,7 +6,7 @@ import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
|
|||||||
import { SettingsPath } from '@/types/SettingsPath';
|
import { SettingsPath } from '@/types/SettingsPath';
|
||||||
import { SettingsListCard } from '@/settings/components/SettingsListCard';
|
import { SettingsListCard } from '@/settings/components/SettingsListCard';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
export const SettingsSSOIdentitiesProvidersListCardWrapper = () => {
|
export const SettingsSSOIdentitiesProvidersListCardWrapper = () => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* @license Enterprise */
|
/* @license Enterprise */
|
||||||
|
|
||||||
import { SettingsSecuritySSORowDropdownMenu } from '@/settings/security/components/SettingsSecuritySSORowDropdownMenu';
|
import { SettingsSecuritySSORowDropdownMenu } from '@/settings/security/components/SettingsSecuritySSORowDropdownMenu';
|
||||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||||
import { getColorBySSOIdentityProviderStatus } from '@/settings/security/utils/getColorBySSOIdentityProviderStatus';
|
import { getColorBySSOIdentityProviderStatus } from '@/settings/security/utils/getColorBySSOIdentityProviderStatus';
|
||||||
import { Status } from 'twenty-ui';
|
import { Status } from 'twenty-ui';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
|
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
|
||||||
import { AuthProviders } from '~/generated-metadata/graphql';
|
import { AuthProviders } from '~/generated-metadata/graphql';
|
||||||
import { capitalize } from '~/utils/string/capitalize';
|
import { capitalize } from '~/utils/string/capitalize';
|
||||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||||
|
|
||||||
const StyledSettingsSecurityOptionsList = styled.div`
|
const StyledSettingsSecurityOptionsList = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
|
|
||||||
import { useDeleteSSOIdentityProvider } from '@/settings/security/hooks/useDeleteSSOIdentityProvider';
|
import { useDeleteSSOIdentityProvider } from '@/settings/security/hooks/useDeleteSSOIdentityProvider';
|
||||||
import { useUpdateSSOIdentityProvider } from '@/settings/security/hooks/useUpdateSSOIdentityProvider';
|
import { useUpdateSSOIdentityProvider } from '@/settings/security/hooks/useUpdateSSOIdentityProvider';
|
||||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* @license Enterprise */
|
/* @license Enterprise */
|
||||||
|
|
||||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||||
import { useSetRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
import {
|
import {
|
||||||
CreateOidcIdentityProviderMutationVariables,
|
CreateOidcIdentityProviderMutationVariables,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* @license Enterprise */
|
/* @license Enterprise */
|
||||||
|
|
||||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||||
import { useSetRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
import {
|
import {
|
||||||
DeleteSsoIdentityProviderMutationVariables,
|
DeleteSsoIdentityProviderMutationVariables,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* @license Enterprise */
|
/* @license Enterprise */
|
||||||
|
|
||||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProviders.state';
|
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||||
import { useSetRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
import {
|
import {
|
||||||
EditSsoIdentityProviderMutationVariables,
|
EditSsoIdentityProviderMutationVariables,
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
export type AuthProvidersKeys =
|
|
||||||
| 'isGoogleAuthEnabled'
|
|
||||||
| 'isMicrosoftAuthEnabled'
|
|
||||||
| 'isPasswordAuthEnabled';
|
|
@ -0,0 +1,20 @@
|
|||||||
|
import { Helmet } from 'react-helmet-async';
|
||||||
|
import { workspacePublicDataState } from '@/auth/states/workspacePublicDataState';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { getImageAbsoluteURI } from '~/utils/image/getImageAbsoluteURI';
|
||||||
|
|
||||||
|
export const PageFavicon = () => {
|
||||||
|
const workspacePublicData = useRecoilValue(workspacePublicDataState);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Helmet>
|
||||||
|
{workspacePublicData?.logo && (
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/x-icon"
|
||||||
|
href={getImageAbsoluteURI(workspacePublicData.logo)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Helmet>
|
||||||
|
);
|
||||||
|
};
|
@ -76,21 +76,5 @@ export const WorkspaceProviderEffect = () => {
|
|||||||
redirectToWorkspace,
|
redirectToWorkspace,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
try {
|
|
||||||
if (isDefined(workspacePublicData?.logo)) {
|
|
||||||
const link: HTMLLinkElement =
|
|
||||||
document.querySelector("link[rel*='icon']") ||
|
|
||||||
document.createElement('link');
|
|
||||||
link.rel = 'icon';
|
|
||||||
link.href = workspacePublicData.logo;
|
|
||||||
document.getElementsByTagName('head')[0].appendChild(link);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
}, [workspacePublicData]);
|
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
|
import { SignInUpWorkspaceScopeFormEffect } from '@/auth/sign-in-up/components/SignInUpWorkspaceScopeFormEffect';
|
||||||
|
|
||||||
const StyledContentContainer = styled.div`
|
const StyledContentContainer = styled.div`
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
||||||
@ -93,7 +94,10 @@ export const Invite = () => {
|
|||||||
<FooterNote />
|
<FooterNote />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
<>
|
||||||
|
<SignInUpWorkspaceScopeFormEffect />
|
||||||
<SignInUpWorkspaceScopeForm />
|
<SignInUpWorkspaceScopeForm />
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,7 @@ import { isMultiWorkspaceEnabledState } from '@/client-config/states/isMultiWork
|
|||||||
import { useUrlManager } from '@/url-manager/hooks/useUrlManager';
|
import { useUrlManager } from '@/url-manager/hooks/useUrlManager';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
import { SignInUpWorkspaceScopeFormEffect } from '@/auth/sign-in-up/components/SignInUpWorkspaceScopeFormEffect';
|
||||||
|
|
||||||
export const SignInUp = () => {
|
export const SignInUp = () => {
|
||||||
const { form } = useSignInUpForm();
|
const { form } = useSignInUpForm();
|
||||||
@ -43,7 +44,12 @@ export const SignInUp = () => {
|
|||||||
isDefined(workspacePublicData) &&
|
isDefined(workspacePublicData) &&
|
||||||
(!isMultiWorkspaceEnabled || isTwentyWorkspaceSubdomain)
|
(!isMultiWorkspaceEnabled || isTwentyWorkspaceSubdomain)
|
||||||
) {
|
) {
|
||||||
return <SignInUpWorkspaceScopeForm />;
|
return (
|
||||||
|
<>
|
||||||
|
<SignInUpWorkspaceScopeFormEffect />
|
||||||
|
<SignInUpWorkspaceScopeForm />
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <SignInUpGlobalScopeForm />;
|
return <SignInUpGlobalScopeForm />;
|
||||||
|
@ -38,7 +38,6 @@ import {
|
|||||||
} from 'src/engine/core-modules/auth/auth.exception';
|
} from 'src/engine/core-modules/auth/auth.exception';
|
||||||
import { OriginHeader } from 'src/engine/decorators/auth/origin-header.decorator';
|
import { OriginHeader } from 'src/engine/decorators/auth/origin-header.decorator';
|
||||||
import { AvailableWorkspaceOutput } from 'src/engine/core-modules/auth/dto/available-workspaces.output';
|
import { AvailableWorkspaceOutput } from 'src/engine/core-modules/auth/dto/available-workspaces.output';
|
||||||
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
|
|
||||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service';
|
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service';
|
||||||
|
|
||||||
import { ChallengeInput } from './dto/challenge.input';
|
import { ChallengeInput } from './dto/challenge.input';
|
||||||
@ -129,13 +128,7 @@ export class AuthResolver {
|
|||||||
targetWorkspaceSubdomain:
|
targetWorkspaceSubdomain:
|
||||||
this.domainManagerService.getWorkspaceSubdomainByOrigin(origin),
|
this.domainManagerService.getWorkspaceSubdomainByOrigin(origin),
|
||||||
fromSSO: false,
|
fromSSO: false,
|
||||||
isAuthEnabled: workspaceValidator.isAuthEnabled(
|
authProvider: 'password',
|
||||||
'password',
|
|
||||||
new AuthException(
|
|
||||||
'Password auth is not enabled for this workspace',
|
|
||||||
AuthExceptionCode.OAUTH_ACCESS_DENIED,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const loginToken = await this.loginTokenService.generateLoginToken(
|
const loginToken = await this.loginTokenService.generateLoginToken(
|
||||||
|
@ -18,13 +18,9 @@ import { GoogleProviderEnabledGuard } from 'src/engine/core-modules/auth/guards/
|
|||||||
import { AuthService } from 'src/engine/core-modules/auth/services/auth.service';
|
import { AuthService } from 'src/engine/core-modules/auth/services/auth.service';
|
||||||
import { GoogleRequest } from 'src/engine/core-modules/auth/strategies/google.auth.strategy';
|
import { GoogleRequest } from 'src/engine/core-modules/auth/strategies/google.auth.strategy';
|
||||||
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
|
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
|
||||||
import {
|
import { AuthException } from 'src/engine/core-modules/auth/auth.exception';
|
||||||
AuthException,
|
|
||||||
AuthExceptionCode,
|
|
||||||
} from 'src/engine/core-modules/auth/auth.exception';
|
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service';
|
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service';
|
||||||
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
|
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
|
|
||||||
@Controller('auth/google')
|
@Controller('auth/google')
|
||||||
@ -70,13 +66,7 @@ export class GoogleAuthController {
|
|||||||
workspacePersonalInviteToken,
|
workspacePersonalInviteToken,
|
||||||
targetWorkspaceSubdomain,
|
targetWorkspaceSubdomain,
|
||||||
fromSSO: true,
|
fromSSO: true,
|
||||||
isAuthEnabled: workspaceValidator.isAuthEnabled(
|
isAuthEnabled: 'google',
|
||||||
'google',
|
|
||||||
new AuthException(
|
|
||||||
'Google auth is not enabled for this workspace',
|
|
||||||
AuthExceptionCode.OAUTH_ACCESS_DENIED,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -15,12 +15,8 @@ import { MicrosoftProviderEnabledGuard } from 'src/engine/core-modules/auth/guar
|
|||||||
import { AuthService } from 'src/engine/core-modules/auth/services/auth.service';
|
import { AuthService } from 'src/engine/core-modules/auth/services/auth.service';
|
||||||
import { MicrosoftRequest } from 'src/engine/core-modules/auth/strategies/microsoft.auth.strategy';
|
import { MicrosoftRequest } from 'src/engine/core-modules/auth/strategies/microsoft.auth.strategy';
|
||||||
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
|
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
|
||||||
import {
|
import { AuthException } from 'src/engine/core-modules/auth/auth.exception';
|
||||||
AuthException,
|
|
||||||
AuthExceptionCode,
|
|
||||||
} from 'src/engine/core-modules/auth/auth.exception';
|
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
|
|
||||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service';
|
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service';
|
||||||
|
|
||||||
@Controller('auth/microsoft')
|
@Controller('auth/microsoft')
|
||||||
@ -66,13 +62,7 @@ export class MicrosoftAuthController {
|
|||||||
workspacePersonalInviteToken,
|
workspacePersonalInviteToken,
|
||||||
targetWorkspaceSubdomain,
|
targetWorkspaceSubdomain,
|
||||||
fromSSO: true,
|
fromSSO: true,
|
||||||
isAuthEnabled: workspaceValidator.isAuthEnabled(
|
authProvider: 'microsoft',
|
||||||
'microsoft',
|
|
||||||
new AuthException(
|
|
||||||
'Microsoft auth is not enabled for this workspace',
|
|
||||||
AuthExceptionCode.OAUTH_ACCESS_DENIED,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const loginToken = await this.loginTokenService.generateLoginToken(
|
const loginToken = await this.loginTokenService.generateLoginToken(
|
||||||
|
@ -45,9 +45,9 @@ import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/use
|
|||||||
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-invitation/services/workspace-invitation.service';
|
||||||
import { AvailableWorkspaceOutput } from 'src/engine/core-modules/auth/dto/available-workspaces.output';
|
import { AvailableWorkspaceOutput } from 'src/engine/core-modules/auth/dto/available-workspaces.output';
|
||||||
import { UserService } from 'src/engine/core-modules/user/services/user.service';
|
import { UserService } from 'src/engine/core-modules/user/services/user.service';
|
||||||
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
|
|
||||||
import { userValidator } from 'src/engine/core-modules/user/user.validate';
|
import { userValidator } from 'src/engine/core-modules/user/user.validate';
|
||||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service';
|
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/service/domain-manager.service';
|
||||||
|
import { WorkspaceAuthProvider } from 'src/engine/core-modules/workspace/types/workspace.type';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
// eslint-disable-next-line @nx/workspace-inject-workspace-repository
|
// eslint-disable-next-line @nx/workspace-inject-workspace-repository
|
||||||
@ -161,7 +161,7 @@ export class AuthService {
|
|||||||
lastName,
|
lastName,
|
||||||
picture,
|
picture,
|
||||||
fromSSO,
|
fromSSO,
|
||||||
isAuthEnabled,
|
authProvider,
|
||||||
}: {
|
}: {
|
||||||
email: string;
|
email: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
@ -172,7 +172,7 @@ export class AuthService {
|
|||||||
picture?: string | null;
|
picture?: string | null;
|
||||||
fromSSO: boolean;
|
fromSSO: boolean;
|
||||||
targetWorkspaceSubdomain?: string;
|
targetWorkspaceSubdomain?: string;
|
||||||
isAuthEnabled?: ReturnType<(typeof workspaceValidator)['isAuthEnabled']>;
|
authProvider?: WorkspaceAuthProvider;
|
||||||
}) {
|
}) {
|
||||||
return await this.signInUpService.signInUp({
|
return await this.signInUpService.signInUp({
|
||||||
email,
|
email,
|
||||||
@ -184,7 +184,7 @@ export class AuthService {
|
|||||||
targetWorkspaceSubdomain,
|
targetWorkspaceSubdomain,
|
||||||
picture,
|
picture,
|
||||||
fromSSO,
|
fromSSO,
|
||||||
isAuthEnabled,
|
authProvider,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ export class AuthService {
|
|||||||
where: { email },
|
where: { email },
|
||||||
});
|
});
|
||||||
|
|
||||||
userValidator.assertIsExist(
|
userValidator.assertIsDefinedOrThrow(
|
||||||
userWithIdAndDefaultWorkspaceId,
|
userWithIdAndDefaultWorkspaceId,
|
||||||
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
||||||
);
|
);
|
||||||
@ -210,7 +210,7 @@ export class AuthService {
|
|||||||
workspaceId &&
|
workspaceId &&
|
||||||
userWithIdAndDefaultWorkspaceId.defaultWorkspaceId !== workspaceId
|
userWithIdAndDefaultWorkspaceId.defaultWorkspaceId !== workspaceId
|
||||||
) {
|
) {
|
||||||
await this.userService.saveDefaultWorkspace(
|
await this.userService.saveDefaultWorkspaceIfUserHasAccessOrThrow(
|
||||||
userWithIdAndDefaultWorkspaceId.id,
|
userWithIdAndDefaultWorkspaceId.id,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
@ -223,7 +223,7 @@ export class AuthService {
|
|||||||
relations: ['defaultWorkspace', 'workspaces', 'workspaces.workspace'],
|
relations: ['defaultWorkspace', 'workspaces', 'workspaces.workspace'],
|
||||||
});
|
});
|
||||||
|
|
||||||
userValidator.assertIsExist(
|
userValidator.assertIsDefinedOrThrow(
|
||||||
user,
|
user,
|
||||||
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
||||||
);
|
);
|
||||||
@ -254,7 +254,7 @@ export class AuthService {
|
|||||||
email,
|
email,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (userValidator.isExist(user)) {
|
if (userValidator.isDefined(user)) {
|
||||||
return {
|
return {
|
||||||
exists: true,
|
exists: true,
|
||||||
availableWorkspaces: await this.findAvailableWorkspacesByEmail(email),
|
availableWorkspaces: await this.findAvailableWorkspacesByEmail(email),
|
||||||
@ -460,7 +460,7 @@ export class AuthService {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
userValidator.assertIsExist(
|
userValidator.assertIsDefinedOrThrow(
|
||||||
user,
|
user,
|
||||||
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
||||||
);
|
);
|
||||||
|
@ -32,6 +32,7 @@ import {
|
|||||||
} from 'src/engine/core-modules/workspace/workspace.entity';
|
} from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
|
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
|
||||||
import { getImageBufferFromUrl } from 'src/utils/image';
|
import { getImageBufferFromUrl } from 'src/utils/image';
|
||||||
|
import { WorkspaceAuthProvider } from 'src/engine/core-modules/workspace/types/workspace.type';
|
||||||
|
|
||||||
export type SignInUpServiceInput = {
|
export type SignInUpServiceInput = {
|
||||||
email: string;
|
email: string;
|
||||||
@ -43,7 +44,7 @@ export type SignInUpServiceInput = {
|
|||||||
picture?: string | null;
|
picture?: string | null;
|
||||||
fromSSO: boolean;
|
fromSSO: boolean;
|
||||||
targetWorkspaceSubdomain?: string;
|
targetWorkspaceSubdomain?: string;
|
||||||
isAuthEnabled?: ReturnType<(typeof workspaceValidator)['isAuthEnabled']>;
|
authProvider?: WorkspaceAuthProvider;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -73,7 +74,7 @@ export class SignInUpService {
|
|||||||
picture,
|
picture,
|
||||||
fromSSO,
|
fromSSO,
|
||||||
targetWorkspaceSubdomain,
|
targetWorkspaceSubdomain,
|
||||||
isAuthEnabled,
|
authProvider,
|
||||||
}: SignInUpServiceInput) {
|
}: SignInUpServiceInput) {
|
||||||
if (!firstName) firstName = '';
|
if (!firstName) firstName = '';
|
||||||
if (!lastName) lastName = '';
|
if (!lastName) lastName = '';
|
||||||
@ -154,7 +155,7 @@ export class SignInUpService {
|
|||||||
lastName,
|
lastName,
|
||||||
picture,
|
picture,
|
||||||
existingUser,
|
existingUser,
|
||||||
isAuthEnabled,
|
authProvider,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.workspaceInvitationService.invalidateWorkspaceInvitation(
|
await this.workspaceInvitationService.invalidateWorkspaceInvitation(
|
||||||
@ -187,7 +188,7 @@ export class SignInUpService {
|
|||||||
lastName,
|
lastName,
|
||||||
picture,
|
picture,
|
||||||
existingUser,
|
existingUser,
|
||||||
isAuthEnabled,
|
authProvider,
|
||||||
}: {
|
}: {
|
||||||
email: string;
|
email: string;
|
||||||
passwordHash: string | undefined;
|
passwordHash: string | undefined;
|
||||||
@ -196,7 +197,7 @@ export class SignInUpService {
|
|||||||
lastName: string;
|
lastName: string;
|
||||||
picture: SignInUpServiceInput['picture'];
|
picture: SignInUpServiceInput['picture'];
|
||||||
existingUser: User | null;
|
existingUser: User | null;
|
||||||
isAuthEnabled?: ReturnType<(typeof workspaceValidator)['isAuthEnabled']>;
|
authProvider?: WorkspaceAuthProvider;
|
||||||
}) {
|
}) {
|
||||||
const isNewUser = !isDefined(existingUser);
|
const isNewUser = !isDefined(existingUser);
|
||||||
let user = existingUser;
|
let user = existingUser;
|
||||||
@ -217,8 +218,16 @@ export class SignInUpService {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isAuthEnabled)
|
if (authProvider) {
|
||||||
workspaceValidator.validateAuth(isAuthEnabled, workspace);
|
workspaceValidator.isAuthEnabledOrThrow(
|
||||||
|
authProvider,
|
||||||
|
workspace,
|
||||||
|
new AuthException(
|
||||||
|
`${authProvider} auth is not enabled for this workspace`,
|
||||||
|
AuthExceptionCode.OAUTH_ACCESS_DENIED,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (isNewUser) {
|
if (isNewUser) {
|
||||||
const imagePath = await this.uploadPicture(picture, workspace.id);
|
const imagePath = await this.uploadPicture(picture, workspace.id);
|
||||||
@ -236,7 +245,7 @@ export class SignInUpService {
|
|||||||
user = await this.userRepository.save(userToCreate);
|
user = await this.userRepository.save(userToCreate);
|
||||||
}
|
}
|
||||||
|
|
||||||
userValidator.assertIsExist(
|
userValidator.assertIsDefinedOrThrow(
|
||||||
user,
|
user,
|
||||||
new AuthException(
|
new AuthException(
|
||||||
'User not found',
|
'User not found',
|
||||||
|
@ -47,7 +47,7 @@ describe('SwitchWorkspaceService', () => {
|
|||||||
{
|
{
|
||||||
provide: UserService,
|
provide: UserService,
|
||||||
useValue: {
|
useValue: {
|
||||||
saveDefaultWorkspace: jest.fn(),
|
saveDefaultWorkspaceIfUserHasAccessOrThrow: jest.fn(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -211,10 +211,9 @@ describe('SwitchWorkspaceService', () => {
|
|||||||
refreshToken: mockRefreshToken,
|
refreshToken: mockRefreshToken,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(userService.saveDefaultWorkspace).toHaveBeenCalledWith(
|
expect(
|
||||||
mockUser.id,
|
userService.saveDefaultWorkspaceIfUserHasAccessOrThrow,
|
||||||
mockWorkspace.id,
|
).toHaveBeenCalledWith(mockUser.id, mockWorkspace.id);
|
||||||
);
|
|
||||||
expect(accessTokenService.generateAccessToken).toHaveBeenCalledWith(
|
expect(accessTokenService.generateAccessToken).toHaveBeenCalledWith(
|
||||||
mockUser.id,
|
mockUser.id,
|
||||||
mockWorkspace.id,
|
mockWorkspace.id,
|
||||||
|
@ -78,7 +78,10 @@ export class SwitchWorkspaceService {
|
|||||||
user: User,
|
user: User,
|
||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
): Promise<AuthTokens> {
|
): Promise<AuthTokens> {
|
||||||
await this.userService.saveDefaultWorkspace(user.id, workspace.id);
|
await this.userService.saveDefaultWorkspaceIfUserHasAccessOrThrow(
|
||||||
|
user.id,
|
||||||
|
workspace.id,
|
||||||
|
);
|
||||||
|
|
||||||
const token = await this.accessTokenService.generateAccessToken(
|
const token = await this.accessTokenService.generateAccessToken(
|
||||||
user.id,
|
user.id,
|
||||||
|
@ -135,7 +135,7 @@ export class UserService extends TypeOrmQueryService<User> {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveDefaultWorkspace(userId: string, workspaceId: string) {
|
async hasUserAccessToWorkspaceOrThrow(userId: string, workspaceId: string) {
|
||||||
const user = await this.userRepository.findOne({
|
const user = await this.userRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: userId,
|
id: userId,
|
||||||
@ -146,13 +146,20 @@ export class UserService extends TypeOrmQueryService<User> {
|
|||||||
relations: ['workspaces'],
|
relations: ['workspaces'],
|
||||||
});
|
});
|
||||||
|
|
||||||
userValidator.assertIsExist(
|
userValidator.assertIsDefinedOrThrow(
|
||||||
user,
|
user,
|
||||||
new AuthException(
|
new AuthException(
|
||||||
'User does not have access to this workspace',
|
'User does not have access to this workspace',
|
||||||
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
AuthExceptionCode.FORBIDDEN_EXCEPTION,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveDefaultWorkspaceIfUserHasAccessOrThrow(
|
||||||
|
userId: string,
|
||||||
|
workspaceId: string,
|
||||||
|
) {
|
||||||
|
await this.hasUserAccessToWorkspaceOrThrow(userId, workspaceId);
|
||||||
|
|
||||||
return await this.userRepository.save({
|
return await this.userRepository.save({
|
||||||
id: userId,
|
id: userId,
|
||||||
|
@ -77,7 +77,10 @@ export class UserResolver {
|
|||||||
this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') &&
|
this.environmentService.get('IS_MULTIWORKSPACE_ENABLED') &&
|
||||||
workspaceId
|
workspaceId
|
||||||
) {
|
) {
|
||||||
await this.userService.saveDefaultWorkspace(userId, workspaceId);
|
await this.userService.saveDefaultWorkspaceIfUserHasAccessOrThrow(
|
||||||
|
userId,
|
||||||
|
workspaceId,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const user = await this.userRepository.findOne({
|
const user = await this.userRepository.findOne({
|
||||||
@ -87,7 +90,7 @@ export class UserResolver {
|
|||||||
relations: ['defaultWorkspace', 'workspaces', 'workspaces.workspace'],
|
relations: ['defaultWorkspace', 'workspaces', 'workspaces.workspace'],
|
||||||
});
|
});
|
||||||
|
|
||||||
userValidator.assertIsExist(
|
userValidator.assertIsDefinedOrThrow(
|
||||||
user,
|
user,
|
||||||
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
new AuthException('User not found', AuthExceptionCode.USER_NOT_FOUND),
|
||||||
);
|
);
|
||||||
|
@ -1,34 +1,24 @@
|
|||||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||||
import { CustomException } from 'src/utils/custom-exception';
|
import { CustomException } from 'src/utils/custom-exception';
|
||||||
|
import { isDefined } from 'src/utils/is-defined';
|
||||||
|
|
||||||
const assertIsExist = (
|
const assertIsDefinedOrThrow = (
|
||||||
user: User | undefined | null,
|
user: User | undefined | null,
|
||||||
exceptionToThrow: CustomException,
|
exceptionToThrow: CustomException,
|
||||||
): asserts user is User => {
|
): asserts user is User => {
|
||||||
if (!user) {
|
if (!isDefined(user)) {
|
||||||
throw exceptionToThrow;
|
throw exceptionToThrow;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const isExist = (user: User | undefined | null): user is User => {
|
const isUserDefined = (user: User | undefined | null): user is User => {
|
||||||
return !!user;
|
return isDefined(user);
|
||||||
};
|
|
||||||
|
|
||||||
const assertHasDefaultWorkspace = (
|
|
||||||
user: User,
|
|
||||||
exceptionToThrow?: CustomException,
|
|
||||||
): asserts user is User & { defaultWorkspaceId: string } => {
|
|
||||||
if (!user.defaultWorkspaceId) {
|
|
||||||
throw exceptionToThrow;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const userValidator: {
|
export const userValidator: {
|
||||||
assertIsExist: typeof assertIsExist;
|
assertIsDefinedOrThrow: typeof assertIsDefinedOrThrow;
|
||||||
assertHasDefaultWorkspace: typeof assertHasDefaultWorkspace;
|
isDefined: typeof isUserDefined;
|
||||||
isExist: typeof isExist;
|
|
||||||
} = {
|
} = {
|
||||||
assertIsExist,
|
assertIsDefinedOrThrow,
|
||||||
assertHasDefaultWorkspace,
|
isDefined: isUserDefined,
|
||||||
isExist,
|
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export type WorkspaceAuthProvider = 'google' | 'microsoft' | 'password';
|
@ -3,8 +3,8 @@ import {
|
|||||||
WorkspaceActivationStatus,
|
WorkspaceActivationStatus,
|
||||||
} from 'src/engine/core-modules/workspace/workspace.entity';
|
} from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { CustomException } from 'src/utils/custom-exception';
|
import { CustomException } from 'src/utils/custom-exception';
|
||||||
|
import { AuthException } from 'src/engine/core-modules/auth/auth.exception';
|
||||||
type WorkspaceAuthProvider = 'google' | 'microsoft' | 'password';
|
import { WorkspaceAuthProvider } from 'src/engine/core-modules/workspace/types/workspace.type';
|
||||||
|
|
||||||
const assertIsExist = (
|
const assertIsExist = (
|
||||||
workspace: Workspace | undefined | null,
|
workspace: Workspace | undefined | null,
|
||||||
@ -25,40 +25,24 @@ const assertIsActive = (
|
|||||||
throw exceptionToThrow;
|
throw exceptionToThrow;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IsAuthEnabled = <P extends WorkspaceAuthProvider>(
|
const isAuthEnabledOrThrow = (
|
||||||
provider: P,
|
provider: WorkspaceAuthProvider,
|
||||||
exceptionToThrow: CustomException,
|
|
||||||
) => (
|
|
||||||
workspace: Workspace,
|
workspace: Workspace,
|
||||||
exceptionToThrowCustom?: CustomException,
|
exceptionToThrowCustom: AuthException,
|
||||||
) => boolean;
|
) => {
|
||||||
|
|
||||||
const isAuthEnabled: IsAuthEnabled = (provider, exceptionToThrow) => {
|
|
||||||
return (workspace, exceptionToThrowCustom = exceptionToThrow) => {
|
|
||||||
if (provider === 'google' && workspace.isGoogleAuthEnabled) return true;
|
if (provider === 'google' && workspace.isGoogleAuthEnabled) return true;
|
||||||
if (provider === 'microsoft' && workspace.isMicrosoftAuthEnabled)
|
if (provider === 'microsoft' && workspace.isMicrosoftAuthEnabled) return true;
|
||||||
return true;
|
|
||||||
if (provider === 'password' && workspace.isPasswordAuthEnabled) return true;
|
if (provider === 'password' && workspace.isPasswordAuthEnabled) return true;
|
||||||
|
|
||||||
if (exceptionToThrowCustom) {
|
|
||||||
throw exceptionToThrowCustom;
|
throw exceptionToThrowCustom;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateAuth = (fn: ReturnType<IsAuthEnabled>, workspace: Workspace) =>
|
|
||||||
fn(workspace);
|
|
||||||
|
|
||||||
export const workspaceValidator: {
|
export const workspaceValidator: {
|
||||||
assertIsExist: typeof assertIsExist;
|
assertIsExist: typeof assertIsExist;
|
||||||
assertIsActive: typeof assertIsActive;
|
assertIsActive: typeof assertIsActive;
|
||||||
isAuthEnabled: IsAuthEnabled;
|
isAuthEnabledOrThrow: typeof isAuthEnabledOrThrow;
|
||||||
validateAuth: typeof validateAuth;
|
|
||||||
} = {
|
} = {
|
||||||
assertIsExist: assertIsExist,
|
assertIsExist: assertIsExist,
|
||||||
assertIsActive: assertIsActive,
|
assertIsActive: assertIsActive,
|
||||||
isAuthEnabled,
|
isAuthEnabledOrThrow: isAuthEnabledOrThrow,
|
||||||
validateAuth,
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user