feature/decouple donations from membership#100
Merged
Conversation
petehayes
commented
Mar 14, 2026
Contributor
- feat: decouple donations from org membership
- test: add E2E tests for donation/membership decoupling
Any authenticated platform user can now donate to any verified organization without becoming an org member. Membership is only granted via explicit invitation or admin-approved request. Changes: - Add withPlatformAuth helper (auth without membership check) - Remove auto-join logic from /my-donations/new page - Update donation API routes to use withPlatformAuth - Update donation sub-routes ([id], receipt) for non-member access - Update public org page CTA: separate Donate and Request Membership - Update RBAC tests for new auth patterns Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add 26 E2E tests across 3 test files covering: Public tests (donation-access.public.spec.ts): - Anonymous users see 'Sign In to Get Started' CTA on public org page - My-donations pages redirect unauthenticated users to login - Public donate page is accessible without auth Authenticated admin tests (donation-access.spec.ts): - My-donations pages render for authenticated members - Donation form works with campaign pre-selection - No auto-join messaging on donation page - Public org page shows 'Dashboard' CTA for members Non-member donor tests (donor-nonmember.donor.spec.ts): - Non-member can access my-donations pages (no Access Denied) - Non-member sees 'Donate Now' + 'Request Membership' CTAs - Non-member cannot access admin routes (dashboard, accounts, etc.) - Visiting donation pages does NOT create org membership Infrastructure changes: - Add 'donor' Playwright project using Clerk emailAddress sign-in - Seed script creates donor user (authenticated, non-member) - Fix auth-setup testMatch regex to avoid matching donor setup Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| @@ -0,0 +1,77 @@ | |||
| import { test, expect, Page } from '@playwright/test'; | |||
The POST /api/organizations/[slug]/access-requests endpoint was using withOrgAuth which requires existing org membership — contradicting its purpose of letting non-members request access. Changed to withPlatformAuth which only requires authentication, allowing any logged-in user to submit a membership request. Also adds E2E test verifying the full membership request flow works for non-member donors, and cleans up AccessRequest records in seed script. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When a user was approved, then removed from the org, they couldn't re-request membership because old resolved AccessRequest records blocked the new insert. Fix: clean up resolved (APPROVED/DENIED) access requests before creating a new one, allowing the re-request flow to work. Also adds: - E2E test for the re-request flow (request → cleanup → re-request) - E2E cleanup endpoint for test state management - Fix unit test mock for deleteMany Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eanup on removal - Remove /api/e2e/cleanup-donor route and middleware entry — test-only code should not ship to production - E2E tests now use direct DB access via e2e/helpers/db.ts instead - Denied users can no longer re-request membership (must contact admin) - When an admin removes a user, their access requests are cleaned up so they can re-request if desired - Add unit test for denied request rejection Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace fragile string-matching error handling with typed ServiceError that carries HTTP status codes. Business logic violations (denied request, duplicate request, etc.) are now returned as proper HTTP responses with user-friendly messages instead of logging as system errors and returning generic 500s. - Add ServiceError class in src/lib/errors/service-error.ts - Service layer throws ServiceError with appropriate status codes - API route catches ServiceError and returns message + status directly - UI shows contextual 'Request Previously Denied' title for denied cases - Only true unexpected errors hit console.error and return 500 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
ServiceError now carries both a user-facing title and description so the API response includes both fields and the UI can display them directly without string-matching error messages. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Since denied users are now blocked from re-requesting, admins need a way to reverse a denial. Changes: - Service: approveAccessRequest accepts both PENDING and DENIED status - Service: new getDeniedRequests() function - API: GET returns both pending and denied requests - UI: collapsible 'previously denied' section below pending requests with an Approve button — low-profile since it's not a typical action - Unit test for approving a denied request Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.