Nest.js权限管理系统开发(七)用户注册

创建user模块

先用nest的命令创建一个 user 模块,

nest g res user

实现user实体

然后就生成了 user 模块,在它的实体中创建一个用户表user.entity.ts,包含 id、用户名、密码,头像、邮箱等等一些字段:

@Entity('sys_user')
export class UserEntity {@Expose()@ApiProperty({ type: String, description: 'id' })@PrimaryGeneratedColumn({ type: 'bigint' })public id: string@Exclude({ toPlainOnly: true }) // 输出屏蔽密码@Column({ type: 'varchar', length: 200, nullable: false, comment: '用户登录密码' })public password: string@Exclude({ toPlainOnly: true }) // 输出屏蔽盐@Column({ type: 'varchar', length: 200, nullable: false, comment: '盐' })public salt: string@Expose()@ApiProperty({ type: String, description: '用户登录账号' })@Column({ type: 'varchar', length: 32, comment: '用户登录账号' })public account: string@Expose()@ApiProperty({ type: String, description: '手机号' })@Column({ type: 'varchar', name: 'phone_num', default: '', length: 20, comment: '用户手机号码' })public phoneNum: string@Expose()@ApiProperty({ type: String, description: '邮箱' })@Column({ type: 'varchar', comment: '邮箱地址', default: '' })public email: string....
}

实现注册路由

接下来看一下注册基本逻辑的实现。注册无非就是新增一个用户,在user.controller.ts规定一个路由/user/register接收用户传来的参数

@Post('register')@ApiOperation({ summary: '用户注册' })@ApiResult(UserEntity)@AllowAnon()async create(@Body() user: CreateUserDto): Promise<UserEntity> {return await this.userService.create(user)}

并将CreateUserDto实现如下:

export class CreateUserDto {@ApiProperty({ description: '用户账号' })@IsString({ message: 'account 类型错误,正确类型 string' })@IsNotEmpty({ message: 'account 不能为空' })@MinLength(5, { message: '账号至少5个字符' })@MaxLength(20, { message: '账号最多20个字符' })readonly account: string@ApiProperty({ description: '密码' })@IsString({ message: 'password 类型错误,正确类型 string' })@IsNotEmpty({ message: 'password 不能为空' })password: string@ApiProperty({ description: '手机号', required: false })@IsString({ message: 'phoneNum 类型错误,正确类型 string' })@IsMobilePhone('zh-CN', { strictMode: false }, { message: '请输入正确的手机号' })@IsOptional()readonly phoneNum?: string@ApiProperty({ description: '邮箱', required: false })@IsString({ message: 'email 类型错误,正确类型 string' })@IsEmail()@IsOptional()readonly email?: string@ApiProperty({ description: '确认密码' })@IsString({ message: ' confirmPassword 类型错误,正确类型 string' })readonly confirmPassword: string@ApiProperty({ description: '头像', required: false })@IsString({ message: 'avatar 类型错误,正确类型 string' })@IsOptional()readonly avatar?: string
}

实现注册逻辑

user.service.ts写注册的逻辑:

  /** 创建用户 */async create(dto: CreateUserDto): Promise<UserEntity> {if (dto.password !== dto.confirmPassword)throw new ApiException(ApiErrorCode.USER_PASSWORD_INVALID, '两次输入密码不一致,请重试')// 防止重复创建 startif (await this.findOneByAccount(dto.account))throw new ApiException(ApiErrorCode.USER_CREATE_EXISTING, '帐号已存在,请调整后重新注册!')if (await this.userRepo.findOne({ where: { phoneNum: dto.phoneNum } }))throw new ApiException(ApiErrorCode.USER_CREATE_EXISTING, '当前手机号已存在,请调整后重新注册')if (await this.userRepo.findOne({ where: { email: dto.email } }))throw new ApiException(ApiErrorCode.USER_CREATE_EXISTING, '当前邮箱已存在,请调整后重新注册')// 防止重复创建 endconst salt = await genSalt()dto.password = await hash(dto.password, salt)// plainToInstance  忽略转换 @Exclude 装饰器const user = plainToInstance(UserEntity, { salt, ...dto }, { ignoreDecorators: true })const result = await this.userManager.transaction(async (transactionalEntityManager) => {return await transactionalEntityManager.save<UserEntity>(user)})return result}

这里我们对提交的数据做一些判断,并对一些账号已存在的情况抛出具体的异常,来提醒用户。由于我们不能存储密码的明文,这里使用bcryptjs来生成salt,然后对密码进行hash之后,再将salt和hash值同用户信息一起存入数据库。需要安装依赖库:

npm i bcryptjs
npm i --save-dev @types/bcryptjs

测试注册接口

模拟一下注册请求:

发现注册成功了:

返回数据修复

但是这里有个问题,返回的数据里既包含了存入数据库的salt和password,也包含了仅用于数据验证的confirmPassword。我们要将返回类型修改为Partial<UserEntity>,并且利用 class-transformer将salt、password和confirmPassword排除在外,实现修改如下:

  /** 创建用户 */async create(dto: CreateUserDto): Promise<Partial<UserEntity>> {if (dto.password !== dto.confirmPassword)throw new ApiException(ApiErrorCode.USER_PASSWORD_INVALID, '两次输入密码不一致,请重试')// 防止重复创建 startif (await this.findOneByAccount(dto.account))throw new ApiException(ApiErrorCode.USER_CREATE_EXISTING, '帐号已存在,请调整后重新注册!')if (await this.userRepo.findOne({ where: { phoneNum: dto.phoneNum } }))throw new ApiException(ApiErrorCode.USER_CREATE_EXISTING, '当前手机号已存在,请调整后重新注册')if (await this.userRepo.findOne({ where: { email: dto.email } }))throw new ApiException(ApiErrorCode.USER_CREATE_EXISTING, '当前邮箱已存在,请调整后重新注册')// 防止重复创建 endconst salt = await genSalt()dto.password = await hash(dto.password, salt)// plainToInstance  忽略转换 @Exclude 装饰器const user = plainToInstance(UserEntity, { salt, ...dto }, { ignoreDecorators: true })const result = await this.userManager.transaction(async (transactionalEntityManager) => {return await transactionalEntityManager.save<UserEntity>(user)})//去掉salt,password,confirmPasswordreturn plainToInstance(UserEntity, instanceToPlain(result), { excludeExtraneousValues: true })}

再请求一下,发现返回接口里不包含敏感信息了:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/705937.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【底层学习】HashMap源码学习

成员变量 // 默认初始容量 就是16 static final int DEFAULT_INITIAL_CAPACITY 1 << 4; // aka 16// 最大容量 static final int MAXIMUM_CAPACITY 1 << 30;// 默认加载因子0.75 static final float DEFAULT_LOAD_FACTOR 0.75f;// 树化阈值&#xff08;链表转为…

IT廉连看——C语言——结构体

IT廉连看——C语言——结构体 一、结构体的声明 1.1 结构的基础知识 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.2 结构的声明 struct tag {member-list; }variable-list; 例如描述一个学生&#xff1a;typedef struct Stu…

SQL Server添加用户登录

我们可以模拟一下让这个数据库可以给其它人使用 1、在计算机中添加一个新用户TeacherWang 2、在Sql Server中添加该计算机用户的登录权限 exec sp_grantlogin LAPTOP-61GDB2Q7\TeacherWang -- 之后这个计算机用户也可以登录数据库了 3、添加数据库的登录用户和密码&#xff0…

进程与线程之线程

首先exec函数族是进程中的常用函数&#xff0c;可以利用另外的进程空间执行不同的程序&#xff0c;在之前的fork创建子进程中会完全复制代码数据段等&#xff0c;而exec函数族则可以实现子进程实现不同的代码 int execl(const char *path, const char *arg, ... …

远超 IVF_FLAT、HNSW,ScaNN 索引算法赢在哪?

Faiss 实现的 ScaNN&#xff0c;又名 FastScan&#xff0c;它使用更小的 PQ 编码和相应的指令集&#xff0c;可以更为友好地访问 CPU 寄存器&#xff0c;展示出优秀的索引性能。 Milvus 从 2.3 版本开始&#xff0c;在 Knowhere 中支持了 ScaNN 算法&#xff0c;在各项 benchma…

JavaAPI常用类03

目录 java.lang.Math Math类 代码 运行 Random类 代码 运行 Date类/Calendar类/ SimpleDateFormat类 Date类 代码 运行 Calendar类 代码 运行 SimpleDateFormat类 代码一 运行 常用的转换符 代码二 运行 java.math BigInteger 代码 运行 BigDecimal …

数字孪生的技术开发平台

数字孪生的开发平台可以基于各种软件和硬件工具来实现&#xff0c;这些平台提供了丰富的功能和工具&#xff0c;帮助开发人员构建、部署和管理数字孪生系统&#xff0c;根据具体的需求和技术要求&#xff0c;开发人员可以选择合适的平台进行开发工作。以下列举了一些常见的数字…

将python两个版本添加环境变量(Mac版)

在运行程序的时候&#xff0c;可能不知道选择哪个版本的程序来执行&#xff0c;先添加环境变量&#xff0c;然后进行选择。 1、查看python安装路径 which python which python3 来查看各个版本的安装位置 2、编辑环境变量配置文件 Macos使用默认终端的shell是bash&#xff0c…

c入门第二十三篇: 学生成绩管理系统优化(支持远程操作)

前言 师弟高兴的说道&#xff1a;“师兄&#xff0c;你猜我今天上课看见谁了&#xff1f;” 我&#xff1a;“谁呢&#xff1f;” 师弟&#xff1a;“程夏&#xff0c;没想到&#xff0c;她竟然来旁听我们计算机系的课程了。虽然我从前门进去的&#xff0c;但是我还是一眼就看…

swing jdk版本导致的显示尺寸不一致问题

Java Swing JFrame size different after upgrade to JRE11 from JRE 7 or 8. How can I make the frame size consistent? - Stack Overflow 从 JRE 7 或 8 升级到 JRE11 后&#xff0c;Java Swing JFrame 大小不同。如何使帧大小一致&#xff1f; - IT工具网 设置虚拟机选项…

01背包问题:组合问题

01背包问题&#xff1a;组合问题 题目 思路 将nums数组分成left和right两组&#xff0c;分别表示相加和相减的两部分&#xff0c;则&#xff1a; left - right targetleft right sum 进而得到left为确定数如下&#xff0c;且left必须为整数&#xff0c;小数表示组合不存在&…

28. 找出字符串中第一个匹配项的下标(力扣LeetCode)

文章目录 28. 找出字符串中第一个匹配项的下标题目描述暴力KMP算法 28. 找出字符串中第一个匹配项的下标 题目描述 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。…

mapbox高德地图与相机

mapbox高德地图与相机 本案例使用Mapbox GL JavaScript库创建高德地图。 演示效果引入 CDN 链接地图显示 创建地图实例定义地图数据源配置地图图层 设置地图样式实现代码 1. 演示效果 2. 引入 CDN 链接 <script src"https://api.mapbox.com/mapbox-gl-js/v2.12.0/mapb…

项目实战:Qt监测操作系统cpu温度v1.1.0(支持windows、linux、国产麒麟系统)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/136277231 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结…

全面升级!Apache HugeGraph 1.2.0版本发布

图数据库以独特的数据管理和分析能力&#xff0c;在企业数智化转型的过程中正在成为数据治理的核心&#xff0c;根据IDC调研显示&#xff0c;95%的企业认为图数据库是重要的数据管理工具&#xff0c;超过65%的厂商认为在业务上图数据库优于其他选择&#xff0c;尤其是在金融风控…

Unity零基础到进阶 | Unity中的 RectTransformUtility 方法整理汇总

Unity零基础到进阶 ☀️| RectTransformUtility 方法整理汇总一、RectTransformUtility 官方文档1.1 RectTransformUtility.CalculateRelativeRectTransformBounds&#xff08;重&#xff09;1.2 RectTransformUtility.FlipLayoutAxes1.3 RectTransformUtility.FlipLayoutOnAxi…

观察者模式与发布订阅模式

观察者模式 定义&#xff1a; 观察者模式是一种行为型设计模式&#xff0c;定义对象间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都得到通知并被自动更新。 结构图&#xff1a; ES6简易代码实现&#xff1a; //ts环境下…

Nginx——安装和反向代理

Nginx安装与应用 1.1 Nginx介绍 Nginx 是一个高性能的HTTP和反向代理服务器,特点是占有内存少&#xff0c;并发能力强 Nginx可以作为静态页面的web服务器&#xff0c;同时还支持CGI协议的动态语言&#xff0c;比如perl、php等。但是不支持java。Java程序只能通过与tomcat配合…

谷歌AI发展史:从阿尔法围棋到Gemini与Gemma的开源创新

谷歌一直是人工智能领域的重要推动者。本文将回顾谷歌AI的发展历程&#xff0c;从阿尔法围棋到现如今的Gemini和Gemma&#xff0c;探讨谷歌在人工智能领域的重大突破和创新。 1. 引言 在计算机科学领域&#xff0c;谷歌一直是人工智能&#xff08;AI&#xff0…

MasterAlign全景视觉点胶应用软件说明书

MasterAlign视觉软件通过高精度的图像处理和机器学习算法&#xff0c;实现了对点胶过程的全面控制和管理。以下是关于MasterAlign在全景视觉点胶应用场景中如何使用的详细说明。看完全文相信一定能让您快速上手使用。