Skip to content

Commit d502f42

Browse files
committed
Fix tenant quota guard syntax and abuse score service
1 parent a5e9b80 commit d502f42

2 files changed

Lines changed: 57 additions & 0 deletions

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { Injectable, CanActivate, ExecutionContext, HttpException } from '@nestjs/common';
2+
3+
@Injectable()
4+
export class TenantQuotaGuard implements CanActivate {
5+
private readonly tiers: Record<string, number> = {
6+
FREE: 100,
7+
PRO: 1000,
8+
ENTERPRISE: -1,
9+
};
10+
private counters = new Map<string, { count: number; resetAt: number }>();
11+
12+
canActivate(context: ExecutionContext): boolean {
13+
const req = context.switchToHttp().getRequest();
14+
const tenantId = req.headers['x-tenant-id'] as string;
15+
if (!tenantId) return true;
16+
17+
const tier = (req as any).tenantTier || 'FREE';
18+
const limit = this.tiers[tier] || this.tiers.FREE;
19+
if (limit === -1) return true;
20+
21+
const now = Date.now();
22+
const key = tenantId;
23+
const entry = this.counters.get(key);
24+
25+
if (!entry || now > entry.resetAt) {
26+
this.counters.set(key, { count: 1, resetAt: now + 60000 });
27+
return true;
28+
}
29+
30+
entry.count++;
31+
if (entry.count > limit) {
32+
throw new HttpException('Tenant rate limit exceeded', 429);
33+
}
34+
return true;
35+
}
36+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Injectable } from '@nestjs/common';
2+
3+
@Injectable()
4+
export class AbuseScoreService {
5+
private scores = new Map<string, { score: number; expiresAt: number }>();
6+
7+
async getCompositeScore(userId: string, ip: string): Promise<number> {
8+
const key = `${userId}:${ip}`;
9+
const entry = this.scores.get(key);
10+
if (!entry || Date.now() > entry.expiresAt) return 0;
11+
return entry.score;
12+
}
13+
14+
addSignal(userId: string, ip: string, weight: number): void {
15+
const key = `${userId}:${ip}`;
16+
const entry = this.scores.get(key);
17+
const now = Date.now();
18+
const newScore = (entry && now <= entry.expiresAt ? entry.score : 0) + weight;
19+
this.scores.set(key, { score: newScore, expiresAt: now + 60000 });
20+
}
21+
}

0 commit comments

Comments
 (0)