Skip to content

Latest commit

 

History

History
210 lines (169 loc) · 5.36 KB

README.md

File metadata and controls

210 lines (169 loc) · 5.36 KB

Nest Logo

Command

Create resource

nest g resource [name_resource] [--no-spec]

file .env

PORT=8081
MONGODB_URI=mongodb://root:123456@localhost:27017/quyenlee?authSource=admin
JWT_SECRET_KEY=aa4f8e2b-0d8a-49d1-be30-f532d78fbb56
JWT_ACCESS_TOKEN_EXPIRES_IN=1000d

file .env.local

MAILDEV_INCOMING_USER=
MAILDEV_INCOMING_PASS=

Change dynamic port get from .env in main.ts

import { ConfigService } from '@nestjs/config';

const configService = app.get(ConfigService);
const port = configService.get<number>('PORT');
await app.listen(port);

Connect mongodb

import { ConfigModule, ConfigService } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';

@Module({
    imports: [
        UsersModule,
        ConfigModule.forRoot({ isGlobal: true, envFilePath: ['.env', '.env.local'] }),  // TODO: Khai bao env file path app read
        MongooseModule.forRootAsync({
            imports: [ConfigModule],
            useFactory: async (configService: ConfigService) => ({
                uri: configService.get<string>('MONGODB_URI'),
            }),
            inject: [ConfigService],
        }),
    ],
    controllers: [AppController],
    providers: [AppService],
})

schemas (in mongodb) is entities (SQL)

A simple schema

import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

export type UserDocument = HydratedDocument<User>;

@Schema()
export class User {
    @Prop()
    name: string;

    @Prop()
    age: number;

    @Prop({ default: UserRoles.USER })
    role: UserRoles;

    @Prop({ default: AccountType.NORMAL })
    accountType: AccountType;
}

export const UserSchema = SchemaFactory.createForClass(User);

Auth Login JWT

import { JwtModule } from '@nestjs/jwt';
import { ConfigModule, ConfigService } from '@nestjs/config';

@Module({
    imports: [
        UsersModule,
        JwtModule.registerAsync({
            imports: [ConfigModule],
            useFactory: async (configService: ConfigService) => ({
                global: true,
                secretOrPrivateKey: configService.get<string>('JWT_SECRET_KEY'),
                signOptions: {
                    expiresIn: configService.get<string>('JWT_ACCESS_TOKEN_EXPIRES_IN'),
                },
            }),
            inject: [ConfigService],
        }),
    ],
    controllers: [AuthController],
    providers: [AuthService],
    exports: [AuthService],
})

Authentication

Should use Passport.

npm i --save-exact @nestjs/[email protected] [email protected] [email protected]
npm i --save-dev @types/passport-local
npm i --save-exact @nestjs/[email protected] [email protected]
npm i --save-dev @types/passport-jwt

Guard and strategy

Each guard have strategy: Ex:

  • JwtAuthGuard have JwtStrategy
  • LocalAuthGuard have LocalStrategy

In controller when use @UseGuards(LocalAuthGuard | JwtAuthGuard) the request return data user by function validate in LocalStrategy | JwtStrategy

Send email authen

npm i --save-exact @nestjs-modules/[email protected] [email protected] [email protected]
npm i --save-dev @types/nodemailer

change config in nest-cli.json

{
    "$schema": "https://json.schemastore.org/nest-cli",
    "collection": "@nestjs/schematics",
    "sourceRoot": "src",
    "compilerOptions": {
        "deleteOutDir": true,
        "assets": ["mail/templates/**/*"] // complie template .hbs
    },
    "watchAssets": true
}

config mail module in app.module.ts

        MailerModule.forRootAsync({
            imports: [ConfigModule],
            useFactory: async (configService: ConfigService) => ({
                transport: {
                    host: 'smtp.gmail.com',
                    port: 465,
                    // ignoreTLS: true,
                    secure: true,
                    auth: {
                        user: configService.get<string>('MAILDEV_INCOMING_USER'),
                        pass: configService.get<string>('MAILDEV_INCOMING_PASS'),
                    },
                },
                defaults: {
                    from: '"No Reply" <no-reply@localhost>',
                },
                // preview: true,
                template: {
                    dir: process.cwd() + '/src/mail/templates/',
                    adapter: new HandlebarsAdapter(), // or new PugAdapter() or new EjsAdapter()
                    options: {
                        strict: true,
                    },
                },
            }),
            inject: [ConfigService],
        }),

And send email when register acount

this.mailerService
    .sendMail({
        to: newUser.email,
        subject: 'Activate your account',
        template: 'register', //where: src/mail/templates/register.hbs
        context: {
            name: newUser.name || newUser.email,
            activationCode: codeId,
        },
    })
    .then(() => {})
    .catch((e) => {
        console.log('co loi roi', e);
    });