From 3674365e6fa6f1f83dc79138b2739a3624ebb750 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 30 May 2023 20:40:04 +0200 Subject: [PATCH] Scope server with workspace (#157) * Rename User to AuthUser to avoid naming conflict with user business entity * Prevent query by workspace in graphql * Make full user and workspace object available in graphql resolvers * Add Seed to create companies and people accross two workspace * Check workspace on all entities findMany, find, create, update) --- front/src/generated/graphql.tsx | 384 ++---------------- front/src/services/api/companies/select.ts | 2 +- front/src/services/api/people/select.ts | 2 +- front/src/services/api/search/search.ts | 8 +- front/src/services/api/users/index.tsx | 2 +- front/src/services/api/users/test.tsx | 2 +- front/src/testing/mock-data/index.ts | 1 - .../refresh-token/refresh-token.model.ts | 2 +- .../workspace-member-count-aggregate.input.ts | 3 +- ...e-member-count-order-by-aggregate.input.ts | 3 +- .../workspace-member-create-many.input.ts | 3 +- ...kspace-member-create-without-user.input.ts | 5 +- .../workspace-member-create.input.ts | 5 +- .../workspace-member-max-aggregate.input.ts | 3 +- ...ace-member-max-order-by-aggregate.input.ts | 3 +- .../workspace-member-min-aggregate.input.ts | 3 +- ...ace-member-min-order-by-aggregate.input.ts | 3 +- ...-member-order-by-with-aggregation.input.ts | 3 +- ...ace-member-order-by-with-relation.input.ts | 5 +- ...mber-scalar-where-with-aggregates.input.ts | 3 +- .../workspace-member-scalar-where.input.ts | 3 +- ...ber-unchecked-create-without-user.input.ts | 3 +- ...workspace-member-unchecked-create.input.ts | 3 +- ...pace-member-unchecked-update-many.input.ts | 3 +- ...ber-unchecked-update-without-user.input.ts | 3 +- ...workspace-member-unchecked-update.input.ts | 3 +- ...kspace-member-update-without-user.input.ts | 5 +- .../workspace-member-update.input.ts | 5 +- .../workspace-member-where.input.ts | 5 +- .../@generated/workspace/workspace.model.ts | 2 +- server/src/api/api.module.ts | 8 +- server/src/api/resolvers/company.resolver.ts | 68 ++-- ...er.decorator.ts => auth-user.decorator.ts} | 6 +- .../decorators/auth-workspace.decorator.ts | 10 + ...{people.resolver.ts => person.resolver.ts} | 60 +-- ...solver.ts => person-relations.resolver.ts} | 0 .../api/resolvers/services/args.service.ts | 18 + server/src/api/resolvers/user.resolver.ts | 36 +- server/src/auth/google.auth.controller.ts | 9 +- .../guards/check-workspace-ownership.guard.ts | 85 ++++ server/src/auth/guards/jwt.auth.guard.ts | 33 +- server/src/auth/services/auth.service.ts | 12 +- .../auth/strategies/google.auth.strategy.ts | 5 + .../src/auth/strategies/jwt.auth.strategy.ts | 2 +- server/src/database/schema.prisma | 4 + server/src/database/seeds/companies.ts | 12 + server/src/database/seeds/people.ts | 15 + 47 files changed, 380 insertions(+), 483 deletions(-) rename server/src/api/resolvers/decorators/{user.decorator.ts => auth-user.decorator.ts} (76%) create mode 100644 server/src/api/resolvers/decorators/auth-workspace.decorator.ts rename server/src/api/resolvers/{people.resolver.ts => person.resolver.ts} (65%) rename server/src/api/resolvers/relations/{people-relations.resolver.ts => person-relations.resolver.ts} (100%) create mode 100644 server/src/api/resolvers/services/args.service.ts create mode 100644 server/src/auth/guards/check-workspace-ownership.guard.ts diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index 3cc0cbc21..5f23a6196 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -67,30 +67,6 @@ export type CompanyCreateInput = { updatedAt?: InputMaybe; }; -export type CompanyCreateManyWorkspaceInput = { - accountOwnerId?: InputMaybe; - address: Scalars['String']; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - domainName: Scalars['String']; - employees?: InputMaybe; - id: Scalars['String']; - name: Scalars['String']; - updatedAt?: InputMaybe; -}; - -export type CompanyCreateManyWorkspaceInputEnvelope = { - data: Array; - skipDuplicates?: InputMaybe; -}; - -export type CompanyCreateNestedManyWithoutWorkspaceInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; -}; - export type CompanyCreateNestedOneWithoutPeopleInput = { connect?: InputMaybe; connectOrCreate?: InputMaybe; @@ -102,11 +78,6 @@ export type CompanyCreateOrConnectWithoutPeopleInput = { where: CompanyWhereUniqueInput; }; -export type CompanyCreateOrConnectWithoutWorkspaceInput = { - create: CompanyCreateWithoutWorkspaceInput; - where: CompanyWhereUniqueInput; -}; - export type CompanyCreateWithoutPeopleInput = { accountOwner?: InputMaybe; address: Scalars['String']; @@ -119,19 +90,6 @@ export type CompanyCreateWithoutPeopleInput = { updatedAt?: InputMaybe; }; -export type CompanyCreateWithoutWorkspaceInput = { - accountOwner?: InputMaybe; - address: Scalars['String']; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - domainName: Scalars['String']; - employees?: InputMaybe; - id: Scalars['String']; - name: Scalars['String']; - people?: InputMaybe; - updatedAt?: InputMaybe; -}; - export type CompanyListRelationFilter = { every?: InputMaybe; none?: InputMaybe; @@ -174,21 +132,6 @@ export enum CompanyScalarFieldEnum { WorkspaceId = 'workspaceId' } -export type CompanyScalarWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - accountOwnerId?: InputMaybe; - address?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - domainName?: InputMaybe; - employees?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - updatedAt?: InputMaybe; -}; - export type CompanyUpdateInput = { accountOwner?: InputMaybe; address?: InputMaybe; @@ -202,36 +145,6 @@ export type CompanyUpdateInput = { updatedAt?: InputMaybe; }; -export type CompanyUpdateManyMutationInput = { - address?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - domainName?: InputMaybe; - employees?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type CompanyUpdateManyWithWhereWithoutWorkspaceInput = { - data: CompanyUpdateManyMutationInput; - where: CompanyScalarWhereInput; -}; - -export type CompanyUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; - delete?: InputMaybe>; - deleteMany?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; - update?: InputMaybe>; - updateMany?: InputMaybe>; - upsert?: InputMaybe>; -}; - export type CompanyUpdateOneWithoutPeopleNestedInput = { connect?: InputMaybe; connectOrCreate?: InputMaybe; @@ -242,11 +155,6 @@ export type CompanyUpdateOneWithoutPeopleNestedInput = { upsert?: InputMaybe; }; -export type CompanyUpdateWithWhereUniqueWithoutWorkspaceInput = { - data: CompanyUpdateWithoutWorkspaceInput; - where: CompanyWhereUniqueInput; -}; - export type CompanyUpdateWithoutPeopleInput = { accountOwner?: InputMaybe; address?: InputMaybe; @@ -259,25 +167,6 @@ export type CompanyUpdateWithoutPeopleInput = { updatedAt?: InputMaybe; }; -export type CompanyUpdateWithoutWorkspaceInput = { - accountOwner?: InputMaybe; - address?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - domainName?: InputMaybe; - employees?: InputMaybe; - id?: InputMaybe; - name?: InputMaybe; - people?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type CompanyUpsertWithWhereUniqueWithoutWorkspaceInput = { - create: CompanyCreateWithoutWorkspaceInput; - update: CompanyUpdateWithoutWorkspaceInput; - where: CompanyWhereUniqueInput; -}; - export type CompanyUpsertWithoutPeopleInput = { create: CompanyCreateWithoutPeopleInput; update: CompanyUpdateWithoutPeopleInput; @@ -363,7 +252,6 @@ export type Mutation = { createOnePerson: Person; deleteManyCompany: AffectedRows; deleteManyPerson: AffectedRows; - deleteOneCompany?: Maybe; updateOneCompany?: Maybe; updateOnePerson?: Maybe; }; @@ -389,11 +277,6 @@ export type MutationDeleteManyPersonArgs = { }; -export type MutationDeleteOneCompanyArgs = { - where: CompanyWhereUniqueInput; -}; - - export type MutationUpdateOneCompanyArgs = { data: CompanyUpdateInput; where: CompanyWhereUniqueInput; @@ -534,24 +417,6 @@ export type PersonCreateManyCompanyInputEnvelope = { skipDuplicates?: InputMaybe; }; -export type PersonCreateManyWorkspaceInput = { - city: Scalars['String']; - companyId?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - email: Scalars['String']; - firstname: Scalars['String']; - id: Scalars['String']; - lastname: Scalars['String']; - phone: Scalars['String']; - updatedAt?: InputMaybe; -}; - -export type PersonCreateManyWorkspaceInputEnvelope = { - data: Array; - skipDuplicates?: InputMaybe; -}; - export type PersonCreateNestedManyWithoutCompanyInput = { connect?: InputMaybe>; connectOrCreate?: InputMaybe>; @@ -559,23 +424,11 @@ export type PersonCreateNestedManyWithoutCompanyInput = { createMany?: InputMaybe; }; -export type PersonCreateNestedManyWithoutWorkspaceInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; -}; - export type PersonCreateOrConnectWithoutCompanyInput = { create: PersonCreateWithoutCompanyInput; where: PersonWhereUniqueInput; }; -export type PersonCreateOrConnectWithoutWorkspaceInput = { - create: PersonCreateWithoutWorkspaceInput; - where: PersonWhereUniqueInput; -}; - export type PersonCreateWithoutCompanyInput = { city: Scalars['String']; createdAt?: InputMaybe; @@ -588,19 +441,6 @@ export type PersonCreateWithoutCompanyInput = { updatedAt?: InputMaybe; }; -export type PersonCreateWithoutWorkspaceInput = { - city: Scalars['String']; - company?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - email: Scalars['String']; - firstname: Scalars['String']; - id: Scalars['String']; - lastname: Scalars['String']; - phone: Scalars['String']; - updatedAt?: InputMaybe; -}; - export type PersonListRelationFilter = { every?: InputMaybe; none?: InputMaybe; @@ -685,11 +525,6 @@ export type PersonUpdateManyWithWhereWithoutCompanyInput = { where: PersonScalarWhereInput; }; -export type PersonUpdateManyWithWhereWithoutWorkspaceInput = { - data: PersonUpdateManyMutationInput; - where: PersonScalarWhereInput; -}; - export type PersonUpdateManyWithoutCompanyNestedInput = { connect?: InputMaybe>; connectOrCreate?: InputMaybe>; @@ -704,30 +539,11 @@ export type PersonUpdateManyWithoutCompanyNestedInput = { upsert?: InputMaybe>; }; -export type PersonUpdateManyWithoutWorkspaceNestedInput = { - connect?: InputMaybe>; - connectOrCreate?: InputMaybe>; - create?: InputMaybe>; - createMany?: InputMaybe; - delete?: InputMaybe>; - deleteMany?: InputMaybe>; - disconnect?: InputMaybe>; - set?: InputMaybe>; - update?: InputMaybe>; - updateMany?: InputMaybe>; - upsert?: InputMaybe>; -}; - export type PersonUpdateWithWhereUniqueWithoutCompanyInput = { data: PersonUpdateWithoutCompanyInput; where: PersonWhereUniqueInput; }; -export type PersonUpdateWithWhereUniqueWithoutWorkspaceInput = { - data: PersonUpdateWithoutWorkspaceInput; - where: PersonWhereUniqueInput; -}; - export type PersonUpdateWithoutCompanyInput = { city?: InputMaybe; createdAt?: InputMaybe; @@ -740,31 +556,12 @@ export type PersonUpdateWithoutCompanyInput = { updatedAt?: InputMaybe; }; -export type PersonUpdateWithoutWorkspaceInput = { - city?: InputMaybe; - company?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - email?: InputMaybe; - firstname?: InputMaybe; - id?: InputMaybe; - lastname?: InputMaybe; - phone?: InputMaybe; - updatedAt?: InputMaybe; -}; - export type PersonUpsertWithWhereUniqueWithoutCompanyInput = { create: PersonCreateWithoutCompanyInput; update: PersonUpdateWithoutCompanyInput; where: PersonWhereUniqueInput; }; -export type PersonUpsertWithWhereUniqueWithoutWorkspaceInput = { - create: PersonCreateWithoutWorkspaceInput; - update: PersonUpdateWithoutWorkspaceInput; - where: PersonWhereUniqueInput; -}; - export type PersonWhereInput = { AND?: InputMaybe>; NOT?: InputMaybe>; @@ -788,14 +585,13 @@ export type PersonWhereUniqueInput = { export type Query = { __typename?: 'Query'; - companies: Array; - people: Array; - user: User; - users: Array; + findManyCompany: Array; + findManyPerson: Array; + findManyUser: Array; }; -export type QueryCompaniesArgs = { +export type QueryFindManyCompanyArgs = { cursor?: InputMaybe; distinct?: InputMaybe>; orderBy?: InputMaybe>; @@ -805,7 +601,7 @@ export type QueryCompaniesArgs = { }; -export type QueryPeopleArgs = { +export type QueryFindManyPersonArgs = { cursor?: InputMaybe; distinct?: InputMaybe>; orderBy?: InputMaybe>; @@ -815,12 +611,7 @@ export type QueryPeopleArgs = { }; -export type QueryUserArgs = { - where: UserWhereUniqueInput; -}; - - -export type QueryUsersArgs = { +export type QueryFindManyUserArgs = { cursor?: InputMaybe; distinct?: InputMaybe>; orderBy?: InputMaybe>; @@ -1225,29 +1016,6 @@ export type WorkspaceCount = { people: Scalars['Int']; }; -export type WorkspaceCreateNestedOneWithoutWorkspaceMemberInput = { - connect?: InputMaybe; - connectOrCreate?: InputMaybe; - create?: InputMaybe; -}; - -export type WorkspaceCreateOrConnectWithoutWorkspaceMemberInput = { - create: WorkspaceCreateWithoutWorkspaceMemberInput; - where: WorkspaceWhereUniqueInput; -}; - -export type WorkspaceCreateWithoutWorkspaceMemberInput = { - companies?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - displayName: Scalars['String']; - domainName: Scalars['String']; - id: Scalars['String']; - logo?: InputMaybe; - people?: InputMaybe; - updatedAt?: InputMaybe; -}; - export type WorkspaceMember = { __typename?: 'WorkspaceMember'; createdAt: Scalars['DateTime']; @@ -1276,17 +1044,6 @@ export type WorkspaceMemberCreateWithoutUserInput = { deletedAt?: InputMaybe; id: Scalars['String']; updatedAt?: InputMaybe; - workspace: WorkspaceCreateNestedOneWithoutWorkspaceMemberInput; -}; - -export type WorkspaceMemberListRelationFilter = { - every?: InputMaybe; - none?: InputMaybe; - some?: InputMaybe; -}; - -export type WorkspaceMemberOrderByRelationAggregateInput = { - _count?: InputMaybe; }; export type WorkspaceMemberOrderByWithRelationInput = { @@ -1296,8 +1053,6 @@ export type WorkspaceMemberOrderByWithRelationInput = { updatedAt?: InputMaybe; user?: InputMaybe; userId?: InputMaybe; - workspace?: InputMaybe; - workspaceId?: InputMaybe; }; export type WorkspaceMemberRelationFilter = { @@ -1320,7 +1075,6 @@ export type WorkspaceMemberUpdateWithoutUserInput = { deletedAt?: InputMaybe; id?: InputMaybe; updatedAt?: InputMaybe; - workspace?: InputMaybe; }; export type WorkspaceMemberUpsertWithoutUserInput = { @@ -1338,8 +1092,6 @@ export type WorkspaceMemberWhereInput = { updatedAt?: InputMaybe; user?: InputMaybe; userId?: InputMaybe; - workspace?: InputMaybe; - workspaceId?: InputMaybe; }; export type WorkspaceMemberWhereUniqueInput = { @@ -1347,77 +1099,13 @@ export type WorkspaceMemberWhereUniqueInput = { userId?: InputMaybe; }; -export type WorkspaceOrderByWithRelationInput = { - WorkspaceMember?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - displayName?: InputMaybe; - domainName?: InputMaybe; - id?: InputMaybe; - logo?: InputMaybe; - people?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type WorkspaceRelationFilter = { - is?: InputMaybe; - isNot?: InputMaybe; -}; - -export type WorkspaceUpdateOneRequiredWithoutWorkspaceMemberNestedInput = { - connect?: InputMaybe; - connectOrCreate?: InputMaybe; - create?: InputMaybe; - update?: InputMaybe; - upsert?: InputMaybe; -}; - -export type WorkspaceUpdateWithoutWorkspaceMemberInput = { - companies?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - displayName?: InputMaybe; - domainName?: InputMaybe; - id?: InputMaybe; - logo?: InputMaybe; - people?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type WorkspaceUpsertWithoutWorkspaceMemberInput = { - create: WorkspaceCreateWithoutWorkspaceMemberInput; - update: WorkspaceUpdateWithoutWorkspaceMemberInput; -}; - -export type WorkspaceWhereInput = { - AND?: InputMaybe>; - NOT?: InputMaybe>; - OR?: InputMaybe>; - WorkspaceMember?: InputMaybe; - companies?: InputMaybe; - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - displayName?: InputMaybe; - domainName?: InputMaybe; - id?: InputMaybe; - logo?: InputMaybe; - people?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type WorkspaceWhereUniqueInput = { - domainName?: InputMaybe; - id?: InputMaybe; -}; - export type GetCompaniesQueryVariables = Exact<{ orderBy?: InputMaybe | CompanyOrderByWithRelationInput>; where?: InputMaybe; }>; -export type GetCompaniesQuery = { __typename?: 'Query', companies: Array<{ __typename?: 'Company', id: string, domainName: string, name: string, createdAt: any, address: string, employees?: number | null, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string } | null }> }; +export type GetCompaniesQuery = { __typename?: 'Query', findManyCompany: Array<{ __typename?: 'Company', id: string, domainName: string, name: string, createdAt: any, address: string, employees?: number | null, accountOwner?: { __typename?: 'User', id: string, email: string, displayName: string } | null }> }; export type UpdateCompanyMutationVariables = Exact<{ id?: InputMaybe; @@ -1458,7 +1146,7 @@ export type GetPeopleQueryVariables = Exact<{ }>; -export type GetPeopleQuery = { __typename?: 'Query', people: Array<{ __typename?: 'Person', id: string, phone: string, email: string, city: string, firstname: string, lastname: string, createdAt: any, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null }> }; +export type GetPeopleQuery = { __typename?: 'Query', findManyPerson: Array<{ __typename?: 'Person', id: string, phone: string, email: string, city: string, firstname: string, lastname: string, createdAt: any, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null }> }; export type UpdatePeopleMutationVariables = Exact<{ id?: InputMaybe; @@ -1513,39 +1201,39 @@ export type SearchUserQueryQuery = { __typename?: 'Query', searchResults: Array< export type EmptyQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type EmptyQueryQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string }> }; +export type EmptyQueryQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string }> }; -export type SearchQueryQueryVariables = Exact<{ +export type SearchCompanyQueryQueryVariables = Exact<{ where?: InputMaybe; limit?: InputMaybe; }>; -export type SearchQueryQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> }; +export type SearchCompanyQueryQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> }; export type GetCurrentUserQueryVariables = Exact<{ uuid?: InputMaybe; }>; -export type GetCurrentUserQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string, email: string, displayName: string, workspaceMember?: { __typename?: 'WorkspaceMember', workspace: { __typename?: 'Workspace', id: string, domainName: string, displayName: string, logo?: string | null } } | null }> }; +export type GetCurrentUserQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string, email: string, displayName: string, workspaceMember?: { __typename?: 'WorkspaceMember', workspace: { __typename?: 'Workspace', id: string, domainName: string, displayName: string, logo?: string | null } } | null }> }; export type GetUsersQueryVariables = Exact<{ [key: string]: never; }>; -export type GetUsersQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string }> }; +export type GetUsersQuery = { __typename?: 'Query', findManyUser: Array<{ __typename?: 'User', id: string }> }; export const GetCompaniesDocument = gql` query GetCompanies($orderBy: [CompanyOrderByWithRelationInput!], $where: CompanyWhereInput) { - companies(orderBy: $orderBy, where: $where) { + findManyCompany(orderBy: $orderBy, where: $where) { id domainName name createdAt address employees - accountOwner: accountOwner { + accountOwner { id email displayName @@ -1714,7 +1402,7 @@ export type DeleteCompaniesMutationResult = Apollo.MutationResult; export const GetPeopleDocument = gql` query GetPeople($orderBy: [PersonOrderByWithRelationInput!], $where: PersonWhereInput, $limit: Int) { - people(orderBy: $orderBy, where: $where, take: $limit) { + findManyPerson(orderBy: $orderBy, where: $where, take: $limit) { id phone email @@ -1901,7 +1589,7 @@ export type DeletePeopleMutationResult = Apollo.MutationResult; export const SearchPeopleQueryDocument = gql` query SearchPeopleQuery($where: PersonWhereInput, $limit: Int) { - searchResults: people(where: $where, take: $limit) { + searchResults: findManyPerson(where: $where, take: $limit) { id phone email @@ -1943,7 +1631,7 @@ export type SearchPeopleQueryLazyQueryHookResult = ReturnType; export const SearchUserQueryDocument = gql` query SearchUserQuery($where: UserWhereInput, $limit: Int) { - searchResults: users(where: $where, take: $limit) { + searchResults: findManyUser(where: $where, take: $limit) { id email displayName @@ -1981,7 +1669,7 @@ export type SearchUserQueryLazyQueryHookResult = ReturnType; export const EmptyQueryDocument = gql` query EmptyQuery { - users { + findManyUser { id } } @@ -2013,47 +1701,47 @@ export function useEmptyQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions export type EmptyQueryQueryHookResult = ReturnType; export type EmptyQueryLazyQueryHookResult = ReturnType; export type EmptyQueryQueryResult = Apollo.QueryResult; -export const SearchQueryDocument = gql` - query SearchQuery($where: CompanyWhereInput, $limit: Int) { - searchResults: companies(where: $where, take: $limit) { +export const SearchCompanyQueryDocument = gql` + query SearchCompanyQuery($where: CompanyWhereInput, $limit: Int) { + searchResults: findManyCompany(where: $where, take: $limit) { id name - domainName: domainName + domainName } } `; /** - * __useSearchQueryQuery__ + * __useSearchCompanyQueryQuery__ * - * To run a query within a React component, call `useSearchQueryQuery` and pass it any options that fit your needs. - * When your component renders, `useSearchQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties + * To run a query within a React component, call `useSearchCompanyQueryQuery` and pass it any options that fit your needs. + * When your component renders, `useSearchCompanyQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties * you can use to render your UI. * * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; * * @example - * const { data, loading, error } = useSearchQueryQuery({ + * const { data, loading, error } = useSearchCompanyQueryQuery({ * variables: { * where: // value for 'where' * limit: // value for 'limit' * }, * }); */ -export function useSearchQueryQuery(baseOptions?: Apollo.QueryHookOptions) { +export function useSearchCompanyQueryQuery(baseOptions?: Apollo.QueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(SearchQueryDocument, options); + return Apollo.useQuery(SearchCompanyQueryDocument, options); } -export function useSearchQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { +export function useSearchCompanyQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(SearchQueryDocument, options); + return Apollo.useLazyQuery(SearchCompanyQueryDocument, options); } -export type SearchQueryQueryHookResult = ReturnType; -export type SearchQueryLazyQueryHookResult = ReturnType; -export type SearchQueryQueryResult = Apollo.QueryResult; +export type SearchCompanyQueryQueryHookResult = ReturnType; +export type SearchCompanyQueryLazyQueryHookResult = ReturnType; +export type SearchCompanyQueryQueryResult = Apollo.QueryResult; export const GetCurrentUserDocument = gql` query getCurrentUser($uuid: String) { - users(where: {id: {equals: $uuid}}) { + findManyUser(where: {id: {equals: $uuid}}) { id email displayName @@ -2098,7 +1786,7 @@ export type GetCurrentUserLazyQueryHookResult = ReturnType; export const GetUsersDocument = gql` query getUsers { - users { + findManyUser { id } } diff --git a/front/src/services/api/companies/select.ts b/front/src/services/api/companies/select.ts index c0e24ab66..2fb4f464a 100644 --- a/front/src/services/api/companies/select.ts +++ b/front/src/services/api/companies/select.ts @@ -14,7 +14,7 @@ export const GET_COMPANIES = gql` $orderBy: [CompanyOrderByWithRelationInput!] $where: CompanyWhereInput ) { - companies(orderBy: $orderBy, where: $where) { + companies: findManyCompany(orderBy: $orderBy, where: $where) { id domainName name diff --git a/front/src/services/api/people/select.ts b/front/src/services/api/people/select.ts index 2d4ecca8d..76942e3d3 100644 --- a/front/src/services/api/people/select.ts +++ b/front/src/services/api/people/select.ts @@ -15,7 +15,7 @@ export const GET_PEOPLE = gql` $where: PersonWhereInput $limit: Int ) { - people(orderBy: $orderBy, where: $where, take: $limit) { + people: findManyPerson(orderBy: $orderBy, where: $where, take: $limit) { id phone email diff --git a/front/src/services/api/search/search.ts b/front/src/services/api/search/search.ts index 8222cd307..8fff8a8e9 100644 --- a/front/src/services/api/search/search.ts +++ b/front/src/services/api/search/search.ts @@ -9,7 +9,7 @@ import { debounce } from '../../../modules/utils/debounce'; export const SEARCH_PEOPLE_QUERY = gql` query SearchPeopleQuery($where: PersonWhereInput, $limit: Int) { - searchResults: people(where: $where, take: $limit) { + searchResults: findManyPerson(where: $where, take: $limit) { id phone email @@ -23,7 +23,7 @@ export const SEARCH_PEOPLE_QUERY = gql` export const SEARCH_USER_QUERY = gql` query SearchUserQuery($where: UserWhereInput, $limit: Int) { - searchResults: users(where: $where, take: $limit) { + searchResults: findManyUser(where: $where, take: $limit) { id email displayName @@ -33,7 +33,7 @@ export const SEARCH_USER_QUERY = gql` // TODO: remove this query export const EMPTY_QUERY = gql` query EmptyQuery { - users { + searchResults: findManyUser { id } } @@ -41,7 +41,7 @@ export const EMPTY_QUERY = gql` export const SEARCH_COMPANY_QUERY = gql` query SearchCompanyQuery($where: CompanyWhereInput, $limit: Int) { - searchResults: companies(where: $where, take: $limit) { + searchResults: findManyCompany(where: $where, take: $limit) { id name domainName diff --git a/front/src/services/api/users/index.tsx b/front/src/services/api/users/index.tsx index ec72ad0ce..a896ecaaf 100644 --- a/front/src/services/api/users/index.tsx +++ b/front/src/services/api/users/index.tsx @@ -3,7 +3,7 @@ import { GraphqlQueryUser } from '../../../interfaces/entities/user.interface'; export const GET_CURRENT_USER = gql` query getCurrentUser($uuid: String) { - users(where: { id: { equals: $uuid } }) { + users: findManyUser(where: { id: { equals: $uuid } }) { id email displayName diff --git a/front/src/services/api/users/test.tsx b/front/src/services/api/users/test.tsx index 82891f106..426098273 100644 --- a/front/src/services/api/users/test.tsx +++ b/front/src/services/api/users/test.tsx @@ -2,7 +2,7 @@ import { gql } from '@apollo/client'; export const GET_CURRENT_USER = gql` query getUsers { - users { + findManyUser { id } } diff --git a/front/src/testing/mock-data/index.ts b/front/src/testing/mock-data/index.ts index e12bac6e2..92b0be28e 100644 --- a/front/src/testing/mock-data/index.ts +++ b/front/src/testing/mock-data/index.ts @@ -74,7 +74,6 @@ export function filterAndSortData( limit: number, ): Array { let filteredData = filterData(data, where); - console.log(filteredData); if (orderBy) { const firstOrderBy = orderBy[0]; diff --git a/server/src/api/@generated/refresh-token/refresh-token.model.ts b/server/src/api/@generated/refresh-token/refresh-token.model.ts index e342d81ff..776ac9989 100644 --- a/server/src/api/@generated/refresh-token/refresh-token.model.ts +++ b/server/src/api/@generated/refresh-token/refresh-token.model.ts @@ -3,7 +3,7 @@ import { ObjectType } from '@nestjs/graphql'; import { ID } from '@nestjs/graphql'; import { User } from '../user/user.model'; -@ObjectType() +@ObjectType({}) export class RefreshToken { @Field(() => ID, { nullable: false }) id!: string; diff --git a/server/src/api/@generated/workspace-member/workspace-member-count-aggregate.input.ts b/server/src/api/@generated/workspace-member/workspace-member-count-aggregate.input.ts index 842fd4697..cda255b14 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-count-aggregate.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-count-aggregate.input.ts @@ -1,5 +1,6 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberCountAggregateInput { @@ -18,7 +19,7 @@ export class WorkspaceMemberCountAggregateInput { @Field(() => Boolean, { nullable: true }) userId?: true; - @Field(() => Boolean, { nullable: true }) + @HideField() workspaceId?: true; @Field(() => Boolean, { nullable: true }) diff --git a/server/src/api/@generated/workspace-member/workspace-member-count-order-by-aggregate.input.ts b/server/src/api/@generated/workspace-member/workspace-member-count-order-by-aggregate.input.ts index da648cfbb..44ea07e76 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-count-order-by-aggregate.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-count-order-by-aggregate.input.ts @@ -1,6 +1,7 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { SortOrder } from '../prisma/sort-order.enum'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberCountOrderByAggregateInput { @@ -19,6 +20,6 @@ export class WorkspaceMemberCountOrderByAggregateInput { @Field(() => SortOrder, { nullable: true }) userId?: keyof typeof SortOrder; - @Field(() => SortOrder, { nullable: true }) + @HideField() workspaceId?: keyof typeof SortOrder; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-create-many.input.ts b/server/src/api/@generated/workspace-member/workspace-member-create-many.input.ts index 883c47e72..3c7aa2e98 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-create-many.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-create-many.input.ts @@ -1,5 +1,6 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberCreateManyInput { @@ -18,6 +19,6 @@ export class WorkspaceMemberCreateManyInput { @Field(() => String, { nullable: false }) userId!: string; - @Field(() => String, { nullable: false }) + @HideField() workspaceId!: string; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-create-without-user.input.ts b/server/src/api/@generated/workspace-member/workspace-member-create-without-user.input.ts index 8153880ba..9ff23d08b 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-create-without-user.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-create-without-user.input.ts @@ -1,6 +1,7 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { WorkspaceCreateNestedOneWithoutWorkspaceMemberInput } from '../workspace/workspace-create-nested-one-without-workspace-member.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberCreateWithoutUserInput { @@ -16,8 +17,6 @@ export class WorkspaceMemberCreateWithoutUserInput { @Field(() => Date, { nullable: true }) deletedAt?: Date | string; - @Field(() => WorkspaceCreateNestedOneWithoutWorkspaceMemberInput, { - nullable: false, - }) + @HideField() workspace!: WorkspaceCreateNestedOneWithoutWorkspaceMemberInput; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-create.input.ts b/server/src/api/@generated/workspace-member/workspace-member-create.input.ts index 6abea0d7b..5bff173c3 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-create.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-create.input.ts @@ -2,6 +2,7 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { UserCreateNestedOneWithoutWorkspaceMemberInput } from '../user/user-create-nested-one-without-workspace-member.input'; import { WorkspaceCreateNestedOneWithoutWorkspaceMemberInput } from '../workspace/workspace-create-nested-one-without-workspace-member.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberCreateInput { @@ -22,8 +23,6 @@ export class WorkspaceMemberCreateInput { }) user!: UserCreateNestedOneWithoutWorkspaceMemberInput; - @Field(() => WorkspaceCreateNestedOneWithoutWorkspaceMemberInput, { - nullable: false, - }) + @HideField() workspace!: WorkspaceCreateNestedOneWithoutWorkspaceMemberInput; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-max-aggregate.input.ts b/server/src/api/@generated/workspace-member/workspace-member-max-aggregate.input.ts index d4384d000..7b0a74711 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-max-aggregate.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-max-aggregate.input.ts @@ -1,5 +1,6 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberMaxAggregateInput { @@ -18,6 +19,6 @@ export class WorkspaceMemberMaxAggregateInput { @Field(() => Boolean, { nullable: true }) userId?: true; - @Field(() => Boolean, { nullable: true }) + @HideField() workspaceId?: true; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-max-order-by-aggregate.input.ts b/server/src/api/@generated/workspace-member/workspace-member-max-order-by-aggregate.input.ts index 6e66c98a8..2e308d0ff 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-max-order-by-aggregate.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-max-order-by-aggregate.input.ts @@ -1,6 +1,7 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { SortOrder } from '../prisma/sort-order.enum'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberMaxOrderByAggregateInput { @@ -19,6 +20,6 @@ export class WorkspaceMemberMaxOrderByAggregateInput { @Field(() => SortOrder, { nullable: true }) userId?: keyof typeof SortOrder; - @Field(() => SortOrder, { nullable: true }) + @HideField() workspaceId?: keyof typeof SortOrder; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-min-aggregate.input.ts b/server/src/api/@generated/workspace-member/workspace-member-min-aggregate.input.ts index 4be957eff..4d5067881 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-min-aggregate.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-min-aggregate.input.ts @@ -1,5 +1,6 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberMinAggregateInput { @@ -18,6 +19,6 @@ export class WorkspaceMemberMinAggregateInput { @Field(() => Boolean, { nullable: true }) userId?: true; - @Field(() => Boolean, { nullable: true }) + @HideField() workspaceId?: true; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-min-order-by-aggregate.input.ts b/server/src/api/@generated/workspace-member/workspace-member-min-order-by-aggregate.input.ts index e02613c4f..75dfbd043 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-min-order-by-aggregate.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-min-order-by-aggregate.input.ts @@ -1,6 +1,7 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { SortOrder } from '../prisma/sort-order.enum'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberMinOrderByAggregateInput { @@ -19,6 +20,6 @@ export class WorkspaceMemberMinOrderByAggregateInput { @Field(() => SortOrder, { nullable: true }) userId?: keyof typeof SortOrder; - @Field(() => SortOrder, { nullable: true }) + @HideField() workspaceId?: keyof typeof SortOrder; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-order-by-with-aggregation.input.ts b/server/src/api/@generated/workspace-member/workspace-member-order-by-with-aggregation.input.ts index c83d18d6d..4281f1efd 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-order-by-with-aggregation.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-order-by-with-aggregation.input.ts @@ -1,6 +1,7 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { SortOrder } from '../prisma/sort-order.enum'; +import { HideField } from '@nestjs/graphql'; import { WorkspaceMemberCountOrderByAggregateInput } from './workspace-member-count-order-by-aggregate.input'; import { WorkspaceMemberMaxOrderByAggregateInput } from './workspace-member-max-order-by-aggregate.input'; import { WorkspaceMemberMinOrderByAggregateInput } from './workspace-member-min-order-by-aggregate.input'; @@ -22,7 +23,7 @@ export class WorkspaceMemberOrderByWithAggregationInput { @Field(() => SortOrder, { nullable: true }) userId?: keyof typeof SortOrder; - @Field(() => SortOrder, { nullable: true }) + @HideField() workspaceId?: keyof typeof SortOrder; @Field(() => WorkspaceMemberCountOrderByAggregateInput, { nullable: true }) diff --git a/server/src/api/@generated/workspace-member/workspace-member-order-by-with-relation.input.ts b/server/src/api/@generated/workspace-member/workspace-member-order-by-with-relation.input.ts index 1f45dee91..341d573ac 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-order-by-with-relation.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-order-by-with-relation.input.ts @@ -1,6 +1,7 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; import { SortOrder } from '../prisma/sort-order.enum'; +import { HideField } from '@nestjs/graphql'; import { UserOrderByWithRelationInput } from '../user/user-order-by-with-relation.input'; import { WorkspaceOrderByWithRelationInput } from '../workspace/workspace-order-by-with-relation.input'; @@ -21,12 +22,12 @@ export class WorkspaceMemberOrderByWithRelationInput { @Field(() => SortOrder, { nullable: true }) userId?: keyof typeof SortOrder; - @Field(() => SortOrder, { nullable: true }) + @HideField() workspaceId?: keyof typeof SortOrder; @Field(() => UserOrderByWithRelationInput, { nullable: true }) user?: UserOrderByWithRelationInput; - @Field(() => WorkspaceOrderByWithRelationInput, { nullable: true }) + @HideField() workspace?: WorkspaceOrderByWithRelationInput; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-scalar-where-with-aggregates.input.ts b/server/src/api/@generated/workspace-member/workspace-member-scalar-where-with-aggregates.input.ts index 71dcbfd09..b8b398120 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-scalar-where-with-aggregates.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-scalar-where-with-aggregates.input.ts @@ -3,6 +3,7 @@ import { InputType } from '@nestjs/graphql'; import { StringWithAggregatesFilter } from '../prisma/string-with-aggregates-filter.input'; import { DateTimeWithAggregatesFilter } from '../prisma/date-time-with-aggregates-filter.input'; import { DateTimeNullableWithAggregatesFilter } from '../prisma/date-time-nullable-with-aggregates-filter.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberScalarWhereWithAggregatesInput { @@ -36,6 +37,6 @@ export class WorkspaceMemberScalarWhereWithAggregatesInput { @Field(() => StringWithAggregatesFilter, { nullable: true }) userId?: StringWithAggregatesFilter; - @Field(() => StringWithAggregatesFilter, { nullable: true }) + @HideField() workspaceId?: StringWithAggregatesFilter; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-scalar-where.input.ts b/server/src/api/@generated/workspace-member/workspace-member-scalar-where.input.ts index 96bb93dea..7803e3713 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-scalar-where.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-scalar-where.input.ts @@ -3,6 +3,7 @@ import { InputType } from '@nestjs/graphql'; import { StringFilter } from '../prisma/string-filter.input'; import { DateTimeFilter } from '../prisma/date-time-filter.input'; import { DateTimeNullableFilter } from '../prisma/date-time-nullable-filter.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberScalarWhereInput { @@ -30,6 +31,6 @@ export class WorkspaceMemberScalarWhereInput { @Field(() => StringFilter, { nullable: true }) userId?: StringFilter; - @Field(() => StringFilter, { nullable: true }) + @HideField() workspaceId?: StringFilter; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-unchecked-create-without-user.input.ts b/server/src/api/@generated/workspace-member/workspace-member-unchecked-create-without-user.input.ts index 74b76533b..7cd761b73 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-unchecked-create-without-user.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-unchecked-create-without-user.input.ts @@ -1,5 +1,6 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberUncheckedCreateWithoutUserInput { @@ -15,6 +16,6 @@ export class WorkspaceMemberUncheckedCreateWithoutUserInput { @Field(() => Date, { nullable: true }) deletedAt?: Date | string; - @Field(() => String, { nullable: false }) + @HideField() workspaceId!: string; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-unchecked-create.input.ts b/server/src/api/@generated/workspace-member/workspace-member-unchecked-create.input.ts index 38e126a1e..2eac82334 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-unchecked-create.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-unchecked-create.input.ts @@ -1,5 +1,6 @@ import { Field } from '@nestjs/graphql'; import { InputType } from '@nestjs/graphql'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberUncheckedCreateInput { @@ -18,6 +19,6 @@ export class WorkspaceMemberUncheckedCreateInput { @Field(() => String, { nullable: false }) userId!: string; - @Field(() => String, { nullable: false }) + @HideField() workspaceId!: string; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-unchecked-update-many.input.ts b/server/src/api/@generated/workspace-member/workspace-member-unchecked-update-many.input.ts index 69d3ad722..ec76968a0 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-unchecked-update-many.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-unchecked-update-many.input.ts @@ -3,6 +3,7 @@ import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; import { DateTimeFieldUpdateOperationsInput } from '../prisma/date-time-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberUncheckedUpdateManyInput { @@ -21,6 +22,6 @@ export class WorkspaceMemberUncheckedUpdateManyInput { @Field(() => StringFieldUpdateOperationsInput, { nullable: true }) userId?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, { nullable: true }) + @HideField() workspaceId?: StringFieldUpdateOperationsInput; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-unchecked-update-without-user.input.ts b/server/src/api/@generated/workspace-member/workspace-member-unchecked-update-without-user.input.ts index acc39f54d..47df86412 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-unchecked-update-without-user.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-unchecked-update-without-user.input.ts @@ -3,6 +3,7 @@ import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; import { DateTimeFieldUpdateOperationsInput } from '../prisma/date-time-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberUncheckedUpdateWithoutUserInput { @@ -18,6 +19,6 @@ export class WorkspaceMemberUncheckedUpdateWithoutUserInput { @Field(() => NullableDateTimeFieldUpdateOperationsInput, { nullable: true }) deletedAt?: NullableDateTimeFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, { nullable: true }) + @HideField() workspaceId?: StringFieldUpdateOperationsInput; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-unchecked-update.input.ts b/server/src/api/@generated/workspace-member/workspace-member-unchecked-update.input.ts index 7eefc2945..d923de7ce 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-unchecked-update.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-unchecked-update.input.ts @@ -3,6 +3,7 @@ import { InputType } from '@nestjs/graphql'; import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update-operations.input'; import { DateTimeFieldUpdateOperationsInput } from '../prisma/date-time-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberUncheckedUpdateInput { @@ -21,6 +22,6 @@ export class WorkspaceMemberUncheckedUpdateInput { @Field(() => StringFieldUpdateOperationsInput, { nullable: true }) userId?: StringFieldUpdateOperationsInput; - @Field(() => StringFieldUpdateOperationsInput, { nullable: true }) + @HideField() workspaceId?: StringFieldUpdateOperationsInput; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-update-without-user.input.ts b/server/src/api/@generated/workspace-member/workspace-member-update-without-user.input.ts index 40f51e018..d70263f2a 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-update-without-user.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-update-without-user.input.ts @@ -4,6 +4,7 @@ import { StringFieldUpdateOperationsInput } from '../prisma/string-field-update- import { DateTimeFieldUpdateOperationsInput } from '../prisma/date-time-field-update-operations.input'; import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { WorkspaceUpdateOneRequiredWithoutWorkspaceMemberNestedInput } from '../workspace/workspace-update-one-required-without-workspace-member-nested.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberUpdateWithoutUserInput { @@ -19,8 +20,6 @@ export class WorkspaceMemberUpdateWithoutUserInput { @Field(() => NullableDateTimeFieldUpdateOperationsInput, { nullable: true }) deletedAt?: NullableDateTimeFieldUpdateOperationsInput; - @Field(() => WorkspaceUpdateOneRequiredWithoutWorkspaceMemberNestedInput, { - nullable: true, - }) + @HideField() workspace?: WorkspaceUpdateOneRequiredWithoutWorkspaceMemberNestedInput; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-update.input.ts b/server/src/api/@generated/workspace-member/workspace-member-update.input.ts index e6ec2b48d..dd9f05c92 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-update.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-update.input.ts @@ -5,6 +5,7 @@ import { DateTimeFieldUpdateOperationsInput } from '../prisma/date-time-field-up import { NullableDateTimeFieldUpdateOperationsInput } from '../prisma/nullable-date-time-field-update-operations.input'; import { UserUpdateOneRequiredWithoutWorkspaceMemberNestedInput } from '../user/user-update-one-required-without-workspace-member-nested.input'; import { WorkspaceUpdateOneRequiredWithoutWorkspaceMemberNestedInput } from '../workspace/workspace-update-one-required-without-workspace-member-nested.input'; +import { HideField } from '@nestjs/graphql'; @InputType() export class WorkspaceMemberUpdateInput { @@ -25,8 +26,6 @@ export class WorkspaceMemberUpdateInput { }) user?: UserUpdateOneRequiredWithoutWorkspaceMemberNestedInput; - @Field(() => WorkspaceUpdateOneRequiredWithoutWorkspaceMemberNestedInput, { - nullable: true, - }) + @HideField() workspace?: WorkspaceUpdateOneRequiredWithoutWorkspaceMemberNestedInput; } diff --git a/server/src/api/@generated/workspace-member/workspace-member-where.input.ts b/server/src/api/@generated/workspace-member/workspace-member-where.input.ts index 9a83387a8..84721be42 100644 --- a/server/src/api/@generated/workspace-member/workspace-member-where.input.ts +++ b/server/src/api/@generated/workspace-member/workspace-member-where.input.ts @@ -3,6 +3,7 @@ import { InputType } from '@nestjs/graphql'; import { StringFilter } from '../prisma/string-filter.input'; import { DateTimeFilter } from '../prisma/date-time-filter.input'; import { DateTimeNullableFilter } from '../prisma/date-time-nullable-filter.input'; +import { HideField } from '@nestjs/graphql'; import { UserRelationFilter } from '../user/user-relation-filter.input'; import { WorkspaceRelationFilter } from '../workspace/workspace-relation-filter.input'; @@ -32,12 +33,12 @@ export class WorkspaceMemberWhereInput { @Field(() => StringFilter, { nullable: true }) userId?: StringFilter; - @Field(() => StringFilter, { nullable: true }) + @HideField() workspaceId?: StringFilter; @Field(() => UserRelationFilter, { nullable: true }) user?: UserRelationFilter; - @Field(() => WorkspaceRelationFilter, { nullable: true }) + @HideField() workspace?: WorkspaceRelationFilter; } diff --git a/server/src/api/@generated/workspace/workspace.model.ts b/server/src/api/@generated/workspace/workspace.model.ts index b6e14990d..45332bb7d 100644 --- a/server/src/api/@generated/workspace/workspace.model.ts +++ b/server/src/api/@generated/workspace/workspace.model.ts @@ -6,7 +6,7 @@ import { Company } from '../company/company.model'; import { Person } from '../person/person.model'; import { WorkspaceCount } from './workspace-count.output'; -@ObjectType() +@ObjectType({}) export class Workspace { @Field(() => ID, { nullable: false }) id!: string; diff --git a/server/src/api/api.module.ts b/server/src/api/api.module.ts index 92a8c99ed..069a657cd 100644 --- a/server/src/api/api.module.ts +++ b/server/src/api/api.module.ts @@ -3,15 +3,16 @@ import { GraphQLModule } from '@nestjs/graphql'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { CompanyResolver } from './resolvers/company.resolver'; import { UserResolver } from './resolvers/user.resolver'; -import { PeopleResolver } from './resolvers/people.resolver'; +import { PersonResolver } from './resolvers/person.resolver'; -import { PersonRelationsResolver } from './resolvers/relations/people-relations.resolver'; +import { PersonRelationsResolver } from './resolvers/relations/person-relations.resolver'; import { UserRelationsResolver } from './resolvers/relations/user-relations.resolver'; import { WorkspaceMemberRelationsResolver } from './resolvers/relations/workspace-member-relations.resolver'; import { ConfigService } from '@nestjs/config'; import { AuthModule } from 'src/auth/auth.module'; import { CompanyRelationsResolver } from './resolvers/relations/company-relations.resolver'; import { PrismaModule } from 'src/database/prisma.module'; +import { ArgsService } from './resolvers/services/args.service'; @Module({ imports: [ @@ -25,9 +26,10 @@ import { PrismaModule } from 'src/database/prisma.module'; ], providers: [ ConfigService, + ArgsService, CompanyResolver, - PeopleResolver, + PersonResolver, UserResolver, CompanyRelationsResolver, diff --git a/server/src/api/resolvers/company.resolver.ts b/server/src/api/resolvers/company.resolver.ts index d7623b00d..f6b53b3ab 100644 --- a/server/src/api/resolvers/company.resolver.ts +++ b/server/src/api/resolvers/company.resolver.ts @@ -1,37 +1,39 @@ import { Resolver, Query, Args, Mutation } from '@nestjs/graphql'; import { JwtAuthGuard } from 'src/auth/guards/jwt.auth.guard'; import { UseGuards } from '@nestjs/common'; -import { User, UserType } from './decorators/user.decorator'; +import { AuthWorkspace } from './decorators/auth-workspace.decorator'; import { PrismaService } from 'src/database/prisma.service'; import { Company } from '../@generated/company/company.model'; import { FindManyCompanyArgs } from '../@generated/company/find-many-company.args'; -import { DeleteOneCompanyArgs } from '../@generated/company/delete-one-company.args'; import { UpdateOneCompanyArgs } from '../@generated/company/update-one-company.args'; import { CreateOneCompanyArgs } from '../@generated/company/create-one-company.args'; import { AffectedRows } from '../@generated/prisma/affected-rows.output'; import { DeleteManyCompanyArgs } from '../@generated/company/delete-many-company.args'; +import { Workspace } from '@prisma/client'; +import { ArgsService } from './services/args.service'; +import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard'; +@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership) @Resolver(() => Company) export class CompanyResolver { - constructor(private readonly prismaService: PrismaService) {} + constructor( + private readonly prismaService: PrismaService, + private readonly argsService: ArgsService, + ) {} - @UseGuards(JwtAuthGuard) @Query(() => [Company]) - async companies(@Args() args: FindManyCompanyArgs) { - return this.prismaService.company.findMany(args); + async findManyCompany( + @Args() args: FindManyCompanyArgs, + @AuthWorkspace() workspace: Workspace, + ) { + const preparedArgs = + await this.argsService.prepareFindManyArgs( + args, + workspace, + ); + return this.prismaService.company.findMany(preparedArgs); } - @UseGuards(JwtAuthGuard) - @Mutation(() => Company, { - nullable: true, - }) - async deleteOneCompany( - @Args() args: DeleteOneCompanyArgs, - ): Promise { - return this.prismaService.company.delete(args); - } - - @UseGuards(JwtAuthGuard) @Mutation(() => Company, { nullable: true, }) @@ -46,23 +48,6 @@ export class CompanyResolver { }); } - @UseGuards(JwtAuthGuard) - @Mutation(() => Company, { - nullable: false, - }) - async createOneCompany( - @Args() args: CreateOneCompanyArgs, - @User() user: UserType, - ): Promise { - return this.prismaService.company.create({ - data: { - ...args.data, - ...{ workspace: { connect: { id: user.workspaceId } } }, - }, - }); - } - - @UseGuards(JwtAuthGuard) @Mutation(() => AffectedRows, { nullable: false, }) @@ -73,4 +58,19 @@ export class CompanyResolver { ...args, }); } + + @Mutation(() => Company, { + nullable: false, + }) + async createOneCompany( + @Args() args: CreateOneCompanyArgs, + @AuthWorkspace() workspace: Workspace, + ): Promise { + return this.prismaService.company.create({ + data: { + ...args.data, + ...{ workspace: { connect: { id: workspace.id } } }, + }, + }); + } } diff --git a/server/src/api/resolvers/decorators/user.decorator.ts b/server/src/api/resolvers/decorators/auth-user.decorator.ts similarity index 76% rename from server/src/api/resolvers/decorators/user.decorator.ts rename to server/src/api/resolvers/decorators/auth-user.decorator.ts index a075ffcab..636c98c6d 100644 --- a/server/src/api/resolvers/decorators/user.decorator.ts +++ b/server/src/api/resolvers/decorators/auth-user.decorator.ts @@ -1,14 +1,10 @@ import { ExecutionContext, createParamDecorator } from '@nestjs/common'; import { GqlExecutionContext } from '@nestjs/graphql'; -export const User = createParamDecorator( +export const AuthUser = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const gqlContext = GqlExecutionContext.create(ctx); const request = gqlContext.getContext().req; return request.user; }, ); - -export type UserType = { - workspaceId: string; -}; diff --git a/server/src/api/resolvers/decorators/auth-workspace.decorator.ts b/server/src/api/resolvers/decorators/auth-workspace.decorator.ts new file mode 100644 index 000000000..43a65695b --- /dev/null +++ b/server/src/api/resolvers/decorators/auth-workspace.decorator.ts @@ -0,0 +1,10 @@ +import { ExecutionContext, createParamDecorator } from '@nestjs/common'; +import { GqlExecutionContext } from '@nestjs/graphql'; + +export const AuthWorkspace = createParamDecorator( + (data: unknown, ctx: ExecutionContext) => { + const gqlContext = GqlExecutionContext.create(ctx); + const request = gqlContext.getContext().req; + return request.workspace; + }, +); diff --git a/server/src/api/resolvers/people.resolver.ts b/server/src/api/resolvers/person.resolver.ts similarity index 65% rename from server/src/api/resolvers/people.resolver.ts rename to server/src/api/resolvers/person.resolver.ts index 121507fdf..90682f522 100644 --- a/server/src/api/resolvers/people.resolver.ts +++ b/server/src/api/resolvers/person.resolver.ts @@ -1,7 +1,6 @@ import { Resolver, Query, Args, Mutation } from '@nestjs/graphql'; import { UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from 'src/auth/guards/jwt.auth.guard'; -import { User, UserType } from './decorators/user.decorator'; import { PrismaService } from 'src/database/prisma.service'; import { Person } from '../@generated/person/person.model'; import { FindManyPersonArgs } from '../@generated/person/find-many-person.args'; @@ -9,22 +8,36 @@ import { UpdateOnePersonArgs } from '../@generated/person/update-one-person.args import { CreateOnePersonArgs } from '../@generated/person/create-one-person.args'; import { AffectedRows } from '../@generated/prisma/affected-rows.output'; import { DeleteManyPersonArgs } from '../@generated/person/delete-many-person.args'; +import { Workspace } from '../@generated/workspace/workspace.model'; +import { AuthWorkspace } from './decorators/auth-workspace.decorator'; +import { ArgsService } from './services/args.service'; +import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard'; +@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership) @Resolver(() => Person) -export class PeopleResolver { - constructor(private readonly prismaService: PrismaService) {} +export class PersonResolver { + constructor( + private readonly prismaService: PrismaService, + private readonly argsService: ArgsService, + ) {} - @UseGuards(JwtAuthGuard) @Query(() => [Person], { nullable: false, }) - async people(@Args() args: FindManyPersonArgs): Promise { + async findManyPerson( + @Args() args: FindManyPersonArgs, + @AuthWorkspace() workspace: Workspace, + ): Promise { + const preparedArgs = + await this.argsService.prepareFindManyArgs( + args, + workspace, + ); return this.prismaService.person.findMany({ - ...args, + ...preparedArgs, }); } - @UseGuards(JwtAuthGuard) @Mutation(() => Person, { nullable: true, }) @@ -34,28 +47,12 @@ export class PeopleResolver { if (!args.data.company?.connect?.id) { args.data.company = { disconnect: true }; } + return this.prismaService.person.update({ ...args, }); } - @UseGuards(JwtAuthGuard) - @Mutation(() => Person, { - nullable: false, - }) - async createOnePerson( - @Args() args: CreateOnePersonArgs, - @User() user: UserType, - ): Promise { - return this.prismaService.person.create({ - data: { - ...args.data, - ...{ workspace: { connect: { id: user.workspaceId } } }, - }, - }); - } - - @UseGuards(JwtAuthGuard) @Mutation(() => AffectedRows, { nullable: false, }) @@ -66,4 +63,19 @@ export class PeopleResolver { ...args, }); } + + @Mutation(() => Person, { + nullable: false, + }) + async createOnePerson( + @Args() args: CreateOnePersonArgs, + @AuthWorkspace() workspace: Workspace, + ): Promise { + return this.prismaService.person.create({ + data: { + ...args.data, + ...{ workspace: { connect: { id: workspace.id } } }, + }, + }); + } } diff --git a/server/src/api/resolvers/relations/people-relations.resolver.ts b/server/src/api/resolvers/relations/person-relations.resolver.ts similarity index 100% rename from server/src/api/resolvers/relations/people-relations.resolver.ts rename to server/src/api/resolvers/relations/person-relations.resolver.ts diff --git a/server/src/api/resolvers/services/args.service.ts b/server/src/api/resolvers/services/args.service.ts new file mode 100644 index 000000000..11a3b5b36 --- /dev/null +++ b/server/src/api/resolvers/services/args.service.ts @@ -0,0 +1,18 @@ +import { Injectable } from '@nestjs/common'; +import { Workspace } from '@prisma/client'; + +type FindManyArgsType = { where?: object; orderBy?: object }; + +@Injectable() +export class ArgsService { + async prepareFindManyArgs( + args: T, + workspace: Workspace, + ): Promise { + args.where = { + ...args.where, + ...{ workspace: { is: { id: { equals: workspace.id } } } }, + }; + return args; + } +} diff --git a/server/src/api/resolvers/user.resolver.ts b/server/src/api/resolvers/user.resolver.ts index 8afbd9146..3eb954001 100644 --- a/server/src/api/resolvers/user.resolver.ts +++ b/server/src/api/resolvers/user.resolver.ts @@ -2,31 +2,39 @@ import { Resolver, Query, Args } from '@nestjs/graphql'; import { PrismaService } from 'src/database/prisma.service'; import { UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from 'src/auth/guards/jwt.auth.guard'; + import { User } from '../@generated/user/user.model'; import { FindManyUserArgs } from '../@generated/user/find-many-user.args'; -import { FindUniqueUserOrThrowArgs } from '../@generated/user/find-unique-user-or-throw.args'; +import { Workspace } from '@prisma/client'; +import { AuthWorkspace } from './decorators/auth-workspace.decorator'; +import { ArgsService } from './services/args.service'; +import { CheckWorkspaceOwnership } from 'src/auth/guards/check-workspace-ownership.guard'; +@UseGuards(JwtAuthGuard, CheckWorkspaceOwnership) @Resolver(() => User) export class UserResolver { - constructor(private readonly prismaService: PrismaService) {} + constructor( + private readonly prismaService: PrismaService, + private readonly argsService: ArgsService, + ) {} - @UseGuards(JwtAuthGuard) @Query(() => [User], { nullable: false, }) - async users(@Args() args: FindManyUserArgs): Promise { + async findManyUser( + @Args() args: FindManyUserArgs, + @AuthWorkspace() workspace: Workspace, + ): Promise { + args.where = { + ...args.where, + ...{ + WorkspaceMember: { + is: { workspace: { is: { id: { equals: workspace.id } } } }, + }, + }, + }; return await this.prismaService.user.findMany({ ...args, }); } - - @UseGuards(JwtAuthGuard) - @Query(() => User, { - nullable: false, - }) - async user(@Args() args: FindUniqueUserOrThrowArgs): Promise { - return await this.prismaService.user.findUnique({ - ...args, - }); - } } diff --git a/server/src/auth/google.auth.controller.ts b/server/src/auth/google.auth.controller.ts index 49aba87cf..a813bd9f4 100644 --- a/server/src/auth/google.auth.controller.ts +++ b/server/src/auth/google.auth.controller.ts @@ -8,8 +8,9 @@ import { UseGuards, } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; -import { Request, Response } from 'express'; +import { Response } from 'express'; import { AuthService } from './services/auth.service'; +import { GoogleRequest } from './strategies/google.auth.strategy'; @Controller('auth/google') export class GoogleAuthController { @@ -24,10 +25,8 @@ export class GoogleAuthController { @Get('redirect') @UseGuards(AuthGuard('google')) - async googleAuthRedirect(@Req() req: Request, @Res() res: Response) { - const user = await this.authService.upsertUser( - req.user as { firstName: string; lastName: string; email: string }, - ); + async googleAuthRedirect(@Req() req: GoogleRequest, @Res() res: Response) { + const user = await this.authService.upsertUser(req.user); if (!user) { throw new HttpException( diff --git a/server/src/auth/guards/check-workspace-ownership.guard.ts b/server/src/auth/guards/check-workspace-ownership.guard.ts new file mode 100644 index 000000000..a762bbd02 --- /dev/null +++ b/server/src/auth/guards/check-workspace-ownership.guard.ts @@ -0,0 +1,85 @@ +import { + CanActivate, + ExecutionContext, + HttpException, + HttpStatus, + Injectable, +} from '@nestjs/common'; +import { GqlExecutionContext } from '@nestjs/graphql'; +import { Request } from 'express'; +import { PrismaService } from 'src/database/prisma.service'; + +type OperationEntity = { + operation?: string; + entity?: string; +}; + +@Injectable() +export class CheckWorkspaceOwnership implements CanActivate { + constructor(private prismaService: PrismaService) {} + + async canActivate(context: ExecutionContext): Promise { + const gqlContext = GqlExecutionContext.create(context); + const request = gqlContext.getContext().req; + + const { operation, entity } = this.fetchOperationAndEntity(request); + const variables = request.body.variables; + const workspace = await request.workspace; + + if (!entity || !operation) { + return false; + } + + if (operation === 'updateOne') { + const object = await this.prismaService[entity].findUniqueOrThrow({ + where: { id: variables.id }, + }); + + if (!object) { + throw new HttpException( + { reason: 'Record not found' }, + HttpStatus.NOT_FOUND, + ); + } + if (object.workspaceId !== workspace.id) { + throw new HttpException( + { reason: 'Record not found' }, + HttpStatus.NOT_FOUND, + ); + } + return true; + } + + if (operation === 'deleteMany') { + // TODO: write this logic + return true; + } + + if (operation === 'findMany') { + return true; + } + + if (operation === 'createOne') { + return true; + } + + return false; + } + + private fetchOperationAndEntity(request: Request): OperationEntity { + if (!request.body.operationName) { + return { operation: undefined, entity: undefined }; + } + + const regex = + /(updateOne|deleteMany|createOne|findMany)(Person|Company|User)/i; + const match = request.body.query.match(regex); + if (match) { + return { + operation: match[1], + entity: match[2].toLowerCase(), + }; + } + return { operation: undefined, entity: undefined }; + } +} diff --git a/server/src/auth/guards/jwt.auth.guard.ts b/server/src/auth/guards/jwt.auth.guard.ts index 333a854fd..d3012b6c0 100644 --- a/server/src/auth/guards/jwt.auth.guard.ts +++ b/server/src/auth/guards/jwt.auth.guard.ts @@ -1,6 +1,8 @@ import { CanActivate, ExecutionContext, + HttpException, + HttpStatus, Injectable, UnauthorizedException, } from '@nestjs/common'; @@ -8,12 +10,15 @@ import { JwtService } from '@nestjs/jwt'; import { GqlExecutionContext } from '@nestjs/graphql'; import { Request } from 'express'; import { ConfigService } from '@nestjs/config'; +import { PrismaService } from 'src/database/prisma.service'; +import { JwtPayload } from '../strategies/jwt.auth.strategy'; @Injectable() export class JwtAuthGuard implements CanActivate { constructor( private jwtService: JwtService, private configService: ConfigService, + private prismaService: PrismaService, ) {} async canActivate(context: ExecutionContext): Promise { @@ -24,10 +29,34 @@ export class JwtAuthGuard implements CanActivate { throw new UnauthorizedException(); } try { - const payload = await this.jwtService.verifyAsync(token, { + const payload: JwtPayload = await this.jwtService.verifyAsync(token, { secret: this.configService.get('JWT_SECRET'), }); - request['user'] = payload; + + const user = this.prismaService.user.findUniqueOrThrow({ + where: { id: payload.userId }, + }); + + if (!user) { + throw new HttpException( + { reason: 'User does not exist' }, + HttpStatus.FORBIDDEN, + ); + } + + const workspace = this.prismaService.workspace.findUniqueOrThrow({ + where: { id: payload.workspaceId }, + }); + + if (!workspace) { + throw new HttpException( + { reason: 'Workspace does not exist' }, + HttpStatus.FORBIDDEN, + ); + } + + request.user = user; + request.workspace = workspace; } catch (exception) { throw new UnauthorizedException(); } diff --git a/server/src/auth/services/auth.service.ts b/server/src/auth/services/auth.service.ts index e013161fe..d0374fab9 100644 --- a/server/src/auth/services/auth.service.ts +++ b/server/src/auth/services/auth.service.ts @@ -8,6 +8,12 @@ import { RefreshTokenRepository } from 'src/entities/refresh-token/refresh-token import { v4 } from 'uuid'; import { RefreshToken, User } from '@prisma/client'; +export type UserPayload = { + firstName: string; + lastName: string; + email: string; +}; + @Injectable() export class AuthService { constructor( @@ -18,11 +24,7 @@ export class AuthService { private refreshTokenRepository: RefreshTokenRepository, ) {} - async upsertUser(rawUser: { - firstName: string; - lastName: string; - email: string; - }) { + async upsertUser(rawUser: UserPayload) { if (!rawUser.email) { throw new HttpException( { reason: 'Email is missing' }, diff --git a/server/src/auth/strategies/google.auth.strategy.ts b/server/src/auth/strategies/google.auth.strategy.ts index 4142045bc..318bd1264 100644 --- a/server/src/auth/strategies/google.auth.strategy.ts +++ b/server/src/auth/strategies/google.auth.strategy.ts @@ -3,6 +3,11 @@ import { Strategy, VerifyCallback } from 'passport-google-oauth20'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { Request } from 'express'; + +export type GoogleRequest = Request & { + user: { firstName: string; lastName: string; email: string }; +}; @Injectable() export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { diff --git a/server/src/auth/strategies/jwt.auth.strategy.ts b/server/src/auth/strategies/jwt.auth.strategy.ts index 9a77fda27..7465345dc 100644 --- a/server/src/auth/strategies/jwt.auth.strategy.ts +++ b/server/src/auth/strategies/jwt.auth.strategy.ts @@ -24,7 +24,7 @@ export class JwtAuthStrategy extends PassportStrategy(Strategy, 'jwt') { }); } - async validate(payload: JwtPayload) { + async validate(payload: JwtPayload): Promise { return { userId: payload.userId, workspaceId: payload.workspaceId }; } } diff --git a/server/src/database/schema.prisma b/server/src/database/schema.prisma index 9f711faed..10af19c21 100644 --- a/server/src/database/schema.prisma +++ b/server/src/database/schema.prisma @@ -35,6 +35,7 @@ model User { @@map("users") } +/// @TypeGraphQL.omit(input: true) model Workspace { id String @id createdAt DateTime @default(now()) @@ -57,7 +58,9 @@ model WorkspaceMember { deletedAt DateTime? userId String @unique user User @relation(fields: [userId], references: [id]) + /// @TypeGraphQL.omit(input: true) workspaceId String + /// @TypeGraphQL.omit(input: true) workspace Workspace @relation(fields: [workspaceId], references: [id]) @@map("workspace_members") @@ -105,6 +108,7 @@ model Person { @@map("people") } +/// @TypeGraphQL.omit(input: true) model RefreshToken { id String @id createdAt DateTime @default(now()) diff --git a/server/src/database/seeds/companies.ts b/server/src/database/seeds/companies.ts index 4aaf839a2..37c53ebd9 100644 --- a/server/src/database/seeds/companies.ts +++ b/server/src/database/seeds/companies.ts @@ -147,4 +147,16 @@ export const seedCompanies = async (prisma: PrismaClient) => { address: '', }, }); + + await prisma.company.upsert({ + where: { id: 'a674fa6c-1455-4c57-afaf-dd5dc086361e' }, + update: {}, + create: { + id: 'a674fa6c-1455-4c57-afaf-dd5dc086361e', + name: 'Instagram', + domainName: 'instagram.com', + workspaceId: '7ed9d212-1c25-4d02-bf25-6aeccf7ea420', + address: '', + }, + }); }; diff --git a/server/src/database/seeds/people.ts b/server/src/database/seeds/people.ts index fbbeef6be..4caa253f0 100644 --- a/server/src/database/seeds/people.ts +++ b/server/src/database/seeds/people.ts @@ -209,4 +209,19 @@ export const seedPeople = async (prisma: PrismaClient) => { email: 'louis.duss@google.com', }, }); + + await prisma.person.upsert({ + where: { id: '240da2ec-2d40-4e49-8df4-9c6a049190dh' }, + update: {}, + create: { + id: '240da2ec-2d40-4e49-8df4-9c6a049190dh', + firstname: 'Lorie', + lastname: 'Vladim', + workspaceId: '7ed9d212-1c25-4d02-bf25-6aeccf7ea420', + phone: '+33788901235', + city: 'Seattle', + companyId: 'a674fa6c-1455-4c57-afaf-dd5dc086361e', + email: 'lorie.vladim@google.com', + }, + }); };