From 823a774598fc5cd3870d61ba2850c5f58bcf1251 Mon Sep 17 00:00:00 2001 From: cbolles Date: Wed, 14 Feb 2024 11:17:13 -0500 Subject: [PATCH 1/4] Add in multi-tenant support --- packages/client/src/context/Auth.context.tsx | 25 ++++++++++++++++--- packages/client/src/graphql/entry/entry.ts | 2 +- packages/client/src/graphql/graphql.ts | 19 +++++++++++++- .../graphql/organization/organization.graphql | 3 ++- .../src/graphql/organization/organization.ts | 3 ++- packages/client/src/graphql/tag/tag.ts | 2 +- .../src/organization/organization.model.ts | 4 +-- 7 files changed, 48 insertions(+), 10 deletions(-) diff --git a/packages/client/src/context/Auth.context.tsx b/packages/client/src/context/Auth.context.tsx index f7001a5d..8a6f912c 100644 --- a/packages/client/src/context/Auth.context.tsx +++ b/packages/client/src/context/Auth.context.tsx @@ -3,6 +3,8 @@ import jwt_decode from 'jwt-decode'; import * as firebaseui from 'firebaseui'; import * as firebase from '@firebase/app'; import * as firebaseauth from '@firebase/auth'; +import {Organization} from '../graphql/graphql'; +import {useGetOrganizationsQuery} from '../graphql/organization/organization'; const firebaseConfig = { apiKey: import.meta.env.VITE_AUTH_API_KEY, @@ -48,6 +50,16 @@ export const AuthProvider: FC = ({ children }) => { const [token, setToken] = useState(localStorage.getItem(AUTH_TOKEN_STR)); const [authenticated, setAuthenticated] = useState(true); const [decodedToken, setDecodedToken] = useState(null); + const [organization, setOrganization] = useState(null); + + const getOrganizationResult = useGetOrganizationsQuery(); + + useEffect(() => { + // TODO: Handle multi-organization login + if (getOrganizationResult.data && getOrganizationResult.data.getOrganizations.length > 0) { + setOrganization(getOrganizationResult.data.getOrganizations[0]); + } + }, [getOrganizationResult.data]); const handleUnauthenticated = () => { // Clear the token and authenticated state @@ -95,7 +107,7 @@ export const AuthProvider: FC = ({ children }) => { return ( - {!authenticated && } + {!authenticated && organization && } {authenticated && children} ); @@ -103,11 +115,18 @@ export const AuthProvider: FC = ({ children }) => { interface FirebaseLoginWrapperProps { setToken: (token: string) => void; + organization: Organization; } -const FirebaseLoginWrapper: FC = ({ setToken }) => { +const FirebaseLoginWrapper: FC = ({ setToken, organization }) => { firebase.initializeApp(firebaseConfig); - const ui = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(firebaseauth.getAuth()); + + // Handle multi-tenant login + const auth = firebaseauth.getAuth(); + auth.tenantId = organization.tenantID; + + + const ui = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(auth); const signInSuccess = async (authResult: any) => { setToken(await authResult.user.getIdToken()); diff --git a/packages/client/src/graphql/entry/entry.ts b/packages/client/src/graphql/entry/entry.ts index 9a64578d..fdd15e24 100644 --- a/packages/client/src/graphql/entry/entry.ts +++ b/packages/client/src/graphql/entry/entry.ts @@ -10,7 +10,7 @@ export type EntryForDatasetQueryVariables = Types.Exact<{ }>; -export type EntryForDatasetQuery = { __typename?: 'Query', entryForDataset: Array<{ __typename?: 'Entry', _id: string, organization: string, entryID: string, contentType: string, dataset: string, creator: string, dateCreated: any, meta: any, signedUrl: string, signedUrlExpiration: number }> }; +export type EntryForDatasetQuery = { __typename?: 'Query', entryForDataset: Array<{ __typename?: 'Entry', _id: string, organization: string, entryID: string, contentType: string, dataset: string, creator: string, dateCreated: any, meta?: any | null, signedUrl: string, signedUrlExpiration: number }> }; export type DeleteEntryMutationVariables = Types.Exact<{ entry: Types.Scalars['ID']['input']; diff --git a/packages/client/src/graphql/graphql.ts b/packages/client/src/graphql/graphql.ts index b699c81b..f868a8e8 100644 --- a/packages/client/src/graphql/graphql.ts +++ b/packages/client/src/graphql/graphql.ts @@ -79,7 +79,7 @@ export type Entry = { dataset: Scalars['ID']['output']; dateCreated: Scalars['DateTime']['output']; entryID: Scalars['String']['output']; - meta: Scalars['JSON']['output']; + meta?: Maybe; organization: Scalars['ID']['output']; signedUrl: Scalars['String']['output']; /** Get the number of milliseconds the signed URL is valid for. */ @@ -177,6 +177,7 @@ export type LexiconEntry = { export type Mutation = { __typename?: 'Mutation'; acceptInvite: InviteModel; + addUserToOrg: Scalars['Boolean']['output']; assignTag?: Maybe; cancelInvite: InviteModel; changeDatasetDescription: Scalars['Boolean']['output']; @@ -228,6 +229,11 @@ export type MutationAcceptInviteArgs = { }; +export type MutationAddUserToOrgArgs = { + organization: Scalars['ID']['input']; +}; + + export type MutationAssignTagArgs = { study: Scalars['ID']['input']; }; @@ -468,6 +474,8 @@ export type Organization = { /** URL where the user logs in against */ authURL: Scalars['String']['output']; name: Scalars['String']['output']; + /** Tenant ID in the Identity Platform */ + tenantID: Scalars['String']['output']; }; export type OrganizationCreate = { @@ -475,6 +483,8 @@ export type OrganizationCreate = { authURL: Scalars['String']['input']; name: Scalars['String']['input']; projectId: Scalars['String']['input']; + /** Tenant ID in the Identity Platform */ + tenantID: Scalars['String']['input']; }; export type Permission = { @@ -589,6 +599,7 @@ export type Query = { projectUsers: Array; publicKey: Array; studyExists: Scalars['Boolean']['output']; + userIsInOrg: Scalars['Boolean']['output']; users: Array; validateCSV: UploadResult; }; @@ -706,6 +717,12 @@ export type QueryStudyExistsArgs = { }; +export type QueryUserIsInOrgArgs = { + org: Scalars['String']['input']; + user: Scalars['String']['input']; +}; + + export type QueryValidateCsvArgs = { session: Scalars['ID']['input']; }; diff --git a/packages/client/src/graphql/organization/organization.graphql b/packages/client/src/graphql/organization/organization.graphql index fb998152..3cc9ed51 100644 --- a/packages/client/src/graphql/organization/organization.graphql +++ b/packages/client/src/graphql/organization/organization.graphql @@ -2,6 +2,7 @@ query getOrganizations { getOrganizations { _id, name, - authURL + authURL, + tenantID } } diff --git a/packages/client/src/graphql/organization/organization.ts b/packages/client/src/graphql/organization/organization.ts index d24a8b68..68072d47 100644 --- a/packages/client/src/graphql/organization/organization.ts +++ b/packages/client/src/graphql/organization/organization.ts @@ -8,7 +8,7 @@ const defaultOptions = {} as const; export type GetOrganizationsQueryVariables = Types.Exact<{ [key: string]: never; }>; -export type GetOrganizationsQuery = { __typename?: 'Query', getOrganizations: Array<{ __typename?: 'Organization', _id: string, name: string, authURL: string }> }; +export type GetOrganizationsQuery = { __typename?: 'Query', getOrganizations: Array<{ __typename?: 'Organization', _id: string, name: string, authURL: string, tenantID: string }> }; export const GetOrganizationsDocument = gql` @@ -17,6 +17,7 @@ export const GetOrganizationsDocument = gql` _id name authURL + tenantID } } `; diff --git a/packages/client/src/graphql/tag/tag.ts b/packages/client/src/graphql/tag/tag.ts index 52a61f7f..58b7f376 100644 --- a/packages/client/src/graphql/tag/tag.ts +++ b/packages/client/src/graphql/tag/tag.ts @@ -35,7 +35,7 @@ export type AssignTagMutationVariables = Types.Exact<{ }>; -export type AssignTagMutation = { __typename?: 'Mutation', assignTag?: { __typename?: 'Tag', _id: string, entry: { __typename?: 'Entry', _id: string, organization: string, entryID: string, contentType: string, dataset: string, creator: string, dateCreated: any, meta: any, signedUrl: string, signedUrlExpiration: number } } | null }; +export type AssignTagMutation = { __typename?: 'Mutation', assignTag?: { __typename?: 'Tag', _id: string, entry: { __typename?: 'Entry', _id: string, organization: string, entryID: string, contentType: string, dataset: string, creator: string, dateCreated: any, meta?: any | null, signedUrl: string, signedUrlExpiration: number } } | null }; export type CompleteTagMutationVariables = Types.Exact<{ tag: Types.Scalars['ID']['input']; diff --git a/packages/server/src/organization/organization.model.ts b/packages/server/src/organization/organization.model.ts index 00463492..95b00caa 100644 --- a/packages/server/src/organization/organization.model.ts +++ b/packages/server/src/organization/organization.model.ts @@ -12,9 +12,9 @@ export class Organization { @Field() name: string; - /** Maps the `projectId` in the auth service back to the organization */ @Prop() - projectId: string; + @Field({ description: 'Tenant ID in the Identity Platform' }) + tenantID: string; @Prop() @Field({ description: 'URL where the user logs in against' }) From 6183c11cba9b56c0466f5c848a515edbd80df759 Mon Sep 17 00:00:00 2001 From: cbolles Date: Wed, 14 Feb 2024 11:27:48 -0500 Subject: [PATCH 2/4] Ability to get organization context from JWT token --- packages/client/src/context/Auth.context.tsx | 10 ++++--- packages/server/src/app.module.ts | 4 +-- packages/server/src/dataset/dataset.module.ts | 4 +-- packages/server/src/entry/entry.module.ts | 4 +-- packages/server/src/jwt/jwt.module.ts | 2 -- packages/server/src/jwt/token.dto.ts | 1 + .../src/organization/organization.guard.ts | 29 ++----------------- .../src/organization/organization.module.ts | 3 +- .../src/organization/organization.service.ts | 4 +-- .../src/permission/permission.module.ts | 4 +-- .../permission/resolvers/owner.resolver.ts | 3 +- .../resolvers/permission.resolver.ts | 2 ++ packages/server/src/project/project.module.ts | 4 +-- packages/server/src/userorg/userorg.model.ts | 13 --------- packages/server/src/userorg/userorg.module.ts | 12 -------- .../server/src/userorg/userorg.resolver.ts | 26 ----------------- .../server/src/userorg/userorg.service.ts | 29 ------------------- 17 files changed, 22 insertions(+), 132 deletions(-) delete mode 100644 packages/server/src/userorg/userorg.model.ts delete mode 100644 packages/server/src/userorg/userorg.module.ts delete mode 100644 packages/server/src/userorg/userorg.resolver.ts delete mode 100644 packages/server/src/userorg/userorg.service.ts diff --git a/packages/client/src/context/Auth.context.tsx b/packages/client/src/context/Auth.context.tsx index 8a6f912c..1c0a4ebf 100644 --- a/packages/client/src/context/Auth.context.tsx +++ b/packages/client/src/context/Auth.context.tsx @@ -3,8 +3,8 @@ import jwt_decode from 'jwt-decode'; import * as firebaseui from 'firebaseui'; import * as firebase from '@firebase/app'; import * as firebaseauth from '@firebase/auth'; -import {Organization} from '../graphql/graphql'; -import {useGetOrganizationsQuery} from '../graphql/organization/organization'; +import { Organization } from '../graphql/graphql'; +import { useGetOrganizationsQuery } from '../graphql/organization/organization'; const firebaseConfig = { apiKey: import.meta.env.VITE_AUTH_API_KEY, @@ -26,6 +26,7 @@ export interface DecodedToken { }; sign_in_provider: string; user_id: string; + tenant: string; }; iat: number; iss: string; @@ -107,7 +108,9 @@ export const AuthProvider: FC = ({ children }) => { return ( - {!authenticated && organization && } + {!authenticated && organization && ( + + )} {authenticated && children} ); @@ -125,7 +128,6 @@ const FirebaseLoginWrapper: FC = ({ setToken, organiz const auth = firebaseauth.getAuth(); auth.tenantId = organization.tenantID; - const ui = firebaseui.auth.AuthUI.getInstance() || new firebaseui.auth.AuthUI(auth); const signInSuccess = async (authResult: any) => { diff --git a/packages/server/src/app.module.ts b/packages/server/src/app.module.ts index 789113db..5fd0016b 100644 --- a/packages/server/src/app.module.ts +++ b/packages/server/src/app.module.ts @@ -14,7 +14,6 @@ import { SharedModule } from './shared/shared.module'; import { JwtModule } from './jwt/jwt.module'; import { PermissionModule } from './permission/permission.module'; import { AuthModule } from './auth/auth.module'; -import { UserOrgModule } from './userorg/userorg.module'; @Module({ imports: [ @@ -45,8 +44,7 @@ import { UserOrgModule } from './userorg/userorg.module'; SharedModule, JwtModule, PermissionModule, - AuthModule, - UserOrgModule + AuthModule ] }) export class AppModule {} diff --git a/packages/server/src/dataset/dataset.module.ts b/packages/server/src/dataset/dataset.module.ts index f616a624..17cc95fa 100644 --- a/packages/server/src/dataset/dataset.module.ts +++ b/packages/server/src/dataset/dataset.module.ts @@ -8,7 +8,6 @@ import { PermissionModule } from '../permission/permission.module'; import { JwtModule } from '../jwt/jwt.module'; import { ProjectModule } from '../project/project.module'; import { OrganizationModule } from '../organization/organization.module'; -import { UserOrgModule } from '../userorg/userorg.module'; @Module({ imports: [ @@ -16,8 +15,7 @@ import { UserOrgModule } from '../userorg/userorg.module'; forwardRef(() => PermissionModule), JwtModule, ProjectModule, - OrganizationModule, - UserOrgModule + OrganizationModule ], providers: [DatasetResolver, DatasetService, DatasetPipe], exports: [DatasetService, DatasetPipe] diff --git a/packages/server/src/entry/entry.module.ts b/packages/server/src/entry/entry.module.ts index 04a04546..01f291cd 100644 --- a/packages/server/src/entry/entry.module.ts +++ b/packages/server/src/entry/entry.module.ts @@ -18,7 +18,6 @@ import { JwtModule } from '../jwt/jwt.module'; import { MongooseMiddlewareService } from '../shared/service/mongoose-callback.service'; import { SharedModule } from '../shared/shared.module'; import { OrganizationModule } from '../organization/organization.module'; -import { UserOrgModule } from '../userorg/userorg.module'; @Module({ imports: [ @@ -45,8 +44,7 @@ import { UserOrgModule } from '../userorg/userorg.module'; GcpModule, PermissionModule, JwtModule, - OrganizationModule, - UserOrgModule + OrganizationModule ], providers: [ EntryResolver, diff --git a/packages/server/src/jwt/jwt.module.ts b/packages/server/src/jwt/jwt.module.ts index a045b434..4ac5d1d4 100644 --- a/packages/server/src/jwt/jwt.module.ts +++ b/packages/server/src/jwt/jwt.module.ts @@ -4,14 +4,12 @@ import { HttpModule } from '@nestjs/axios'; import { JwtAuthGuard } from './jwt.guard'; import { JwtStrategy } from './jwt.strategy'; import { OrganizationModule } from '../organization/organization.module'; -import { UserOrgModule } from '../userorg/userorg.module'; import { JwtSecretRequestType, JwtModule as NestJwtModule } from '@nestjs/jwt'; @Module({ imports: [ HttpModule, forwardRef(() => OrganizationModule), - UserOrgModule, NestJwtModule.registerAsync({ imports: [forwardRef(() => JwtModule)], inject: [JwtService], diff --git a/packages/server/src/jwt/token.dto.ts b/packages/server/src/jwt/token.dto.ts index 30141cb6..d4b7002f 100644 --- a/packages/server/src/jwt/token.dto.ts +++ b/packages/server/src/jwt/token.dto.ts @@ -11,6 +11,7 @@ export interface TokenPayload { }; sign_in_provider: string; user_id: string; + tenant: string; }; iat: number; iss: string; diff --git a/packages/server/src/organization/organization.guard.ts b/packages/server/src/organization/organization.guard.ts index 84e554f7..78e2ea9c 100644 --- a/packages/server/src/organization/organization.guard.ts +++ b/packages/server/src/organization/organization.guard.ts @@ -1,43 +1,20 @@ import { Injectable, ExecutionContext, CanActivate } from '@nestjs/common'; import { GqlExecutionContext } from '@nestjs/graphql'; import { OrganizationService } from './organization.service'; -import { UserOrgService } from '../userorg/userorg.service'; @Injectable() export class OrganizationGuard implements CanActivate { - constructor( - private readonly organizationService: OrganizationService, - private readonly userOrgService: UserOrgService - ) {} + constructor(private readonly organizationService: OrganizationService) {} async canActivate(context: ExecutionContext): Promise { const ctx = GqlExecutionContext.create(context); + const user = ctx.getContext().req.user; - // Check for the organization in the headers - const organizationID = ctx.getContext().req.headers.organization; - if (organizationID == undefined || organizationID == 'undefined') { - return false; - } - if (typeof organizationID !== 'string') { - return false; - } - - // Check if the organization exists - const organization = await this.organizationService.findOne(organizationID); + const organization = await this.organizationService.findByTenantID(user.firebase.tenant); if (!organization) { return false; } - // Check to see if the user is in the organization - const user = ctx.getContext().req.user; - if (!user) { - return false; - } - const userOrg = await this.userOrgService.userIsInOrg(user.user_id, organizationID); - if (!userOrg) { - return false; - } - // Add the organization to the request ctx.getContext().req.organization = organization; diff --git a/packages/server/src/organization/organization.module.ts b/packages/server/src/organization/organization.module.ts index ebcb9e70..be0c4528 100644 --- a/packages/server/src/organization/organization.module.ts +++ b/packages/server/src/organization/organization.module.ts @@ -4,10 +4,9 @@ import { OrganizationService } from './organization.service'; import { MongooseModule } from '@nestjs/mongoose'; import { Organization, OrganizationSchema } from './organization.model'; import { CreateOrganizationPipe } from './pipes/create.pipe'; -import { UserOrgModule } from '../userorg/userorg.module'; @Module({ - imports: [MongooseModule.forFeature([{ name: Organization.name, schema: OrganizationSchema }]), UserOrgModule], + imports: [MongooseModule.forFeature([{ name: Organization.name, schema: OrganizationSchema }])], providers: [OrganizationResolver, OrganizationService, CreateOrganizationPipe], exports: [OrganizationService] }) diff --git a/packages/server/src/organization/organization.service.ts b/packages/server/src/organization/organization.service.ts index 8140a174..6f9ed41c 100644 --- a/packages/server/src/organization/organization.service.ts +++ b/packages/server/src/organization/organization.service.ts @@ -24,7 +24,7 @@ export class OrganizationService { return this.orgModel.findOne({ name }); } - async findByProject(projectId: string): Promise { - return this.orgModel.findOne({ projectId }); + async findByTenantID(tenantID: string): Promise { + return this.orgModel.findOne({ tenantID }); } } diff --git a/packages/server/src/permission/permission.module.ts b/packages/server/src/permission/permission.module.ts index 023db01b..6ffb235a 100644 --- a/packages/server/src/permission/permission.module.ts +++ b/packages/server/src/permission/permission.module.ts @@ -11,7 +11,6 @@ import { DatasetPermissionResolver } from './resolvers/dataset.resolver'; import { DatasetModule } from '../dataset/dataset.module'; import { PermissionResolver } from './resolvers/permission.resolver'; import { OrganizationModule } from '../organization/organization.module'; -import { UserOrgModule } from '../userorg/userorg.module'; @Module({ imports: [ @@ -19,8 +18,7 @@ import { UserOrgModule } from '../userorg/userorg.module'; AuthModule, forwardRef(() => StudyModule), forwardRef(() => DatasetModule), - OrganizationModule, - UserOrgModule + OrganizationModule ], providers: [ casbinProvider, diff --git a/packages/server/src/permission/resolvers/owner.resolver.ts b/packages/server/src/permission/resolvers/owner.resolver.ts index ce05d930..a3d19c56 100644 --- a/packages/server/src/permission/resolvers/owner.resolver.ts +++ b/packages/server/src/permission/resolvers/owner.resolver.ts @@ -9,8 +9,9 @@ import { Inject, UnauthorizedException, UseGuards } from '@nestjs/common'; import { Roles } from '../permissions/roles'; import { PermissionService } from '../permission.service'; import { JwtAuthGuard } from '../../jwt/jwt.guard'; +import { OrganizationGuard } from '../../organization/organization.guard'; -@UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard, OrganizationGuard) @Resolver() export class OwnerPermissionResolver { constructor( diff --git a/packages/server/src/permission/resolvers/permission.resolver.ts b/packages/server/src/permission/resolvers/permission.resolver.ts index 9c5cc10e..04dcc33e 100644 --- a/packages/server/src/permission/resolvers/permission.resolver.ts +++ b/packages/server/src/permission/resolvers/permission.resolver.ts @@ -32,6 +32,8 @@ export class PermissionResolver { let project: Project | null = null; let study: Study | null = null; + console.log(organization); + if (projectID) { project = await this.projectPipe.transform(projectID); } diff --git a/packages/server/src/project/project.module.ts b/packages/server/src/project/project.module.ts index 11c223bc..8bca0a19 100644 --- a/packages/server/src/project/project.module.ts +++ b/packages/server/src/project/project.module.ts @@ -9,7 +9,6 @@ import { SharedModule } from 'src/shared/shared.module'; import { JwtModule } from '../jwt/jwt.module'; import { PermissionModule } from '../permission/permission.module'; import { OrganizationModule } from '../organization/organization.module'; -import { UserOrgModule } from '../userorg/userorg.module'; @Module({ imports: [ @@ -32,8 +31,7 @@ import { UserOrgModule } from '../userorg/userorg.module'; ]), JwtModule, forwardRef(() => PermissionModule), - OrganizationModule, - UserOrgModule + OrganizationModule ], providers: [ProjectResolver, ProjectService, ProjectPipe], exports: [ProjectPipe, ProjectService] diff --git a/packages/server/src/userorg/userorg.model.ts b/packages/server/src/userorg/userorg.model.ts deleted file mode 100644 index 8d3bb8d7..00000000 --- a/packages/server/src/userorg/userorg.model.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose'; - -@Schema() -export class UserOrg { - @Prop() - user: string; - - @Prop() - org: string; -} - -export type UserOrgDocument = UserOrg & Document; -export const UserOrgSchema = SchemaFactory.createForClass(UserOrg); diff --git a/packages/server/src/userorg/userorg.module.ts b/packages/server/src/userorg/userorg.module.ts deleted file mode 100644 index 13337afb..00000000 --- a/packages/server/src/userorg/userorg.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from '@nestjs/common'; -import { UserOrgService } from './userorg.service'; -import { UserOrg, UserOrgSchema } from './userorg.model'; -import { MongooseModule } from '@nestjs/mongoose'; -import { UserOrgResolver } from './userorg.resolver'; - -@Module({ - imports: [MongooseModule.forFeature([{ name: UserOrg.name, schema: UserOrgSchema }])], - providers: [UserOrgService, UserOrgResolver], - exports: [UserOrgService] -}) -export class UserOrgModule {} diff --git a/packages/server/src/userorg/userorg.resolver.ts b/packages/server/src/userorg/userorg.resolver.ts deleted file mode 100644 index dac0acf6..00000000 --- a/packages/server/src/userorg/userorg.resolver.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ID, Resolver, Query, Mutation, Args } from '@nestjs/graphql'; -import { UserOrgService } from './userorg.service'; -import { TokenContext } from '../jwt/token.context'; -import { TokenPayload } from '../jwt/token.dto'; -import { JwtAuthGuard } from '../jwt/jwt.guard'; -import { UseGuards } from '@nestjs/common'; - -@Resolver() -export class UserOrgResolver { - constructor(private readonly userOrgService: UserOrgService) {} - - @Query(() => Boolean) - async userIsInOrg(@Args('user') user: string, @Args('org') org: string): Promise { - return this.userOrgService.userIsInOrg(user, org); - } - - @UseGuards(JwtAuthGuard) - @Mutation(() => Boolean) - async addUserToOrg( - @Args('organization', { type: () => ID }) organization: string, - @TokenContext() user: TokenPayload - ): Promise { - await this.userOrgService.create(user.user_id, organization); - return true; - } -} diff --git a/packages/server/src/userorg/userorg.service.ts b/packages/server/src/userorg/userorg.service.ts deleted file mode 100644 index 6c17de42..00000000 --- a/packages/server/src/userorg/userorg.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { InjectModel } from '@nestjs/mongoose'; -import { Model } from 'mongoose'; -import { UserOrg, UserOrgDocument } from './userorg.model'; - -@Injectable() -export class UserOrgService { - constructor(@InjectModel(UserOrg.name) private userOrgModel: Model) {} - - async create(user: string, org: string): Promise { - const existing = await this.find(user, org); - if (existing) { - return existing; - } - return this.userOrgModel.create({ user, org }); - } - - async findUserForOrg(org: string): Promise { - return this.userOrgModel.find({ org }); - } - - async userIsInOrg(user: string, org: string): Promise { - return !!(await this.find(user, org)); - } - - async find(user: string, org: string): Promise { - return this.userOrgModel.findOne({ user, org }); - } -} From 230d1cf3556b351965991e075125860eb03df991 Mon Sep 17 00:00:00 2001 From: cbolles Date: Wed, 14 Feb 2024 11:29:11 -0500 Subject: [PATCH 3/4] Remove extra print debug --- packages/server/src/permission/resolvers/permission.resolver.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/server/src/permission/resolvers/permission.resolver.ts b/packages/server/src/permission/resolvers/permission.resolver.ts index 04dcc33e..9c5cc10e 100644 --- a/packages/server/src/permission/resolvers/permission.resolver.ts +++ b/packages/server/src/permission/resolvers/permission.resolver.ts @@ -32,8 +32,6 @@ export class PermissionResolver { let project: Project | null = null; let study: Study | null = null; - console.log(organization); - if (projectID) { project = await this.projectPipe.transform(projectID); } From b817b8b3c6d6348d5f6e607cbf5cc80bb40823e7 Mon Sep 17 00:00:00 2001 From: cbolles Date: Wed, 14 Feb 2024 11:31:57 -0500 Subject: [PATCH 4/4] Remove stale operation --- packages/client/src/graphql/graphql.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/client/src/graphql/graphql.ts b/packages/client/src/graphql/graphql.ts index f868a8e8..82136cb3 100644 --- a/packages/client/src/graphql/graphql.ts +++ b/packages/client/src/graphql/graphql.ts @@ -177,7 +177,6 @@ export type LexiconEntry = { export type Mutation = { __typename?: 'Mutation'; acceptInvite: InviteModel; - addUserToOrg: Scalars['Boolean']['output']; assignTag?: Maybe; cancelInvite: InviteModel; changeDatasetDescription: Scalars['Boolean']['output']; @@ -229,11 +228,6 @@ export type MutationAcceptInviteArgs = { }; -export type MutationAddUserToOrgArgs = { - organization: Scalars['ID']['input']; -}; - - export type MutationAssignTagArgs = { study: Scalars['ID']['input']; }; @@ -599,7 +593,6 @@ export type Query = { projectUsers: Array; publicKey: Array; studyExists: Scalars['Boolean']['output']; - userIsInOrg: Scalars['Boolean']['output']; users: Array; validateCSV: UploadResult; }; @@ -717,12 +710,6 @@ export type QueryStudyExistsArgs = { }; -export type QueryUserIsInOrgArgs = { - org: Scalars['String']['input']; - user: Scalars['String']['input']; -}; - - export type QueryValidateCsvArgs = { session: Scalars['ID']['input']; };