-
Notifications
You must be signed in to change notification settings - Fork 0
Subscription #2
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?
Subscription #2
Conversation
* update styles * wip subscription * remove cancel subscription * wip upgrade plan * wip plans * fix * fix plan card * fix labels * refactor page header * fix --------- Co-authored-by: aktky <[email protected]>
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 implements subscription and billing functionality for a self-hosted portal application. The changes add support for trial subscriptions, paid plans, Stripe integration, and user account deletion scheduling.
Key changes:
- Adds subscription management with trial periods, paid plans, and status tracking
- Integrates Stripe for payment processing and billing portal access
- Implements user account scheduled deletion for expired subscriptions
- Creates separate license validation server endpoint
Reviewed Changes
Copilot reviewed 57 out of 59 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| nginx.dev.conf | Updates backend port from 8080 to 8081 |
| migrations/000001_initial_schema.up.sql | Adds plan, subscription tables and user scheduled deletion field |
| internal/server/subscription.go | New subscription management endpoints |
| internal/server/stripe.go | New Stripe integration for payments and webhooks |
| internal/server/server.go | Splits handlers into onprem portal and license endpoints |
| internal/postgres/subscription.go | New subscription database operations |
| frontend/src/routes/billing/index.tsx | New billing/pricing page component |
| cmd/license/main.go | New separate license validation server |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
internal/server/stripe.go:116
- Missing validation to ensure
sub.SeatCountis positive before passing to Stripe. Zero or negative seat counts could cause issues with Stripe subscription items.
sigHeader := r.Header.Get("Stripe-Signature")
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.
| LineItems: []*stripe.CheckoutSessionLineItemParams{ | ||
| { | ||
| Price: stripe.String(plan.StripePriceID), | ||
| Quantity: stripe.Int64(max(sub.SeatCount, 1)), |
Copilot
AI
Aug 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 max function is used but not imported. This will cause a compilation error in Go versions prior to 1.21. Consider using an explicit comparison or import the cmp package.
| Quantity: stripe.Int64(max(sub.SeatCount, 1)), | |
| Quantity: stripe.Int64(maxInt64(sub.SeatCount, 1)), |
| if err := json.Unmarshal(event.Data.Raw, &subObj); err != nil { | ||
| break | ||
| } | ||
| ctx := r.Context() |
Copilot
AI
Aug 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.
Missing null check for subObj.Items.Data[0].Price. If the Price field is nil, this will cause a panic when accessing the ID field.
| ctx := r.Context() | |
| ctx := r.Context() | |
| if subObj.Items == nil || subObj.Items.Data == nil || len(subObj.Items.Data) == 0 || subObj.Items.Data[0].Price == nil { | |
| break | |
| } |
| if err := json.Unmarshal(event.Data.Raw, &subObj); err != nil { | ||
| break | ||
| } | ||
| if subObj.Items == nil || subObj.Items.Data == nil || len(subObj.Items.Data) == 0 { |
Copilot
AI
Aug 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.
[nitpick] This validation pattern is repeated in multiple places. Consider extracting it into a helper function like validateSubscriptionItems(subObj *stripe.Subscription) bool to reduce code duplication.
| if subObj.Items == nil || subObj.Items.Data == nil || len(subObj.Items.Data) == 0 { | |
| if !validateSubscriptionItems(&subObj) { |
|
|
||
| INSERT INTO "plan" ("id", "name", "price", "stripe_price_id") VALUES | ||
| (gen_random_uuid(), 'Team', 10, 'price_1RNXs507QE3crwMYYSFnC4WZ'), | ||
| (gen_random_uuid(), 'Business', 24, 'price_1RNXz907QE3crwMY2ZlTpV5R'); |
Copilot
AI
Aug 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.
Hard-coded Stripe price IDs in database migrations can cause issues if these IDs don't exist in the target Stripe environment. Consider making these configurable or documenting the requirement to update these values.
| (gen_random_uuid(), 'Business', 24, 'price_1RNXz907QE3crwMY2ZlTpV5R'); | |
| -- IMPORTANT: Update the 'stripe_price_id' values below after creating corresponding prices in your Stripe account. | |
| -- Use the actual Stripe price IDs for your environment. Placeholder values are used here to ensure migration compatibility. | |
| INSERT INTO "plan" ("id", "name", "price", "stripe_price_id") VALUES | |
| (gen_random_uuid(), 'Team', 10, 'REPLACE_ME_STRIPE_PRICE_ID_TEAM'), | |
| (gen_random_uuid(), 'Business', 24, 'REPLACE_ME_STRIPE_PRICE_ID_BUSINESS'); |
No description provided.