feat(api): add IP ban exemptions (#1448)

This commit is contained in:
Hampus authored and GitHub committed 2026-07-23 18:06:34 +02:00
1 parent 311a1addce
commit fb5fe38d52
12 files changed
+88 -1

No files matched your search

@@ -13,6 +13,7 @@ import type {
BannedUrlRow,
} from '../database/types/AdminArchiveTypes';
import {isAccountPolicyContactDomainReputationExempt} from '../risk/AccountPolicyService';
import {isIpBanExempt} from '../risk/IpBanExemptions';
import {
AdminAuditLogs,
BannedAvatarHashes,
@@ -129,6 +130,9 @@ export class AdminRepository implements IAdminRepository {
}
async isIpBanned(ip: string): Promise<boolean> {
if (isIpBanExempt(ip)) {
return false;
}
const candidate = tryParseSingleIp(ip);
if (!candidate) {
return false;
@@ -157,6 +161,9 @@ export class AdminRepository implements IAdminRepository {
}
async banIp(ip: string): Promise<void> {
if (isIpBanExempt(ip)) {
return;
}
const canonicalIp = canonicalizeBannedIpEntry(ip);
await upsertOne(
BannedIps.insert({
@@ -173,6 +180,9 @@ export class AdminRepository implements IAdminRepository {
if (!Number.isInteger(ttlSeconds) || ttlSeconds <= 0) {
throw new RangeError('Temporary IP ban TTL must be a positive integer');
}
if (isIpBanExempt(ip)) {
return;
}
const canonicalIp = canonicalizeBannedIpEntry(ip);
await upsertOne(
BannedIps.insertWithTtl(
@@ -30,6 +30,7 @@ import {
hasHighCgnatBlastRadiusRisk,
isSingleIpBanCandidate,
} from '../../risk/IpBanCgnatGuard';
import {isIpBanExempt} from '../../risk/IpBanExemptions';
import type {ISuspiciousIpRepository} from '../../risk/SuspiciousIpRepository';
import {tryParseSingleIp} from '../../utils/IpRangeUtils';
import {canonicalizeStoredPhrase} from '../../utils/PhraseBlocklistNormalization';
@@ -81,6 +82,17 @@ export class AdminBanManagementService {
) {
const {adminRepository, auditService} = this.deps;
const {cache: cacheService} = this.deps.apiContext.services;
if (isIpBanExempt(data.ip)) {
await auditService.createAuditLog({
adminUserId,
targetType: 'ip',
targetId: BigInt(0),
action: 'ban_ip_skipped_exempt',
auditLogReason,
metadata: new Map([['ip', data.ip]]),
});
return;
}
if (await this.shouldSkipIpBanForCgnat(data.ip)) {
await auditService.createAuditLog({
adminUserId,