67 lines
1.6 KiB
TypeScript
67 lines
1.6 KiB
TypeScript
import { requireUser } from "../../utils/auth";
|
|
import { getActiveCooldown, resolveCooldown } from "../../db/cooldown";
|
|
import { signCooldownToken } from "../../utils/cooldownToken";
|
|
|
|
/** GET /api/cooldown/status — Current cooldown state for the authenticated user. */
|
|
export default defineEventHandler(async (event) => {
|
|
const user = await requireUser(event);
|
|
|
|
const cooldown = await getActiveCooldown(user.id);
|
|
const now = new Date();
|
|
|
|
if (!cooldown) {
|
|
// No cooldown ever started (or all were cancelled/resolved).
|
|
return {
|
|
success: true,
|
|
data: {
|
|
active: false,
|
|
remainingSeconds: 0,
|
|
cooldownEndsAt: null,
|
|
canDisableProtection: true,
|
|
token: null, // no cooldown row to bind to; app may proceed freely
|
|
},
|
|
};
|
|
}
|
|
|
|
const expired = now >= cooldown.cooldownEndsAt;
|
|
|
|
if (expired) {
|
|
// Auto-resolve so we don't re-check next time.
|
|
await resolveCooldown(cooldown.id);
|
|
|
|
const token = await signCooldownToken(
|
|
user.id,
|
|
cooldown.tokenJti,
|
|
cooldown.cooldownEndsAt,
|
|
);
|
|
|
|
return {
|
|
success: true,
|
|
data: {
|
|
active: false,
|
|
remainingSeconds: 0,
|
|
cooldownEndsAt: cooldown.cooldownEndsAt.toISOString(),
|
|
canDisableProtection: true,
|
|
token,
|
|
},
|
|
};
|
|
}
|
|
|
|
// Still counting down.
|
|
const remainingSeconds = Math.max(
|
|
0,
|
|
Math.floor((cooldown.cooldownEndsAt.getTime() - now.getTime()) / 1000),
|
|
);
|
|
|
|
return {
|
|
success: true,
|
|
data: {
|
|
active: true,
|
|
remainingSeconds,
|
|
cooldownEndsAt: cooldown.cooldownEndsAt.toISOString(),
|
|
canDisableProtection: false,
|
|
token: null,
|
|
},
|
|
};
|
|
});
|