Add possibility to invite members to workspace (#579)
* Add possibility to invite members to workspace * Update endpoints * Wrap up front end * Fix according to review * Fix lint
This commit is contained in:
@ -39,6 +39,7 @@ function AuthRoutes() {
|
|||||||
<Route path={AuthPath.Index} element={<Index />} />
|
<Route path={AuthPath.Index} element={<Index />} />
|
||||||
<Route path={AuthPath.Callback} element={<Verify />} />
|
<Route path={AuthPath.Callback} element={<Verify />} />
|
||||||
<Route path={AuthPath.PasswordLogin} element={<PasswordLogin />} />
|
<Route path={AuthPath.PasswordLogin} element={<PasswordLogin />} />
|
||||||
|
<Route path={AuthPath.InviteLink} element={<PasswordLogin />} />
|
||||||
<Route
|
<Route
|
||||||
path={AuthPath.CreateWorkspace}
|
path={AuthPath.CreateWorkspace}
|
||||||
element={<CreateWorkspace />}
|
element={<CreateWorkspace />}
|
||||||
|
|||||||
@ -1163,6 +1163,7 @@ export type Mutation = {
|
|||||||
deleteManyPipelineProgress: AffectedRows;
|
deleteManyPipelineProgress: AffectedRows;
|
||||||
deleteWorkspaceMember: WorkspaceMember;
|
deleteWorkspaceMember: WorkspaceMember;
|
||||||
renewToken: AuthTokens;
|
renewToken: AuthTokens;
|
||||||
|
signUp: LoginToken;
|
||||||
updateOneCommentThread: CommentThread;
|
updateOneCommentThread: CommentThread;
|
||||||
updateOneCompany?: Maybe<Company>;
|
updateOneCompany?: Maybe<Company>;
|
||||||
updateOnePerson?: Maybe<Person>;
|
updateOnePerson?: Maybe<Person>;
|
||||||
@ -1244,6 +1245,13 @@ export type MutationRenewTokenArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationSignUpArgs = {
|
||||||
|
email: Scalars['String'];
|
||||||
|
password: Scalars['String'];
|
||||||
|
workspaceInviteHash?: InputMaybe<Scalars['String']>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationUpdateOneCommentThreadArgs = {
|
export type MutationUpdateOneCommentThreadArgs = {
|
||||||
data: CommentThreadUpdateInput;
|
data: CommentThreadUpdateInput;
|
||||||
where: CommentThreadWhereUniqueInput;
|
where: CommentThreadWhereUniqueInput;
|
||||||
@ -2439,6 +2447,7 @@ export type PipelineWhereUniqueInput = {
|
|||||||
export type Query = {
|
export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
checkUserExists: UserExists;
|
checkUserExists: UserExists;
|
||||||
|
checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid;
|
||||||
clientConfig: ClientConfig;
|
clientConfig: ClientConfig;
|
||||||
currentUser: User;
|
currentUser: User;
|
||||||
currentWorkspace: Workspace;
|
currentWorkspace: Workspace;
|
||||||
@ -2460,6 +2469,11 @@ export type QueryCheckUserExistsArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type QueryCheckWorkspaceInviteHashIsValidArgs = {
|
||||||
|
inviteHash: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type QueryFindManyCommentThreadsArgs = {
|
export type QueryFindManyCommentThreadsArgs = {
|
||||||
cursor?: InputMaybe<CommentThreadWhereUniqueInput>;
|
cursor?: InputMaybe<CommentThreadWhereUniqueInput>;
|
||||||
distinct?: InputMaybe<Array<CommentThreadScalarFieldEnum>>;
|
distinct?: InputMaybe<Array<CommentThreadScalarFieldEnum>>;
|
||||||
@ -2917,6 +2931,7 @@ export type Workspace = {
|
|||||||
displayName?: Maybe<Scalars['String']>;
|
displayName?: Maybe<Scalars['String']>;
|
||||||
domainName?: Maybe<Scalars['String']>;
|
domainName?: Maybe<Scalars['String']>;
|
||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
|
inviteHash?: Maybe<Scalars['String']>;
|
||||||
logo?: Maybe<Scalars['String']>;
|
logo?: Maybe<Scalars['String']>;
|
||||||
people?: Maybe<Array<Person>>;
|
people?: Maybe<Array<Person>>;
|
||||||
pipelineProgresses?: Maybe<Array<PipelineProgress>>;
|
pipelineProgresses?: Maybe<Array<PipelineProgress>>;
|
||||||
@ -2926,6 +2941,11 @@ export type Workspace = {
|
|||||||
workspaceMember?: Maybe<Array<WorkspaceMember>>;
|
workspaceMember?: Maybe<Array<WorkspaceMember>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type WorkspaceInviteHashValid = {
|
||||||
|
__typename?: 'WorkspaceInviteHashValid';
|
||||||
|
isValid: Scalars['Boolean'];
|
||||||
|
};
|
||||||
|
|
||||||
export type WorkspaceMember = {
|
export type WorkspaceMember = {
|
||||||
__typename?: 'WorkspaceMember';
|
__typename?: 'WorkspaceMember';
|
||||||
createdAt: Scalars['DateTime'];
|
createdAt: Scalars['DateTime'];
|
||||||
@ -3054,6 +3074,7 @@ export type WorkspaceUpdateInput = {
|
|||||||
displayName?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
|
displayName?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
|
||||||
domainName?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
|
domainName?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
|
||||||
id?: InputMaybe<StringFieldUpdateOperationsInput>;
|
id?: InputMaybe<StringFieldUpdateOperationsInput>;
|
||||||
|
inviteHash?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
|
||||||
logo?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
|
logo?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
|
||||||
people?: InputMaybe<PersonUpdateManyWithoutWorkspaceNestedInput>;
|
people?: InputMaybe<PersonUpdateManyWithoutWorkspaceNestedInput>;
|
||||||
pipelineProgresses?: InputMaybe<PipelineProgressUpdateManyWithoutWorkspaceNestedInput>;
|
pipelineProgresses?: InputMaybe<PipelineProgressUpdateManyWithoutWorkspaceNestedInput>;
|
||||||
@ -3086,6 +3107,23 @@ export type ChallengeMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type ChallengeMutation = { __typename?: 'Mutation', challenge: { __typename?: 'LoginToken', loginToken: { __typename?: 'AuthToken', expiresAt: string, token: string } } };
|
export type ChallengeMutation = { __typename?: 'Mutation', challenge: { __typename?: 'LoginToken', loginToken: { __typename?: 'AuthToken', expiresAt: string, token: string } } };
|
||||||
|
|
||||||
|
export type SignUpMutationVariables = Exact<{
|
||||||
|
email: Scalars['String'];
|
||||||
|
password: Scalars['String'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type SignUpMutation = { __typename?: 'Mutation', signUp: { __typename?: 'LoginToken', loginToken: { __typename?: 'AuthToken', expiresAt: string, token: string } } };
|
||||||
|
|
||||||
|
export type SignUpToWorkspaceMutationVariables = Exact<{
|
||||||
|
email: Scalars['String'];
|
||||||
|
password: Scalars['String'];
|
||||||
|
workspaceInviteHash: Scalars['String'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type SignUpToWorkspaceMutation = { __typename?: 'Mutation', signUp: { __typename?: 'LoginToken', loginToken: { __typename?: 'AuthToken', expiresAt: string, token: string } } };
|
||||||
|
|
||||||
export type VerifyMutationVariables = Exact<{
|
export type VerifyMutationVariables = Exact<{
|
||||||
loginToken: Scalars['String'];
|
loginToken: Scalars['String'];
|
||||||
}>;
|
}>;
|
||||||
@ -3526,6 +3564,85 @@ export function useChallengeMutation(baseOptions?: Apollo.MutationHookOptions<Ch
|
|||||||
export type ChallengeMutationHookResult = ReturnType<typeof useChallengeMutation>;
|
export type ChallengeMutationHookResult = ReturnType<typeof useChallengeMutation>;
|
||||||
export type ChallengeMutationResult = Apollo.MutationResult<ChallengeMutation>;
|
export type ChallengeMutationResult = Apollo.MutationResult<ChallengeMutation>;
|
||||||
export type ChallengeMutationOptions = Apollo.BaseMutationOptions<ChallengeMutation, ChallengeMutationVariables>;
|
export type ChallengeMutationOptions = Apollo.BaseMutationOptions<ChallengeMutation, ChallengeMutationVariables>;
|
||||||
|
export const SignUpDocument = gql`
|
||||||
|
mutation SignUp($email: String!, $password: String!) {
|
||||||
|
signUp(email: $email, password: $password) {
|
||||||
|
loginToken {
|
||||||
|
expiresAt
|
||||||
|
token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type SignUpMutationFn = Apollo.MutationFunction<SignUpMutation, SignUpMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useSignUpMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useSignUpMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useSignUpMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [signUpMutation, { data, loading, error }] = useSignUpMutation({
|
||||||
|
* variables: {
|
||||||
|
* email: // value for 'email'
|
||||||
|
* password: // value for 'password'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useSignUpMutation(baseOptions?: Apollo.MutationHookOptions<SignUpMutation, SignUpMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<SignUpMutation, SignUpMutationVariables>(SignUpDocument, options);
|
||||||
|
}
|
||||||
|
export type SignUpMutationHookResult = ReturnType<typeof useSignUpMutation>;
|
||||||
|
export type SignUpMutationResult = Apollo.MutationResult<SignUpMutation>;
|
||||||
|
export type SignUpMutationOptions = Apollo.BaseMutationOptions<SignUpMutation, SignUpMutationVariables>;
|
||||||
|
export const SignUpToWorkspaceDocument = gql`
|
||||||
|
mutation SignUpToWorkspace($email: String!, $password: String!, $workspaceInviteHash: String!) {
|
||||||
|
signUp(
|
||||||
|
email: $email
|
||||||
|
password: $password
|
||||||
|
workspaceInviteHash: $workspaceInviteHash
|
||||||
|
) {
|
||||||
|
loginToken {
|
||||||
|
expiresAt
|
||||||
|
token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type SignUpToWorkspaceMutationFn = Apollo.MutationFunction<SignUpToWorkspaceMutation, SignUpToWorkspaceMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useSignUpToWorkspaceMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useSignUpToWorkspaceMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useSignUpToWorkspaceMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [signUpToWorkspaceMutation, { data, loading, error }] = useSignUpToWorkspaceMutation({
|
||||||
|
* variables: {
|
||||||
|
* email: // value for 'email'
|
||||||
|
* password: // value for 'password'
|
||||||
|
* workspaceInviteHash: // value for 'workspaceInviteHash'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useSignUpToWorkspaceMutation(baseOptions?: Apollo.MutationHookOptions<SignUpToWorkspaceMutation, SignUpToWorkspaceMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<SignUpToWorkspaceMutation, SignUpToWorkspaceMutationVariables>(SignUpToWorkspaceDocument, options);
|
||||||
|
}
|
||||||
|
export type SignUpToWorkspaceMutationHookResult = ReturnType<typeof useSignUpToWorkspaceMutation>;
|
||||||
|
export type SignUpToWorkspaceMutationResult = Apollo.MutationResult<SignUpToWorkspaceMutation>;
|
||||||
|
export type SignUpToWorkspaceMutationOptions = Apollo.BaseMutationOptions<SignUpToWorkspaceMutation, SignUpToWorkspaceMutationVariables>;
|
||||||
export const VerifyDocument = gql`
|
export const VerifyDocument = gql`
|
||||||
mutation Verify($loginToken: String!) {
|
mutation Verify($loginToken: String!) {
|
||||||
verify(loginToken: $loginToken) {
|
verify(loginToken: $loginToken) {
|
||||||
|
|||||||
@ -27,15 +27,15 @@ root.render(
|
|||||||
<ApolloProvider>
|
<ApolloProvider>
|
||||||
<AppThemeProvider>
|
<AppThemeProvider>
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<UserProvider>
|
<HotkeysProvider initiallyActiveScopes={INITIAL_HOTKEYS_SCOPES}>
|
||||||
<ClientConfigProvider>
|
<BrowserRouter>
|
||||||
<HotkeysProvider initiallyActiveScopes={INITIAL_HOTKEYS_SCOPES}>
|
<UserProvider>
|
||||||
<BrowserRouter>
|
<ClientConfigProvider>
|
||||||
<App />
|
<App />
|
||||||
</BrowserRouter>
|
</ClientConfigProvider>
|
||||||
</HotkeysProvider>
|
</UserProvider>
|
||||||
</ClientConfigProvider>
|
</BrowserRouter>
|
||||||
</UserProvider>
|
</HotkeysProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
</AppThemeProvider>
|
</AppThemeProvider>
|
||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { useChallengeMutation, useVerifyMutation } from '~/generated/graphql';
|
import {
|
||||||
|
useChallengeMutation,
|
||||||
|
useSignUpMutation,
|
||||||
|
useSignUpToWorkspaceMutation,
|
||||||
|
useVerifyMutation,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
import { currentUserState } from '../states/currentUserState';
|
import { currentUserState } from '../states/currentUserState';
|
||||||
import { isAuthenticatingState } from '../states/isAuthenticatingState';
|
import { isAuthenticatingState } from '../states/isAuthenticatingState';
|
||||||
@ -13,6 +18,8 @@ export function useAuth() {
|
|||||||
const [, setIsAuthenticating] = useRecoilState(isAuthenticatingState);
|
const [, setIsAuthenticating] = useRecoilState(isAuthenticatingState);
|
||||||
|
|
||||||
const [challenge] = useChallengeMutation();
|
const [challenge] = useChallengeMutation();
|
||||||
|
const [signUp] = useSignUpMutation();
|
||||||
|
const [SignUpToWorkspace] = useSignUpToWorkspaceMutation();
|
||||||
const [verify] = useVerifyMutation();
|
const [verify] = useVerifyMutation();
|
||||||
|
|
||||||
const handleChallenge = useCallback(
|
const handleChallenge = useCallback(
|
||||||
@ -74,10 +81,57 @@ export function useAuth() {
|
|||||||
setTokenPair(null);
|
setTokenPair(null);
|
||||||
}, [setTokenPair]);
|
}, [setTokenPair]);
|
||||||
|
|
||||||
|
const handleSignUp = useCallback(
|
||||||
|
async (email: string, password: string) => {
|
||||||
|
const signUpResult = await signUp({
|
||||||
|
variables: {
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (signUpResult.errors) {
|
||||||
|
throw signUpResult.errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!signUpResult.data?.signUp) {
|
||||||
|
throw new Error('No login token');
|
||||||
|
}
|
||||||
|
|
||||||
|
await handleVerify(signUpResult.data?.signUp.loginToken.token);
|
||||||
|
},
|
||||||
|
[signUp, handleVerify],
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSignUpToWorkspace = useCallback(
|
||||||
|
async (email: string, password: string, workspaceInviteHash: string) => {
|
||||||
|
const signUpResult = await SignUpToWorkspace({
|
||||||
|
variables: {
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
workspaceInviteHash,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (signUpResult.errors) {
|
||||||
|
throw signUpResult.errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!signUpResult.data?.signUp) {
|
||||||
|
throw new Error('No login token');
|
||||||
|
}
|
||||||
|
|
||||||
|
await handleVerify(signUpResult.data?.signUp.loginToken.token);
|
||||||
|
},
|
||||||
|
[SignUpToWorkspace, handleVerify],
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
challenge: handleChallenge,
|
challenge: handleChallenge,
|
||||||
verify: handleVerify,
|
verify: handleVerify,
|
||||||
login: handleLogin,
|
login: handleLogin,
|
||||||
|
signUp: handleSignUp,
|
||||||
|
signUpToWorkspace: handleSignUpToWorkspace,
|
||||||
logout: handleLogout,
|
logout: handleLogout,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,36 @@ export const CHALLENGE = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const SIGN_UP = gql`
|
||||||
|
mutation SignUp($email: String!, $password: String!) {
|
||||||
|
signUp(email: $email, password: $password) {
|
||||||
|
loginToken {
|
||||||
|
expiresAt
|
||||||
|
token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SIGN_UP_TO_WORKSPACE = gql`
|
||||||
|
mutation SignUpToWorkspace(
|
||||||
|
$email: String!
|
||||||
|
$password: String!
|
||||||
|
$workspaceInviteHash: String!
|
||||||
|
) {
|
||||||
|
signUp(
|
||||||
|
email: $email
|
||||||
|
password: $password
|
||||||
|
workspaceInviteHash: $workspaceInviteHash
|
||||||
|
) {
|
||||||
|
loginToken {
|
||||||
|
expiresAt
|
||||||
|
token
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const VERIFY = gql`
|
export const VERIFY = gql`
|
||||||
mutation Verify($loginToken: String!) {
|
mutation Verify($loginToken: String!) {
|
||||||
verify(loginToken: $loginToken) {
|
verify(loginToken: $loginToken) {
|
||||||
|
|||||||
@ -130,10 +130,10 @@ export function CommentThread({
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (commentThread) {
|
if (commentThread && !title) {
|
||||||
setTitle(commentThread?.title ?? '');
|
setTitle(commentThread?.title ?? '');
|
||||||
}
|
}
|
||||||
}, [commentThread]);
|
}, [commentThread, title]);
|
||||||
|
|
||||||
if (!commentThread) {
|
if (!commentThread) {
|
||||||
return <></>;
|
return <></>;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
@ -62,35 +62,61 @@ export function PasswordLogin() {
|
|||||||
);
|
);
|
||||||
const [formError, setFormError] = useState('');
|
const [formError, setFormError] = useState('');
|
||||||
|
|
||||||
const { login } = useAuth();
|
const { login, signUp, signUpToWorkspace } = useAuth();
|
||||||
|
|
||||||
const handleLogin = useCallback(async () => {
|
|
||||||
try {
|
|
||||||
setMockMode(false);
|
|
||||||
|
|
||||||
await login(authFlowUserEmail, internalPassword);
|
|
||||||
|
|
||||||
navigate('/auth/create/workspace');
|
|
||||||
} catch (err: any) {
|
|
||||||
setFormError(err.message);
|
|
||||||
}
|
|
||||||
}, [login, authFlowUserEmail, internalPassword, setMockMode, navigate]);
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
'enter',
|
|
||||||
() => {
|
|
||||||
handleLogin();
|
|
||||||
},
|
|
||||||
InternalHotkeysScope.PasswordLogin,
|
|
||||||
[handleLogin],
|
|
||||||
);
|
|
||||||
|
|
||||||
const { loading, data } = useCheckUserExistsQuery({
|
const { loading, data } = useCheckUserExistsQuery({
|
||||||
variables: {
|
variables: {
|
||||||
email: authFlowUserEmail,
|
email: authFlowUserEmail,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMockMode(true);
|
||||||
|
}, [setMockMode]);
|
||||||
|
|
||||||
|
const workspaceInviteHash = useParams().workspaceInviteHash;
|
||||||
|
|
||||||
|
const handleSubmit = useCallback(async () => {
|
||||||
|
try {
|
||||||
|
setMockMode(false);
|
||||||
|
if (data?.checkUserExists.exists) {
|
||||||
|
await login(authFlowUserEmail, internalPassword);
|
||||||
|
} else {
|
||||||
|
if (workspaceInviteHash) {
|
||||||
|
await signUpToWorkspace(
|
||||||
|
authFlowUserEmail,
|
||||||
|
internalPassword,
|
||||||
|
workspaceInviteHash,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await signUp(authFlowUserEmail, internalPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
navigate('/auth/create/workspace');
|
||||||
|
} catch (err: any) {
|
||||||
|
setFormError(err.message);
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
login,
|
||||||
|
signUp,
|
||||||
|
signUpToWorkspace,
|
||||||
|
authFlowUserEmail,
|
||||||
|
internalPassword,
|
||||||
|
setMockMode,
|
||||||
|
navigate,
|
||||||
|
data?.checkUserExists.exists,
|
||||||
|
|
||||||
|
workspaceInviteHash,
|
||||||
|
]);
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
'enter',
|
||||||
|
() => {
|
||||||
|
handleSubmit();
|
||||||
|
},
|
||||||
|
InternalHotkeysScope.PasswordLogin,
|
||||||
|
[handleSubmit],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Logo />
|
<Logo />
|
||||||
@ -124,7 +150,7 @@ export function PasswordLogin() {
|
|||||||
<StyledButtonContainer>
|
<StyledButtonContainer>
|
||||||
<MainButton
|
<MainButton
|
||||||
title="Continue"
|
title="Continue"
|
||||||
onClick={handleLogin}
|
onClick={handleSubmit}
|
||||||
disabled={!authFlowUserEmail || !internalPassword || loading}
|
disabled={!authFlowUserEmail || !internalPassword || loading}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -4,4 +4,5 @@ export enum AuthPath {
|
|||||||
PasswordLogin = 'password-login',
|
PasswordLogin = 'password-login',
|
||||||
CreateWorkspace = 'create/workspace',
|
CreateWorkspace = 'create/workspace',
|
||||||
CreateProfile = 'create/profile',
|
CreateProfile = 'create/profile',
|
||||||
|
InviteLink = 'invite/:workspaceInviteHash',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ type MockedUser = Pick<
|
|||||||
workspaceMember: Pick<WorkspaceMember, 'id' | '__typename'> & {
|
workspaceMember: Pick<WorkspaceMember, 'id' | '__typename'> & {
|
||||||
workspace: Pick<
|
workspace: Pick<
|
||||||
Workspace,
|
Workspace,
|
||||||
'id' | 'displayName' | 'domainName' | 'logo' | '__typename'
|
'id' | 'displayName' | 'domainName' | 'logo' | 'inviteHash' | '__typename'
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -35,6 +35,7 @@ export const mockedUsersData: Array<MockedUser> = [
|
|||||||
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b',
|
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b',
|
||||||
displayName: 'Twenty',
|
displayName: 'Twenty',
|
||||||
domainName: 'twenty.com',
|
domainName: 'twenty.com',
|
||||||
|
inviteHash: 'twenty.com-invite-hash',
|
||||||
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII=',
|
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII=',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -54,6 +55,7 @@ export const mockedUsersData: Array<MockedUser> = [
|
|||||||
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b',
|
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b',
|
||||||
displayName: 'Twenty',
|
displayName: 'Twenty',
|
||||||
domainName: 'twenty.com',
|
domainName: 'twenty.com',
|
||||||
|
inviteHash: 'twenty.com-invite-hash',
|
||||||
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII=',
|
logo: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACb0lEQVR4nO2VO4taQRTHr3AblbjxEVlwCwVhg7BoqqCIjy/gAyyFWNlYBOxsfH0KuxgQGwXRUkGuL2S7i1barGAgiwbdW93SnGOc4BonPiKahf3DwXFmuP/fPM4ZlvmlTxAhCBdzHnEQWYiv7Mr4C3NeuVYhQYDPzOUUQgDLBQGcLHNhvQK8DACPx8PTxiqVyvISG43GbyaT6Qfpn06n0m63e/tPAPF4vJ1MJu8kEsnWTCkWi1yr1RKGw+GDRqPBOTfr44vFQvD7/Q/lcpmaaVQAr9fLp1IpO22c47hGOBz+MB6PH+Vy+VYDAL8qlUoGtVotzOfzq4MAgsHgE/6KojiQyWR/bKVSqbSszHFM8Pl8z1YK48JsNltCOBwOnrYLO+8AAIjb+nHbycoTiUQfDJ7tFq4YAHiVSmXBxcD41u8flQU8z7fhzO0r83atVns3Go3u9Xr9x0O/RQXo9/tsIBBg6vX606a52Wz+bZ7P5/WwG29gxSJzhKgA6XTaDoFNF+krFAocmC//4yWEcSf2wTm7mCO19xFgSsKOLI16vV7b7XY7mRNoLwA0JymJ5uQIzgIAuX5PzDElT2m+E8BqtQ4ymcx7Yq7T6a6ZE4sKgOadTucaCwkxp1UzlEKh0GDxIXOwDWHAdi6Xe3swQDQa/Q7mywoolUpvsaptymazDWKxmBHTlWXZm405BFZoNpuGgwEmk4mE2SGtVivii4f1AO7J3ZopkQCQj7Ar1FeRChCJRJzVapX6DKNIfSc1Ax+wtQWQ55h6bH8FWDfYV4fO3wlwDr0C/BcADYiTPCxHqIEA2QsCZAkAKnRGkMbKN/sTX5YHPQ1e7SkAAAAASUVORK5CYII=',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -17,6 +17,9 @@ export class WorkspaceCountAggregateInput {
|
|||||||
@Field(() => Boolean, {nullable:true})
|
@Field(() => Boolean, {nullable:true})
|
||||||
logo?: true;
|
logo?: true;
|
||||||
|
|
||||||
|
@Field(() => Boolean, {nullable:true})
|
||||||
|
inviteHash?: true;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: true;
|
deletedAt?: true;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,9 @@ export class WorkspaceCountAggregate {
|
|||||||
@Field(() => Int, {nullable:false})
|
@Field(() => Int, {nullable:false})
|
||||||
logo!: number;
|
logo!: number;
|
||||||
|
|
||||||
|
@Field(() => Int, {nullable:false})
|
||||||
|
inviteHash!: number;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt!: number;
|
deletedAt!: number;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,9 @@ export class WorkspaceCountOrderByAggregateInput {
|
|||||||
@Field(() => SortOrder, {nullable:true})
|
@Field(() => SortOrder, {nullable:true})
|
||||||
logo?: keyof typeof SortOrder;
|
logo?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
@Field(() => SortOrder, {nullable:true})
|
||||||
|
inviteHash?: keyof typeof SortOrder;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: keyof typeof SortOrder;
|
deletedAt?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,11 @@ export class WorkspaceCreateManyInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceCreateWithoutCommentThreadsInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceCreateWithoutCommentsInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceCreateWithoutCompaniesInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceCreateWithoutPeopleInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceCreateWithoutPipelineProgressesInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceCreateWithoutPipelineStagesInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceCreateWithoutPipelinesInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceCreateWithoutWorkspaceMemberInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,11 @@ export class WorkspaceCreateInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,11 @@ export class WorkspaceGroupBy {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,9 @@ export class WorkspaceMaxAggregateInput {
|
|||||||
@Field(() => Boolean, {nullable:true})
|
@Field(() => Boolean, {nullable:true})
|
||||||
logo?: true;
|
logo?: true;
|
||||||
|
|
||||||
|
@Field(() => Boolean, {nullable:true})
|
||||||
|
inviteHash?: true;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: true;
|
deletedAt?: true;
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,11 @@ export class WorkspaceMaxAggregate {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,9 @@ export class WorkspaceMaxOrderByAggregateInput {
|
|||||||
@Field(() => SortOrder, {nullable:true})
|
@Field(() => SortOrder, {nullable:true})
|
||||||
logo?: keyof typeof SortOrder;
|
logo?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
@Field(() => SortOrder, {nullable:true})
|
||||||
|
inviteHash?: keyof typeof SortOrder;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: keyof typeof SortOrder;
|
deletedAt?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,9 @@ export class WorkspaceMinAggregateInput {
|
|||||||
@Field(() => Boolean, {nullable:true})
|
@Field(() => Boolean, {nullable:true})
|
||||||
logo?: true;
|
logo?: true;
|
||||||
|
|
||||||
|
@Field(() => Boolean, {nullable:true})
|
||||||
|
inviteHash?: true;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: true;
|
deletedAt?: true;
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,11 @@ export class WorkspaceMinAggregate {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,9 @@ export class WorkspaceMinOrderByAggregateInput {
|
|||||||
@Field(() => SortOrder, {nullable:true})
|
@Field(() => SortOrder, {nullable:true})
|
||||||
logo?: keyof typeof SortOrder;
|
logo?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
@Field(() => SortOrder, {nullable:true})
|
||||||
|
inviteHash?: keyof typeof SortOrder;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: keyof typeof SortOrder;
|
deletedAt?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,9 @@ export class WorkspaceOrderByWithAggregationInput {
|
|||||||
@Field(() => SortOrder, {nullable:true})
|
@Field(() => SortOrder, {nullable:true})
|
||||||
logo?: keyof typeof SortOrder;
|
logo?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
@Field(() => SortOrder, {nullable:true})
|
||||||
|
inviteHash?: keyof typeof SortOrder;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: keyof typeof SortOrder;
|
deletedAt?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,9 @@ export class WorkspaceOrderByWithRelationInput {
|
|||||||
@Field(() => SortOrder, {nullable:true})
|
@Field(() => SortOrder, {nullable:true})
|
||||||
logo?: keyof typeof SortOrder;
|
logo?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
@Field(() => SortOrder, {nullable:true})
|
||||||
|
inviteHash?: keyof typeof SortOrder;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: keyof typeof SortOrder;
|
deletedAt?: keyof typeof SortOrder;
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ export enum WorkspaceScalarFieldEnum {
|
|||||||
domainName = "domainName",
|
domainName = "domainName",
|
||||||
displayName = "displayName",
|
displayName = "displayName",
|
||||||
logo = "logo",
|
logo = "logo",
|
||||||
|
inviteHash = "inviteHash",
|
||||||
deletedAt = "deletedAt",
|
deletedAt = "deletedAt",
|
||||||
createdAt = "createdAt",
|
createdAt = "createdAt",
|
||||||
updatedAt = "updatedAt"
|
updatedAt = "updatedAt"
|
||||||
|
|||||||
@ -30,6 +30,9 @@ export class WorkspaceScalarWhereWithAggregatesInput {
|
|||||||
@Field(() => StringNullableWithAggregatesFilter, {nullable:true})
|
@Field(() => StringNullableWithAggregatesFilter, {nullable:true})
|
||||||
logo?: StringNullableWithAggregatesFilter;
|
logo?: StringNullableWithAggregatesFilter;
|
||||||
|
|
||||||
|
@Field(() => StringNullableWithAggregatesFilter, {nullable:true})
|
||||||
|
inviteHash?: StringNullableWithAggregatesFilter;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: DateTimeNullableWithAggregatesFilter;
|
deletedAt?: DateTimeNullableWithAggregatesFilter;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceUncheckedCreateWithoutCommentThreadsInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceUncheckedCreateWithoutCommentsInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceUncheckedCreateWithoutCompaniesInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceUncheckedCreateWithoutPeopleInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceUncheckedCreateWithoutPipelineProgressesInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceUncheckedCreateWithoutPipelineStagesInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceUncheckedCreateWithoutPipelinesInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -33,6 +33,11 @@ export class WorkspaceUncheckedCreateWithoutWorkspaceMemberInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -34,6 +34,11 @@ export class WorkspaceUncheckedCreateInput {
|
|||||||
@Validator.IsOptional()
|
@Validator.IsOptional()
|
||||||
logo?: string;
|
logo?: string;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
@Validator.IsString()
|
||||||
|
@Validator.IsOptional()
|
||||||
|
inviteHash?: string;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: Date | string;
|
deletedAt?: Date | string;
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,9 @@ export class WorkspaceUncheckedUpdateManyInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUncheckedUpdateWithoutCommentThreadsInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUncheckedUpdateWithoutCommentsInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUncheckedUpdateWithoutCompaniesInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUncheckedUpdateWithoutPeopleInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUncheckedUpdateWithoutPipelineProgressesInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUncheckedUpdateWithoutPipelineStagesInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUncheckedUpdateWithoutPipelinesInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUncheckedUpdateWithoutWorkspaceMemberInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,9 @@ export class WorkspaceUncheckedUpdateInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,9 @@ export class WorkspaceUpdateManyMutationInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUpdateWithoutCommentThreadsInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUpdateWithoutCommentsInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUpdateWithoutCompaniesInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUpdateWithoutPeopleInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUpdateWithoutPipelineProgressesInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUpdateWithoutPipelineStagesInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUpdateWithoutPipelinesInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,9 @@ export class WorkspaceUpdateWithoutWorkspaceMemberInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,9 @@ export class WorkspaceUpdateInput {
|
|||||||
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
logo?: NullableStringFieldUpdateOperationsInput;
|
logo?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
@Field(() => NullableStringFieldUpdateOperationsInput, {nullable:true})
|
||||||
|
inviteHash?: NullableStringFieldUpdateOperationsInput;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
deletedAt?: NullableDateTimeFieldUpdateOperationsInput;
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,9 @@ export class WorkspaceWhereInput {
|
|||||||
@Field(() => StringNullableFilter, {nullable:true})
|
@Field(() => StringNullableFilter, {nullable:true})
|
||||||
logo?: StringNullableFilter;
|
logo?: StringNullableFilter;
|
||||||
|
|
||||||
|
@Field(() => StringNullableFilter, {nullable:true})
|
||||||
|
inviteHash?: StringNullableFilter;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt?: DateTimeNullableFilter;
|
deletedAt?: DateTimeNullableFilter;
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,9 @@ export class Workspace {
|
|||||||
@Field(() => String, {nullable:true})
|
@Field(() => String, {nullable:true})
|
||||||
logo!: string | null;
|
logo!: string | null;
|
||||||
|
|
||||||
|
@Field(() => String, {nullable:true})
|
||||||
|
inviteHash!: string | null;
|
||||||
|
|
||||||
@HideField()
|
@HideField()
|
||||||
deletedAt!: Date | null;
|
deletedAt!: Date | null;
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { VerifyAuthController } from './controllers/verify-auth.controller';
|
|||||||
import { TokenService } from './services/token.service';
|
import { TokenService } from './services/token.service';
|
||||||
import { AuthResolver } from './auth.resolver';
|
import { AuthResolver } from './auth.resolver';
|
||||||
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/integrations/environment/environment.service';
|
||||||
|
import { WorkspaceModule } from '../workspace/workspace.module';
|
||||||
|
|
||||||
const jwtModule = JwtModule.registerAsync({
|
const jwtModule = JwtModule.registerAsync({
|
||||||
useFactory: async (environmentService: EnvironmentService) => {
|
useFactory: async (environmentService: EnvironmentService) => {
|
||||||
@ -23,7 +24,7 @@ const jwtModule = JwtModule.registerAsync({
|
|||||||
});
|
});
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [jwtModule, UserModule],
|
imports: [jwtModule, UserModule, WorkspaceModule],
|
||||||
controllers: [GoogleAuthController, VerifyAuthController],
|
controllers: [GoogleAuthController, VerifyAuthController],
|
||||||
providers: [
|
providers: [
|
||||||
AuthService,
|
AuthService,
|
||||||
|
|||||||
@ -15,6 +15,9 @@ import {
|
|||||||
import { Prisma } from '@prisma/client';
|
import { Prisma } from '@prisma/client';
|
||||||
import { UserExists } from './dto/user-exists.entity';
|
import { UserExists } from './dto/user-exists.entity';
|
||||||
import { CheckUserExistsInput } from './dto/user-exists.input';
|
import { CheckUserExistsInput } from './dto/user-exists.input';
|
||||||
|
import { WorkspaceInviteHashValid } from './dto/workspace-invite-hash-valid.entity';
|
||||||
|
import { WorkspaceInviteHashValidInput } from './dto/workspace-invite-hash.input';
|
||||||
|
import { SignUpInput } from './dto/sign-up.input';
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class AuthResolver {
|
export class AuthResolver {
|
||||||
@ -33,6 +36,15 @@ export class AuthResolver {
|
|||||||
return { exists };
|
return { exists };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Query(() => WorkspaceInviteHashValid)
|
||||||
|
async checkWorkspaceInviteHashIsValid(
|
||||||
|
@Args() workspaceInviteHashValidInput: WorkspaceInviteHashValidInput,
|
||||||
|
): Promise<WorkspaceInviteHashValid> {
|
||||||
|
return await this.authService.checkWorkspaceInviteHashIsValid(
|
||||||
|
workspaceInviteHashValidInput.inviteHash,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Mutation(() => LoginToken)
|
@Mutation(() => LoginToken)
|
||||||
async challenge(@Args() challengeInput: ChallengeInput): Promise<LoginToken> {
|
async challenge(@Args() challengeInput: ChallengeInput): Promise<LoginToken> {
|
||||||
const user = await this.authService.challenge(challengeInput);
|
const user = await this.authService.challenge(challengeInput);
|
||||||
@ -41,6 +53,14 @@ export class AuthResolver {
|
|||||||
return { loginToken };
|
return { loginToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mutation(() => LoginToken)
|
||||||
|
async signUp(@Args() signUpInput: SignUpInput): Promise<LoginToken> {
|
||||||
|
const user = await this.authService.signUp(signUpInput);
|
||||||
|
const loginToken = await this.tokenService.generateLoginToken(user.email);
|
||||||
|
|
||||||
|
return { loginToken };
|
||||||
|
}
|
||||||
|
|
||||||
@Mutation(() => Verify)
|
@Mutation(() => Verify)
|
||||||
async verify(
|
async verify(
|
||||||
@Args() verifyInput: VerifyInput,
|
@Args() verifyInput: VerifyInput,
|
||||||
|
|||||||
20
server/src/core/auth/dto/sign-up.input.ts
Normal file
20
server/src/core/auth/dto/sign-up.input.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { ArgsType, Field } from '@nestjs/graphql';
|
||||||
|
import { IsEmail, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
@ArgsType()
|
||||||
|
export class SignUpInput {
|
||||||
|
@Field(() => String)
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsEmail()
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
password: string;
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
workspaceInviteHash?: string;
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { Field, ObjectType } from '@nestjs/graphql';
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class WorkspaceInviteHashValid {
|
||||||
|
@Field(() => Boolean)
|
||||||
|
isValid: boolean;
|
||||||
|
}
|
||||||
11
server/src/core/auth/dto/workspace-invite-hash.input.ts
Normal file
11
server/src/core/auth/dto/workspace-invite-hash.input.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { ArgsType, Field } from '@nestjs/graphql';
|
||||||
|
import { IsNotEmpty, IsString, MinLength } from 'class-validator';
|
||||||
|
|
||||||
|
@ArgsType()
|
||||||
|
export class WorkspaceInviteHashValidInput {
|
||||||
|
@Field(() => String)
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@MinLength(10)
|
||||||
|
inviteHash: string;
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing';
|
|||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service';
|
||||||
import { TokenService } from './token.service';
|
import { TokenService } from './token.service';
|
||||||
import { UserService } from 'src/core/user/user.service';
|
import { UserService } from 'src/core/user/user.service';
|
||||||
|
import { WorkspaceService } from 'src/core/workspace/services/workspace.service';
|
||||||
|
|
||||||
describe('AuthService', () => {
|
describe('AuthService', () => {
|
||||||
let service: AuthService;
|
let service: AuthService;
|
||||||
@ -18,6 +19,10 @@ describe('AuthService', () => {
|
|||||||
provide: UserService,
|
provide: UserService,
|
||||||
useValue: {},
|
useValue: {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: WorkspaceService,
|
||||||
|
useValue: {},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,9 @@ import { Verify } from '../dto/verify.entity';
|
|||||||
import { TokenService } from './token.service';
|
import { TokenService } from './token.service';
|
||||||
import { Prisma } from '@prisma/client';
|
import { Prisma } from '@prisma/client';
|
||||||
import { UserExists } from '../dto/user-exists.entity';
|
import { UserExists } from '../dto/user-exists.entity';
|
||||||
|
import { WorkspaceService } from 'src/core/workspace/services/workspace.service';
|
||||||
|
import { WorkspaceInviteHashValid } from '../dto/workspace-invite-hash-valid.entity';
|
||||||
|
import { SignUpInput } from '../dto/sign-up.input';
|
||||||
|
|
||||||
export type UserPayload = {
|
export type UserPayload = {
|
||||||
firstName: string;
|
firstName: string;
|
||||||
@ -24,31 +27,16 @@ export class AuthService {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly tokenService: TokenService,
|
private readonly tokenService: TokenService,
|
||||||
private readonly userService: UserService,
|
private readonly userService: UserService,
|
||||||
|
private readonly workspaceService: WorkspaceService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async challenge(challengeInput: ChallengeInput) {
|
async challenge(challengeInput: ChallengeInput) {
|
||||||
let user = await this.userService.findUnique({
|
const user = await this.userService.findUnique({
|
||||||
where: {
|
where: {
|
||||||
email: challengeInput.email,
|
email: challengeInput.email,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const isPasswordValid = PASSWORD_REGEX.test(challengeInput.password);
|
|
||||||
|
|
||||||
assert(!!user || isPasswordValid, 'Password too weak', BadRequestException);
|
|
||||||
|
|
||||||
if (!user) {
|
|
||||||
const passwordHash = await hashPassword(challengeInput.password);
|
|
||||||
|
|
||||||
user = await this.userService.createUser({
|
|
||||||
data: {
|
|
||||||
email: challengeInput.email,
|
|
||||||
passwordHash,
|
|
||||||
locale: 'en',
|
|
||||||
},
|
|
||||||
} as Prisma.UserCreateArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(user, "This user doesn't exist", NotFoundException);
|
assert(user, "This user doesn't exist", NotFoundException);
|
||||||
assert(user.passwordHash, 'Incorrect login method', ForbiddenException);
|
assert(user.passwordHash, 'Incorrect login method', ForbiddenException);
|
||||||
|
|
||||||
@ -62,6 +50,53 @@ export class AuthService {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async signUp(signUpInput: SignUpInput) {
|
||||||
|
const existingUser = await this.userService.findUnique({
|
||||||
|
where: {
|
||||||
|
email: signUpInput.email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
assert(!existingUser, 'This user already exists', ForbiddenException);
|
||||||
|
|
||||||
|
const isPasswordValid = PASSWORD_REGEX.test(signUpInput.password);
|
||||||
|
assert(isPasswordValid, 'Password too weak', BadRequestException);
|
||||||
|
|
||||||
|
const passwordHash = await hashPassword(signUpInput.password);
|
||||||
|
|
||||||
|
if (signUpInput.workspaceInviteHash) {
|
||||||
|
const workspace = await this.workspaceService.findFirst({
|
||||||
|
where: {
|
||||||
|
inviteHash: signUpInput.workspaceInviteHash,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert(
|
||||||
|
workspace,
|
||||||
|
'This workspace inviteHash is invalid',
|
||||||
|
ForbiddenException,
|
||||||
|
);
|
||||||
|
|
||||||
|
return await this.userService.createUser(
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
email: signUpInput.email,
|
||||||
|
passwordHash,
|
||||||
|
locale: 'en',
|
||||||
|
},
|
||||||
|
} as Prisma.UserCreateArgs,
|
||||||
|
workspace.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.userService.createUser({
|
||||||
|
data: {
|
||||||
|
email: signUpInput.email,
|
||||||
|
passwordHash,
|
||||||
|
locale: 'en',
|
||||||
|
},
|
||||||
|
} as Prisma.UserCreateArgs);
|
||||||
|
}
|
||||||
|
|
||||||
async verify(
|
async verify(
|
||||||
email: string,
|
email: string,
|
||||||
select: Prisma.UserSelect & {
|
select: Prisma.UserSelect & {
|
||||||
@ -101,4 +136,16 @@ export class AuthService {
|
|||||||
|
|
||||||
return { exists: !!user };
|
return { exists: !!user };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkWorkspaceInviteHashIsValid(
|
||||||
|
inviteHash: string,
|
||||||
|
): Promise<WorkspaceInviteHashValid> {
|
||||||
|
const workspace = await this.workspaceService.findFirst({
|
||||||
|
where: {
|
||||||
|
inviteHash,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { isValid: !!workspace };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,7 @@ export class UserService {
|
|||||||
// Customs
|
// Customs
|
||||||
async createUser<T extends Prisma.UserCreateArgs>(
|
async createUser<T extends Prisma.UserCreateArgs>(
|
||||||
args: Prisma.SelectSubset<T, Prisma.UserCreateArgs>,
|
args: Prisma.SelectSubset<T, Prisma.UserCreateArgs>,
|
||||||
|
workspaceId?: string,
|
||||||
): Promise<Prisma.UserGetPayload<T>> {
|
): Promise<Prisma.UserGetPayload<T>> {
|
||||||
assert(args.data.email, 'email is missing', BadRequestException);
|
assert(args.data.email, 'email is missing', BadRequestException);
|
||||||
|
|
||||||
@ -55,14 +56,23 @@ export class UserService {
|
|||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
...(args.data as Prisma.UserCreateInput),
|
...(args.data as Prisma.UserCreateInput),
|
||||||
// Assign the user to a new workspace by default
|
|
||||||
workspaceMember: {
|
workspaceMember: workspaceId
|
||||||
create: {
|
? {
|
||||||
workspace: {
|
create: {
|
||||||
create: {},
|
workspace: {
|
||||||
|
connect: { id: workspaceId },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: // Assign the user to a new workspace by default
|
||||||
|
{
|
||||||
|
create: {
|
||||||
|
workspace: {
|
||||||
|
create: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
},
|
|
||||||
locale: 'en',
|
locale: 'en',
|
||||||
},
|
},
|
||||||
update: {},
|
update: {},
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "workspaces" ADD COLUMN "inviteHash" TEXT;
|
||||||
@ -196,6 +196,9 @@ model Workspace {
|
|||||||
/// @Validator.IsString()
|
/// @Validator.IsString()
|
||||||
/// @Validator.IsOptional()
|
/// @Validator.IsOptional()
|
||||||
logo String?
|
logo String?
|
||||||
|
/// @Validator.IsString()
|
||||||
|
/// @Validator.IsOptional()
|
||||||
|
inviteHash String?
|
||||||
|
|
||||||
workspaceMember WorkspaceMember[]
|
workspaceMember WorkspaceMember[]
|
||||||
companies Company[]
|
companies Company[]
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user