From 7adef8da5f428c3746a7de4ff82ce16e08037e08 Mon Sep 17 00:00:00 2001 From: cbolles Date: Mon, 12 Feb 2024 15:40:18 -0500 Subject: [PATCH 1/4] Store user to organization mapping --- packages/gateway/src/app.module.ts | 2 ++ packages/server/src/app.module.ts | 4 ++- packages/server/src/jwt/jwt.strategy.ts | 34 +++++++++++++------ packages/server/src/userorg/userorg.model.ts | 13 +++++++ packages/server/src/userorg/userorg.module.ts | 13 +++++++ .../server/src/userorg/userorg.resolver.ts | 23 +++++++++++++ .../server/src/userorg/userorg.service.ts | 29 ++++++++++++++++ 7 files changed, 106 insertions(+), 12 deletions(-) create mode 100644 packages/server/src/userorg/userorg.model.ts create mode 100644 packages/server/src/userorg/userorg.module.ts create mode 100644 packages/server/src/userorg/userorg.resolver.ts create mode 100644 packages/server/src/userorg/userorg.service.ts diff --git a/packages/gateway/src/app.module.ts b/packages/gateway/src/app.module.ts index 9743a07b..dbaa0ab7 100644 --- a/packages/gateway/src/app.module.ts +++ b/packages/gateway/src/app.module.ts @@ -23,6 +23,8 @@ import configuration from './config/configuration'; if (context.req && context.req.headers) { // Copy over authentication request.http!.headers.set('authorization', context.req.headers.authorization); + // Copy over the organization context + request.http!.headers.set('organization', context.req.headers.organization); } } }); diff --git a/packages/server/src/app.module.ts b/packages/server/src/app.module.ts index 5fd0016b..789113db 100644 --- a/packages/server/src/app.module.ts +++ b/packages/server/src/app.module.ts @@ -14,6 +14,7 @@ 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: [ @@ -44,7 +45,8 @@ import { AuthModule } from './auth/auth.module'; SharedModule, JwtModule, PermissionModule, - AuthModule + AuthModule, + UserOrgModule ] }) export class AppModule {} diff --git a/packages/server/src/jwt/jwt.strategy.ts b/packages/server/src/jwt/jwt.strategy.ts index 639f3ca2..9b8a283f 100644 --- a/packages/server/src/jwt/jwt.strategy.ts +++ b/packages/server/src/jwt/jwt.strategy.ts @@ -1,4 +1,4 @@ -import { Injectable, BadRequestException, UnauthorizedException } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-local'; import { TokenPayload } from './token.dto'; @@ -30,14 +30,32 @@ export class JwtStrategy extends PassportStrategy(Strategy) { return; } + // Grab the organization + const organizationID = req.headers.organization; + console.log('organizationID', organizationID); + if (organizationID == undefined || organizationID == 'undefined') { + this.fail({ message: 'Invalid Organization' }, 400); + return; + } + if (typeof organizationID !== 'string') { + this.fail({ message: 'Invalid Organization' }, 400); + return; + } + const organization = await this.organizationService.findOne(organizationID); + if (!organization) { + console.log('no organization'); + this.fail({ message: 'Invalid Organization' }, 400); + return; + } + // Validate the token const payload = await this.jwtService.validate(rawToken); if (!payload) { - this.fail({ meessage: 'Invalid Token' }, 400); + this.fail({ message: 'Invalid Token' }, 400); return; } - this.success(await this.validate(payload)); + this.success(await this.validate(payload, organization)); } /** @@ -45,16 +63,10 @@ export class JwtStrategy extends PassportStrategy(Strategy) { * queried from the database and not part of the JWT token. This allows * the organization to then be pulled in via the organization context */ - async validate(payload: TokenPayload): Promise { - // TODO: Change out hardcoded project ID - const organization = await this.organizationService.findByProject('fe231d0b-5f01-4e52-9bc1-561e76b1e02d'); - if (!organization) { - throw new BadRequestException('Organization not found'); - } - + async validate(payload: TokenPayload, organization: Organization): Promise { return { ...payload, - organization: organization + organization }; } } diff --git a/packages/server/src/userorg/userorg.model.ts b/packages/server/src/userorg/userorg.model.ts new file mode 100644 index 00000000..8d3bb8d7 --- /dev/null +++ b/packages/server/src/userorg/userorg.model.ts @@ -0,0 +1,13 @@ +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 new file mode 100644 index 00000000..5fd00271 --- /dev/null +++ b/packages/server/src/userorg/userorg.module.ts @@ -0,0 +1,13 @@ +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] +}) +export class UserOrgModule {} diff --git a/packages/server/src/userorg/userorg.resolver.ts b/packages/server/src/userorg/userorg.resolver.ts new file mode 100644 index 00000000..08f11c64 --- /dev/null +++ b/packages/server/src/userorg/userorg.resolver.ts @@ -0,0 +1,23 @@ +import { Resolver } from '@nestjs/graphql'; +import { Query, Mutation, Args } from '@nestjs/graphql'; +import { UserOrgService } from './userorg.service'; +import { OrganizationContext } from '../organization/organization.context'; +import { Organization } from '../organization/organization.model'; +import { TokenContext } from '../jwt/token.context'; +import { TokenPayload } from '../jwt/token.dto'; + +@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); + } + + @Mutation(() => Boolean) + async addUserToOrg(@TokenContext() user: TokenPayload, @OrganizationContext() org: Organization): Promise { + await this.userOrgService.create(user.user_id, org._id.toString()); + return true; + } +} diff --git a/packages/server/src/userorg/userorg.service.ts b/packages/server/src/userorg/userorg.service.ts new file mode 100644 index 00000000..6c17de42 --- /dev/null +++ b/packages/server/src/userorg/userorg.service.ts @@ -0,0 +1,29 @@ +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 66ffc85cd1825984bd531f88d4a8c41bfc5eddf4 Mon Sep 17 00:00:00 2001 From: cbolles Date: Mon, 12 Feb 2024 15:58:27 -0500 Subject: [PATCH 2/4] Splitting organization and JWT logic --- packages/server/src/jwt/jwt.module.ts | 3 +- packages/server/src/jwt/jwt.strategy.ts | 34 +++------------ .../src/organization/organization.context.ts | 2 +- .../src/organization/organization.guard.ts | 43 +++++++++++++++++++ .../src/organization/organization.module.ts | 3 +- packages/server/src/userorg/userorg.module.ts | 3 +- .../server/src/userorg/userorg.resolver.ts | 12 +++--- 7 files changed, 61 insertions(+), 39 deletions(-) create mode 100644 packages/server/src/organization/organization.guard.ts diff --git a/packages/server/src/jwt/jwt.module.ts b/packages/server/src/jwt/jwt.module.ts index 8d326146..e59eac10 100644 --- a/packages/server/src/jwt/jwt.module.ts +++ b/packages/server/src/jwt/jwt.module.ts @@ -4,9 +4,10 @@ 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'; @Module({ - imports: [HttpModule, forwardRef(() => OrganizationModule)], + imports: [HttpModule, forwardRef(() => OrganizationModule), UserOrgModule], providers: [JwtService, JwtAuthGuard, JwtStrategy], exports: [JwtService] }) diff --git a/packages/server/src/jwt/jwt.strategy.ts b/packages/server/src/jwt/jwt.strategy.ts index 9b8a283f..75f597dc 100644 --- a/packages/server/src/jwt/jwt.strategy.ts +++ b/packages/server/src/jwt/jwt.strategy.ts @@ -2,20 +2,14 @@ import { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-local'; import { TokenPayload } from './token.dto'; -import { OrganizationService } from '../organization/organization.service'; -import { Organization } from 'src/organization/organization.model'; import { Request } from 'express'; import { ParamsDictionary } from 'express-serve-static-core'; import { ParsedQs } from 'qs'; import { JwtService } from './jwt.service'; -interface JwtStrategyValidate extends TokenPayload { - organization: Organization; -} - @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { - constructor(private readonly organizationService: OrganizationService, private readonly jwtService: JwtService) { + constructor(private readonly jwtService: JwtService) { super(); } @@ -30,24 +24,6 @@ export class JwtStrategy extends PassportStrategy(Strategy) { return; } - // Grab the organization - const organizationID = req.headers.organization; - console.log('organizationID', organizationID); - if (organizationID == undefined || organizationID == 'undefined') { - this.fail({ message: 'Invalid Organization' }, 400); - return; - } - if (typeof organizationID !== 'string') { - this.fail({ message: 'Invalid Organization' }, 400); - return; - } - const organization = await this.organizationService.findOne(organizationID); - if (!organization) { - console.log('no organization'); - this.fail({ message: 'Invalid Organization' }, 400); - return; - } - // Validate the token const payload = await this.jwtService.validate(rawToken); if (!payload) { @@ -55,7 +31,8 @@ export class JwtStrategy extends PassportStrategy(Strategy) { return; } - this.success(await this.validate(payload, organization)); + const result = await this.validate(payload); + this.success(result); } /** @@ -63,10 +40,9 @@ export class JwtStrategy extends PassportStrategy(Strategy) { * queried from the database and not part of the JWT token. This allows * the organization to then be pulled in via the organization context */ - async validate(payload: TokenPayload, organization: Organization): Promise { + async validate(payload: TokenPayload): Promise { return { - ...payload, - organization + ...payload }; } } diff --git a/packages/server/src/organization/organization.context.ts b/packages/server/src/organization/organization.context.ts index 954009d9..68c4aa48 100644 --- a/packages/server/src/organization/organization.context.ts +++ b/packages/server/src/organization/organization.context.ts @@ -3,5 +3,5 @@ import { GqlExecutionContext } from '@nestjs/graphql'; export const OrganizationContext = createParamDecorator((_data: unknown, ctx: ExecutionContext) => { const gqlCtx = GqlExecutionContext.create(ctx); - return gqlCtx.getContext().req.user.organization; + return gqlCtx.getContext().req.organization; }); diff --git a/packages/server/src/organization/organization.guard.ts b/packages/server/src/organization/organization.guard.ts new file mode 100644 index 00000000..8ec2ea1a --- /dev/null +++ b/packages/server/src/organization/organization.guard.ts @@ -0,0 +1,43 @@ +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) {} + + async canActivate(context: ExecutionContext): Promise { + const ctx = GqlExecutionContext.create(context); + + // 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); + 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; + + return true; + } +} diff --git a/packages/server/src/organization/organization.module.ts b/packages/server/src/organization/organization.module.ts index be0c4528..ebcb9e70 100644 --- a/packages/server/src/organization/organization.module.ts +++ b/packages/server/src/organization/organization.module.ts @@ -4,9 +4,10 @@ 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 }])], + imports: [MongooseModule.forFeature([{ name: Organization.name, schema: OrganizationSchema }]), UserOrgModule], providers: [OrganizationResolver, OrganizationService, CreateOrganizationPipe], exports: [OrganizationService] }) diff --git a/packages/server/src/userorg/userorg.module.ts b/packages/server/src/userorg/userorg.module.ts index 5fd00271..d169ac82 100644 --- a/packages/server/src/userorg/userorg.module.ts +++ b/packages/server/src/userorg/userorg.module.ts @@ -8,6 +8,7 @@ import { UserOrgResolver } from './userorg.resolver'; imports: [ MongooseModule.forFeature([{ name: UserOrg.name, schema: UserOrgSchema }]) ], - providers: [UserOrgService, UserOrgResolver] + 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 index 08f11c64..c7372aae 100644 --- a/packages/server/src/userorg/userorg.resolver.ts +++ b/packages/server/src/userorg/userorg.resolver.ts @@ -1,10 +1,9 @@ -import { Resolver } from '@nestjs/graphql'; -import { Query, Mutation, Args } from '@nestjs/graphql'; +import { ID, Resolver, Query, Mutation, Args } from '@nestjs/graphql'; import { UserOrgService } from './userorg.service'; -import { OrganizationContext } from '../organization/organization.context'; -import { Organization } from '../organization/organization.model'; 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 { @@ -15,9 +14,10 @@ export class UserOrgResolver { return this.userOrgService.userIsInOrg(user, org); } + @UseGuards(JwtAuthGuard) @Mutation(() => Boolean) - async addUserToOrg(@TokenContext() user: TokenPayload, @OrganizationContext() org: Organization): Promise { - await this.userOrgService.create(user.user_id, org._id.toString()); + async addUserToOrg(@Args('organization', { type: () => ID }) organization: string, @TokenContext() user: TokenPayload): Promise { + await this.userOrgService.create(user.user_id, organization); return true; } } From 306a9c78c010bb3e809bffc8dbf6d75d2aceafbc Mon Sep 17 00:00:00 2001 From: cbolles Date: Mon, 12 Feb 2024 16:13:01 -0500 Subject: [PATCH 3/4] Add organization context as needed --- packages/client/src/App.tsx | 3 ++- packages/server/src/dataset/dataset.module.ts | 6 +++++- packages/server/src/dataset/dataset.resolver.ts | 4 ++-- packages/server/src/entry/entry.module.ts | 6 +++++- packages/server/src/entry/resolvers/entry.resolver.ts | 3 ++- packages/server/src/permission/permission.module.ts | 6 +++++- .../server/src/permission/resolvers/permission.resolver.ts | 3 ++- packages/server/src/project/project.module.ts | 6 +++++- packages/server/src/project/project.resolver.ts | 3 ++- 9 files changed, 30 insertions(+), 10 deletions(-) diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx index e6ee6cd8..6984421e 100644 --- a/packages/client/src/App.tsx +++ b/packages/client/src/App.tsx @@ -55,7 +55,8 @@ const App: FC = () => { return { headers: { ...headers, - authorization: token ? `Bearer ${token}` : '' + authorization: token ? `Bearer ${token}` : '', + organization: import.meta.env.VITE_ORGANIZATION_ID || '' } }; }); diff --git a/packages/server/src/dataset/dataset.module.ts b/packages/server/src/dataset/dataset.module.ts index 2bdcff3b..f616a624 100644 --- a/packages/server/src/dataset/dataset.module.ts +++ b/packages/server/src/dataset/dataset.module.ts @@ -7,13 +7,17 @@ import { DatasetPipe } from './pipes/dataset.pipe'; 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: [ MongooseModule.forFeature([{ name: Dataset.name, schema: DatasetSchema }]), forwardRef(() => PermissionModule), JwtModule, - ProjectModule + ProjectModule, + OrganizationModule, + UserOrgModule ], providers: [DatasetResolver, DatasetService, DatasetPipe], exports: [DatasetService, DatasetPipe] diff --git a/packages/server/src/dataset/dataset.resolver.ts b/packages/server/src/dataset/dataset.resolver.ts index 30e79dcf..9cfd387a 100644 --- a/packages/server/src/dataset/dataset.resolver.ts +++ b/packages/server/src/dataset/dataset.resolver.ts @@ -15,9 +15,9 @@ import { DatasetPermissions } from '../permission/permissions/dataset'; import { ProjectPipe } from '../project/pipes/project.pipe'; import { Project } from '../project/project.model'; import { ProjectPermissions } from '../permission/permissions/project'; +import { OrganizationGuard } from '../organization/organization.guard'; -// TODO: Add authentication -@UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard, OrganizationGuard) @Resolver(() => Dataset) export class DatasetResolver { constructor( diff --git a/packages/server/src/entry/entry.module.ts b/packages/server/src/entry/entry.module.ts index 034d2896..04a04546 100644 --- a/packages/server/src/entry/entry.module.ts +++ b/packages/server/src/entry/entry.module.ts @@ -17,6 +17,8 @@ import { PermissionModule } from '../permission/permission.module'; 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: [ @@ -42,7 +44,9 @@ import { SharedModule } from '../shared/shared.module'; DatasetModule, GcpModule, PermissionModule, - JwtModule + JwtModule, + OrganizationModule, + UserOrgModule ], providers: [ EntryResolver, diff --git a/packages/server/src/entry/resolvers/entry.resolver.ts b/packages/server/src/entry/resolvers/entry.resolver.ts index 51d0c9c1..1d43c561 100644 --- a/packages/server/src/entry/resolvers/entry.resolver.ts +++ b/packages/server/src/entry/resolvers/entry.resolver.ts @@ -13,8 +13,9 @@ import { TokenContext } from '../../jwt/token.context'; import { OrganizationContext } from '../../organization/organization.context'; import { Organization } from '../../organization/organization.model'; import { EntryPipe } from '../pipes/entry.pipe'; +import { OrganizationGuard } from '../../organization/organization.guard'; -@UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard, OrganizationGuard) @Resolver(() => Entry) export class EntryResolver { constructor( diff --git a/packages/server/src/permission/permission.module.ts b/packages/server/src/permission/permission.module.ts index bbe82ac0..023db01b 100644 --- a/packages/server/src/permission/permission.module.ts +++ b/packages/server/src/permission/permission.module.ts @@ -10,13 +10,17 @@ import { StudyPermissionResolver } from './resolvers/study.resolver'; 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: [ forwardRef(() => ProjectModule), AuthModule, forwardRef(() => StudyModule), - forwardRef(() => DatasetModule) + forwardRef(() => DatasetModule), + OrganizationModule, + UserOrgModule ], providers: [ casbinProvider, diff --git a/packages/server/src/permission/resolvers/permission.resolver.ts b/packages/server/src/permission/resolvers/permission.resolver.ts index 2a17c610..9c5cc10e 100644 --- a/packages/server/src/permission/resolvers/permission.resolver.ts +++ b/packages/server/src/permission/resolvers/permission.resolver.ts @@ -11,8 +11,9 @@ import { OrganizationContext } from '../../organization/organization.context'; import { Organization } from '../../organization/organization.model'; import { UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from '../../jwt/jwt.guard'; +import { OrganizationGuard } from '../../organization/organization.guard'; -@UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard, OrganizationGuard) @Resolver() export class PermissionResolver { constructor( diff --git a/packages/server/src/project/project.module.ts b/packages/server/src/project/project.module.ts index fa584f5d..11c223bc 100644 --- a/packages/server/src/project/project.module.ts +++ b/packages/server/src/project/project.module.ts @@ -8,6 +8,8 @@ import { MongooseMiddlewareService } from 'src/shared/service/mongoose-callback. 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: [ @@ -29,7 +31,9 @@ import { PermissionModule } from '../permission/permission.module'; } ]), JwtModule, - forwardRef(() => PermissionModule) + forwardRef(() => PermissionModule), + OrganizationModule, + UserOrgModule ], providers: [ProjectResolver, ProjectService, ProjectPipe], exports: [ProjectPipe, ProjectService] diff --git a/packages/server/src/project/project.resolver.ts b/packages/server/src/project/project.resolver.ts index e20c1496..1bce80af 100644 --- a/packages/server/src/project/project.resolver.ts +++ b/packages/server/src/project/project.resolver.ts @@ -12,8 +12,9 @@ import { TokenPayload } from '../jwt/token.dto'; import { CASBIN_PROVIDER } from '../permission/casbin.provider'; import * as casbin from 'casbin'; import { ProjectPermissions } from '../permission/permissions/project'; +import { OrganizationGuard } from '../organization/organization.guard'; -@UseGuards(JwtAuthGuard) +@UseGuards(JwtAuthGuard, OrganizationGuard) @Resolver(() => Project) export class ProjectResolver { constructor( From 02e327de4cd2488e5739eaedda37cd38bfcb8a76 Mon Sep 17 00:00:00 2001 From: cbolles Date: Mon, 12 Feb 2024 16:13:56 -0500 Subject: [PATCH 4/4] Fix formatting --- packages/server/src/organization/organization.guard.ts | 5 ++++- packages/server/src/userorg/userorg.module.ts | 6 ++---- packages/server/src/userorg/userorg.resolver.ts | 5 ++++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/server/src/organization/organization.guard.ts b/packages/server/src/organization/organization.guard.ts index 8ec2ea1a..84e554f7 100644 --- a/packages/server/src/organization/organization.guard.ts +++ b/packages/server/src/organization/organization.guard.ts @@ -5,7 +5,10 @@ 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, + private readonly userOrgService: UserOrgService + ) {} async canActivate(context: ExecutionContext): Promise { const ctx = GqlExecutionContext.create(context); diff --git a/packages/server/src/userorg/userorg.module.ts b/packages/server/src/userorg/userorg.module.ts index d169ac82..13337afb 100644 --- a/packages/server/src/userorg/userorg.module.ts +++ b/packages/server/src/userorg/userorg.module.ts @@ -1,13 +1,11 @@ import { Module } from '@nestjs/common'; import { UserOrgService } from './userorg.service'; import { UserOrg, UserOrgSchema } from './userorg.model'; -import { MongooseModule } from '@nestjs/mongoose' +import { MongooseModule } from '@nestjs/mongoose'; import { UserOrgResolver } from './userorg.resolver'; @Module({ - imports: [ - MongooseModule.forFeature([{ name: UserOrg.name, schema: UserOrgSchema }]) - ], + imports: [MongooseModule.forFeature([{ name: UserOrg.name, schema: UserOrgSchema }])], providers: [UserOrgService, UserOrgResolver], exports: [UserOrgService] }) diff --git a/packages/server/src/userorg/userorg.resolver.ts b/packages/server/src/userorg/userorg.resolver.ts index c7372aae..dac0acf6 100644 --- a/packages/server/src/userorg/userorg.resolver.ts +++ b/packages/server/src/userorg/userorg.resolver.ts @@ -16,7 +16,10 @@ export class UserOrgResolver { @UseGuards(JwtAuthGuard) @Mutation(() => Boolean) - async addUserToOrg(@Args('organization', { type: () => ID }) organization: string, @TokenContext() user: TokenPayload): Promise { + async addUserToOrg( + @Args('organization', { type: () => ID }) organization: string, + @TokenContext() user: TokenPayload + ): Promise { await this.userOrgService.create(user.user_id, organization); return true; }