-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Reward Logic #2673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reward Logic #2673
Changes from all commits
0d1269e
bf1f329
ce36c8f
0b8aa60
2d1f815
407ad1e
8d8f5c1
7c00bfd
e413adf
15a0421
447bb83
e9760f6
3a13c2b
03ba9ee
62333f5
bd2ddbf
df673d0
febf0db
81bb21b
3d83003
06e3542
57c3b7b
377518b
6a4839c
0fee4f2
d072c0f
806a88a
7c140e3
e3daabe
8e70d0d
771cf17
eef1e6d
420bc73
06d940a
79f304d
472e9a6
9909f9f
7663d31
189cfc6
b4337bf
9ea1395
e73bab0
d74812b
439c3ca
9429df8
dee0263
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3,11 +3,13 @@ | |||||||||||||||||||||||||||||||||||||||||
import { recordAuditLog } from "@/lib/api/audit-logs/record-audit-log"; | ||||||||||||||||||||||||||||||||||||||||||
import { getRewardOrThrow } from "@/lib/api/partners/get-reward-or-throw"; | ||||||||||||||||||||||||||||||||||||||||||
import { getDefaultProgramIdOrThrow } from "@/lib/api/programs/get-default-program-id-or-throw"; | ||||||||||||||||||||||||||||||||||||||||||
import { getPlanCapabilities } from "@/lib/plan-capabilities"; | ||||||||||||||||||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||||||||||||||||||
REWARD_EVENT_COLUMN_MAPPING, | ||||||||||||||||||||||||||||||||||||||||||
updateRewardSchema, | ||||||||||||||||||||||||||||||||||||||||||
} from "@/lib/zod/schemas/rewards"; | ||||||||||||||||||||||||||||||||||||||||||
import { prisma } from "@dub/prisma"; | ||||||||||||||||||||||||||||||||||||||||||
import { Prisma } from "@dub/prisma/client"; | ||||||||||||||||||||||||||||||||||||||||||
import { Reward } from "@prisma/client"; | ||||||||||||||||||||||||||||||||||||||||||
import { waitUntil } from "@vercel/functions"; | ||||||||||||||||||||||||||||||||||||||||||
import { authActionClient } from "../safe-action"; | ||||||||||||||||||||||||||||||||||||||||||
|
@@ -23,6 +25,7 @@ export const updateRewardAction = authActionClient | |||||||||||||||||||||||||||||||||||||||||
type, | ||||||||||||||||||||||||||||||||||||||||||
includedPartnerIds, | ||||||||||||||||||||||||||||||||||||||||||
excludedPartnerIds, | ||||||||||||||||||||||||||||||||||||||||||
modifiers, | ||||||||||||||||||||||||||||||||||||||||||
} = parsedInput; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
includedPartnerIds = includedPartnerIds || []; | ||||||||||||||||||||||||||||||||||||||||||
|
@@ -35,6 +38,14 @@ export const updateRewardAction = authActionClient | |||||||||||||||||||||||||||||||||||||||||
programId, | ||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||
modifiers && | ||||||||||||||||||||||||||||||||||||||||||
!getPlanCapabilities(workspace.plan).canUseAdvancedRewardLogic | ||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||
throw new Error( | ||||||||||||||||||||||||||||||||||||||||||
"Advanced reward structures are only available on the Advanced plan and above.", | ||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+41
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Plan capability bypass risk The plan capability check occurs after extracting modifiers from user input. If workspace data is stale or manipulated, this validation could be bypassed, allowing unauthorized access to advanced features. Consider refreshing workspace plan validation and adding server-side double-checking: + // Refresh workspace to ensure latest plan data
+ const refreshedWorkspace = await prisma.workspace.findUnique({
+ where: { id: workspace.id },
+ select: { plan: true }
+ });
+
if (
modifiers &&
- !getPlanCapabilities(workspace.plan).canUseAdvancedRewardLogic
+ !getPlanCapabilities(refreshedWorkspace?.plan || workspace.plan).canUseAdvancedRewardLogic
) 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
const finalPartnerIds = [...includedPartnerIds, ...excludedPartnerIds]; | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
if (finalPartnerIds && finalPartnerIds.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||
|
@@ -66,6 +77,7 @@ export const updateRewardAction = authActionClient | |||||||||||||||||||||||||||||||||||||||||
type, | ||||||||||||||||||||||||||||||||||||||||||
amount, | ||||||||||||||||||||||||||||||||||||||||||
maxDuration, | ||||||||||||||||||||||||||||||||||||||||||
modifiers: modifiers === null ? Prisma.JsonNull : modifiers, | ||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Plan capability bypass risk
Same security concern as in update-reward.ts - the plan capability check occurs after extracting modifiers and could be bypassed if workspace data is stale.
Apply the same fix as recommended for update-reward.ts:
📝 Committable suggestion
🤖 Prompt for AI Agents