2
0
Просмотр исходного кода

✨ feat(auth): add user account status check functionality

- add user disabled status check in authentication flow
- add user deleted status verification during login
- update auth middleware to validate user status before granting access

🐛 fix(auth): improve error handling for disabled users

- add specific error message for disabled accounts in auth service
- update client to show friendly message when account is disabled
- clear token and authentication state when disabled user tries to access

📦 build(deps): add jsonwebtoken types package

- install @types/jsonwebtoken@^9.0.10 for type safety in authentication code
yourname 6 месяцев назад
Родитель
Сommit
cef95a90fe

+ 1 - 0
package.json

@@ -98,6 +98,7 @@
     "@types/bcrypt": "^6.0.0",
     "@types/debug": "^4.1.12",
     "@types/express": "^5.0.3",
+    "@types/jsonwebtoken": "^9.0.10",
     "@types/node": "^24.0.10",
     "@types/react": "^19.1.8",
     "@types/react-dom": "^19.1.6",

+ 11 - 0
pnpm-lock.yaml

@@ -258,6 +258,9 @@ importers:
       '@types/express':
         specifier: ^5.0.3
         version: 5.0.3
+      '@types/jsonwebtoken':
+        specifier: ^9.0.10
+        version: 9.0.10
       '@types/node':
         specifier: ^24.0.10
         version: 24.1.0
@@ -1713,6 +1716,9 @@ packages:
   '@types/http-errors@2.0.5':
     resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==}
 
+  '@types/jsonwebtoken@9.0.10':
+    resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
+
   '@types/long@4.0.2':
     resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
 
@@ -5031,6 +5037,11 @@ snapshots:
 
   '@types/http-errors@2.0.5': {}
 
+  '@types/jsonwebtoken@9.0.10':
+    dependencies:
+      '@types/ms': 2.1.0
+      '@types/node': 24.1.0
+
   '@types/long@4.0.2': {}
 
   '@types/mime@1.3.5': {}

+ 7 - 0
src/client/mobile/hooks/AuthProvider.tsx

@@ -72,6 +72,13 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
         setIsAuthenticated(true);
         return { isValid: true, user: currentUser };
       } catch (error) {
+        // 如果认证失败,清除token
+        if (error instanceof Error && error.message.includes('disabled')) {
+          // 用户被禁用,清除本地token
+          setToken(null);
+          localStorage.removeItem('mobile_token');
+          delete axios.defaults.headers.common['Authorization'];
+        }
         return { isValid: false };
       }
     },

+ 8 - 1
src/client/mobile/pages/AuthPage.tsx

@@ -63,7 +63,14 @@ const AuthPage: React.FC = () => {
       }
     } catch (error) {
       console.error('Authentication error:', error);
-      toast.error((error as Error).message || '认证失败,请稍后重试');
+      const errorMessage = (error as Error).message || '认证失败,请稍后重试';
+      
+      // 为用户禁用状态提供更友好的错误消息
+      if (errorMessage.includes('disabled')) {
+        toast.error('您的账号已被禁用,请联系管理员');
+      } else {
+        toast.error(errorMessage);
+      }
     } finally {
       setLoading(false);
     }

+ 9 - 0
src/server/middleware/auth.middleware.ts

@@ -26,6 +26,15 @@ export async function authMiddleware(c: Context<AuthContext>, next: Next) {
       return c.json({ message: 'User not found' }, 401);
     }
 
+    // 检查用户状态
+    if (user.isDisabled === 1) {
+      return c.json({ message: 'User is disabled' }, 403);
+    }
+
+    if (user.isDeleted === 1) {
+      return c.json({ message: 'User not found' }, 401);
+    }
+
     c.set('user', user);
     c.set('token', token);
     await next();

+ 9 - 0
src/server/modules/auth/auth.service.ts

@@ -53,6 +53,15 @@ export class AuthService {
         throw new Error('User not found');
       }
 
+      // 检查用户状态
+      if (user.isDisabled === 1) {
+        throw new Error('User is disabled');
+      }
+
+      if (user.isDeleted === 1) {
+        throw new Error('User not found');
+      }
+
       const isPasswordValid = await this.userService.verifyPassword(user, password);
       if (!isPasswordValid) {
         throw new Error('Invalid password');