* Add create api-key route * Import module * Remove required mutation parameter * Fix Authentication * Generate random key * Update Read ApiKeyAbility handler * Add findMany apiKey route * Remove useless attribute * Use signed token for apiKeys * Authenticate with api keys * Fix typo * Add a test for apiKey module * Revoke token when api key does not exist * Handler expiresAt parameter * Fix user passport * Code review returns: Add API_TOKEN_SECRET * Code review returns: Rename variable * Code review returns: Update code style * Update apiKey schema * Update create token route * Update delete token route * Filter revoked api keys from listApiKeys * Rename endpoint * Set default expiry to 2 years * Code review returns: Update comment * Generate token after create apiKey * Code review returns: Update env variable * Code review returns: Move method to proper service --------- Co-authored-by: martmull <martmull@hotmail.com>
122 lines
3.7 KiB
TypeScript
122 lines
3.7 KiB
TypeScript
import { Module } from '@nestjs/common';
|
|
import { GraphQLModule } from '@nestjs/graphql';
|
|
import { ConfigModule } from '@nestjs/config';
|
|
import { APP_FILTER, ModuleRef } from '@nestjs/core';
|
|
|
|
import { YogaDriver, YogaDriverConfig } from '@graphql-yoga/nestjs';
|
|
import GraphQLJSON from 'graphql-type-json';
|
|
import { GraphQLError, GraphQLSchema } from 'graphql';
|
|
import { ExtractJwt } from 'passport-jwt';
|
|
import { TokenExpiredError, JsonWebTokenError, verify } from 'jsonwebtoken';
|
|
|
|
import { AppService } from './app.service';
|
|
|
|
import { CoreModule } from './core/core.module';
|
|
import { IntegrationsModule } from './integrations/integrations.module';
|
|
import { PrismaModule } from './database/prisma.module';
|
|
import { HealthModule } from './health/health.module';
|
|
import { AbilityModule } from './ability/ability.module';
|
|
import { TenantModule } from './tenant/tenant.module';
|
|
import { EnvironmentService } from './integrations/environment/environment.service';
|
|
import {
|
|
JwtAuthStrategy,
|
|
JwtPayload,
|
|
} from './core/auth/strategies/jwt.auth.strategy';
|
|
import { TenantService } from './tenant/tenant.service';
|
|
import { ExceptionFilter } from './filters/exception.filter';
|
|
|
|
@Module({
|
|
imports: [
|
|
ConfigModule.forRoot({
|
|
isGlobal: true,
|
|
}),
|
|
GraphQLModule.forRoot<YogaDriverConfig>({
|
|
context: ({ req }) => ({ req }),
|
|
driver: YogaDriver,
|
|
autoSchemaFile: true,
|
|
include: [CoreModule],
|
|
conditionalSchema: async (request) => {
|
|
try {
|
|
// Get the SchemaGenerationService from the AppModule
|
|
const tenantService = AppModule.moduleRef.get(TenantService, {
|
|
strict: false,
|
|
});
|
|
|
|
// Get the JwtAuthStrategy from the AppModule
|
|
const jwtStrategy = AppModule.moduleRef.get(JwtAuthStrategy, {
|
|
strict: false,
|
|
});
|
|
|
|
// Get the EnvironmentService from the AppModule
|
|
const environmentService = AppModule.moduleRef.get(
|
|
EnvironmentService,
|
|
{
|
|
strict: false,
|
|
},
|
|
);
|
|
|
|
// Extract JWT from the request
|
|
const token = ExtractJwt.fromAuthHeaderAsBearerToken()(request.req);
|
|
|
|
// If there is no token or flexible backend is disabled, return an empty schema
|
|
if (!token || !environmentService.isFlexibleBackendEnabled()) {
|
|
return new GraphQLSchema({});
|
|
}
|
|
|
|
// Verify and decode JWT
|
|
const decoded = verify(
|
|
token,
|
|
environmentService.getAccessTokenSecret(),
|
|
);
|
|
|
|
// Validate JWT
|
|
const { workspace } = await jwtStrategy.validate(
|
|
decoded as JwtPayload,
|
|
);
|
|
|
|
return await tenantService.createTenantSchema(workspace.id);
|
|
} catch (error) {
|
|
if (error instanceof JsonWebTokenError) {
|
|
//mockedUserJWT
|
|
throw new GraphQLError('Unauthenticated', {
|
|
extensions: {
|
|
code: 'UNAUTHENTICATED',
|
|
},
|
|
});
|
|
}
|
|
if (error instanceof TokenExpiredError) {
|
|
throw new GraphQLError('Unauthenticated', {
|
|
extensions: {
|
|
code: 'UNAUTHENTICATED',
|
|
},
|
|
});
|
|
}
|
|
throw error;
|
|
}
|
|
},
|
|
resolvers: { JSON: GraphQLJSON },
|
|
plugins: [],
|
|
}),
|
|
PrismaModule,
|
|
HealthModule,
|
|
AbilityModule,
|
|
IntegrationsModule,
|
|
CoreModule,
|
|
TenantModule,
|
|
],
|
|
providers: [
|
|
AppService,
|
|
{
|
|
provide: APP_FILTER,
|
|
useClass: ExceptionFilter,
|
|
},
|
|
],
|
|
})
|
|
export class AppModule {
|
|
static moduleRef: ModuleRef;
|
|
|
|
constructor(private moduleRef: ModuleRef) {
|
|
AppModule.moduleRef = this.moduleRef;
|
|
}
|
|
}
|