Skip to content

Commit 71a41e8

Browse files
tmthecoderllam36
andauthored
file services bucket tagging + file service config setup (#200)
Co-authored-by: Long Lam <llam36@gatech.edu>
1 parent a131841 commit 71a41e8

21 files changed

Lines changed: 454 additions & 76 deletions

‎packages/api-gateway/src/models/file_config.dto.ts‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,15 @@ export class FileConfigResponse {
5353
this.buckets = fileConfig.buckets;
5454
}
5555
}
56+
57+
export class SetupFileServiceResponse {
58+
@ApiProperty({
59+
type: 'boolean',
60+
description: 'Whether file services were successfully setup',
61+
})
62+
success: boolean;
63+
64+
constructor(res: FileConfigProto.SetupResponse) {
65+
this.success = res.success;
66+
}
67+
}

‎packages/api-gateway/src/modules/file_config/file_config.controller.ts‎

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import {
55
Inject,
66
OnModuleInit,
77
Param,
8+
Post,
89
} from '@nestjs/common';
910
import { ClientGrpc } from '@nestjs/microservices';
1011
import {
1112
ApiBadRequestResponse,
1213
ApiBearerAuth,
14+
ApiCreatedResponse,
1315
ApiNotFoundResponse,
1416
ApiOkResponse,
1517
ApiOperation,
@@ -19,26 +21,39 @@ import {
1921
import { AuthCommonProto, FileConfigProto } from 'juno-proto';
2022
import { lastValueFrom } from 'rxjs';
2123
import { ApiKey } from 'src/decorators/api_key.decorator';
22-
import { FileConfigResponse } from 'src/models/file_config.dto';
24+
import {
25+
FileConfigResponse,
26+
SetupFileServiceResponse,
27+
} from 'src/models/file_config.dto';
2328

24-
const { FILE_SERVICE_CONFIG_DB_SERVICE_NAME } = FileConfigProto;
29+
const {
30+
FILE_SERVICE_CONFIG_DB_SERVICE_NAME,
31+
FILE_SERVICE_CONFIG_SERVICE_NAME,
32+
} = FileConfigProto;
2533

2634
@ApiBearerAuth('api_key')
2735
@ApiTags('file_config')
2836
@Controller('file')
2937
export class FileConfigController implements OnModuleInit {
38+
private fileConfigService: FileConfigProto.FileServiceConfigServiceClient;
3039
private fileConfigDBService: FileConfigProto.FileServiceConfigDbServiceClient;
3140

3241
constructor(
3342
@Inject(FILE_SERVICE_CONFIG_DB_SERVICE_NAME)
43+
private fileConfigDbClient: ClientGrpc,
44+
@Inject(FILE_SERVICE_CONFIG_SERVICE_NAME)
3445
private fileConfigClient: ClientGrpc,
3546
) {}
3647

3748
onModuleInit() {
3849
this.fileConfigDBService =
39-
this.fileConfigClient.getService<FileConfigProto.FileServiceConfigDbServiceClient>(
50+
this.fileConfigDbClient.getService<FileConfigProto.FileServiceConfigDbServiceClient>(
4051
FILE_SERVICE_CONFIG_DB_SERVICE_NAME,
4152
);
53+
this.fileConfigService =
54+
this.fileConfigClient.getService<FileConfigProto.FileServiceConfigServiceClient>(
55+
FILE_SERVICE_CONFIG_SERVICE_NAME,
56+
);
4257
}
4358

4459
@Get('config/:projectId')
@@ -75,4 +90,27 @@ export class FileConfigController implements OnModuleInit {
7590

7691
return new FileConfigResponse(await lastValueFrom(config));
7792
}
93+
94+
@ApiOperation({
95+
summary: 'Sets up file services for the Project/Environment',
96+
})
97+
@ApiCreatedResponse({
98+
description: 'File Services setup successfully',
99+
type: SetupFileServiceResponse,
100+
})
101+
@ApiUnauthorizedResponse({ description: 'Unauthorized' })
102+
@ApiBadRequestResponse({ description: 'Bad Request' })
103+
@Post('config/setup')
104+
async setup(
105+
@ApiKey() apiKey: AuthCommonProto.ApiKey,
106+
): Promise<SetupFileServiceResponse> {
107+
const setupResponse = await lastValueFrom(
108+
this.fileConfigService.setup({
109+
projectId: apiKey.project.id,
110+
environment: apiKey.environment,
111+
}),
112+
);
113+
114+
return new SetupFileServiceResponse(setupResponse);
115+
}
78116
}

‎packages/api-gateway/src/modules/file_config/file_config.module.ts‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import {
1515
API_KEY_SERVICE_NAME,
1616
JUNO_API_KEY_PACKAGE_NAME,
1717
} from 'juno-proto/dist/gen/api_key';
18-
import { FILE_SERVICE_CONFIG_DB_SERVICE_NAME } from 'juno-proto/dist/gen/file_config';
18+
import {
19+
FILE_SERVICE_CONFIG_DB_SERVICE_NAME,
20+
FILE_SERVICE_CONFIG_SERVICE_NAME,
21+
} from 'juno-proto/dist/gen/file_config';
1922
import {
2023
JWT_SERVICE_NAME,
2124
JUNO_JWT_PACKAGE_NAME,
@@ -45,6 +48,15 @@ import {
4548
protoPath: FileConfigProtoFile,
4649
},
4750
},
51+
{
52+
name: FILE_SERVICE_CONFIG_SERVICE_NAME,
53+
transport: Transport.GRPC,
54+
options: {
55+
url: process.env.FILE_SERVICE_ADDR,
56+
package: FileConfigProto.JUNO_FILE_SERVICE_CONFIG_PACKAGE_NAME,
57+
protoPath: FileConfigProtoFile,
58+
},
59+
},
4860
{
4961
name: JWT_SERVICE_NAME,
5062
transport: Transport.GRPC,

‎packages/api-gateway/test/file_bucket.e2e-spec.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ describe('File Bucket Routes', () => {
143143
},
144144
};
145145
const client = new S3Client(metadata);
146-
const command = new DeleteBucketCommand({ Bucket: uniqueBucketName });
146+
const command = new DeleteBucketCommand({
147+
Bucket: `${uniqueBucketName}-0-prod`,
148+
});
147149

148150
await client.send(command);
149151
});
@@ -223,7 +225,7 @@ describe('File Bucket Routes', () => {
223225
};
224226
const client = new S3Client(metadata);
225227
const command = new DeleteBucketCommand({
226-
Bucket: uniqueBucketName + '-duplicate',
228+
Bucket: uniqueBucketName + '-duplicate-0-prod',
227229
});
228230

229231
await client.send(command);

‎packages/api-gateway/test/file_config.e2e-spec.ts‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import { Test, TestingModule } from '@nestjs/testing';
1+
import * as GRPC from '@grpc/grpc-js';
2+
import * as ProtoLoader from '@grpc/proto-loader';
23
import {
34
ClassSerializerInterceptor,
45
INestApplication,
56
ValidationPipe,
67
} from '@nestjs/common';
7-
import { AppModule } from './../src/app.module';
88
import { Reflector } from '@nestjs/core';
9-
import * as request from 'supertest';
9+
import { Test, TestingModule } from '@nestjs/testing';
1010
import { ResetProtoFile } from 'juno-proto';
11-
import * as GRPC from '@grpc/grpc-js';
12-
import * as ProtoLoader from '@grpc/proto-loader';
1311
import { RpcExceptionFilter } from 'src/rpc_exception_filter';
12+
import * as request from 'supertest';
13+
import { AppModule } from './../src/app.module';
1414

1515
let app: INestApplication;
1616
const ADMIN_EMAIL = 'test-superadmin@test.com';
@@ -101,4 +101,17 @@ describe('File Config Routes', () => {
101101
.set('Authorization', 'Bearer ' + apiKey)
102102
.expect(404);
103103
});
104+
105+
it('Should setup file services for a valid project + api key', async () => {
106+
return await request(app.getHttpServer())
107+
.post('/file/config/setup')
108+
.set('Authorization', 'Bearer ' + apiKey)
109+
.expect(201);
110+
});
111+
112+
it('Should throw a 401 status error when setup file services without valid credentials', async () => {
113+
return await request(app.getHttpServer())
114+
.post('/file/config/setup')
115+
.expect(401);
116+
});
104117
});

‎packages/db-service/src/modules/file_config/file_config.controller.ts‎

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import { status } from '@grpc/grpc-js';
12
import { Controller } from '@nestjs/common';
2-
import { FileServiceConfigService } from './file_config.service';
33
import { RpcException } from '@nestjs/microservices';
4-
import { status } from '@grpc/grpc-js';
5-
import { FileConfigProto } from 'juno-proto';
64
import { Prisma } from '@prisma/client';
5+
import { FileConfigProto } from 'juno-proto';
6+
import { FileServiceConfigService } from './file_config.service';
77

88
@Controller()
99
@FileConfigProto.FileServiceConfigDbServiceControllerMethods()
@@ -26,16 +26,15 @@ export class FileConfigController
2626
environment,
2727
});
2828
if (existingConfig) {
29-
throw new RpcException({
30-
code: status.ALREADY_EXISTS,
31-
message: 'Config already exists',
32-
});
29+
return {
30+
id: existingConfig.id,
31+
environment: existingConfig.environment,
32+
files: [],
33+
buckets: [],
34+
};
3335
}
34-
} catch (error) {
35-
throw new RpcException({
36-
code: status.ALREADY_EXISTS,
37-
message: 'Config already exists',
38-
});
36+
} catch {
37+
// Intentionally ignoring getConfig error for now
3938
}
4039

4140
const config = await this.fileServiceConfigService.createConfig(request);

‎packages/db-service/test/file_config.e2e-spec.ts‎

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { Test, TestingModule } from '@nestjs/testing';
2-
import { INestMicroservice } from '@nestjs/common';
3-
import { AppModule } from '../src/app.module';
4-
import * as ProtoLoader from '@grpc/proto-loader';
51
import * as GRPC from '@grpc/grpc-js';
2+
import * as ProtoLoader from '@grpc/proto-loader';
3+
import { INestMicroservice } from '@nestjs/common';
64
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
5+
import { Test, TestingModule } from '@nestjs/testing';
76
import {
87
FileConfigProto,
98
FileConfigProtoFile,
109
ResetProto,
1110
ResetProtoFile,
1211
} from 'juno-proto';
12+
import { AppModule } from '../src/app.module';
1313

1414
let app: INestMicroservice;
1515
let createdConfigId: number;
@@ -135,8 +135,8 @@ describe('File Service Config Tests', () => {
135135
});
136136

137137
it('creates a duplicate file service config', async () => {
138-
try {
139-
await new Promise((resolve, reject) => {
138+
const response: FileConfigProto.FileServiceConfig = await new Promise(
139+
(resolve, reject) => {
140140
configClient.createConfig(
141141
{
142142
projectId: 0,
@@ -152,10 +152,9 @@ describe('File Service Config Tests', () => {
152152
}
153153
},
154154
);
155-
});
156-
} catch (err) {
157-
expect(err).toBeDefined();
158-
}
155+
},
156+
);
157+
expect(response).toHaveProperty('id');
159158
});
160159

161160
it('deletes a config', async () => {

‎packages/file-service/src/app.module.ts‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import { Module } from '@nestjs/common';
2+
import { SentryModule } from '@sentry/nestjs/setup';
23
import { AppController } from './app.controller';
34
import { AppService } from './app.service';
4-
import { SentryModule } from '@sentry/nestjs/setup';
5-
import { HealthModule } from './modules/health/health.module';
6-
import { FileUploadModule } from './modules/file_upload/file_upload.module';
7-
import { FileProviderModule } from './modules/file_provider/file_provider.module';
85
import { FileBucketModule } from './modules/file_bucket/file_bucket.module';
6+
import { FileConfigModule } from './modules/file_config/file_config.module';
7+
import { FileProviderModule } from './modules/file_provider/file_provider.module';
8+
import { FileTransferModule } from './modules/file_transfer/file_transfer.module';
9+
import { HealthModule } from './modules/health/health.module';
910

1011
@Module({
1112
imports: [
1213
SentryModule.forRoot(),
1314
HealthModule,
14-
FileUploadModule,
15+
FileTransferModule,
1516
FileProviderModule,
1617
FileBucketModule,
18+
FileConfigModule,
1719
],
1820
controllers: [AppController],
1921
providers: [AppService],

‎packages/file-service/src/modules/file_bucket/azure_handler.ts‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ export class AzureBucketHandler {
4646
): Promise<FileBucketProto.Bucket> {
4747
try {
4848
const blobClient = await this.getBlobServiceClient();
49-
await blobClient.getContainerClient(request.name).create();
49+
await blobClient
50+
.getContainerClient(
51+
`${request.name}-${request.configId}-${request.configEnv}`,
52+
)
53+
.create();
5054

5155
const dbBucket = await lastValueFrom(
5256
this.fileDBService.createBucket(request),
@@ -72,7 +76,11 @@ export class AzureBucketHandler {
7276
}),
7377
);
7478
const blobClient = await this.getBlobServiceClient();
75-
await blobClient.getContainerClient(request.name).delete();
79+
await blobClient
80+
.getContainerClient(
81+
`${request.name}-${request.configId}-${request.configEnv}`,
82+
)
83+
.delete();
7684
return bucket;
7785
} catch (error) {
7886
throw new RpcException({

‎packages/file-service/src/modules/file_bucket/s3_handler.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class S3BucketHandler {
3636
try {
3737
const s3Client = await this.getS3Client('us-east-005');
3838
const createBucketCommand = new CreateBucketCommand({
39-
Bucket: request.name,
39+
Bucket: `${request.name}-${request.configId}-${request.configEnv}`,
4040
});
4141
await s3Client.send(createBucketCommand);
4242

@@ -64,7 +64,7 @@ export class S3BucketHandler {
6464
try {
6565
const s3Client = await this.getS3Client('us-east-005');
6666
const deleteBucketCommand = new DeleteBucketCommand({
67-
Bucket: request.name,
67+
Bucket: `${request.name}-${request.configId}-${request.configEnv}`,
6868
});
6969
await s3Client.send(deleteBucketCommand);
7070
const bucket = await lastValueFrom(

0 commit comments

Comments
 (0)