Files
Syed Ali ShahbazandGitHub a2bee76da6 feat: Add spam blocker DI structure (#24040)
* --init

* --

* replace old structure with new DI

* fix type

* --

* moving stuff around

* moving stuff around again

* minor clean up

* --

* resolve conflict

* clea up

* old schema clean up

* further clean up

* removing unwanted merged responsibilities

* --

* improve DI and SOLID

* some type fixes

* --1

* clean up --cont

* fix DI in facade for test

* more fix

* fix

* checking

* o.o

* fix import

* fix failing test --2

* fix failing test --3

* fix failing test --4

* normalization use

* introduce facade container injection

* uniform async telemetry spans

* further improvements

* replace prismock with repo mocks

* ensure we don't pass prisma outside of repo

* fix import

* remove try catch from repo calls

* async await fixes

* using deps pattern

* more clean up and fixes

* more clean up

* address feedback --1

* separation of concern

* clean up

* test clean up

* feedback --2

* remove extra fetch

* remove await

* migrate _post test from prismock

* fix type

* --

* fix tokens path

* rename AuditRepo

* test --1

* update _post to integration test

* fix test

* fix test

* test fix maybe?

* --

* feedback

* feedback

* fixes

* more feedback

* NIT

* use sentry and logger imports as planned

* assertion in test

* add missing test case

* add tests for controllers and services

* NITs

* fix domain normalisation
2025-10-14 10:16:18 +03:00

120 lines
3.2 KiB
TypeScript

import type { User } from "@calcom/prisma/client";
import { WatchlistType } from "@calcom/prisma/enums";
import type { Watchlist } from "../types";
import { normalizeEmail, normalizeDomain, normalizeUsername } from "../utils/normalization";
import type { WatchlistEntryDTO, WatchlistListResponseDTO, BlockingCheckResultDTO } from "./types";
export function mapWatchlistToDTO(
watchlist: Watchlist & {
createdBy?: User | null;
updatedBy?: User | null;
}
): WatchlistEntryDTO {
return {
id: watchlist.id,
type: watchlist.type,
value: watchlist.value,
description: watchlist.description,
action: watchlist.action,
source: watchlist.source,
isGlobal: watchlist.isGlobal,
lastUpdatedAt: watchlist.lastUpdatedAt.toISOString(),
organizationId: watchlist.organizationId,
createdBy: watchlist.createdBy
? {
id: watchlist.createdBy.id,
name: watchlist.createdBy.name,
email: watchlist.createdBy.email,
avatarUrl: watchlist.createdBy.avatarUrl,
}
: null,
updatedBy: watchlist.updatedBy
? {
id: watchlist.updatedBy.id,
name: watchlist.updatedBy.name,
email: watchlist.updatedBy.email,
avatarUrl: watchlist.updatedBy.avatarUrl,
}
: null,
};
}
export function mapWatchlistListToDTO(
watchlists: Array<
Watchlist & {
createdBy?: User | null;
updatedBy?: User | null;
}
>,
pagination?: {
total: number;
page: number;
limit: number;
}
): WatchlistListResponseDTO {
return {
entries: watchlists.map(mapWatchlistToDTO),
pagination: pagination
? {
...pagination,
hasMore: pagination.page * pagination.limit < pagination.total,
}
: undefined,
};
}
export function mapBlockingResultToDTO(result: {
isBlocked: boolean;
reason?: WatchlistType;
watchlistEntry?: WatchlistEntryDTO | null;
}): BlockingCheckResultDTO {
return {
isBlocked: result.isBlocked,
reason: result.reason,
matchedEntry: result.watchlistEntry
? {
id: result.watchlistEntry.id,
type: result.watchlistEntry.type,
value: result.watchlistEntry.value,
action: result.watchlistEntry.action,
}
: undefined,
};
}
export function sanitizeWatchlistEntryDTO(dto: WatchlistEntryDTO): WatchlistEntryDTO {
return {
...dto,
createdBy: dto.createdBy
? {
id: dto.createdBy.id,
name: dto.createdBy.name,
email: "", // Hide email in public responses
avatarUrl: dto.createdBy.avatarUrl,
}
: null,
updatedBy: dto.updatedBy
? {
id: dto.updatedBy.id,
name: dto.updatedBy.name,
email: "", // Hide email in public responses
avatarUrl: dto.updatedBy.avatarUrl,
}
: null,
};
}
export function sanitizeWatchlistValue(type: WatchlistType, value: string): string {
switch (type) {
case WatchlistType.EMAIL:
return normalizeEmail(value);
case WatchlistType.DOMAIN:
return normalizeDomain(value);
case WatchlistType.USERNAME:
return normalizeUsername(value);
default:
return value.trim();
}
}