From 8eda01f86ee94b5862598e7912f3e7cb2c545368 Mon Sep 17 00:00:00 2001 From: Jeremy Yin Date: Sat, 29 Jun 2019 16:49:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E7=94=A8=E6=88=B7=EF=BC=9B?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=8D=95=E4=B8=AA=E7=94=A8=E6=88=B7=EF=BC=9B?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E5=AD=97=E6=AE=B5=E6=8E=92=E9=99=A4=EF=BC=9B?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E5=8A=A0=E5=AF=86=EF=BC=9B=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=AF=86=E7=A0=81=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 3 ++ src/modules/user/user.controller.ts | 29 ++++++++++++++++-- src/modules/user/user.dto.ts | 9 ++++++ src/modules/user/user.entity.ts | 32 ++++++++++++++++++++ src/modules/user/user.module.ts | 5 ++++ src/modules/user/user.service.ts | 46 +++++++++++++++++++++++++++-- yarn.lock | 25 +++++++++++++++- 7 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 src/modules/user/user.dto.ts create mode 100644 src/modules/user/user.entity.ts diff --git a/package.json b/package.json index 72b13f9..e6a6aa0 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,9 @@ "@nestjs/core": "^6.0.0", "@nestjs/platform-express": "^6.0.0", "@nestjs/typeorm": "^6.1.2", + "@types/bcrypt": "^3.0.0", + "bcrypt": "^3.0.6", + "class-transformer": "^0.2.3", "mysql": "^2.17.1", "reflect-metadata": "^0.1.12", "rimraf": "^2.6.2", diff --git a/src/modules/user/user.controller.ts b/src/modules/user/user.controller.ts index ad8c2a6..2428bf6 100644 --- a/src/modules/user/user.controller.ts +++ b/src/modules/user/user.controller.ts @@ -1,4 +1,27 @@ -import { Controller } from '@nestjs/common'; +import { Controller, Post, Body, Get, Param, UseInterceptors, ClassSerializerInterceptor, Put } from '@nestjs/common'; +import { UserService } from './user.service'; +import { UserDto, UpdatePasswordDto } from './user.dto'; -@Controller('user') -export class UserController {} +@Controller('users') +export class UserController { + constructor( + private readonly userService: UserService, + ) {} + + @Post() + async store(@Body() data: UserDto) { + return await this.userService.store(data); + } + + @Get(':id') + @UseInterceptors(ClassSerializerInterceptor) + async show(@Param('id') id: string) { + return await this.userService.show(id); + } + + @Put(':id/password') + @UseInterceptors(ClassSerializerInterceptor) + async updatePassword(@Param('id') id: string, @Body() data: UpdatePasswordDto) { + return await this.userService.updatePassword(id, data) + } +} diff --git a/src/modules/user/user.dto.ts b/src/modules/user/user.dto.ts new file mode 100644 index 0000000..adab684 --- /dev/null +++ b/src/modules/user/user.dto.ts @@ -0,0 +1,9 @@ +export class UserDto { + readonly username: string; + readonly password: string; +} + +export class UpdatePasswordDto { + readonly password: string; + readonly newPassword: string; +} \ No newline at end of file diff --git a/src/modules/user/user.entity.ts b/src/modules/user/user.entity.ts new file mode 100644 index 0000000..04953c5 --- /dev/null +++ b/src/modules/user/user.entity.ts @@ -0,0 +1,32 @@ +import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, BeforeInsert, BeforeUpdate } from 'typeorm'; +import * as bcrypt from 'bcrypt'; +import { Exclude } from 'class-transformer'; + +@Entity() +export class User { + @PrimaryGeneratedColumn() + id: number; + + @Column('varchar', { unique: true }) + username: string; + + @Column('longtext', { nullable: true }) + @Exclude() + password: string; + + @CreateDateColumn() + created: Date; + + @UpdateDateColumn() + updated: Date; + + @BeforeInsert() + @BeforeUpdate() + async hashPassword() { + this.password = await bcrypt.hash(this.password, 10); + } + + async comparePassword(password: string) { + return await bcrypt.compare(password, this.password); + } +} \ No newline at end of file diff --git a/src/modules/user/user.module.ts b/src/modules/user/user.module.ts index b3801b5..3979957 100644 --- a/src/modules/user/user.module.ts +++ b/src/modules/user/user.module.ts @@ -1,8 +1,13 @@ import { Module } from '@nestjs/common'; import { UserController } from './user.controller'; import { UserService } from './user.service'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { User } from './user.entity'; @Module({ + imports: [ + TypeOrmModule.forFeature([User]), + ], controllers: [UserController], providers: [UserService] }) diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts index 668a7d6..e2e7fc1 100644 --- a/src/modules/user/user.service.ts +++ b/src/modules/user/user.service.ts @@ -1,4 +1,46 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { User } from './user.entity'; +import { UserDto, UpdatePasswordDto } from './user.dto'; @Injectable() -export class UserService {} +export class UserService { + constructor( + @InjectRepository(User) + private readonly userRepository: Repository, + ) { } + + async store(data: UserDto) { + const { username } = data; + const user = await this.userRepository.findOne({ username }); + if (user) { + throw new BadRequestException('用户已经存在'); + } + const entity = await this.userRepository.create(data); + await this.userRepository.save(entity); + return entity; + } + + async show(id: string) { + const entity = await this.userRepository.findOne(id); + if (!entity) { + throw new NotFoundException('没有找到用户'); + } + return entity; + } + + async updatePassword(id: string, data: UpdatePasswordDto) { + const { password, newPassword } = data; + const entity = await this.userRepository.findOne(id) + if (!entity) { + throw new NotFoundException('没有找到用户') + } + const match = await entity.comparePassword(password) + if (!match) { + throw new BadRequestException('密码错误') + } + entity.password = newPassword + return await this.userRepository.save(entity) + } +} diff --git a/yarn.lock b/yarn.lock index a968ae4..c146f31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -72,6 +72,11 @@ consola "^2.3.0" node-fetch "^2.3.0" +"@types/bcrypt@^3.0.0": + version "3.0.0" + resolved "https://registry.npm.taobao.org/@types/bcrypt/download/@types/bcrypt-3.0.0.tgz#851489a9065a067cb7f3c9cbe4ce9bed8bba0876" + integrity sha1-hRSJqQZaBny388nL5M6b7Yu6CHY= + "@types/body-parser@*": version "1.17.0" resolved "https://registry.npm.taobao.org/@types/body-parser/download/@types/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" @@ -612,6 +617,14 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bcrypt@^3.0.6: + version "3.0.6" + resolved "https://registry.npm.taobao.org/bcrypt/download/bcrypt-3.0.6.tgz#f607846df62d27e60d5e795612c4f67d70206eb2" + integrity sha1-9geEbfYtJ+YNXnlWEsT2fXAgbrI= + dependencies: + nan "2.13.2" + node-pre-gyp "0.12.0" + bignumber.js@7.2.1: version "7.2.1" resolved "https://registry.npm.taobao.org/bignumber.js/download/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" @@ -837,6 +850,11 @@ ci-info@^1.5.0: resolved "https://registry.npm.taobao.org/ci-info/download/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" integrity sha1-LKINu5zrMtRSSmgzAzE/AwSx5Jc= +class-transformer@^0.2.3: + version "0.2.3" + resolved "https://registry.npm.taobao.org/class-transformer/download/class-transformer-0.2.3.tgz#598c92ca71dcca73f91ccb875d74a3847ccfa32d" + integrity sha1-WYySynHcynP5HMuHXXSjhHzPoy0= + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -3371,6 +3389,11 @@ mz@^2.4.0: object-assign "^4.0.1" thenify-all "^1.0.0" +nan@2.13.2: + version "2.13.2" + resolved "https://registry.npm.taobao.org/nan/download/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" + integrity sha1-9R3Hrma6fV1V4ebU2AkugCya7+c= + nan@^2.12.1: version "2.14.0" resolved "https://registry.npm.taobao.org/nan/download/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" @@ -3448,7 +3471,7 @@ node-notifier@^5.2.1: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@^0.12.0: +node-pre-gyp@0.12.0, node-pre-gyp@^0.12.0: version "0.12.0" resolved "https://registry.npm.taobao.org/node-pre-gyp/download/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" integrity sha1-ObpLsUOdoDApX4meO1ILd4V2YUk=