All checks were successful
Build and Release / Create Release (push) Successful in 0s
Build and Release / Unit Tests (push) Successful in 3m10s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 5m13s
Build and Release / Lint (push) Successful in 5m25s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 3m13s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 8h5m42s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Successful in 7m30s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Successful in 7m55s
Build and Release / Build Binary (linux/arm64) (push) Successful in 7m36s
Implement complete subscription monetization system for repositories with Stripe and PayPal integration. Includes: - Database models and migrations for monetization settings, subscription products, and user subscriptions - Payment provider abstraction layer with Stripe and PayPal implementations - Admin UI for configuring payment providers and viewing subscriptions - Repository settings UI for managing subscription products and tiers - Subscription checkout flow and webhook handlers for payment events - Access control to gate repository code behind active subscriptions
87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
// Copyright 2026 MarketAlly. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package context
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
monetize_model "code.gitcaddy.com/server/v3/models/monetize"
|
|
perm_model "code.gitcaddy.com/server/v3/models/perm"
|
|
"code.gitcaddy.com/server/v3/modules/setting"
|
|
"code.gitcaddy.com/server/v3/modules/templates"
|
|
)
|
|
|
|
const tplSubscribe templates.TplName = "repo/subscribe"
|
|
|
|
// RequireSubscriptionForCode returns middleware that gates code access behind a paid subscription.
|
|
// It checks:
|
|
// 1. Is monetization enabled globally?
|
|
// 2. Does this repo have subscriptions enabled?
|
|
// 3. Is the user the owner, admin, or collaborator with write access? (bypass)
|
|
// 4. Is the user a site admin? (bypass)
|
|
// 5. Does the user have an active subscription? If not, show the subscribe page.
|
|
func RequireSubscriptionForCode() func(ctx *Context) {
|
|
return func(ctx *Context) {
|
|
if !setting.Monetize.Enabled {
|
|
return
|
|
}
|
|
|
|
if ctx.Repo.Repository == nil || !ctx.Repo.Repository.SubscriptionsEnabled {
|
|
return
|
|
}
|
|
|
|
// Bypass for owner, admin, and collaborators with write+ access
|
|
if ctx.Repo.IsOwner() || ctx.Repo.IsAdmin() {
|
|
return
|
|
}
|
|
if ctx.Repo.Permission.AccessMode >= perm_model.AccessModeWrite {
|
|
return
|
|
}
|
|
|
|
// Bypass for site admins
|
|
if ctx.Doer != nil && ctx.Doer.IsAdmin {
|
|
return
|
|
}
|
|
|
|
// Bypass for unauthenticated users on public repos — they see the subscribe prompt
|
|
if ctx.Doer == nil {
|
|
ctx.Redirect(ctx.Repo.RepoLink + "/subscribe")
|
|
return
|
|
}
|
|
|
|
// Check if user has an active subscription
|
|
hasAccess, err := monetize_model.HasActiveSubscription(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID)
|
|
if err != nil {
|
|
ctx.ServerError("HasActiveSubscription", err)
|
|
return
|
|
}
|
|
if hasAccess {
|
|
return
|
|
}
|
|
|
|
// Show subscribe page with HTTP 402
|
|
ctx.Data["Title"] = ctx.Tr("repo.subscribe.title")
|
|
|
|
products, err := monetize_model.GetActiveProductsByRepoID(ctx, ctx.Repo.Repository.ID)
|
|
if err != nil {
|
|
ctx.ServerError("GetActiveProductsByRepoID", err)
|
|
return
|
|
}
|
|
ctx.Data["Products"] = products
|
|
|
|
settings, err := monetize_model.GetSetting(ctx)
|
|
if err != nil {
|
|
ctx.ServerError("GetSetting", err)
|
|
return
|
|
}
|
|
ctx.Data["StripeEnabled"] = settings.StripeEnabled
|
|
ctx.Data["StripePublishableKey"] = settings.StripePublishableKey
|
|
ctx.Data["PayPalEnabled"] = settings.PayPalEnabled
|
|
ctx.Data["PayPalClientID"] = settings.PayPalClientID
|
|
ctx.Data["PayPalSandbox"] = settings.PayPalSandbox
|
|
|
|
ctx.HTML(http.StatusPaymentRequired, tplSubscribe)
|
|
}
|
|
}
|