From 6883a148d8eda111b4762a9a16fbd326c5fd04d0 Mon Sep 17 00:00:00 2001 From: Juan Mrad Date: Tue, 14 Apr 2026 22:27:59 -0500 Subject: [PATCH] [Vulnerabilities] Remove lodash by migrating from better mutation to plugin-functional and fix minor lint warnings (#216) * [Vulnerabilities] Remove lodash by migrating from better mutation to plugin-functional and fix minor lint wwarnings * remove bad merge main --- client/src/components/ErrorBoundary.tsx | 2 +- client/src/utils/itemUtils.ts | 2 +- client/src/utils/tree.test.ts | 2 +- client/src/utils/tree.ts | 2 +- client/src/webpages/App.tsx | 16 +- .../item_types/ItemTypeRequestCodeSamples.tsx | 2 +- ...wQueueRuleConditionMediaMatchingValues.tsx | 25 +- .../ReportingRuleInsightsActionsChart.tsx | 4 +- .../RuleFormConditionMatchingValues.tsx | 9 +- .../RuleFormSignalModalSubcategoryGallery.tsx | 29 +-- server/.eslintrc.cjs | 19 +- server/api.ts | 4 +- server/condition_evaluator/conditionSet.ts | 29 ++- server/eslint.config.mjs | 14 +- server/graphql/datasources/RuleApi.ts | 29 +-- server/graphql/datasources/UserApi.ts | 19 +- server/graphql/modules/actionStatistics.ts | 10 +- server/graphql/modules/insights.ts | 2 +- server/graphql/modules/signal.test.ts | 1 - server/iocContainer/index.ts | 152 ++++++------ server/package-lock.json | 192 +++++++++------ server/package.json | 5 +- server/routes/content/ContentRoutes.test.ts | 13 +- server/routes/gdpr/gdprRoutes.test.ts | 12 +- server/routes/index.test.ts | 15 +- server/routes/index.ts | 1 - .../integration_logos/serveIntegrationLogo.ts | 8 +- .../serveIntegrationLogoWithBackground.ts | 10 +- server/routes/items/ItemRoutes.test.ts | 12 +- server/routes/policies/PoliciesRoutes.test.ts | 10 +- .../routes/reporting/ReportingRoutes.test.ts | 9 +- server/routes/reporting/submitAppeal.ts | 5 +- server/routes/reporting/submitReport.ts | 64 ++--- server/rule_engine/ActionPublisher.test.ts | 218 +++++++++--------- server/rule_engine/ActionPublisher.ts | 22 +- .../actionStatisticsService.ts | 12 +- .../analyticsLoggers/ContentApiLogger.ts | 2 +- .../analyticsLoggers/ItemModelScoreLogger.ts | 2 +- .../itemInvestigationService.test.ts | 3 +- .../extractItemDataValues.ts | 2 +- .../fieldTypeHandlers.test.ts | 1 - .../manualReviewToolService.test.ts | 3 +- .../manualReviewToolService.ts | 37 +-- .../modules/JobDecisioning.ts | 2 +- .../modules/JobEnrichment.ts | 7 +- .../modules/JobRouting.test.ts | 18 +- .../moderationConfigService.test.ts | 32 +-- .../moderationConfigService.ts | 4 +- .../ncmecService/ncmecEnqueueToMrt.ts | 89 +++---- .../services/ncmecService/ncmecReporting.ts | 76 +++--- .../signalExecutionService.test.ts | 24 +- .../detectRulePassRateAnomaliesJob.test.ts | 10 +- .../getRuleAnomalyDetectionStatistics.test.ts | 12 +- .../ruleHistoryService.test.ts | 2 +- .../signalAuthService/signalAuthService.ts | 16 +- .../services/signalsService/SignalsService.ts | 26 +-- .../helpers/instantiateBuiltInSignals.ts | 1 - .../aggregation/AggregationSignal.test.ts | 18 +- .../GoogleContentSafetyImageSignal.ts | 2 +- .../content_safety/googleContentSafetyLib.ts | 9 +- .../moderation/openAIModerationUtils.ts | 1 - .../OpenAiWhisperTranscriptionSignal.ts | 1 - .../zentropi/zentropiUtils.ts | 8 +- .../computeUserScore.test.ts | 1 - .../userStatisticsService/computeUserScore.ts | 2 - .../fetchUserActionStatistics.test.ts | 7 +- .../fetchUserSubmissionStatistics.test.ts | 7 +- .../userStrikeService.test.ts | 3 +- .../dataWarehouse/ClickhouseAdapter.ts | 32 ++- .../dataWarehouse/DataWarehouseFactory.ts | 72 +++--- server/test/extendExpect.ts | 2 +- server/test/mockHelpers/jestMocks.ts | 2 +- server/test/setupMockedServer.ts | 29 ++- .../getRuleAnomalyDetectionStatistics.ts | 1 - server/test/utils.ts | 8 +- server/utils/encoding.ts | 1 - server/utils/iterables.test.ts | 13 +- server/utils/language.ts | 1 - server/utils/misc.ts | 1 - server/utils/url.test.ts | 3 - .../RetryFailedNcmecDecisionsJob.ts | 111 ++++----- 81 files changed, 923 insertions(+), 761 deletions(-) diff --git a/client/src/components/ErrorBoundary.tsx b/client/src/components/ErrorBoundary.tsx index 04828db..042935b 100644 --- a/client/src/components/ErrorBoundary.tsx +++ b/client/src/components/ErrorBoundary.tsx @@ -13,7 +13,7 @@ const withNavigate = }; // This is used twice so it has to be extracted into an interface -// eslint-disable-next-line no-restricted-syntax + interface ErrorBoundaryProps { children: React.ReactNode; buttonTitle?: string; diff --git a/client/src/utils/itemUtils.ts b/client/src/utils/itemUtils.ts index 3c28205..de0bf6d 100644 --- a/client/src/utils/itemUtils.ts +++ b/client/src/utils/itemUtils.ts @@ -82,7 +82,7 @@ export function getFieldValueForRole< if (Array.isArray(fieldValue)) { throw new Error('Unexpected array when getting field value'); } - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + return fieldValue.value satisfies ScalarTypeRuntimeType as ScalarTypeRuntimeType< FieldRoleToScalarType[Role & keyof FieldRoleToScalarType] >; diff --git a/client/src/utils/tree.test.ts b/client/src/utils/tree.test.ts index 06ecfc1..127be22 100644 --- a/client/src/utils/tree.test.ts +++ b/client/src/utils/tree.test.ts @@ -43,7 +43,7 @@ describe('Tree tests', () => { const filteredTree = tree.filterTree((node) => node.includes(filterString)); expect(filteredTree).not.toBeNull(); - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + const filteredTreeValues = convertTreeToList(filteredTree!); expect( filteredTreeValues diff --git a/client/src/utils/tree.ts b/client/src/utils/tree.ts index b0e0b44..5e573ce 100644 --- a/client/src/utils/tree.ts +++ b/client/src/utils/tree.ts @@ -89,7 +89,7 @@ export class Tree { size() { let size = 0; - // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const _ of this.preOrderTraversal()) { size++; } diff --git a/client/src/webpages/App.tsx b/client/src/webpages/App.tsx index cc1d547..9b87bbe 100644 --- a/client/src/webpages/App.tsx +++ b/client/src/webpages/App.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/jsx-key */ import React, { Suspense } from 'react'; import { createBrowserRouter, @@ -15,11 +14,16 @@ import { useGQLUserAndOrgQuery } from '../graphql/generated'; import { RequireAuth, RequireLoggedOut } from '../routing/auth'; import AwaitingApproval from './auth/AwaitingApproval'; import RejectedByAdmin from './auth/RejectedByAdmin'; + import './dashboard/Dashboard.css'; const Login = React.lazy(async () => import('./auth/Login')); -const ForgotPassword = React.lazy(async () => import('./auth/forgot_password/ForgotPassword')); -const ResetPassword = React.lazy(async () => import('./auth/forgot_password/ResetPassword')); +const ForgotPassword = React.lazy( + async () => import('./auth/forgot_password/ForgotPassword'), +); +const ResetPassword = React.lazy( + async () => import('./auth/forgot_password/ResetPassword'), +); const SignUp = React.lazy(async () => import('./auth/SignUp')); const LoginSSO = React.lazy(async () => import('./auth/LoginSSO')); /** @@ -37,16 +41,16 @@ const LoginSSO = React.lazy(async () => import('./auth/LoginSSO')); function RootRedirect() { const { loading, data } = useGQLUserAndOrgQuery(); - + if (loading) { return ; } - + // If user is logged in, redirect to dashboard, otherwise to login if (data?.me) { return ; } - + return ; } diff --git a/client/src/webpages/dashboard/item_types/ItemTypeRequestCodeSamples.tsx b/client/src/webpages/dashboard/item_types/ItemTypeRequestCodeSamples.tsx index d0f2c66..e41e415 100644 --- a/client/src/webpages/dashboard/item_types/ItemTypeRequestCodeSamples.tsx +++ b/client/src/webpages/dashboard/item_types/ItemTypeRequestCodeSamples.tsx @@ -99,7 +99,7 @@ export default function ItemTypeRequestCodeSamples(props: { }} style={{ ...atelierSulphurpoolLight, - // eslint-disable-next-line id-denylist + 'hljs-string': { color: '#75787B', }, diff --git a/client/src/webpages/dashboard/mrt/queue_routing/condition/matching_values/ManualReviewQueueRuleConditionMediaMatchingValues.tsx b/client/src/webpages/dashboard/mrt/queue_routing/condition/matching_values/ManualReviewQueueRuleConditionMediaMatchingValues.tsx index 8d290ac..a0f7783 100644 --- a/client/src/webpages/dashboard/mrt/queue_routing/condition/matching_values/ManualReviewQueueRuleConditionMediaMatchingValues.tsx +++ b/client/src/webpages/dashboard/mrt/queue_routing/condition/matching_values/ManualReviewQueueRuleConditionMediaMatchingValues.tsx @@ -1,8 +1,8 @@ -/* eslint-disable no-console */ import { Select } from 'antd'; import ComponentLoading from '../../../../../../components/common/ComponentLoading'; import { selectFilterByLabelOption } from '@/webpages/dashboard/components/antDesignUtils'; + import { useGQLHashBanksQuery } from '../../../../../../graphql/generated'; import { RuleFormLeafCondition } from '../../../../rules/types'; import { ManualReviewQueueRoutingStaticTokenField } from '../../ManualReviewQueueRoutingStaticField'; @@ -15,7 +15,12 @@ export default function ManualReviewQueueRuleConditionMediaMatchingValues(props: onUpdateSelectedBankIds(imageBankIds: readonly string[]): void; allConditions?: RuleFormLeafCondition[]; }) { - const { condition, editing, onUpdateSelectedBankIds, allConditions = [] } = props; + const { + condition, + editing, + onUpdateSelectedBankIds, + allConditions = [], + } = props; const { loading, error, data } = useGQLHashBanksQuery(); const hashBanks = data?.hashBanks ?? []; @@ -24,7 +29,7 @@ export default function ManualReviewQueueRuleConditionMediaMatchingValues(props: const selectedBankIds = new Set( allConditions .filter((c) => c !== condition) // Exclude current condition by reference - .flatMap((c) => c.matchingValues?.imageBankIds ?? []) + .flatMap((c) => c.matchingValues?.imageBankIds ?? []), ); if (loading) { @@ -48,9 +53,9 @@ export default function ManualReviewQueueRuleConditionMediaMatchingValues(props: dropdownMatchSelectWidth={false} > {hashBanks.map((bank) => ( -