From 699abf69c7553da0729bdb767a820fc479e41dd3 Mon Sep 17 00:00:00 2001 From: hashbk Date: Sun, 9 Aug 2026 19:58:46 +0800 Subject: [PATCH 1/2] fix(auth): store has_password and has_totp flags in user info The frontend expects has_password and has_totp inside the user info object, but the backend was not providing them. Store these as flags in the info JSON when the password or TOTP is set, so they are returned naturally via getUserInfo() without loading select:false columns. --- src/modules/auth/services/auth-tfa.service.ts | 6 ++++++ src/modules/auth/services/auth.service.ts | 4 ++++ src/modules/ldap/ldap.service.ts | 4 ++++ src/modules/oidc/services/oidc.service.ts | 4 ++++ src/modules/user/entities/user.entity.ts | 2 ++ src/modules/user/user.service.ts | 17 +++++++++++++++++ 6 files changed, 37 insertions(+) diff --git a/src/modules/auth/services/auth-tfa.service.ts b/src/modules/auth/services/auth-tfa.service.ts index 8089ec4..f33a51e 100644 --- a/src/modules/auth/services/auth-tfa.service.ts +++ b/src/modules/auth/services/auth-tfa.service.ts @@ -127,6 +127,7 @@ export class AuthTfaService { delete other.tfa_pending_secret; userInfo.other = other; + userInfo.has_totp = true; user.setUserInfo(userInfo); await this.userRepository.save(user); @@ -163,6 +164,11 @@ export class AuthTfaService { } user.tfaSecret = ''; + + const userInfo = user.getUserInfo(); + userInfo.has_totp = false; + user.setUserInfo(userInfo); + await this.userRepository.save(user); return { message: '2FA已禁用' }; diff --git a/src/modules/auth/services/auth.service.ts b/src/modules/auth/services/auth.service.ts index 15011c4..02754e8 100644 --- a/src/modules/auth/services/auth.service.ts +++ b/src/modules/auth/services/auth.service.ts @@ -96,6 +96,10 @@ export class AuthService { userGroupGuid, }); + const userInfo = user.getUserInfo(); + userInfo.has_password = true; + user.setUserInfo(userInfo); + await this.userRepository.save(user); this.logger.log(`新用户注册成功: ${username}`); diff --git a/src/modules/ldap/ldap.service.ts b/src/modules/ldap/ldap.service.ts index 07ab973..f9e0740 100644 --- a/src/modules/ldap/ldap.service.ts +++ b/src/modules/ldap/ldap.service.ts @@ -406,6 +406,10 @@ export class LdapService { user.oidcSubject = ldapSubject; user.userGroupGuid = userGroupGuid; + const userInfo = user.getUserInfo(); + userInfo.has_password = false; + user.setUserInfo(userInfo); + await this.userRepository.save(user); this.logger.log(`LDAP 用户已创建: ${finalUsername}`); return user; diff --git a/src/modules/oidc/services/oidc.service.ts b/src/modules/oidc/services/oidc.service.ts index 1adc288..8d91293 100644 --- a/src/modules/oidc/services/oidc.service.ts +++ b/src/modules/oidc/services/oidc.service.ts @@ -815,6 +815,10 @@ export class OidcService { user.oidcSubject = oidcSubject; user.userGroupGuid = userGroupGuid; + const userInfo = user.getUserInfo(); + userInfo.has_password = false; + user.setUserInfo(userInfo); + await this.userRepository.save(user); this.logger.log( `OIDC user created: ${finalUsername} via ${providerName}`, diff --git a/src/modules/user/entities/user.entity.ts b/src/modules/user/entities/user.entity.ts index df9a136..ccfabf2 100644 --- a/src/modules/user/entities/user.entity.ts +++ b/src/modules/user/entities/user.entity.ts @@ -31,6 +31,8 @@ export enum UserStatus { export interface UserInfo { email_verification?: boolean; email_alarm_notification?: boolean; + has_password?: boolean; + has_totp?: boolean; other?: Record; } diff --git a/src/modules/user/user.service.ts b/src/modules/user/user.service.ts index 2426b0e..5aa092e 100644 --- a/src/modules/user/user.service.ts +++ b/src/modules/user/user.service.ts @@ -197,6 +197,10 @@ export class UserService { user.isAdmin = false; user.userGroupGuid = userGroupGuid; + const userInfo = user.getUserInfo(); + userInfo.has_password = true; + user.setUserInfo(userInfo); + await this.userRepository.save(user); return { message: '用户创建成功' }; @@ -234,6 +238,10 @@ export class UserService { user.isAdmin = false; user.userGroupGuid = userGroupGuid; + const userInfo = user.getUserInfo(); + userInfo.has_password = false; + user.setUserInfo(userInfo); + await this.userRepository.save(user); // 生成邀请令牌 @@ -347,6 +355,10 @@ export class UserService { user.password = await bcrypt.hash(dto.password, 10); user.status = UserStatus.ACTIVE; + const userInfo = user.getUserInfo(); + userInfo.has_password = true; + user.setUserInfo(userInfo); + await this.userRepository.save(user); // 标记邀请已使用 @@ -504,6 +516,11 @@ export class UserService { } user.password = await bcrypt.hash(dto.new_password, 10); + + const userInfo = user.getUserInfo(); + userInfo.has_password = true; + user.setUserInfo(userInfo); + await this.userRepository.save(user); return { message: '密码修改成功' }; From a1101e24924794da690660c989491ec3f3fcbd01 Mon Sep 17 00:00:00 2001 From: hashbk Date: Sun, 9 Aug 2026 20:02:06 +0800 Subject: [PATCH 2/2] fix(auth-tfa): reuse existing userInfo variable in disableTfa --- src/modules/auth/services/auth-tfa.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/auth/services/auth-tfa.service.ts b/src/modules/auth/services/auth-tfa.service.ts index f33a51e..a8a89c6 100644 --- a/src/modules/auth/services/auth-tfa.service.ts +++ b/src/modules/auth/services/auth-tfa.service.ts @@ -165,7 +165,7 @@ export class AuthTfaService { user.tfaSecret = ''; - const userInfo = user.getUserInfo(); + userInfo.has_totp = false; user.setUserInfo(userInfo);