Skip to content

Commit b2f5b15

Browse files
authored
Remove partnerFraudReport fraud flag (dubinc#3662)
1 parent 69bb6c4 commit b2f5b15

18 files changed

Lines changed: 268 additions & 208 deletions

File tree

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/partners/applications/page-client.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import useWorkspace from "@/lib/swr/use-workspace";
99
import { EnrolledPartnerProps, PartnerPlatformProps } from "@/lib/types";
1010
import { useBulkApprovePartnersModal } from "@/ui/modals/bulk-approve-partners-modal";
1111
import { useBulkRejectPartnersModal } from "@/ui/modals/bulk-reject-partners-modal";
12+
import { useApprovePartnerApplicationModal } from "@/ui/modals/approve-partner-application-modal";
1213
import { useRejectPartnerApplicationModal } from "@/ui/modals/reject-partner-application-modal";
1314
import { GroupColorCircle } from "@/ui/partners/groups/group-color-circle";
1415
import { PartnerApplicationSheet } from "@/ui/partners/partner-application-sheet";
@@ -30,7 +31,7 @@ import {
3031
useRouterStuff,
3132
useTable,
3233
} from "@dub/ui";
33-
import { Dots, Users, UserXmark } from "@dub/ui/icons";
34+
import { Dots, UserCheck, Users, UserXmark } from "@dub/ui/icons";
3435
import { COUNTRIES, fetcher, formatDate } from "@dub/utils";
3536
import { Row } from "@tanstack/react-table";
3637
import { Command } from "cmdk";
@@ -512,6 +513,17 @@ function RowMenuButton({
512513
}) {
513514
const [isOpen, setIsOpen] = useState(false);
514515

516+
const {
517+
ApprovePartnerApplicationModal,
518+
setShowApprovePartnerApplicationModal,
519+
} = useApprovePartnerApplicationModal({
520+
partner: row.original,
521+
groupId: row.original.groupId,
522+
onConfirm: async () => {
523+
await mutatePrefix(["/api/partners", "/api/partners/count"]);
524+
},
525+
});
526+
515527
const {
516528
RejectPartnerApplicationModal,
517529
setShowRejectPartnerApplicationModal,
@@ -524,13 +536,24 @@ function RowMenuButton({
524536

525537
return (
526538
<>
539+
{ApprovePartnerApplicationModal}
527540
{RejectPartnerApplicationModal}
528541
<Popover
529542
openPopover={isOpen}
530543
setOpenPopover={setIsOpen}
531544
content={
532545
<Command tabIndex={0} loop className="focus:outline-none">
533546
<Command.List className="flex w-screen flex-col gap-1 p-1.5 text-sm focus-visible:outline-none sm:w-auto sm:min-w-[200px]">
547+
<MenuItem
548+
as={Command.Item}
549+
icon={UserCheck}
550+
onSelect={() => {
551+
setIsOpen(false);
552+
setShowApprovePartnerApplicationModal(true);
553+
}}
554+
>
555+
Approve application
556+
</MenuItem>
534557
<MenuItem
535558
as={Command.Item}
536559
icon={UserXmark}

apps/web/lib/actions/partners/bulk-reject-partner-applications.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use server";
22

33
import { recordAuditLog } from "@/lib/api/audit-logs/record-audit-log";
4-
import { reportFraudToNetwork } from "@/lib/api/fraud/report-fraud-to-network";
54
import { resolveFraudGroups } from "@/lib/api/fraud/resolve-fraud-groups";
65
import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw";
76
import { bulkRejectPartnersSchema } from "@/lib/zod/schemas/partners";
@@ -16,7 +15,7 @@ export const bulkRejectPartnerApplicationsAction = authActionClient
1615
.inputSchema(bulkRejectPartnersSchema)
1716
.action(async ({ parsedInput, ctx }) => {
1817
const { workspace, user } = ctx;
19-
const { partnerIds, reportFraud } = parsedInput;
18+
const { partnerIds } = parsedInput;
2019

2120
throwIfNoPermission({
2221
role: workspace.role,
@@ -71,10 +70,6 @@ export const bulkRejectPartnerApplicationsAction = authActionClient
7170
"Resolved automatically because the partner application was rejected.",
7271
});
7372

74-
const rejectedPartnerIds = [
75-
...new Set(programEnrollments.map((pe) => pe.partner.id)),
76-
];
77-
7873
waitUntil(
7974
(async () => {
8075
await Promise.allSettled([
@@ -94,13 +89,6 @@ export const bulkRejectPartnerApplicationsAction = authActionClient
9489
],
9590
})),
9691
),
97-
98-
reportFraud && rejectedPartnerIds.length > 0
99-
? reportFraudToNetwork({
100-
programId,
101-
partnerIds: rejectedPartnerIds,
102-
})
103-
: Promise.resolve(),
10492
]);
10593
})(),
10694
);

apps/web/lib/actions/partners/reject-partner-application.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use server";
22

33
import { recordAuditLog } from "@/lib/api/audit-logs/record-audit-log";
4-
import { reportFraudToNetwork } from "@/lib/api/fraud/report-fraud-to-network";
54
import { resolveFraudGroups } from "@/lib/api/fraud/resolve-fraud-groups";
65
import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw";
76
import { rejectPartnerSchema } from "@/lib/zod/schemas/partners";
@@ -16,7 +15,7 @@ export const rejectPartnerApplicationAction = authActionClient
1615
.inputSchema(rejectPartnerSchema)
1716
.action(async ({ parsedInput, ctx }) => {
1817
const { workspace, user } = ctx;
19-
const { partnerId, reportFraud } = parsedInput;
18+
const { partnerId } = parsedInput;
2019

2120
throwIfNoPermission({
2221
role: workspace.role,
@@ -84,13 +83,6 @@ export const rejectPartnerApplicationAction = authActionClient
8483
resolutionReason:
8584
"Resolved automatically because the partner application was rejected.",
8685
}),
87-
88-
reportFraud
89-
? reportFraudToNetwork({
90-
programId,
91-
partnerIds: [partnerId],
92-
})
93-
: Promise.resolve(),
9486
]);
9587
})(),
9688
);

apps/web/lib/api/fraud/constants.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,6 @@ export const FRAUD_RULES: FraudRuleInfo[] = [
3838
},
3939

4040
// Partner rules
41-
{
42-
type: "partnerFraudReport",
43-
name: "Fraud report",
44-
description:
45-
"This partner was rejected from another program due to suspected fraud during their application.",
46-
scope: "partner",
47-
severity: "high",
48-
configurable: true,
49-
},
5041
{
5142
type: "partnerCrossProgramBan",
5243
name: "Cross-program ban",

apps/web/lib/api/fraud/execute-fraud-rule.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ const FRAUD_RULES_REGISTRY: Record<
2323
referralSourceBanned: checkReferralSourceBanned,
2424
paidTrafficDetected: checkPaidTrafficDetected,
2525
partnerCrossProgramBan: defineFraudRuleStub("partnerCrossProgramBan"),
26-
partnerFraudReport: defineFraudRuleStub("partnerFraudReport"),
2726
partnerDuplicatePayoutMethod: defineFraudRuleStub(
2827
"partnerDuplicatePayoutMethod",
2928
),

apps/web/lib/api/fraud/report-fraud-to-network.ts

Lines changed: 0 additions & 69 deletions
This file was deleted.

apps/web/lib/api/fraud/utils.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ function getIdentityFieldsForFraudEvent({
102102
return {
103103
sourceProgramId,
104104
};
105-
106-
case "partnerFraudReport":
107-
return {};
108105
}
109106
}
110107

apps/web/lib/zod/schemas/fraud.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,6 @@ export const updateFraudRuleSettingsSchema = z.object({
247247
customerEmailSuspiciousDomain: toggleOnlyFraudRuleSchema,
248248
partnerCrossProgramBan: toggleOnlyFraudRuleSchema,
249249
partnerDuplicatePayoutMethod: toggleOnlyFraudRuleSchema,
250-
partnerFraudReport: toggleOnlyFraudRuleSchema,
251250
});
252251

253252
const baseFraudEventSchema = z.object({
@@ -322,6 +321,4 @@ export const fraudEventSchemas = {
322321
}),
323322

324323
partnerDuplicatePayoutMethod: baseFraudEventSchema,
325-
326-
partnerFraudReport: baseFraudEventSchema,
327324
};

apps/web/lib/zod/schemas/partners.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -847,13 +847,6 @@ export const bulkApprovePartnersSchema = z.object({
847847
export const rejectPartnerSchema = z.object({
848848
workspaceId: z.string(),
849849
partnerId: z.string(),
850-
reportFraud: z
851-
.boolean()
852-
.optional()
853-
.default(false)
854-
.describe(
855-
"Whether to report this partner for suspected fraud to help keep the network safe.",
856-
),
857850
});
858851

859852
export const bulkRejectPartnersSchema = z.object({
@@ -863,13 +856,6 @@ export const bulkRejectPartnersSchema = z.object({
863856
.max(100)
864857
.min(1)
865858
.transform((v) => [...new Set(v)]),
866-
reportFraud: z
867-
.boolean()
868-
.optional()
869-
.default(false)
870-
.describe(
871-
"Whether to report these partners for suspected fraud to help keep the network safe.",
872-
),
873859
});
874860

875861
export const retrievePartnerLinksSchema = partnerIdTenantIdSchema;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* One-off: removes FraudRule rows, FraudEventGroup rows, and FraudEvent rows
3+
* for the retired `partnerFraudReport` rule type.
4+
*
5+
* Run **before** deploying the schema that drops `partnerFraudReport` from
6+
* `FraudRuleType` (so the Prisma client still knows the value), or use the
7+
* `as any` casts below so it still type-checks after the enum is removed.
8+
*
9+
* Usage (from `apps/web`):
10+
* pnpm script migrations/remove-partner-fraud-report-fraud-data
11+
*/
12+
import { prisma } from "@dub/prisma";
13+
import "dotenv-flow/config";
14+
15+
async function main() {
16+
const legacyGroupWhere = { type: "partnerFraudReport" } as any;
17+
18+
const eventDelete = await prisma.fraudEvent.deleteMany({
19+
where: {
20+
fraudEventGroup: legacyGroupWhere,
21+
},
22+
});
23+
24+
console.log(`Deleted ${eventDelete.count} fraud events`);
25+
26+
const groupDelete = await prisma.fraudEventGroup.deleteMany({
27+
where: legacyGroupWhere,
28+
});
29+
30+
console.log(`Deleted ${groupDelete.count} fraud event groups`);
31+
32+
const ruleDelete = await prisma.fraudRule.deleteMany({
33+
where: legacyGroupWhere,
34+
});
35+
36+
console.log(`Deleted ${ruleDelete.count} fraud rules`);
37+
}
38+
39+
main()
40+
.catch((e) => {
41+
console.error(e);
42+
process.exit(1);
43+
})
44+
.finally(async () => {
45+
await prisma.$disconnect();
46+
});

0 commit comments

Comments
 (0)