上一章中, 我们完成了鉴权功能, 也就是 Auth 模块, 顺便简单实现了下注册和登录功能. 这一章我们就来正式的将登录和实现功能做完, 含有完整的数据校验和转化.
在正式的开始完善功能之前, 我们现清理重构一下已有的代码.
我们上一张的登录和注册是写在 app.controller.ts
中的, 如果所有的路由都写在这里的话就会比较杂乱, 所以我们将它移动到 Auth 模块下.
首先生成 AuthController
然后将 /auth/register
和 /auth/login
移到 AuthController 下
auth.controller.ts1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import { Body, Controller, Post, Request, UseGuards } from '@nestjs/common' import { AuthGuard } from '@nestjs/passport' import { UserService } from '../user/user.service' import { AuthService } from './auth.service'
@Controller('auth') export class AuthController { constructor( private readonly userService: UserService, private readonly authService: AuthService, ) {}
@Post('/register') async register( @Body() requestBody: { email: string; username: string; password: string }, ) { const user = await this.userService.createUser(requestBody) const token = this.authService.generateToken(user.id, user.username) return { user: { ...user, token }, } }
@UseGuards(AuthGuard('local')) @Post('/login') async login(@Request() req) { const { user } = req const token = this.authService.generateToken(user.id, user.username) return { user: { ...user, token }, } } }
|
顺便也移动下测试代码, 这里就不再赘述了.
我们在 Auth 模块下添加一个 dto 目录, 然后新建一个 src/auth/dto/register.dto.ts
用于存储 Data Transfer Object
register.dto.ts1 2 3 4 5
| export class RegisterDto { readonly email: string readonly username: string readonly password: string }
|
同理,增加 src/auth/dto/login.dto.ts
, 这里就不在赘述了。
然后在 register 方法中修改入参
auth.controller.ts1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| export class AuthController { @Post('/register') async register(@Body() registerDto: RegisterDto) { const user = await this.userService.createUser(registerDto) const token = this.authService.generateToken(user.id, user.username) return { user: { ...user, token }, } } @UseGuards(AuthGuard('local')) @Post('/login') async login(@Body() loginDto: LoginDto) { return loginDto }
}
|
nest 推荐我们使用class-validator
做类型验证, 首先安装这个依赖
1
| yarn add class-validator class-transformer
|
然后在 main.ts
中加入自动验证的 pipe
main.ts1 2 3 4 5 6 7 8 9 10 11
| import { NestFactory } from '@nestjs/core' import { AppModule } from './app.module' + import { ValidationPipe } from '@nestjs/common'
async function bootstrap () { const app = await NestFactory.create(AppModule) + app.useGlobalPipes(new ValidationPipe()) await app.listen(3000) }
bootstrap()
|
然后在 DTO 中加入注解
register.dto.ts1 2 3 4 5 6 7 8 9 10 11 12
| import { IsEmail, IsNotEmpty } from 'class-validator'
export class RegisterDto { @IsEmail() readonly email: string
@IsNotEmpty() readonly username: string
@IsNotEmpty() readonly password: string }
|
为了保证我们能有正确的返回值,我们需要自己声明 Response Object
在 auth
下建立 auth.interface.ts
auth.interface.ts1 2 3 4 5 6 7 8 9 10 11
| export interface AuthData { username: string email: string bio: string image?: string token: string }
export interface AuthRO { user: AuthData }
|
然后在 controller 里补充 DTO 和返回值类型
auth.controller.ts1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @Controller('auth') export class AuthController { constructor ( private readonly userService: UserService, private readonly authService: AuthService, ) {}
@Post('/register') + async register (@Body() registerDto: RegisterDto): Promise<AuthRO> { const user = await this.userService.createUser(requestBody) const token = this.authService.generateToken(user.id, user.username) return { user: { ...user, token }, } }
@UseGuards(AuthGuard('local')) @Post('/login') + async login (@Body() loginDto: LoginDto): Promise<AuthRO> { return loginDto } }
|