mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 11:18:17 +00:00
feat: dev and staging bypass
This commit is contained in:
@@ -8,6 +8,7 @@ import { OtpRepository } from "./otp.repository";
|
||||
|
||||
import { NotificationsService } from "../notifications/notifications.service";
|
||||
import { EmailClientService } from "../notifications/email-client.service";
|
||||
import { isBypassEnv, DEV_BYPASS_OTP } from "../../common/dev-bypass.util";
|
||||
|
||||
/**
|
||||
* Where a code goes. At least one of phone/email must be set — enforced by the
|
||||
@@ -146,6 +147,21 @@ export class OtpService {
|
||||
`otp.issue channels=${channels.join("+")} target=${label} action=${rotated ? "rotate" : "create"}`,
|
||||
);
|
||||
|
||||
// Dev/staging only: the row above still exists (so a real code would
|
||||
// still verify), but skip the real SMS/email send — no carrier cost, no
|
||||
// dependency on RabbitMQ/the mail relay being up. Verify with the fixed
|
||||
// DEV_BYPASS_OTP code instead of whatever landed in the row.
|
||||
if (isBypassEnv()) {
|
||||
this.logger.warn(
|
||||
`otp.dispatch.bypassed target=${label} — dev/staging, no real SMS/email sent (verify with ${DEV_BYPASS_OTP})`,
|
||||
);
|
||||
return {
|
||||
success: true,
|
||||
delivered: true,
|
||||
message: "OTP sent successfully",
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: do NOT reset the brute-force attempt counter on send. Clearing it
|
||||
// here let an attacker wipe the per-target guess budget just by calling
|
||||
// /otp/send between guesses. The counter is cleared only when the code is
|
||||
@@ -394,7 +410,10 @@ export class OtpService {
|
||||
|
||||
// invalid otp — per-target attempt cap so a 6-digit code can't be
|
||||
// brute-forced within its TTL; the code is burned once the budget is spent.
|
||||
if (otpData.otp !== otp) {
|
||||
// Dev/staging only: a fixed code verifies any pending OTP row without
|
||||
// knowing the real one — the row still has to exist (sendOtp still runs).
|
||||
const bypassed = isBypassEnv() && otp === DEV_BYPASS_OTP;
|
||||
if (otpData.otp !== otp && !bypassed) {
|
||||
const attempts = (this.actionAttempts.get(key) ?? 0) + 1;
|
||||
if (attempts >= this.MAX_ACTION_ATTEMPTS) {
|
||||
await this.otpRepository.deleteOtp(otpData);
|
||||
@@ -482,7 +501,10 @@ export class OtpService {
|
||||
);
|
||||
}
|
||||
|
||||
if (otpData.otp !== otp) {
|
||||
// Dev/staging only: a fixed code verifies any pending OTP row without
|
||||
// knowing the real one — the row still has to exist (sendOtp still runs).
|
||||
const bypassed = isBypassEnv() && otp === DEV_BYPASS_OTP;
|
||||
if (otpData.otp !== otp && !bypassed) {
|
||||
const attempts = (this.actionAttempts.get(key) ?? 0) + 1;
|
||||
|
||||
if (attempts >= this.MAX_ACTION_ATTEMPTS) {
|
||||
|
||||
Reference in New Issue
Block a user