{"record":{"id":"c1df4f43179be0bf","repo":"yikart/AiToEarn","slug":"token-mail","errorCode":null,"errorMessage":"token和mail是必须的","messagePattern":"token和mail是必须的","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.controller.ts","lineNumber":33,"sourceCode":"// @UseGuards(AuthGuard)\nexport class TikTokController {\n  constructor(\n    private readonly tikTokService: TikTokService,\n    private readonly tikTokAuthService: TikTokAuthService,\n  ) {}\n\n  /**\n   * 获取TikTok授权URL\n   */\n  @Get('auth/url')\n  @ApiOperation({ summary: '获取TikTok授权URL' })\n  @ApiQuery({ name: 'mail', required: false, description: '用户邮箱' })\n  async getAuthUrl(\n    @GetToken() systemToken: TokenInfo,\n    @Query('mail') mail: string,\n  ) {\n    if (!systemToken.id || !mail) {\n      throw new BadRequestException('token和mail是必须的');\n    }\n    return this.tikTokAuthService.getAuthorizationUrl(systemToken.id, mail);\n  }\n\n  /**\n   * TikTok OAuth2回调处理\n   */\n\n  @ApiOperation({ summary: 'TikTok OAuth2回调处理' })\n  @Public()\n  @ApiQuery({ name: 'code', type: String, description: 'OAuth2授权码' })\n  @ApiQuery({ name: 'state', type: String, description: '状态码' })\n  @Get('auth/callback')\n  async handleAuthCallback(\n    @Query('code') code: string,\n    @Query('state') state: string,\n    @Res() res: Response,\n  ) {","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-electron/server/src/modules/plat/tiktok/tiktok.controller.ts#L15-L51","documentation":"A BadRequestException raised by the getAuthUrl controller handler when the request is missing required inputs: the authenticated user's id from the system token or the mail query parameter. The handler needs both to bind the TikTok OAuth state to a local user.","triggerScenarios":"Calling GET /tiktok/auth-url without the mail query parameter, or without a valid system token (GetToken decorator fails to resolve token.id) — e.g. an unauthenticated request or a missing/expired Authorization header.","commonSituations":"Frontend forgot to append ?mail=..., the JWT/Authorization header was dropped by a proxy, the system token expired so token.id is undefined, calling the endpoint without login.","solutions":["Add the mail query parameter to the request URL.","Ensure the request carries a valid system token (Authorization header with a current token) so systemToken.id resolves.","Re-login to obtain a fresh system token if it expired.","In the client, validate inputs before calling and show a form validation error instead of hitting the API."],"exampleFix":"// before\nconst url = `/api/plat/tiktok/auth-url`;\n// after — client side\nif (!userEmail) throw new Error('mail is required');\nconst url = `/api/plat/tiktok/auth-url?mail=${encodeURIComponent(userEmail)}`;\n// with headers: { Authorization: `Bearer ${systemToken}` }","handlingStrategy":"validation","validationCode":"// client-side pre-check\nif (!systemToken?.id) throw new Error('system token missing — log in first');\nif (!mail || !/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(mail)) throw new Error('mail query param required');","typeGuard":"function canRequestAuthUrl(p: { systemToken?: { id?: string }; mail?: string }): p is { systemToken: { id: string }; mail: string } {\n  return typeof p.systemToken?.id === 'string' && typeof p.mail === 'string' && p.mail.includes('@');\n}","tryCatchPattern":"try {\n  return await api.getTikTokAuthUrl(mail);\n} catch (e) {\n  if ((e as any).status === 400 && /token和mail/.test((e as Error).message)) {\n    await ensureLoggedIn();\n    return api.getTikTokAuthUrl(mail);\n  }\n  throw e;\n}","preventionTips":["Attach the Authorization header to every authenticated request (check proxies don't strip it).","Encode the mail parameter with encodeURIComponent.","Re-login when the system token expires.","Validate inputs client-side before calling the endpoint."],"tags":["validation","bad-request","controller","tiktok"],"backgroundTag":"missing-required-parameter","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}