mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2026-10-25 10:07:57 +00:00
110 lines
4.7 KiB
TypeScript
110 lines
4.7 KiB
TypeScript
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
|
import { ConfigService } from '@nestjs/config';
|
|
import { plainToInstance } from 'class-transformer';
|
|
import moment from 'moment';
|
|
import { Region, SimpleAuthenticationDetailsProvider } from 'oci-common';
|
|
import { ObjectStorageClient } from 'oci-objectstorage';
|
|
import { CreatePreauthenticatedRequestDetails } from 'oci-objectstorage/lib/model';
|
|
import path from 'path';
|
|
import { CacheService } from '~/common/modules/cache/services';
|
|
import { BUCKETS } from '../constants';
|
|
import { UploadDocumentRequestDto } from '../dtos/request';
|
|
import { UploadResponseDto } from '../dtos/response';
|
|
import { Document } from '../entities';
|
|
import { generateNewFileName } from '../utils';
|
|
const TWO = 2;
|
|
@Injectable()
|
|
export class OciService {
|
|
private readonly ociClient: ObjectStorageClient;
|
|
private readonly tenancyId: string = this.configService.getOrThrow('OCI_TENANCY_ID');
|
|
private readonly userId: string = this.configService.getOrThrow('OCI_USER_ID');
|
|
private readonly fingerprint: string = this.configService.getOrThrow('OCI_FINGERPRINT');
|
|
private readonly privateKey: string = this.configService.getOrThrow('OCI_PRIVATE_KEY');
|
|
private readonly passPhrase: string = this.configService.getOrThrow('OCI_PASSPHRASE');
|
|
private readonly namespace: string = this.configService.getOrThrow('OCI_NAMESPACE');
|
|
private readonly region: string = this.configService.getOrThrow('OCI_REGION');
|
|
private readonly logger = new Logger(OciService.name);
|
|
constructor(private configService: ConfigService, private readonly cacheService: CacheService) {
|
|
this.ociClient = new ObjectStorageClient({
|
|
authenticationDetailsProvider: new SimpleAuthenticationDetailsProvider(
|
|
this.tenancyId,
|
|
this.userId,
|
|
this.fingerprint,
|
|
Buffer.from(this.privateKey, 'base64').toString('utf-8'),
|
|
this.passPhrase,
|
|
Region.fromRegionId(this.region),
|
|
),
|
|
});
|
|
}
|
|
|
|
async uploadFile(file: Express.Multer.File, { documentType }: UploadDocumentRequestDto): Promise<UploadResponseDto> {
|
|
this.logger.log(`Uploading file with type ${documentType}`);
|
|
const bucketName = BUCKETS[documentType];
|
|
const objectName = generateNewFileName(file.originalname);
|
|
|
|
if (!bucketName) {
|
|
this.logger.error('Could not find bucket name for document type', documentType);
|
|
throw new BadRequestException('DOCUMENT.TYPE_NOT_SUPPORTED');
|
|
}
|
|
|
|
this.logger.debug(`Uploading file to bucket ${bucketName} with object name ${objectName}`);
|
|
await this.ociClient.putObject({
|
|
namespaceName: this.namespace,
|
|
bucketName,
|
|
putObjectBody: file.buffer,
|
|
contentLength: file.buffer.length,
|
|
objectName,
|
|
});
|
|
|
|
this.logger.log(`File uploaded successfully to bucket ${bucketName} with object name ${objectName}`);
|
|
|
|
return plainToInstance(UploadResponseDto, {
|
|
name: objectName,
|
|
extension: path.extname(file.originalname),
|
|
url: `https://objectstorage.${this.region}.oraclecloud.com/n/${this.namespace}/b/${bucketName}/o/${objectName}`,
|
|
documentType,
|
|
});
|
|
}
|
|
|
|
async generatePreSignedUrl(document?: Document): Promise<string | any> {
|
|
this.logger.log(`Generating pre-signed url for document ${document?.id}`);
|
|
if (!document) {
|
|
this.logger.error('Document not found, skipping pre-signed url generation');
|
|
return null;
|
|
}
|
|
|
|
const cachedUrl = await this.cacheService.get<string>(document.id);
|
|
|
|
if (cachedUrl) {
|
|
this.logger.debug(`Returning cached pre-signed url for document ${document.id}`);
|
|
return cachedUrl;
|
|
}
|
|
|
|
const bucketName = BUCKETS[document.documentType];
|
|
const objectName = document.name;
|
|
const expiration = moment().add(TWO, 'hours').toDate();
|
|
|
|
try {
|
|
this.logger.debug(`Generating pre-signed url for object ${objectName} in bucket ${bucketName}`);
|
|
const res = await this.ociClient.createPreauthenticatedRequest({
|
|
namespaceName: this.namespace,
|
|
bucketName,
|
|
createPreauthenticatedRequestDetails: {
|
|
name: objectName,
|
|
accessType: CreatePreauthenticatedRequestDetails.AccessType.AnyObjectRead,
|
|
timeExpires: expiration,
|
|
objectName,
|
|
},
|
|
retryConfiguration: { terminationStrategy: { shouldTerminate: () => true } },
|
|
});
|
|
this.logger.log(`Pre-signed url generated successfully for document ${document.id}`);
|
|
await this.cacheService.set(document.id, res.preauthenticatedRequest.fullPath + objectName, '1h');
|
|
this.logger.log(`Pre-signed url cached for document ${document.id}`);
|
|
return res.preauthenticatedRequest.fullPath + objectName;
|
|
} catch (error) {
|
|
this.logger.error(`Error generating pre-signed url: ${error}`);
|
|
return document.name;
|
|
}
|
|
}
|
|
}
|