Files
commerce/test/api/billing/suite_test.go
zeekay f7aabf72f7 SuperAdmin is the identity edge's verdict, and commerce compares no org
IsSuperAdmin folded the case of the home org and fell back to the owner
claim, the org of the application that minted the token, and the money
bits were granted on X-User-Owner == admin. Cloud writes X-User-Owner for
an admin-org application and an admin-org person's API key as well as for
a person, so either could mint money and edit the catalog here while
being nobody in the rest of the same process. Every gate now reads
X-User-IsAdmin, which the edge strips and writes from authz.Claims.Sudo
alone; the standalone EdgeAuth decides it with that predicate over the
verified token's signed membership set. X-User-IsAdmin no longer doubles
as the org-admin bit, which is X-User-IsOrgAdmin. No machine is
SuperAdmin. Global admin is SuperAdmin wherever it named this predicate.
2026-10-18 22:08:47 -07:00

83 lines
2.4 KiB
Go

package test
import (
"net/http"
"strconv"
"testing"
billingApi "github.com/hanzoai/commerce/api/billing"
"github.com/hanzoai/commerce/datastore"
"github.com/hanzoai/commerce/middleware/iammiddleware"
"github.com/hanzoai/commerce/models/fixtures"
"github.com/hanzoai/commerce/models/organization"
"github.com/hanzoai/commerce/util/permission"
"github.com/hanzoai/commerce/util/test/ae"
"github.com/hanzoai/commerce/util/test/zipclient"
"github.com/hanzoai/commerce/util/zipctx"
. "github.com/hanzoai/commerce/util/test/ginkgo"
)
// The suite drives the FULL billing surface, which includes money-MINT routes
// (credit-grants, deposit) reachable only by a SuperAdmin: an IAM principal whose
// home org is the reserved "admin" org. It presents the identity the boundary
// mints for the platform's own application (X-User-Owner: admin), the same
// principal api/billing's platformApp stamps, and pins X-Org-Id to the fixture
// org ("suchtees") so every spec stays in one namespace.
func Test(t *testing.T) {
Setup("api/billing", t)
}
var (
ctx ae.Context
db *datastore.Datastore
org *organization.Organization
cl *zipclient.Client
accessToken string
)
// Setup test context
var _ = BeforeSuite(func() {
// Create new test context
ctx = ae.NewContext()
// Synthetic request context for fixtures
c := zipctx.New(ctx)
// Run default fixtures to setup organization
org = fixtures.Organization(c).(*organization.Organization)
tok, _ := org.GetTokenByName("test-secret-key")
org.MustUpdate()
accessToken = tok.String
// Save namespaced db
db = datastore.New(org.Namespaced(ctx))
// Create client
cl = zipclient.New(ctx)
// A per-org access token carries only org-level Admin and is (correctly) 403
// on the mint routes: an org owner must never self-mint spendable balance.
perms := strconv.FormatInt(int64(permission.Admin|permission.Live), 10)
cl.Defaults(func(r *http.Request) {
r.Header.Set("X-User-Id", "app_platform")
r.Header.Set("X-User-Owner", "admin")
r.Header.Set("X-User-IsAdmin", "true")
r.Header.Set("X-Org-Id", org.Name)
r.Header.Set("X-User-Permissions", perms)
})
cl.IgnoreErrors(true)
// Validate the identity headers the way the boundary does in production,
// then add the billing API routes behind it.
cl.Router.Use(iammiddleware.IAMTokenRequired())
billingApi.Route(cl.Router)
})
// Tear-down test context
var _ = AfterSuite(func() {
ctx.Close()
})