Quellcode durchsuchen

feat: include username in login token

ChenYu vor 4 Monaten
Ursprung
Commit
3bb1d92122

+ 11 - 0
backend/src/modules/auth/auth.service.spec.ts

@@ -72,6 +72,17 @@ describe('AuthService', () => {
       name: 'Ogawa',
       email: 'stylist@example.com',
     });
+
+    expect(jwtService.signAsync).toHaveBeenCalledWith(
+      {
+        sub: 1,
+        email: 'stylist@example.com',
+        username: 'Ogawa',
+      },
+      expect.objectContaining({
+        expiresIn: '7d',
+      }),
+    );
   });
 
   it('throws AUTH_INVALID_CREDENTIALS when the password does not match', async () => {

+ 1 - 0
backend/src/modules/auth/auth.service.ts

@@ -42,6 +42,7 @@ export class AuthService {
       {
         sub: Number(stylist.id),
         email: stylist.email,
+        username: stylist.username,
       },
       {
         expiresIn:

+ 22 - 0
backend/test/auth.e2e-spec.ts

@@ -39,10 +39,32 @@ describe('Auth (e2e)', () => {
     });
   });
 
+  it('/api/v1/auth/stylist/login (POST) returns a token payload with username', async () => {
+    const response = await request(app.getHttpServer())
+      .post('/api/v1/auth/stylist/login')
+      .send({
+        email: 'stylist@example.com',
+        password: 'Passw0rd!',
+        remember: false,
+      })
+      .expect(201);
+
+    const payload = await jwtService.verifyAsync<{
+      sub: number;
+      email: string;
+      username: string;
+    }>(response.body.data.token);
+
+    expect(payload.sub).toBe(1);
+    expect(payload.email).toBe('stylist@example.com');
+    expect(payload.username).toBe('Ogawa');
+  });
+
   it('/api/v1/customers (GET) accepts a valid signed token', async () => {
     const token = await jwtService.signAsync({
       sub: 1,
       email: 'stylist@example.com',
+      username: 'Ogawa',
     });
 
     const response = await request(app.getHttpServer())

+ 2 - 1
docs/superpowers/specs/2026-06-28-stylist-login-minimal-closed-loop-design.md

@@ -170,7 +170,8 @@
 
 - 本 case 只签发单个 access token。
 - token 类型采用 JWT。
-- payload 只包含最小必要身份字段,例如 `sub` 和 `email`。
+- payload 只包含最小必要身份字段,例如 `sub`、`email`、`username`。
+- `username` 供工作台欢迎区直接消费,不再额外请求 `/me` 接口。
 - 不在 token 中塞入模板数量、客户统计等业务数据,避免 token 承担缓存职责。
 
 ### Remember 语义