prisma\ (用于管理数据库迁移、定义数据模型和数据填充)
migrations\ (日志记录,不用管)
schema.prisma (定义数据模型)
seed.ts (用于填充数据库初始数据的文件)
src\
auth\ (包含处理用户认证的模块代码)
dto\ (定义数据传输对象)
register.dto.ts (数据对象)
auth.controller.ts (处理路由等)
auth.module.ts (模块)
auth.service.ts (逻辑)
common\ (包含通用的功能代码)
rules\ (自定义验证规则)
is-confirm.rule.ts
is-not-exists.rule.ts
validate.ts (通用数据验证)
prisma\
prisma.module.ts (模块)
prisma.service.ts (处理与Prisma数据库交互的服务)
app.module.ts (模块)
main.ts (主入口)
transform.inteceptor.ts (响应拦截器)
——————————————————————————————————————
定义数据库模型
- generator client {
- provider = "prisma-client-js"
- }
-
- datasource db {
- provider = "mysql"
- url = env("DATABASE_URL")
- }
-
- model user {
- id Int @id @default(autoincrement()) @db.UnsignedInt
- name String @unique
- password String
- }
-
- model article {
- id Int @id @default(autoincrement()) @db.UnsignedInt
- title String
- content String @db.Text
- }
填充数据库数据
- import { PrismaClient } from "@prisma/client"
- import { hash } from "argon2"
- import { Random } from "mockjs"
-
- const prisma = new PrismaClient() //注册Prisma
- async function run() {
- await prisma.user.create({ //往user表里面插入数据
- data: {
- name: "admin",
- password: await hash("admin8888") //转成hash
- }
- })
- for (let i = 0; i < 50; i++) { //填充50组
- await prisma.article.create({ //往article表里面插入数据
- data: {
- title: Random.ctitle(10, 30), //随机题目
- content: Random.cparagraph(10, 20), //随机内容
- }
- })
- }
-
- }
- run()
——————————————————————————————————————
- import { Module } from '@nestjs/common';
- import { AuthModule } from './auth/auth.module'; //引入验证模块
- import { PrismaModule } from './prisma/prisma.module'; //引入prisma模块
-
-
- @Module({
- imports: [ AuthModule , PrismaModule ], //插入
- })
- export class AppModule {}
——————————————————————————————————————
auth
dto
- import { IsNotEmpty } from "class-validator"; //引入默认不为空验证
- import { IsNotExistsRule } from "../../common/rules/is-not-exists.rule"; //引入自定义验证
- import { IsConfiemRule } from "../../common/rules/is-confirm.rule"; //引入自定义验证
-
- export default class RegisterDto {
- @IsNotEmpty({ message:'用户名不能为空' }) //验证规则
- @IsNotExistsRule("user" , { message: "用户已经存在" }) //验证规则
- name:string; //类型
-
- @IsNotEmpty({ message:'密码不能为空' })
- @IsConfiemRule({ message: "两次密码不一致" })
- password:string
-
- @IsNotEmpty({message: "确认密码不能为空"})
- password_confirm: string
- }
- import { Controller , Body , Post } from '@nestjs/common'
- import { AuthService } from './auth.service';
- import RegisterDto from './dto/register.dto'; //引入验证规则
-
- @Controller()
- export class AuthController{
- constructor(private auth: AuthService) {}
-
- @Post('register') //post请求,路由为register
- login(@Body() dto: RegisterDto) { //获取body数据 为dto : 验证规则
- return this.auth.register(dto) //执行auth的register函数
- }
- }
- import { Injectable } from '@nestjs/common'
- import RegisterDto from './dto/register.dto';
- import { PrismaService } from './../prisma/prisma.service'; //引入全局配置prisma
- import { hash } from 'argon2';
- import { JwtService } from '@nestjs/jwt';
-
- @Injectable()
- export class AuthService {
- constructor(private prisma:PrismaService , private jwt: JwtService){}
-
- async register(dto: RegisterDto){ //验证通过后执行这里
- const user = await this.prisma.user.create({ //等候创建
- data:{
- name: dto.name,
- password: await hash(dto.password)
- }
- })
- return this.token(user); //执行token函数
- }
-
- private async token({ id , name }){
- return {
- token: await this.jwt.signAsync({ //执行配置好后的jwt
- name ,
- sub: id
- })
- }
- }
- }
- import { Module } from '@nestjs/common'
- import { AuthService } from './auth.service'
- import { AuthController } from './auth.controller'
- import { JwtModule } from '@nestjs/jwt'
- import { ConfigModule, ConfigService } from '@nestjs/config'
-
- @Module({
- imports: [ //TODO 配置JWT
- JwtModule.registerAsync({
- imports: [ConfigModule],
- inject: [ConfigService],
- useFactory: (config: ConfigService) => {
- return {
- secret: config.get('TOKEN_SECRET'), //密钥在.env里配置
- signOptions: { expiresIn: '60d' } //持续时间
- }
- },
- })
- ], //END
- controllers: [AuthController], //引入控制器
- providers: [AuthService] //引入函数
- })
-
- export class AuthModule{}
common
rules
- import { PrismaClient } from '@prisma/client'
- import { registerDecorator , ValidationArguments , ValidationOptions } from 'class-validator'
-
- //表字段是否唯一
- export function IsConfiemRule( //这里定义规则名称
- validationOptions?: ValidationOptions
- ) {
- return function (object: Record<string , any>, propertyName: string) {
- registerDecorator({
- name: 'IsConfiemRule', //同上
- target: object.constructor,
- propertyName: propertyName,
- constraints: [],
- options: validationOptions,
- validator: {
- async validate(value: string, args: ValidationArguments) {
- //TODO
- return Boolean(value == args.object[`${args.property}_confirm`]) //true为通过,false为不通过
- //END
- }
- }
- })
- }
- }
- import { PrismaClient } from '@prisma/client'
- import { registerDecorator , ValidationArguments , ValidationOptions } from 'class-validator'
-
- //表字段是否唯一
- export function IsNotExistsRule(
- table: string,
- validationOptions?: ValidationOptions
- ) {
- return function (object: Record<string , any>, propertyName: string) {
- registerDecorator({
- name: 'IsNotExistsRule',
- target: object.constructor,
- propertyName: propertyName,
- constraints: [table],
- options: validationOptions,
- validator: {
- async validate(value: string, args: ValidationArguments) {
- //TODO
- const prisma = new PrismaClient
- const res = await prisma[table].findFirst({
- where: {
- [args.property]: value
- }
- })
- return !Boolean(res)
- //END
- }
- }
- })
- }
- }
- //同上
- import { HttpException, HttpStatus, ValidationPipe } from "@nestjs/common";
- import { ValidationError } from "class-validator";
-
- export default class Validate extends ValidationPipe {
- protected flattenValidationErrors(validationErrors: ValidationError[]): string[] {
- const messages = {}
- validationErrors.forEach(error => { //遍历出必要错误返回给前端
- messages[error.property] = Object.values(error.constraints)[0];
- })
-
- throw new HttpException({ //返回给前端的错误
- code: 422,
- messages
- }, HttpStatus.UNPROCESSABLE_ENTITY);
- }
- }
prisma
- import { Global, Module } from '@nestjs/common'
- import { PrismaService } from './prisma.service';
-
-
- @Global() // 全局模块
- @Module({
- providers: [PrismaService],
- exports: [PrismaService]
- })
-
- export class PrismaModule{}
- import { PrismaClient } from '@prisma/client'
- import { Injectable } from '@nestjs/common'
-
- @Injectable()
- export class PrismaService extends PrismaClient{
- constructor(){
- super({
- log:['query']
- })
- }
- }
- import { CallHandler , ExecutionContext , Injectable , NestInterceptor } from '@nestjs/common'
- import { map } from 'rxjs/operators'
-
- @Injectable()
- export class TransformInterceptor implements NestInterceptor { //修改一下数据格式
- intercept(context: ExecutionContext, next: CallHandler) {
- return next.handle().pipe(
- map((data) => {
- return {
- data
- }
- })
- )
- }
- }
- import { NestFactory } from '@nestjs/core';
- import { AppModule } from './app.module';
- import Validate from './common/validate';
- import { TransformInterceptor } from './transform.inteceptor';
-
- async function bootstrap() {
- const app = await NestFactory.create(AppModule);
- app.useGlobalPipes(new Validate()) //返回给前端的错误数据
- app.useGlobalInterceptors(new TransformInterceptor()) //返回给前端的正确数据(响应拦截器)
- await app.listen(3000); //监听的端口号
- }
- bootstrap();