Skip to content

Add sponsor role feature - gate Create access to sponsors#254

Merged
Benjtalkshow merged 2 commits into
boundlessfi:mainfrom
Delightech28:feature/sponsor-role
May 30, 2026
Merged

Add sponsor role feature - gate Create access to sponsors#254
Benjtalkshow merged 2 commits into
boundlessfi:mainfrom
Delightech28:feature/sponsor-role

Conversation

@Delightech28
Copy link
Copy Markdown
Contributor

@Delightech28 Delightech28 commented May 29, 2026

Add sponsor role to user session and gate Create access

Description

Restricts bounty creation to users with a sponsor role. Previously, any authenticated user could create a bounty. This change implements a role-based access control system with sponsor and contributor roles.

Related Issue

Closes #207

Changes Made

1. Extended User Session Type

  • Added role: "sponsor" | "contributor" field to User interface
  • Defaults to "contributor" for existing users
  • Uses the inferAdditionalFields plugin that's already in place

Files:

  • lib/server-auth.ts - Updated User interface and getCurrentUser()
  • lib/auth-client.ts - Added role to inferAdditionalFields plugin
  • hooks/use-user-mutations.ts - Added role to UpdateUserParams

2. Gated Navbar Create Link

  • Create link only visible when role === "sponsor"
  • Uses authClient.useSession() to read role from session

File: components/global-navbar.tsx

3. Protected Create Route

  • /bounty/create now checks user role on mount
  • Non-sponsors are automatically redirected to /bounty
  • Shows nothing while checking authentication

File: app/bounty/create/page.tsx

4. Settings Role Toggle

  • New "Sponsor Access" section in settings under Account Settings
  • Toggle button allows contributors to promote to sponsor (and vice versa)
  • Changes persist via useUpdateUserMutation()
  • Updates are reflected after next page navigation

File: components/settings/profile-tab.tsx

Acceptance Criteria

  • Contributors do not see the Create link in the navbar
  • Visiting /bounty/create as a contributor redirects to /bounty
  • Sponsors see Create in the navbar and the form on /bounty/create
  • Settings has a toggle to promote a contributor to sponsor (and back)
  • Changes are reflected after page navigation

Testing Checklist

  • Test as contributor user - Create link should be hidden
  • Test as contributor accessing /bounty/create - should redirect to /bounty
  • Test toggling contributor → sponsor in settings - Create link should appear
  • Test toggling sponsor → contributor in settings - Create link should disappear
  • Test page refresh after role change - role should persist

Notes

  • The bounty creation form placeholder is included; implementation can be added separately
  • Role defaults to "contributor" for backward compatibility
  • Session cache is updated optimistically for better UX

closes #207

Summary by CodeRabbit

  • New Features
    • Added a bounty creation page for sponsors (placeholder UI; non-sponsors are redirected).
    • Global navigation now shows a "Create" link only for sponsor users.
    • Account Settings gains "Sponsor Access" with a role toggle to switch between contributor and sponsor; toggle shows updating state and is disabled while saving.

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

@Delightech28 is attempting to deploy a commit to the Threadflow Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 29, 2026

@Delightech28 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Warning

Review limit reached

@Delightech28, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 36 minutes and 4 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8ef110a6-9db8-49f4-9d70-8aecb973941d

📥 Commits

Reviewing files that changed from the base of the PR and between 2a833b6 and 70ee9fe.

📒 Files selected for processing (4)
  • app/bounty/create/page.tsx
  • components/global-navbar.tsx
  • components/settings/profile-tab.tsx
  • hooks/use-user-role.ts
📝 Walkthrough

Walkthrough

This PR adds a sponsor role to the user session and gates bounty creation access. It extends auth types with a role (defaulting to "contributor"), hides the Create navbar link for non-sponsors, protects /bounty/create with a redirect, and adds a settings toggle to switch roles.

Changes

Sponsor Role Gating and Access Control

Layer / File(s) Summary
User role schema and auth client configuration
lib/server-auth.ts, lib/auth-client.ts
User type now includes optional role: "sponsor" | "contributor". Server auth normalizes/defaults role to "contributor", and auth client infers the additional role field.
Mutation support for role updates
hooks/use-user-mutations.ts
UpdateUserParams extended with optional `role?: "sponsor"
Navigation gating for sponsors
components/global-navbar.tsx
GlobalNavbar reads session role and only renders the /bounty/create "Create" link when userRole === "sponsor".
Bounty creation page protection
app/bounty/create/page.tsx
New client page checks session role, returns null while pending or for non-sponsors, redirects resolved non-sponsors to /bounty, and renders a placeholder UI for sponsors.
Role toggle in account settings
components/settings/profile-tab.tsx
Adds session-aware role reading, isTogglingRole state, optimistic cache update and mutateAsync call to toggle role, rollback on error, and a Sponsor Access button with loading state and spinner.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • Benjtalkshow

Poem

🐰 I toggled roles beneath the moonlit sky,
Sponsor or contributor—just one hop to try,
The navbar hides what you should not see,
Bounties await where sponsors roam free.
nibbles a carrot and hops back to code

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a sponsor role feature and gating Create access to sponsors, which matches the primary objective of the PR.
Linked Issues check ✅ Passed All coding requirements from issue #207 are implemented: role field added to session, navbar Create link gated to sponsors, /bounty/create redirects non-sponsors, settings toggle added, and all acceptance criteria are addressed.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #207 requirements; no out-of-scope modifications detected in the modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@Benjtalkshow Benjtalkshow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The role gating logic is correct: backend validates the role value and defaults to contributor, client inferAdditionalFields makes updateUser type-safe, the navbar and route both check the session, and the settings toggle uses an optimistic update with rollback. All five acceptance criteria are met functionally.

Three things to fix before merge.

The branch is 10 commits behind upstream main. pnpm tsc --noEmit fails on e2e/bounty-creation.spec.ts because PR #248 (which deleted that file) isn't in your branch. Please rebase against upstream/main and the errors go away.

The (session?.user as { role?: string } | undefined)?.role as "sponsor" | "contributor" | undefined cast is duplicated in global-navbar.tsx, app/bounty/create/page.tsx, and components/settings/profile-tab.tsx. Extract it to a single useUserRole() hook that returns the typed role, so callers stop repeating the cast.

/bounty/create renders "Coming soon..." with a TODO comment. The bounty creation form isn't built yet (issue #181 is still open), so a placeholder is fine, but make it look intentional. Replace it with a small card explaining the form is coming, or render null until the form exists. A bare TODO comment in production code reads as unfinished.

Once those three are in, this is ready.

@Delightech28 Delightech28 force-pushed the feature/sponsor-role branch from 8ce0f3a to 2a833b6 Compare May 29, 2026 11:05
@Delightech28
Copy link
Copy Markdown
Contributor Author

Thanks for the detailed feedback! I've addressed all three issues:

  1. Rebased against upstream/main ✅
  1. Extracted duplicated role cast ✅
  • Created new [use-user-role.ts hook that encapsulates the type-safe role extraction

  • Updated [global-navbar.tsx], [page.tsx], and [profile-tab.tsx] to use the hook

  • Removed all duplicate cast logic

  1. Improved placeholder UI ✅
  • Replaced bare "Coming soon..." and TODO comment in /bounty/create

  • Now uses a styled Card component with AlertCircle icon and descriptive text

  • Looks intentional and professional, not hastily coded

All changes pushed to this branch. Ready for merge!

@Benjtalkshow Benjtalkshow merged commit f86c0a6 into boundlessfi:main May 30, 2026
2 of 4 checks passed
Benjtalkshow added a commit that referenced this pull request May 30, 2026
Fixes react/no-unescaped-entities lint error introduced in #254.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a sponsor role to the user session and gate Create access

2 participants