Skip to content

Instantly share code, notes, and snippets.

@abc0990cba
Forked from sandeepsuvit/.env
Created March 21, 2024 19:16
Show Gist options
  • Select an option

  • Save abc0990cba/078d3f2ba865b72cf61869a90ce8af64 to your computer and use it in GitHub Desktop.

Select an option

Save abc0990cba/078d3f2ba865b72cf61869a90ce8af64 to your computer and use it in GitHub Desktop.

Revisions

  1. @sandeepsuvit sandeepsuvit revised this gist Jul 30, 2019. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions auth-user.decorator.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,4 @@
    import { createParamDecorator } from '@nestjs/common';

    // Decorator function to extract the data
    export const AuthUser = createParamDecorator((data, req) => data ? req.authInfo.user[data] : req.authInfo.user);
  2. @sandeepsuvit sandeepsuvit revised this gist Jul 30, 2019. 1 changed file with 4 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions roles.decorator.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,4 @@
    import { SetMetadata } from '@nestjs/common';

    // Decorator function to extract the roles data
    export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
  3. @sandeepsuvit sandeepsuvit created this gist Jul 29, 2019.
    7 changes: 7 additions & 0 deletions .env
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    ##
    # File properties
    ##
    UPLOAD_LOCATION=/Users/dummyusername/Documents/temp/nvaluate
    # Max 5Mb allowed
    MAX_FILE_SIZE=5
    MAX_FILE_COUNTS=20
    46 changes: 46 additions & 0 deletions abstract-attachment.dto.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    import { IsNotEmpty, IsBoolean, ValidateIf } from 'class-validator';
    import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';

    export class AbstractAttachmentDto {
    @ApiModelProperty()
    @IsNotEmpty()
    fileName: string;

    @ApiModelProperty()
    @IsNotEmpty()
    originalFileName: string;

    @ApiModelProperty()
    @IsNotEmpty()
    mediaType: string;

    @ApiModelProperty()
    @IsNotEmpty()
    fileSize: number;

    @ApiModelPropertyOptional({ default: false })
    @IsBoolean()
    isCommentAttachment: boolean = false;

    // Validate this field if the attachment is not for a comment
    @ApiModelProperty({ required: this.isCommentAttachment ? true : false })
    @ValidateIf(o => o.isCommentAttachment ? false : true)
    @IsNotEmpty()
    parent?: string;

    constructor(
    fileName: string,
    originalFileName: string,
    mediaType: string,
    fileSize: number,
    isCommentAttachment: boolean,
    parent?: string,
    ) {
    this.fileName = fileName;
    this.originalFileName = originalFileName;
    this.mediaType = mediaType;
    this.fileSize = fileSize;
    this.parent = parent;
    this.isCommentAttachment = isCommentAttachment;
    }
    }
    38 changes: 38 additions & 0 deletions abstract-attachment.service.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,38 @@
    import { Injectable } from '@nestjs/common';
    import { InjectModel } from '@nestjs/mongoose';
    import { Model } from 'mongoose';
    import { IAttachment } from '../../core/interfaces/attachment.interface';
    import { AbstractAttachmentDto } from './../dtos/abstract-attachment.dto';

    @Injectable()
    export class AbstractAttachmentService {
    constructor(
    @InjectModel('Attachment') private readonly attachmentModel: Model<IAttachment>,
    ) {}

    /**
    * Add attachment
    *
    * @param {any[]} files
    * @param {string} userId
    * @returns {Promise<IAttachment[]>}
    * @memberof AbstractAttachmentService
    */
    async addAttachments(files: any[], userId: string): Promise<IAttachment[]> {
    const attachments: IAttachment[] = [];

    for (const file of files) {
    // Get the file properties
    const { filename, originalname, mimetype, size } = file;

    // Form the attachment object
    let attachment = new AbstractAttachmentDto(filename, originalname, mimetype, size, true);

    // Collect all attachments
    attachments.push(new this.attachmentModel(attachment));
    }

    // Persist the data
    return await this.attachmentModel.insertMany(attachments);
    }
    }
    45 changes: 45 additions & 0 deletions common.controller.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,45 @@
    import { Body, Controller, Post, UploadedFiles, UseGuards, UseInterceptors, Get, Query } from '@nestjs/common';
    import { FilesInterceptor } from '@nestjs/platform-express/multer';
    import { ApiBadRequestResponse, ApiBearerAuth, ApiConsumes, ApiCreatedResponse, ApiForbiddenResponse, ApiImplicitFile, ApiOperation, ApiUseTags, ApiOkResponse } from '@nestjs/swagger';
    import { UploadTypesEnum } from '../core/enums/upload-types.enum';
    import { AuthUser } from './../shared/decorators/auth-user.decorator';
    import { AuthGuard } from './../shared/guards/auth.gaurd';
    import { RolesGuard } from './../shared/guards/roles.guard';
    import { MulterUtils } from './../shared/services/multer-utils.service';
    import { AbstractAttachmentService } from './services/abstract-attachment.service';

    /**
    * Controller to manage all common enpoints
    *
    * @export
    * @class CommonController
    */
    @ApiUseTags('common')
    @Controller('common')
    export class CommonController {
    constructor(
    private attachmentService: AbstractAttachmentService,
    ) {}

    /**
    * Upload attachments
    * Note: The controller method
    *
    * @param {string} authUserId
    * @param {any[]} files
    * @memberof CommonController
    */
    @Post('/actions/addAttachments')
    @ApiOperation({ title: 'Upload attachments' })
    @ApiCreatedResponse({ description: 'The record has been created successfully' })
    @ApiBadRequestResponse({ description: 'Bad Request' })
    @ApiForbiddenResponse({ description: 'Forbidden' })
    @ApiConsumes('multipart/form-data')
    @ApiImplicitFile({ name: 'files', required: true, description: 'File Attachments' })
    @UseInterceptors(FilesInterceptor('files', +process.env.MAX_FILE_COUNTS, MulterUtils.getConfig(UploadTypesEnum.ANY)))
    @ApiBearerAuth()
    @UseGuards(AuthGuard)
    uploadAttachments(@AuthUser('_id') authUserId: string, @UploadedFiles() files: any[]) {
    return this.attachmentService.addAttachments(files, authUserId);
    }
    }
    60 changes: 60 additions & 0 deletions multer-utils.service.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,60 @@
    import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
    import { existsSync, mkdirSync } from 'fs';
    import { diskStorage } from 'multer';
    import { extname } from 'path';
    import { v4 as uuid } from 'uuid';
    import { UploadTypesEnum } from '../../core/enums/upload-types.enum';

    /**
    * Multer utils
    *
    * @export
    * @class MulterUtils
    */
    @Injectable()
    export class MulterUtils {
    /**
    * Config for allowed files
    *
    * @static
    * @param {UploadTypeEnum} filesAllowed
    * @returns
    * @memberof MulterUtils
    */
    static getConfig(filesAllowed: UploadTypesEnum) {
    return {
    // Enable file size limits
    limits: {
    fileSize: +process.env.MAX_FILE_SIZE * 1024 * 1024,
    },
    // Check the mimetypes to allow for upload
    fileFilter: (req: any, file: any, cb: any) => {
    if (file.mimetype.match(`/(${filesAllowed})$`)) {
    // Allow storage of file
    cb(null, true);
    } else {
    // Reject file
    cb(new HttpException(`Unsupported file type ${extname(file.originalname)}`, HttpStatus.BAD_REQUEST), false);
    }
    },
    // Storage properties
    storage: diskStorage({
    // Destination storage path details
    destination: (req: any, file: any, cb: any) => {
    const uploadPath = process.env.UPLOAD_LOCATION;
    // Create folder if doesnt exist
    if (!existsSync(uploadPath)) {
    mkdirSync(uploadPath);
    }
    cb(null, uploadPath);
    },
    // File modification details
    filename: (req: any, file: any, cb: any) => {
    // Calling the callback passing the random name generated with
    // the original extension name
    cb(null, `${uuid()}${extname(file.originalname)}`);
    },
    }),
    };
    }
    }
    18 changes: 18 additions & 0 deletions multer.config.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,18 @@
    import { MulterModuleOptions, MulterOptionsFactory } from '@nestjs/platform-express/multer';

    /**
    * Multer options configuration
    *
    * Note: Place this file inside `src/config` folder
    *
    * @export
    * @class CustomMulterOptions
    * @implements {MulterOptionsFactory}
    */
    export class CustomMulterOptions implements MulterOptionsFactory {
    createMulterOptions(): MulterModuleOptions {
    return {
    dest: process.env.UPLOAD_LOCATION,
    };
    }
    }
    12 changes: 12 additions & 0 deletions upload-types.enum.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@

    /**
    * Upload types enum
    *
    * @export
    * @enum {number}
    */
    export enum UploadTypesEnum {
    ANY = 'jpg|jpeg|png|gif|pdf|docx|doc|xlsx|xls',
    IMAGES = 'jpg|jpeg|png|gif',
    DOCS = 'pdf|docx|doc|xlsx|xls',
    }