https://docs.3rcd.com/nestjs/chapter23 学习到用户模块和JWT认证这个章节遇到一些问题
1、登录凭证:可以是用户名,手机号,邮箱地址,这几个凭证单独来看都是唯一的,但是如果用户名是一个手机号码且和另一个账号的手机号是一样的,密码也是一致的情况下,
登录验证查询只返回一个,是不是就是会造成混淆了?

2、模块增加完之后生成了数据迁移脚本,但是涉及到表关联,生成的脚本执行是失败的,因为comment表关联用户表,新增了用户id的字段和用户表关联,同时这个字段是不能为空的,
comment表有数据但是用户表是没有数据的,导致执行失败。文档里有写如果是已上线项目扩展,则建议手动编写
,这种场景一般要怎么处理?要创建一个临时用户来解决吗?
public async up(queryRunner: typeorm.QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE \`user_refresh_token\` (\`id\` varchar(36) NOT NULL, \`value\` varchar(500) NOT NULL COMMENT '令牌字符串', \`expiredAt\` datetime NOT NULL COMMENT '令牌过期时间', \`createdAt\` datetime(6) NOT NULL COMMENT '令牌创建时间' DEFAULT CURRENT_TIMESTAMP(6), \`accessTokenId\` varchar(36) NULL, UNIQUE INDEX \`REL_0fb9e76570bb35fd7dd7f78f73\` (\`accessTokenId\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB
`);
await queryRunner.query(`
CREATE TABLE \`user_access_token\` (\`id\` varchar(36) NOT NULL, \`value\` varchar(500) NOT NULL COMMENT '令牌字符串', \`expiredAt\` datetime NOT NULL COMMENT '令牌过期时间', \`createdAt\` datetime(6) NOT NULL COMMENT '令牌创建时间' DEFAULT CURRENT_TIMESTAMP(6), \`userId\` varchar(36) NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB
`);
await queryRunner.query(`
CREATE TABLE \`user\` (\`id\` varchar(36) NOT NULL, \`nickname\` varchar(64) NULL COMMENT '昵称', \`username\` varchar(64) NOT NULL COMMENT '用户名', \`password\` varchar(500) NOT NULL COMMENT '用户密码', \`phone\` varchar(64) NOT NULL COMMENT '用户手机号', \`email\` varchar(256) NULL COMMENT '用户邮箱', \`createdAt\` datetime(6) NOT NULL COMMENT '用户创建时间' DEFAULT CURRENT_TIMESTAMP(6), \`updatedAt\` datetime(6) NOT NULL COMMENT '用户更新时间' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`deletedAt\` datetime(6) NULL COMMENT '用户销户时间', UNIQUE INDEX \`IDX_78a916df40e02a9deb1c4b75ed\` (\`username\`), UNIQUE INDEX \`IDX_8e1f623798118e629b46a9e629\` (\`phone\`), UNIQUE INDEX \`IDX_e12875dfb3b1d92d7d7c5377e2\` (\`email\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB
`);
await queryRunner.query(`
ALTER TABLE \`content_comment\` ADD \`authorId\` varchar(36) NOT NULL
`);
await queryRunner.query(`
ALTER TABLE \`content_posts\` ADD \`authorId\` varchar(36) NOT NULL
`);
await queryRunner.query(`
ALTER TABLE \`content_comment\` ADD CONSTRAINT \`FK_70b9cb9c33e723c66ea68715268\` FOREIGN KEY (\`authorId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
`);
await queryRunner.query(`
ALTER TABLE \`content_posts\` ADD CONSTRAINT \`FK_8fcc2d81ced7b8ade2bbd151b1a\` FOREIGN KEY (\`authorId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE
`);
await queryRunner.query(`
ALTER TABLE \`user_refresh_token\` ADD CONSTRAINT \`FK_0fb9e76570bb35fd7dd7f78f73c\` FOREIGN KEY (\`accessTokenId\`) REFERENCES \`user_access_token\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
`);
await queryRunner.query(`
ALTER TABLE \`user_access_token\` ADD CONSTRAINT \`FK_c9c6ac4970ddbe5a8c4887e1e7e\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION
`);
}
3、在调接口测试的时候,执行到token想过的部分报错
async generateAccessToken(
user: UserEntity,
now: dayjs.Dayjs,
): Promise<{ accessToken: AccessTokenEntity; refreshToken: RefreshTokenEntity }> {
const config = await getUserConfig<JwtConfig>(this.configure, 'jwt');
const accessTokenPayload: JwtPayload = { sub: user.id, iat: now.unix() };
const signed = this.jwtService.sign(accessTokenPayload);
const accessToken = new AccessTokenEntity();
accessToken.value = signed;
accessToken.user = user;
accessToken.expiredAt = now.add(config.tokenExpired, 'second').toDate();
await accessToken.save();
const refreshToken = await this.generateRefreshToken(
accessToken,
await getTime(this.configure),
);
return { accessToken, refreshToken };
}
执行到await accessToken.save();
的时候报错,报错信息是TypeORMError: Connection is not established with mysql database
查了下这个是由于BaseEntity里的dataSource为空导致的, 看了下源码找到塞值的地方,调用链是DatabaseModule.forRoot =>TypeOrmModule.forRoot =>TypeOrmCoreModule.forRoot => await this.createDataSourceFactory(options)
=> dataSource.initialize()
=> dataSource.buildMetadatas()
=>
for (const entityMetadata of entityMetadatas) {
if (
InstanceChecker.isBaseEntityConstructor(entityMetadata.target)
) {
entityMetadata.target.useDataSource(this)
}
}
断点调试的时候 也可以看到代码在这里执行了,但是就是执行失败,不知道是什么原因了,麻烦帮忙看下 @Cloneable
代码仓库 https://git.3rcd.com/shuijiangui/nestapp.git
