1- import { DataSource } from 'typeorm' ;
1+ import { DataSource , EntityManager } from 'typeorm' ;
22import { JwtService } from '@nestjs/jwt' ;
33import { ConfigService } from '@nestjs/config' ;
44import generateId from 'omnibox-backend/utils/generate-id' ;
55import { UserService } from 'omnibox-backend/user/user.service' ;
66import { NamespacesService } from 'omnibox-backend/namespaces/namespaces.service' ;
77import { WechatCheckResponseDto } from './dto/wechat-login.dto' ;
88import {
9+ BadRequestException ,
910 Injectable ,
11+ InternalServerErrorException ,
12+ Logger ,
1013 UnauthorizedException ,
11- BadRequestException ,
1214} from '@nestjs/common' ;
1315
1416@Injectable ( )
1517export class WechatService {
18+ private readonly logger = new Logger ( WechatService . name ) ;
19+
1620 private readonly appId : string ;
1721 private readonly appSecret : string ;
1822 private readonly redirectUri : string ;
@@ -28,6 +32,9 @@ export class WechatService {
2832 }
2933 > ( ) ;
3034
35+ private readonly minUsernameLength = 2 ;
36+ private readonly maxUsernameLength = 32 ;
37+
3138 constructor (
3239 private readonly configService : ConfigService ,
3340 private readonly jwtService : JwtService ,
@@ -90,6 +97,46 @@ export class WechatService {
9097 return `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${ this . appId } &redirect_uri=${ encodeURIComponent ( this . redirectUri ) } &response_type=code&scope=snsapi_userinfo&state=${ state } #wechat_redirect` ;
9198 }
9299
100+ generateSuffix ( ) : string {
101+ return (
102+ '_' +
103+ generateId ( 4 , 'useandomTPXpxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrict' )
104+ ) ;
105+ }
106+
107+ async getValidUsername (
108+ nickname : string ,
109+ manager : EntityManager ,
110+ ) : Promise < string > {
111+ let username = nickname ;
112+
113+ if ( username . length > this . maxUsernameLength ) {
114+ username = nickname . slice ( 0 , this . maxUsernameLength ) ;
115+ }
116+ if ( username . length >= this . minUsernameLength ) {
117+ const user = await this . userService . findByUsername ( username , manager ) ;
118+ if ( ! user ) {
119+ return username ;
120+ }
121+ }
122+
123+ username = nickname . slice ( 0 , this . maxUsernameLength - 5 ) ;
124+ for ( let i = 0 ; i < 5 ; i ++ ) {
125+ const suffix = this . generateSuffix ( ) ;
126+ const user = await this . userService . findByUsername (
127+ username + suffix ,
128+ manager ,
129+ ) ;
130+ if ( ! user ) {
131+ return username + suffix ;
132+ }
133+ }
134+
135+ throw new InternalServerErrorException (
136+ 'Unable to generate a valid username' ,
137+ ) ;
138+ }
139+
93140 async handleCallback ( code : string , state : string ) : Promise < any > {
94141 const stateInfo = this . qrCodeStates . get ( state ) ;
95142 if ( ! stateInfo ) {
@@ -134,22 +181,9 @@ export class WechatService {
134181 return returnValue ;
135182 }
136183 return await this . dataSource . transaction ( async ( manager ) => {
137- let username = userData . nickname ;
138- const suffix =
139- '_' +
140- generateId ( 4 , 'useandomTPXpxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrict' ) ;
141- if ( userData . nickname . length < 2 ) {
142- username = userData . nickname + suffix ;
143- } else if ( userData . nickname . length > 32 ) {
144- username = userData . nickname . slice ( 0 , 27 ) + suffix ;
145- }
146- const existingUser = await this . userService . findByUsername (
147- username ,
148- manager ,
149- ) ;
150- if ( existingUser ) {
151- username = userData . nickname . slice ( 0 , 22 ) + suffix ;
152- }
184+ const nickname : string = userData . nickname ;
185+ const username : string = await this . getValidUsername ( nickname , manager ) ;
186+ this . logger . debug ( { nickname, username } ) ;
153187 const wechatUser = await this . userService . createUserBinding (
154188 {
155189 username,
0 commit comments