Skip to content

Commit f63164e

Browse files
feat(comments): add organization ID support for comment components (#1980)
Co-authored-by: Tofik Hasanov <[email protected]>
1 parent 002bb3e commit f63164e

File tree

14 files changed

+79
-22
lines changed

14 files changed

+79
-22
lines changed

apps/api/src/comments/comment-mention-notifier.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ function tryNormalizeContextUrl(params: {
7070
if (!allowedOrigins.has(url.origin)) return null;
7171

7272
// Ensure the URL is for the same org so we don't accidentally deep-link elsewhere.
73-
if (!url.pathname.includes(`/${organizationId}/`)) return null;
73+
// Use startsWith to prevent path traversal attacks (e.g., /attacker_org/victim_org/)
74+
if (!url.pathname.startsWith(`/${organizationId}/`)) return null;
7475

7576
return url.toString();
7677
} catch {

apps/app/src/app/(app)/[orgId]/policies/[policyId]/components/PolicyPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export default function PolicyPage({
1313
allControls,
1414
isPendingApproval,
1515
policyId,
16+
organizationId,
1617
logs,
1718
}: {
1819
policy: (Policy & { approver: (Member & { user: User }) | null }) | null;
@@ -21,6 +22,8 @@ export default function PolicyPage({
2122
allControls: Control[];
2223
isPendingApproval: boolean;
2324
policyId: string;
25+
/** Organization ID - required for correct org context in comments */
26+
organizationId: string;
2427
logs: AuditLogWithRelations[];
2528
}) {
2629
return (
@@ -42,7 +45,7 @@ export default function PolicyPage({
4245

4346
<RecentAuditLogs logs={logs} />
4447

45-
<Comments entityId={policyId} entityType="policy" />
48+
<Comments entityId={policyId} entityType="policy" organizationId={organizationId} />
4649
</>
4750
);
4851
}

apps/app/src/app/(app)/[orgId]/policies/[policyId]/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default async function PolicyDetails({
2929
<PolicyPage
3030
policy={policy}
3131
policyId={policyId}
32+
organizationId={orgId}
3233
assignees={assignees}
3334
mappedControls={mappedControls}
3435
allControls={allControls}

apps/app/src/app/(app)/[orgId]/risk/[riskId]/components/RiskActions.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ import { useState } from 'react';
2323
import { toast } from 'sonner';
2424
import { useSWRConfig } from 'swr';
2525

26-
export function RiskActions({ riskId }: { riskId: string }) {
26+
export function RiskActions({ riskId, orgId }: { riskId: string; orgId: string }) {
2727
const { mutate: globalMutate } = useSWRConfig();
2828
const [isConfirmOpen, setIsConfirmOpen] = useState(false);
2929

3030
// Get SWR mutate function to refresh risk data after mutations
31-
const { mutate: refreshRisk } = useRisk(riskId);
31+
// Pass orgId to ensure same cache key as RiskPageClient
32+
const { mutate: refreshRisk } = useRisk(riskId, { organizationId: orgId });
3233

3334
const regenerate = useAction(regenerateRiskMitigationAction, {
3435
onSuccess: () => {

apps/app/src/app/(app)/[orgId]/risk/[riskId]/components/RiskPageClient.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export function RiskPageClient({
8383
)}
8484
<TaskItems entityId={riskId} entityType="risk" organizationId={orgId} />
8585
{!isViewingTask && (
86-
<Comments entityId={riskId} entityType={CommentEntityType.risk} />
86+
<Comments entityId={riskId} entityType={CommentEntityType.risk} organizationId={orgId} />
8787
)}
8888
</div>
8989
);

apps/app/src/app/(app)/[orgId]/risk/[riskId]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export default async function RiskPage({ searchParams, params }: PageProps) {
4949
]
5050
: [{ label: risk.title, current: true }]),
5151
]}
52-
headerRight={<RiskActions riskId={riskId} />}
52+
headerRight={<RiskActions riskId={riskId} orgId={orgId} />}
5353
>
5454
<RiskPageClient
5555
riskId={riskId}

apps/app/src/app/(app)/[orgId]/tasks/[taskId]/components/SingleTask.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ export function SingleTask({
215215
<Comments
216216
entityId={task.id}
217217
entityType={CommentEntityType.task}
218+
organizationId={orgId}
218219
variant="inline"
219220
title=""
220221
/>

apps/app/src/app/(app)/[orgId]/vendors/[vendorId]/components/VendorActions.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ import { useState } from 'react';
2424
import { toast } from 'sonner';
2525
import { useSWRConfig } from 'swr';
2626

27-
export function VendorActions({ vendorId }: { vendorId: string }) {
27+
export function VendorActions({ vendorId, orgId }: { vendorId: string; orgId: string }) {
2828
const { mutate: globalMutate } = useSWRConfig();
2929
const [_, setOpen] = useQueryState('vendor-overview-sheet');
3030
const [isConfirmOpen, setIsConfirmOpen] = useState(false);
3131

3232
// Get SWR mutate function to refresh vendor data after mutations
33-
const { mutate: refreshVendor } = useVendor(vendorId);
33+
// Pass orgId to ensure same cache key as VendorPageClient
34+
const { mutate: refreshVendor } = useVendor(vendorId, { organizationId: orgId });
3435

3536
const regenerate = useAction(regenerateVendorMitigationAction, {
3637
onSuccess: () => {

apps/app/src/app/(app)/[orgId]/vendors/[vendorId]/components/VendorPageClient.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export function VendorPageClient({
100100
organizationId={orgId}
101101
/>
102102
{!isViewingTask && (
103-
<Comments entityId={vendorId} entityType={CommentEntityType.vendor} />
103+
<Comments entityId={vendorId} entityType={CommentEntityType.vendor} organizationId={orgId} />
104104
)}
105105
</div>
106106
</>

apps/app/src/app/(app)/[orgId]/vendors/[vendorId]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export default async function VendorPage({ params, searchParams }: PageProps) {
4949
current: !isViewingTask,
5050
},
5151
]}
52-
headerRight={<VendorActions vendorId={vendorId} />}
52+
headerRight={<VendorActions vendorId={vendorId} orgId={orgId} />}
5353
>
5454
<VendorPageClient
5555
vendorId={vendorId}

0 commit comments

Comments
 (0)