30 lines
873 B
TypeScript
30 lines
873 B
TypeScript
import bcrypt from "bcryptjs";
|
|
import { getRedis } from "./redis";
|
|
|
|
const RATE_LIMIT_PREFIX = "ratelimit:login:";
|
|
const RATE_LIMIT_WINDOW = 900; // 15 minutes
|
|
const RATE_LIMIT_MAX = 10;
|
|
|
|
export async function verifyPassword(plaintext: string): Promise<boolean> {
|
|
const hash = process.env.ADMIN_PASSWORD_HASH;
|
|
if (!hash) {
|
|
console.error("ADMIN_PASSWORD_HASH env var not set — admin login disabled");
|
|
return false;
|
|
}
|
|
return bcrypt.compare(plaintext, hash);
|
|
}
|
|
|
|
export async function checkRateLimit(
|
|
ip: string,
|
|
): Promise<{ allowed: boolean; remaining: number }> {
|
|
const redis = getRedis();
|
|
const key = `${RATE_LIMIT_PREFIX}${ip}`;
|
|
const count = await redis.incr(key);
|
|
if (count === 1) {
|
|
await redis.expire(key, RATE_LIMIT_WINDOW);
|
|
}
|
|
return {
|
|
allowed: count <= RATE_LIMIT_MAX,
|
|
remaining: Math.max(0, RATE_LIMIT_MAX - count),
|
|
};
|
|
}
|