Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File Service Config Environments & Provider Types #166

Merged
merged 8 commits into from
Feb 12, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions packages/api-gateway/src/models/file_provider.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { IsNotEmpty } from 'class-validator';

import { ApiProperty } from '@nestjs/swagger';
import { FileProviderProto } from 'juno-proto';
import { Transform } from 'class-transformer';

class AccessKey {
@ApiProperty({
Expand Down Expand Up @@ -43,6 +44,11 @@ export class RegisterFileProviderModel {
})
@IsNotEmpty()
providerName: string;

@IsNotEmpty()
@Transform(toEnum)
@ApiProperty({ description: 'File provider type' })
type: FileProviderProto.ProviderType;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider adding example values to @ApiProperty to show valid provider types (S3, AZURE)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

valid

}

export class FileProviderResponse {
Expand All @@ -57,3 +63,16 @@ export class FileProviderResponse {
this.metadata = fileProvider.metadata;
}
}

function toEnum(params: {
value: string;
}): FileProviderProto.ProviderType | undefined {
switch (params.value) {
case 'S3':
return FileProviderProto.ProviderType.S3;
case 'AZURE':
return FileProviderProto.ProviderType.AZURE;
default:
return undefined;
}
UZ9 marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { lastValueFrom } from 'rxjs';
import { FileBucketProto } from 'juno-proto';
import { AuthCommonProto, FileBucketProto } from 'juno-proto';
import {
ApiBearerAuth,
ApiOperation,
Expand All @@ -19,6 +19,7 @@ import {
RegisterFileBucketModel,
FileBucketResponse,
} from 'src/models/file_bucket.dto';
import { ApiKey } from 'src/decorators/api_key.decorator';

const { BUCKET_FILE_SERVICE_NAME } = FileBucketProto;

Expand Down Expand Up @@ -52,13 +53,15 @@ export class FileBucketController implements OnModuleInit {
type: FileBucketResponse,
})
async registerFileBucket(
@ApiKey() apiKey: AuthCommonProto.ApiKey,
@Body() params: RegisterFileBucketModel,
): Promise<FileBucketResponse> {
const grpcResponse = this.fileBucketService.registerBucket({
name: params.name,
configId: params.configId,
fileProviderName: params.fileProviderName,
FileServiceFile: params.FileServiceFile,
UZ9 marked this conversation as resolved.
Show resolved Hide resolved
configEnv: apiKey.environment,
});

const bucketData = await lastValueFrom(grpcResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { lastValueFrom } from 'rxjs';
import { FileProto } from 'juno-proto';
import { AuthCommonProto, FileProto } from 'juno-proto';
import {
ApiBearerAuth,
ApiOperation,
Expand All @@ -19,6 +19,7 @@ import {
DownloadFileModel,
DownloadFileResponse,
} from 'src/models/file_download.dto';
import { ApiKey } from 'src/decorators/api_key.decorator';

const { FILE_SERVICE_NAME } = FileProto;

Expand Down Expand Up @@ -56,9 +57,15 @@ export class FileDownloadController implements OnModuleInit {
type: DownloadFileResponse,
})
async downloadFile(
@ApiKey() apiKey: AuthCommonProto.ApiKey,
@Body('') params: DownloadFileModel,
): Promise<DownloadFileResponse> {
const res = await lastValueFrom(this.fileService.downloadFile(params));
const res = await lastValueFrom(
this.fileService.downloadFile({
configEnv: apiKey.environment,
...params,
}),
UZ9 marked this conversation as resolved.
Show resolved Hide resolved
);

return new DownloadFileResponse(res);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export class FileProviderController implements OnModuleInit {
providerName: params.providerName,
privateAccessKey: params.accessKey.privateAccessKey,
publicAccessKey: params.accessKey.publicAccessKey,
type: params.type,
});

return new FileProviderResponse(await lastValueFrom(fileProvider));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@nestjs/common';
import { ClientGrpc } from '@nestjs/microservices';
import { lastValueFrom } from 'rxjs';
import { FileProto } from 'juno-proto';
import { AuthCommonProto, FileProto } from 'juno-proto';
import {
ApiBearerAuth,
ApiOperation,
Expand All @@ -19,6 +19,7 @@ import {
UploadFileResponse,
UploadFileModel,
} from 'src/models/file_upload.dto';
import { ApiKey } from 'src/decorators/api_key.decorator';

const { FILE_SERVICE_NAME } = FileProto;

Expand Down Expand Up @@ -54,6 +55,7 @@ export class FileUploadController implements OnModuleInit {
type: UploadFileResponse,
})
async uploadFile(
@ApiKey() apiKey: AuthCommonProto.ApiKey,
@Body('') params: UploadFileModel,
): Promise<UploadFileResponse> {
const uploadFile = this.fileService.uploadFile({
Expand All @@ -62,6 +64,7 @@ export class FileUploadController implements OnModuleInit {
providerName: params.providerName,
configId: params.configId,
region: params.region,
configEnv: apiKey.environment,
});

return new UploadFileResponse(await lastValueFrom(uploadFile));
Expand Down
15 changes: 9 additions & 6 deletions packages/api-gateway/test/file_bucket.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { AppModule } from './../src/app.module';
import { Reflector } from '@nestjs/core';
import * as request from 'supertest';
import {
FileBucketProto,
ResetProtoFile,
FileProviderProtoFile,
FileProviderProto,
} from 'juno-proto';
import * as GRPC from '@grpc/grpc-js';
import * as ProtoLoader from '@grpc/proto-loader';
Expand All @@ -28,6 +28,8 @@ const secretAccessKey = process.env.secretAccessKey;
const baseURL = process.env.baseURL;
const providerName = 'backblazeb2-upload';

jest.setTimeout(10000);

async function APIKeyForProjectName(projectName: string): Promise<string> {
const key = await request(app.getHttpServer())
.post('/auth/key')
Expand Down Expand Up @@ -90,6 +92,7 @@ beforeAll(async () => {
}),
metadata: JSON.stringify({ endpoint: baseURL }),
bucket: [],
type: FileProviderProto.ProviderType.S3,
},
(err: any) => {
if (err) return reject(err);
Expand Down Expand Up @@ -118,7 +121,7 @@ describe('File Bucket Routes', () => {
});

it('Creating a bucket successfully', async () => {
const fileBucketBody: FileBucketProto.RegisterBucketRequest = {
const fileBucketBody = {
name: uniqueBucketName,
configId: 0,
fileProviderName: providerName,
Expand Down Expand Up @@ -146,7 +149,7 @@ describe('File Bucket Routes', () => {
});

it('Unsuccessful creation due to missing bucket name', async () => {
const fileBucketBody: FileBucketProto.RegisterBucketRequest = {
const fileBucketBody = {
name: '',
configId: 1,
fileProviderName: 'Test Provider',
Expand All @@ -161,7 +164,7 @@ describe('File Bucket Routes', () => {
});

it('Unsuccessful creation due to missing config ID', async () => {
const fileBucketBody: FileBucketProto.RegisterBucketRequest = {
const fileBucketBody = {
name: uniqueBucketName,
configId: undefined,
fileProviderName: 'Test Provider',
Expand All @@ -176,7 +179,7 @@ describe('File Bucket Routes', () => {
});

it('Unsuccessful creation due to missing file provider name', async () => {
const fileBucketBody: FileBucketProto.RegisterBucketRequest = {
const fileBucketBody = {
name: uniqueBucketName,
configId: 1,
fileProviderName: '',
Expand All @@ -191,7 +194,7 @@ describe('File Bucket Routes', () => {
});

it('Creating an existing bucket (should fail)', async () => {
const fileBucketBody: FileBucketProto.RegisterBucketRequest = {
const fileBucketBody = {
name: uniqueBucketName + '-duplicate',
configId: 0,
fileProviderName: providerName,
Expand Down
4 changes: 4 additions & 0 deletions packages/api-gateway/test/file_download.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
FileProviderProtoFile,
FileBucketProtoFile,
ResetProtoFile,
FileProviderProto,
} from 'juno-proto';
import * as GRPC from '@grpc/grpc-js';
import * as ProtoLoader from '@grpc/proto-loader';
Expand Down Expand Up @@ -84,6 +85,7 @@ beforeAll(async () => {
}),
metadata: JSON.stringify({ endpoint: baseURL }),
bucket: [],
type: FileProviderProto.ProviderType.S3,
},
() => {
resolve(0);
Expand All @@ -105,6 +107,7 @@ beforeAll(async () => {
name: bucketName,
configId: configId,
fileProviderName: providerName,
configEnv: 'prod',
files: [],
},
() => {
Expand All @@ -124,6 +127,7 @@ beforeAll(async () => {
fileId: {
bucketName: bucketName,
configId: configId,
configEnv: 'prod',
path: validFile,
},
metadata: '',
Expand Down
28 changes: 19 additions & 9 deletions packages/api-gateway/test/file_provider.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { AppModule } from './../src/app.module';
import { Reflector } from '@nestjs/core';
import * as request from 'supertest';
import { FileProviderProto, ResetProtoFile } from 'juno-proto';
import { ResetProtoFile } from 'juno-proto';
import * as GRPC from '@grpc/grpc-js';
import * as ProtoLoader from '@grpc/proto-loader';

Expand Down Expand Up @@ -73,11 +73,12 @@ beforeEach(async () => {

describe('File Provider Verification Routes', () => {
it('Missing provider name file provider without auth key', () => {
const fileProviderBody: FileProviderProto.RegisterProviderRequest = {
const fileProviderBody = {
providerName: '',
publicAccessKey: 'Test Public Access Key',
privateAccessKey: 'Test Private Access Key',
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Request body structure is inconsistent with the valid test case (lines 218-225) which uses nested accessKey object

Suggested change
const fileProviderBody = {
providerName: '',
publicAccessKey: 'Test Public Access Key',
privateAccessKey: 'Test Private Access Key',
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};
const fileProviderBody = {
providerName: '',
accessKey: {
publicAccessKey: 'Test Public Access Key',
privateAccessKey: 'Test Private Access Key',
},
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review was wrong (it should be what you put) but it does seem like we have the wrong access key format in several of the e2e tests (nested)--could you take a look?


return request(app.getHttpServer())
Expand All @@ -87,11 +88,12 @@ describe('File Provider Verification Routes', () => {
});

it('Missing public access key file provider without auth key', () => {
const fileProviderBody: FileProviderProto.RegisterProviderRequest = {
const fileProviderBody = {
providerName: 'Test Provider',
publicAccessKey: '',
privateAccessKey: 'Test Private Access Key',
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};

return request(app.getHttpServer())
Expand All @@ -101,11 +103,12 @@ describe('File Provider Verification Routes', () => {
});

it('Missing private access key file provider without auth key', () => {
const fileProviderBody: FileProviderProto.RegisterProviderRequest = {
const fileProviderBody = {
providerName: 'Test Provider',
publicAccessKey: 'Test Public Access Key',
privateAccessKey: '',
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};

return request(app.getHttpServer())
Expand All @@ -115,11 +118,12 @@ describe('File Provider Verification Routes', () => {
});

it('Missing base url file provider without auth key', () => {
const fileProviderBody: FileProviderProto.RegisterProviderRequest = {
const fileProviderBody = {
providerName: 'Test Provider',
publicAccessKey: 'Test Public Access Key',
privateAccessKey: 'Test Private Access Key',
baseUrl: '',
type: 'S3',
};

return request(app.getHttpServer())
Expand All @@ -136,6 +140,7 @@ describe('File Provider Verification Routes', () => {
privateAccessKey: 'Test Private Access Key',
},
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};

return request(app.getHttpServer())
Expand All @@ -145,11 +150,12 @@ describe('File Provider Verification Routes', () => {
});

it('Missing provider name file provider with auth key', () => {
const fileProviderBody: FileProviderProto.RegisterProviderRequest = {
const fileProviderBody = {
providerName: '',
publicAccessKey: 'Test Public Access Key',
privateAccessKey: 'Test Private Access Key',
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};

return request(app.getHttpServer())
Expand All @@ -160,11 +166,12 @@ describe('File Provider Verification Routes', () => {
});

it('Missing public access key file provider with auth key', () => {
const fileProviderBody: FileProviderProto.RegisterProviderRequest = {
const fileProviderBody = {
providerName: 'Test Provider',
publicAccessKey: '',
privateAccessKey: 'Test Private Access Key',
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};

return request(app.getHttpServer())
Expand All @@ -175,11 +182,12 @@ describe('File Provider Verification Routes', () => {
});

it('Missing private access key file provider with auth key', () => {
const fileProviderBody: FileProviderProto.RegisterProviderRequest = {
const fileProviderBody = {
providerName: 'Test Provider',
publicAccessKey: 'Test Public Access Key',
privateAccessKey: '',
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};

return request(app.getHttpServer())
Expand All @@ -190,11 +198,12 @@ describe('File Provider Verification Routes', () => {
});

it('Missing base url file provider with auth key', () => {
const fileProviderBody: FileProviderProto.RegisterProviderRequest = {
const fileProviderBody = {
providerName: 'Test Provider',
publicAccessKey: 'Test Public Access Key',
privateAccessKey: 'Test Private Access Key',
baseUrl: '',
type: 'S3',
};

return request(app.getHttpServer())
Expand All @@ -212,6 +221,7 @@ describe('File Provider Verification Routes', () => {
privateAccessKey: 'Test Private Access Key',
},
baseUrl: 'https://aws.amazon.com/s3',
type: 'S3',
};

return request(app.getHttpServer())
Expand Down
Loading