-
Notifications
You must be signed in to change notification settings - Fork 50
feat(team): enforce admin role and Pro plan for team invitations #1991
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
base: main
Are you sure you want to change the base?
feat(team): enforce admin role and Pro plan for team invitations #1991
Conversation
Add validation checks to sendInvitationsAction: - Verify current user has admin role before sending invitations - Verify current team is on Pro plan before allowing invitations
|
|
Finished running flow.
|
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.
Pull Request Overview
This PR adds access control and plan validation to team invitations by restricting invitation sending to admin users on Pro plans only.
- Validates that the current user has admin role before allowing invitations
- Ensures the team is on a Pro plan before permitting invitation functionality
- Reorganizes the function flow to perform validations before proceeding with invitation logic
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
|
|
||
| const currentTeam = await fetchCurrentTeam(); | ||
| if (!isProPlan(currentTeam)) { | ||
| throw new Error("Team invitations require a Pro plan"); |
Copilot
AI
Oct 14, 2025
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.
The error message should be more descriptive and include guidance on how to upgrade. Consider: 'Team invitations are only available on Pro plans. Please upgrade your plan to send invitations.'
| throw new Error("Team invitations require a Pro plan"); | |
| throw new Error("Team invitations are only available on Pro plans. Please upgrade your plan to send invitations."); |
| !currentUserRoleResult.success || | ||
| currentUserRoleResult.data !== "admin" | ||
| ) { | ||
| throw new Error("Only admin users can send invitations"); |
Copilot
AI
Oct 14, 2025
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.
The error message should be more user-friendly and descriptive. Consider: 'You must be a team admin to send invitations. Please contact your team admin for assistance.'
| throw new Error("Only admin users can send invitations"); | |
| throw new Error("You must be a team admin to send invitations. Please contact your team admin for assistance."); |
WalkthroughAdds admin-role authorization and Pro plan checks to sendInvitationsAction before fetching the current user. On failure, the action throws early. If checks pass, it proceeds with the existing per-email invitation creation, email dispatch, and error aggregation logic. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User
participant A as sendInvitationsAction
participant R as getCurrentUserRole
participant P as getCurrentTeamPlan
participant C as getCurrentUser
participant I as createInvitation
participant E as sendEmail
U->>A: invoke with email list
A->>R: fetch current user role
R-->>A: role
alt Not Admin
A-->>U: throw "not authorized"
else Admin
A->>P: fetch team plan
P-->>A: plan (Pro/Other)
alt Not Pro
A-->>U: throw "plan not eligible"
else Pro
A->>C: get current user
C-->>A: user
loop for each email
A->>I: create invitation
I-->>A: invitation|error
alt created
A->>E: send invitation email
E-->>A: sent|error
end
end
A-->>U: aggregated results
end
end
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Compliance Guide 🔍Below is a summary of compliance checks for this PR:
Compliance status legend🟢 - Fully Compliant🟡 - Partial Compliant 🔴 - Not Compliant ⚪ - Requires Further Human Verification 🏷️ - Compliance label |
||||||||||||||||||
PR Code Suggestions ✨Explore these optional code suggestions:
|
||||||||||||
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.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/studio.giselles.ai/app/(main)/settings/team/actions.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/development-guide.mdc)
**/*.{ts,tsx}: Use Biome for formatting with tab indentation and double quotes
Follow organized imports pattern (enabled in biome.json)
Use TypeScript for type safety; avoidanytypes
Use Next.js patterns for web applications
Use async/await for asynchronous code rather than promises
Error handling: use try/catch blocks and propagate errors appropriately
Use kebab-case for all filenames (e.g.,user-profile.ts)
Use camelCase for variables, functions, and methods (e.g.,userEmail)
Use prefixes likeis,has,can,shouldfor boolean variables and functions for clarity
Use verbs or verb phrases that clearly indicate purpose for function naming (e.g.,calculateTotalPrice(), notprocess())If breaking changes are introduced in new AI SDK versions, update code to accommodate those changes
**/*.{ts,tsx}: Avoid using theanytype in TypeScript
Use async/await for asynchronous code and include proper error handling
Variables and functions should be camelCase
Boolean variables and functions should use is/has/can/should prefixes where appropriate
Function names should clearly indicate their purpose
Files:
apps/studio.giselles.ai/app/(main)/settings/team/actions.ts
**/*
📄 CodeRabbit inference engine (.cursor/rules/naming-guide.mdc)
All filenames should use kebab-case (lowercase with hyphens)
Files:
apps/studio.giselles.ai/app/(main)/settings/team/actions.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/naming-guide.mdc)
**/*.{js,jsx,ts,tsx}: React components and classes should use PascalCase
Variables, functions, and methods should use camelCase
Use verbs or verb phrases for function names; names should clearly indicate what the function does; avoid ambiguous names that could lead to misuse
Use nouns or noun phrases for variable names; names should describe what the variable represents; avoid single-letter variables except in very short scopes
Use prefixes like 'is', 'has', 'can', 'should' for both variables and functions returning boolean values; make the true/false meaning clear
Files:
apps/studio.giselles.ai/app/(main)/settings/team/actions.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: check
🔇 Additional comments (2)
apps/studio.giselles.ai/app/(main)/settings/team/actions.ts (2)
636-636: Efficient optimization by deferring user fetch.Moving
fetchCurrentUserafter the authorization checks avoids an unnecessary database call when permission checks fail. The user data is still correctly passed tocreateInvitationon line 646.
623-629: Add missing Pro plan check to resendInvitationAction
invite-member-dialoghandles thrown errors fromsendInvitationsAction.resendInvitationActioncurrently only enforces admin role—mirror the Pro plan check fromsendInvitationsActionfor consistency.
| const currentTeam = await fetchCurrentTeam(); | ||
| if (!isProPlan(currentTeam)) { | ||
| throw new Error("Team invitations require a Pro plan"); | ||
| } |
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.
Pro plan validation is correct, but resendInvitationAction lacks the same check.
The Pro plan check appropriately restricts team invitations to Pro plan teams, consistent with the PR objective.
However, resendInvitationAction (lines 732-773) creates a new invitation (line 757) without validating the Pro plan. This inconsistency allows non-Pro teams to bypass the restriction by resending existing invitations.
Add the Pro plan check to resendInvitationAction after the admin check:
export async function resendInvitationAction(
_prevState: ActionResult | undefined,
formData: FormData,
): Promise<ActionResult> {
const token = formData.get("token") as string;
try {
// Check if current user is admin
const currentUserRoleResult = await getCurrentUserRole();
if (
!currentUserRoleResult.success ||
currentUserRoleResult.data !== "admin"
) {
throw new Error("Only admin users can resend invitations");
}
const invitations = await listInvitations();
const invitation = invitations.find((inv) => inv.token === token);
if (!invitation) {
throw new Error("Invitation not found");
}
// 1. revoke existing invitation
await revokeInvitation(token);
// 2. create new invitation
const currentTeam = await fetchCurrentTeam();
+ if (!isProPlan(currentTeam)) {
+ throw new Error("Team invitations require a Pro plan");
+ }
const currentUser = await fetchCurrentUser();
const newInvitation = await createInvitation(
invitation.email,
invitation.role,
currentTeam,
currentUser,
);
// 3. send invitation email
await sendInvitationEmail(newInvitation);
revalidatePath("/settings/team/members");
return { success: true };
} catch (e: unknown) {
return {
success: false,
error: e instanceof Error ? e.message : "Unknown error",
};
}
}
🔍 QA Testing Assistant by Giselle📋 Manual QA ChecklistBased on the changes in this PR, here are the key areas to test manually:
✨ Prompt for AI AgentsUse the following prompts with Cursor or Claude Code to automate E2E testing: 📝 E2E Test Generation Prompt |
User description
Summary
Enforce admin role and Pro plan for team invitations.
Related Issue
None.
Changes
Add validation checks to sendInvitationsAction:
Testing
Other Information
PR Type
Enhancement
Description
Add admin role validation before sending team invitations
Add Pro plan requirement check for team invitation feature
Reorder user and team fetching logic for early validation
Diagram Walkthrough
File Walkthrough
actions.ts
Add role and plan validation to invitation actionapps/studio.giselles.ai/app/(main)/settings/team/actions.ts
getCurrentUserRole()check to verify admin permissions beforesending invitations
isProPlan()validation to ensure team has Pro plan subscriptionNote
Gate
sendInvitationsActionbehind admin role and Pro plan checks, throwing errors if unmet.getCurrentUserRole()inapps/studio.giselles.ai/app/(main)/settings/team/actions.ts.isProPlan(currentTeam)before creating invitations.currentUserafter permission/plan checks.Written by Cursor Bugbot for commit 0c10ab2. This will update automatically on new commits. Configure here.
Summary by CodeRabbit