FIX Catcha

This commit is contained in:
SepehrYahyaee
2026-05-24 10:56:28 +03:30
parent 4d4106a8ab
commit 866696094f
18 changed files with 243 additions and 223 deletions

View File

@@ -20,9 +20,9 @@ import {
ApiBearerAuth,
} from "@nestjs/swagger";
import { ActorAuthService } from "src/auth/auth-services/actor.auth.service";
import { CaptchaAccountService } from "src/auth/auth-services/captcha-account.service";
import { CaptchaChallengeService } from "src/captcha/captcha-challenge.service";
import { CaptchaResponseDto } from "src/auth/dto/captcha-response.dto";
import { GetActorCaptchaQueryDto } from "src/auth/dto/get-actor-captcha.dto";
import { GetCaptchaImageQueryDto } from "src/auth/dto/get-captcha-image-query.dto";
import {
ForgetPasswordSendCodeDto,
ForgetPasswordVerifyCodeDto,
@@ -45,33 +45,29 @@ import { CurrentUser } from "src/decorators/user.decorator";
export class ActorAuthController {
constructor(
private readonly actorAuthService: ActorAuthService,
private readonly captchaAccountService: CaptchaAccountService,
private readonly captchaChallengeService: CaptchaChallengeService,
) {}
@Get("captcha")
@ApiOperation({
summary: "Get login captcha for an actor account",
summary: "Get a login captcha",
description:
"Returns an SVG captcha stored on the actor record.\n\n" +
"**Viewing the image:** Swagger displays `image` as plain text. To see the captcha:\n" +
"- Add `format=raw` and open the request URL in a new browser tab, or\n" +
"- Copy the full `image` value from the JSON response and paste it into the browser address bar, or\n" +
"- In your app: `<img src={response.image} alt=\"captcha\" />`\n\n" +
"Type the characters shown in the image into the `captcha` field on POST /actor/login.",
"Issues a new captcha challenge. Returns `captchaId`, `image`, and `expiresAt`. " +
"Send `captchaId` and the typed characters as `captcha` on POST /actor/login.\n\n" +
"Optional `format=raw` returns image/svg+xml for browser preview (same captchaId is in JSON when omitted).",
})
@ApiResponse({ status: 200, type: CaptchaResponseDto })
async getCaptcha(
@Query() query: GetActorCaptchaQueryDto,
@Query() query: GetCaptchaImageQueryDto,
@Res({ passthrough: true }) res: Response,
) {
const result = await this.captchaAccountService.issueActorCaptcha(
query.username,
query.role,
);
const result = await this.captchaChallengeService.issue();
if (query.format === "raw") {
const base64 = result.image.replace(/^data:image\/svg\+xml;base64,/, "");
const svg = Buffer.from(base64, "base64").toString("utf8");
const svg = await this.captchaChallengeService.getImageById(
result.captchaId,
);
res.setHeader("X-Captcha-Id", result.captchaId);
res.type("image/svg+xml");
res.send(svg);
return;
@@ -80,6 +76,20 @@ export class ActorAuthController {
return result;
}
@Get("captcha/:captchaId/image")
@ApiOperation({
summary: "View captcha image by id",
description: "Returns raw SVG for a previously issued captcha challenge.",
})
async getCaptchaImage(
@Param("captchaId") captchaId: string,
@Res({ passthrough: true }) res: Response,
) {
const svg = await this.captchaChallengeService.getImageById(captchaId);
res.type("image/svg+xml");
res.send(svg);
}
/**
* @deprecated Use the unified actor onboarding flow instead. This endpoint
* will be removed in a future release.
@@ -154,6 +164,7 @@ export class ActorAuthController {
role: "company",
username: "saman_insurer@gmail.com",
password: "123321",
captchaId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
captcha: "a7bx2",
},
},
@@ -164,6 +175,7 @@ export class ActorAuthController {
role: "expert",
username: "blame@gmail.com",
password: "123321",
captchaId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
captcha: "a7bx2",
},
},
@@ -174,6 +186,7 @@ export class ActorAuthController {
role: "damage_expert",
username: "claim@gmail.com",
password: "123321",
captchaId: "f47ac10b-58cc-4372-a567-0e02b2c3d479",
captcha: "a7bx2",
},
},