Merge pull request #906 from dvd741-a/main

Add File based Storage toggle for Photos
This commit is contained in:
Amruth Pillai
2022-06-18 16:53:05 +02:00
committed by GitHub
9 changed files with 53329 additions and 247 deletions
+30
View File
@@ -2,6 +2,36 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [3.6.1](https://github.com/dvd741-a/Reactive-Resume/compare/v3.6.0...v3.6.1) (2022-06-05)
## [3.6.0](https://github.com/dvd741-a/Reactive-Resume/compare/v3.3.4...v3.6.0) (2022-06-05)
### Features
* **all:** upgrade to v3.4.0 ([87d381f](https://github.com/dvd741-a/Reactive-Resume/commit/87d381fe8eab9ca4624df5de6e8b9ab18a072b67))
* **i18n:** add Hungrarian (Magyar) language ([35fe4e2](https://github.com/dvd741-a/Reactive-Resume/commit/35fe4e27744b6f7325b25db2cf3b626ed8598623))
### Bug Fixes
* **i18n:** fix language mismatch in exported pdf ([62fd63e](https://github.com/dvd741-a/Reactive-Resume/commit/62fd63e41fe10fba843a40fb08191f5944f2b2fc))
* **typeorm:** update typeorm to latest 0.2.x for secpatch ([5bdb92b](https://github.com/dvd741-a/Reactive-Resume/commit/5bdb92b1cff9e56879f9bbf31801d6554a00a8d5))
## [3.5.0](https://github.com/dvd741-a/Reactive-Resume/compare/v3.3.4...v3.5.0) (2022-06-05)
### Features
* **all:** upgrade to v3.4.0 ([87d381f](https://github.com/dvd741-a/Reactive-Resume/commit/87d381fe8eab9ca4624df5de6e8b9ab18a072b67))
* **i18n:** add Hungrarian (Magyar) language ([35fe4e2](https://github.com/dvd741-a/Reactive-Resume/commit/35fe4e27744b6f7325b25db2cf3b626ed8598623))
### Bug Fixes
* **i18n:** fix language mismatch in exported pdf ([62fd63e](https://github.com/dvd741-a/Reactive-Resume/commit/62fd63e41fe10fba843a40fb08191f5944f2b2fc))
* **typeorm:** update typeorm to latest 0.2.x for secpatch ([5bdb92b](https://github.com/dvd741-a/Reactive-Resume/commit/5bdb92b1cff9e56879f9bbf31801d6554a00a8d5))
### [3.4.5](https://github.com/AmruthPillai/Reactive-Resume/compare/v3.4.4...v3.4.5) (2022-05-24)
+49813
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -34,6 +34,9 @@
"start": "env-cmd --silent concurrently --kill-others \"pnpm run start:*\""
},
"dependencies": {
"@aws-sdk/client-s3": "^3.100.0",
"@docusaurus/core": "^2.0.0-beta.21",
"@docusaurus/preset-classic": "^2.0.0-beta.21",
"concurrently": "^7.1.0",
"env-cmd": "^10.1.0"
},
+3420 -212
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+2
View File
@@ -43,6 +43,8 @@ RUN pnpm install -F server --frozen-lockfile --prod
COPY --from=builder /app/server/dist ./server/dist
VOLUME /app/server/dist/assets/uploads
EXPOSE 3100
ENV PORT 3100
+1
View File
@@ -7,4 +7,5 @@ export default registerAs('storage', () => ({
urlPrefix: process.env.STORAGE_URL_PREFIX,
accessKey: process.env.STORAGE_ACCESS_KEY,
secretKey: process.env.STORAGE_SECRET_KEY,
s3Enabled: process.env.STORAGE_S3_ENABLED,
}));
-2
View File
@@ -35,8 +35,6 @@ export class ResumeController {
@UseGuards(JwtAuthGuard)
@Get()
async findAllByUser(@User('id') userId: number) {
console.log('findAllByUser', userId);
return this.resumeService.findAllByUser(userId);
}
+60 -33
View File
@@ -3,6 +3,7 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Resume as ResumeSchema } from '@reactive-resume/schema';
import fs from 'fs';
import { pick, sample, set } from 'lodash';
import { nanoid } from 'nanoid';
import { extname } from 'path';
@@ -23,20 +24,24 @@ export const SHORT_ID_LENGTH = 8;
@Injectable()
export class ResumeService {
private s3Client: S3Client;
private s3Enabled: boolean;
constructor(
@InjectRepository(Resume) private resumeRepository: Repository<Resume>,
private configService: ConfigService,
private usersService: UsersService
) {
this.s3Client = new S3({
endpoint: configService.get<string>('storage.endpoint'),
region: configService.get<string>('storage.region'),
credentials: {
accessKeyId: configService.get<string>('storage.accessKey'),
secretAccessKey: configService.get<string>('storage.secretKey'),
},
});
this.s3Enabled = configService.get<string>('storage.s3Enabled') !== 'false';
if (this.s3Enabled) {
this.s3Client = new S3({
endpoint: configService.get<string>('storage.endpoint'),
region: configService.get<string>('storage.region'),
credentials: {
accessKeyId: configService.get<string>('storage.accessKey'),
secretAccessKey: configService.get<string>('storage.secretKey'),
},
});
}
}
async create(createResumeDto: CreateResumeDto, userId: number) {
@@ -230,40 +235,62 @@ export class ResumeService {
async uploadPhoto(id: number, userId: number, file: Express.Multer.File) {
const resume = await this.findOne(id, userId);
const urlPrefix = this.configService.get<string>('storage.urlPrefix');
const filename = new Date().getTime() + extname(file.originalname);
const key = `uploads/${userId}/${id}/${filename}`;
await this.s3Client.send(
new PutObjectCommand({
Bucket: this.configService.get<string>('storage.bucket'),
Key: key,
Body: file.buffer,
ACL: 'public-read',
})
);
const publicUrl = urlPrefix + key;
const updatedResume = set(resume, 'basics.photo.url', publicUrl);
let updatedResume = null;
if (this.s3Enabled) {
const urlPrefix = this.configService.get<string>('storage.urlPrefix');
const key = `uploads/${userId}/${id}/${filename}`;
const publicUrl = urlPrefix + key;
await this.s3Client.send(
new PutObjectCommand({
Bucket: this.configService.get<string>('storage.bucket'),
Key: key,
Body: file.buffer,
ACL: 'public-read',
})
);
updatedResume = set(resume, 'basics.photo.url', publicUrl);
} else {
const path = `${__dirname}/../assets/uploads/${userId}/${id}/`;
fs.mkdir(path, { recursive: true }, (err) => {
if (err) {
console.log(err);
}
fs.writeFile(path + filename, file.buffer, (err) => {
if (err) {
console.log(err);
}
});
});
updatedResume = set(resume, 'basics.photo.url', `/api/assets/uploads/${userId}/${id}/` + filename);
}
return this.resumeRepository.save<Resume>(updatedResume);
}
async deletePhoto(id: number, userId: number) {
const resume = await this.findOne(id, userId);
const urlPrefix = this.configService.get<string>('storage.urlPrefix');
const publicUrl = resume.basics.photo.url;
const key = publicUrl.replace(urlPrefix, '');
await this.s3Client.send(
new DeleteObjectCommand({
Bucket: this.configService.get<string>('storage.bucket'),
Key: key,
})
);
if (this.s3Enabled) {
const urlPrefix = this.configService.get<string>('storage.urlPrefix');
const key = publicUrl.replace(urlPrefix, '');
await this.s3Client.send(
new DeleteObjectCommand({
Bucket: this.configService.get<string>('storage.bucket'),
Key: key,
})
);
} else {
const filePath = __dirname + '/../' + resume.basics.photo.url.replace('/api/', '');
if (fs.existsSync(filePath)) {
fs.unlink(filePath, (err) => {
if (err) {
console.log(err);
}
});
}
}
const updatedResume = set(resume, 'basics.photo.url', '');
return this.resumeRepository.save<Resume>(updatedResume);