mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-13 08:13:49 +10:00
File Storage toggle
This commit is contained in:
@ -10,6 +10,7 @@
|
||||
"lint": "eslint --fix --ext .ts ./src"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.81.0",
|
||||
"@nestjs/axios": "^0.0.7",
|
||||
"@nestjs/common": "^8.4.4",
|
||||
"@nestjs/config": "^2.0.0",
|
||||
@ -52,6 +53,7 @@
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^8.2.5",
|
||||
"@nestjs/schematics": "^8.0.10",
|
||||
"@reactive-resume/schema": "workspace:*",
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
"@types/express": "^4.17.13",
|
||||
|
||||
@ -7,6 +7,7 @@ import authConfig from './auth.config';
|
||||
import databaseConfig from './database.config';
|
||||
import googleConfig from './google.config';
|
||||
import sendgridConfig from './sendgrid.config';
|
||||
import storageConfig from './storage.config';
|
||||
|
||||
const validationSchema = Joi.object({
|
||||
// App
|
||||
@ -40,12 +41,20 @@ const validationSchema = Joi.object({
|
||||
SENDGRID_FORGOT_PASSWORD_TEMPLATE_ID: Joi.string().allow(''),
|
||||
SENDGRID_FROM_NAME: Joi.string().allow(''),
|
||||
SENDGRID_FROM_EMAIL: Joi.string().allow(''),
|
||||
|
||||
// Storage
|
||||
STORAGE_BUCKET: Joi.string().allow(''),
|
||||
STORAGE_REGION: Joi.string().allow(''),
|
||||
STORAGE_ENDPOINT: Joi.string().allow(''),
|
||||
STORAGE_URL_PREFIX: Joi.string().allow(''),
|
||||
STORAGE_ACCESS_KEY: Joi.string().allow(''),
|
||||
STORAGE_SECRET_KEY: Joi.string().allow(''),
|
||||
});
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
NestConfigModule.forRoot({
|
||||
load: [appConfig, authConfig, databaseConfig, googleConfig, sendgridConfig],
|
||||
load: [appConfig, authConfig, databaseConfig, googleConfig, sendgridConfig, storageConfig],
|
||||
validationSchema: validationSchema,
|
||||
}),
|
||||
],
|
||||
|
||||
@ -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,
|
||||
}));
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { DeleteObjectCommand, PutObjectCommand, S3, S3Client } from '@aws-sdk/client-s3';
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
@ -22,11 +23,26 @@ 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.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) {
|
||||
try {
|
||||
@ -219,26 +235,60 @@ export class ResumeService {
|
||||
async uploadPhoto(id: number, userId: number, file: Express.Multer.File) {
|
||||
const resume = await this.findOne(id, userId);
|
||||
|
||||
const filename = id + '--' + new Date().getTime() + extname(file.originalname);
|
||||
const key = `uploads/${userId}/${id}/${filename}`;
|
||||
fs.writeFile(__dirname + '/../assets/' + key, file.buffer, (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
const updatedResume = set(resume, 'basics.photo.url', '/api/assets/' + key);
|
||||
const filename = new Date().getTime() + extname(file.originalname);
|
||||
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) throw 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 publicUrl = resume.basics.photo.url;
|
||||
if (this.s3Enabled) {
|
||||
const urlPrefix = this.configService.get<string>('storage.urlPrefix');
|
||||
const key = publicUrl.replace(urlPrefix, '');
|
||||
|
||||
fs.unlink(__dirname + '/../' + resume.basics.photo.url.replace('/api/', ''), (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user