organization

package
v1.799.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2026 License: Apache-2.0, MIT Imports: 32 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultAppName   = "Hanzo App"
	DefaultStoreName = "Default"
)

Variables

View Source
var ErrSecretLikeName = errors.New("organization: refusing to provision org from a bearer-shaped name")

ErrSecretLikeName is returned when an untrusted, gateway-supplied org name is actually a raw API key / bearer token rather than a real org identifier.

View Source
var (
	UserNotTopLevel = errors.New("User is not in the top level namespace.")
)

Functions

func IsSecretLikeName

func IsSecretLikeName(name string) bool

IsSecretLikeName reports whether an org identifier looks like a raw API key / bearer token rather than a real organization slug. Real orgs are short slugs ("hanzo", "adnexus"), UUIDs, or numeric ids; leaked provider keys carry a recognizable prefix — Anthropic (sk-ant-), OpenAI (sk-proj-), DigitalOcean (sk-do-), and Hanzo (sk-hz- / hk-).

Any code that provisions an org via GetOrCreate from an untrusted, gateway-supplied name MUST reject these first: otherwise a caller who presents a raw key as their bearer causes the key to be persisted as an org name and tenant id, leaking the secret into the datastore (incident 2026-07-02). This mirrors the DB backstop trigger trg_reject_bearer_tenant on _entities.

The check is intentionally prefix-based (matching the DB trigger) so it never rejects a real slug: "skunkworks" and "hkust" do not start with "sk-"/"hk-".

func Query

Types

type ByName

type ByName []*Organization

func (ByName) Len

func (o ByName) Len() int

func (ByName) Less

func (o ByName) Less(i, j int) bool

func (ByName) Swap

func (o ByName) Swap(i, j int)

type Organization

type Organization struct {
	mixin.Model[Organization]
	mixin.AccessTokens
	wallet.WalletHolder

	Name       string   `json:"name"`
	FullName   string   `json:"fullName"`
	Owners     []string `json:"owners,omitempty" datastore:",noindex"`
	Admins     []string `json:"admins,omitempty" datastore:",noindex"`
	Moderators []string `json:"moderators,omitempty" datastore:",noindex"`
	Enabled    bool     `json:"enabled"`

	BillingEmail     string                  `json:"billingEmail,omitempty"`
	Phone            string                  `json:"phone,omitempty"`
	Address          Address                 `json:"address,omitempty"`
	SocialMedia      socialmedia.SocialMedia `json:"socialMedia,omitEmpty"`
	Websites         []website.Website       `json:"websites,omitEmpty"`
	WalletPassphrase string                  `json:"-"`

	Timezone string `json:"timezone"`

	Country string `json:"country"`
	TaxId   string `json:"taxId"`

	// Used in generating email templates
	LogoUrl string `json:"logoUrl"`

	// Where is the user's dashboard?
	DashboardUrl string `json:"dashboardUrl"`

	// Fee structure for this organization
	Fees pricing.Fees `json:"fees" datastore:",noindex"`

	// Partner fees (private, should be up to partner to disclose)
	Partners []pricing.Partner `json:"-" datastore:",noindex"`

	// Email settings
	Email email.Settings `json:"email" datastore:",noindex"`

	// Default Store
	DefaultStore string `json:"defaultStore"`

	// Default App
	DefaultApp string `json:"defaultApp"`

	// Plan settings
	Plan struct {
		PlanId    string
		StartDate time.Time
	} `json:"-"`

	// Affiliate configuration
	Affiliate integration.Affiliate `json:"-" datastore:",noindex"`

	// Signup options
	SignUpOptions struct {
		// Controls the enabled status of account after creation
		AccountsEnabledByDefault bool `json:"accountsEnabledByDefault"`

		// Allow direct affiliate sign up
		AllowAffiliateSignup bool `json:"allowAffiliateSignup"`

		// Turns off required backend checks
		NoNameRequired     bool `json:"noNameRequired"`
		NoPasswordRequired bool `json:"noPasswordRequired"`

		// Requires password set on create confirmation
		TwoStageEnabled bool `json:"twoStageEnabled"`
		ImmediateLogin  bool `json:"immediateLogin"`

		UsernameRequired bool `json:"usernameRequired"`
	} `json:"signUpOptions" datastore:",noindex"`

	// Whether we use live or test tokens, mostly applicable to stripe
	Live bool `json:"live"`

	// TODO: Remain to PaymentWhitelist for clarity
	// List of comma deliminated email globs that result in charges of 50 cents
	EmailWhitelist string `json:"emailWhitelist" datastore:",noindex"`

	// integration
	Integrations  integration.Integrations `json:"-" datastore:"-"`
	Integrations_ string                   `json:"-" datastore:",noindex"`

	// Analytics config
	Analytics analytics.Analytics `json:"analytics" datastore:",noindex"`

	// Bitcoi settings
	Bitcoin integration.Bitcoin `json:"-"`

	// Ethereum settings
	Ethereum integration.Ethereum `json:"-"`

	// Mailchimp settings
	Mailchimp integration.Mailchimp `json:"-"`

	// Mandrill settings
	Mandrill integration.Mandrill `json:"-"`

	// Mercury bank connection
	Mercury integration.Mercury `json:"-"`

	// Netlify settings
	Netlify integration.Netlify `json:"-"`

	// Paypal connection
	Paypal integration.Paypal `json:"-"`

	// Plaid connection
	Plaid integration.Plaid `json:"-"`

	// ReAmaze settings
	Reamaze integration.Reamaze `json:"-"`

	Recaptcha integration.Recaptcha `json:"-" datastore:",noindex"`

	// Salesforce settings
	Salesforce integration.Salesforce `json:"-"`

	// Shipwire settings
	Shipwire integration.Shipwire `json:"-"`

	// Square connection
	Square integration.Square `json:"-"`

	// Stripe connection
	Stripe integration.Stripe `json:"-"`

	// Wire transfer settings
	Wire integration.WireTransfer `json:"-"`

	// AuthorizeNet connection
	AuthorizeNet integration.AuthorizeNet `json:"-"`

	// Adyen connection
	Adyen integration.Adyen `json:"-"`

	// Braintree connection
	Braintree integration.Braintree `json:"-"`

	// Recurly connection
	Recurly integration.Recurly `json:"-"`

	// LemonSqueezy connection
	LemonSqueezy integration.LemonSqueezy `json:"-"`

	SecurityToken integration.SecurityToken `json:"-"`

	Currency currency.Type `json:"currency"`
}

func New

func (*Organization) AddAdmin

func (o *Organization) AddAdmin(userOrId string)

Add admin to organization

func (*Organization) AddDefaultTokens

func (o *Organization) AddDefaultTokens()

Old JWT / AccessToken AUTH

func (*Organization) AddOwner

func (o *Organization) AddOwner(userOrId string)

Add admin to organization

func (*Organization) AfterCreate

func (o *Organization) AfterCreate() error

func (Organization) AuthorizeNetToken

func (o Organization) AuthorizeNetToken(sandbox bool) integration.AuthorizeNetConnection

func (*Organization) BeforeCreate

func (o *Organization) BeforeCreate() error

Hooks

func (*Organization) Defaults

func (o *Organization) Defaults()

func (Organization) GetDefaultApp

func (o Organization) GetDefaultApp() (*app.App, error)

Return DefaultApp

func (Organization) GetDefaultStore

func (o Organization) GetDefaultStore() (*store.Store, error)

Return DefaultStore

func (*Organization) GetReferenceToken

func (o *Organization) GetReferenceToken(usr *user.User) (*oauthtoken.Token, bool, error)

func (Organization) GetStripeAccessToken

func (o Organization) GetStripeAccessToken(userId string) (string, error)

func (*Organization) Init

func (o *Organization) Init(db *datastore.Datastore)

func (Organization) IsAdmin

func (o Organization) IsAdmin(userOrId interface{}) bool

func (Organization) IsOwner

func (o Organization) IsOwner(userOrId interface{}) bool

func (Organization) IsTestEmail

func (o Organization) IsTestEmail(email string) bool

func (*Organization) Load

func (o *Organization) Load(ps []datastore.Property) (err error)

func (Organization) Namespace

func (o Organization) Namespace() string

Namespace returns the datastore namespace for this organization.

SECURITY: every org — without exception — is strictly scoped to its own name. There is NO org-name escape hatch. The legacy `Name=="platform" -> "" (global/cross-org namespace)` bypass was REMOVED: it keyed cross-org datastore access on an org-NAME string, fully decoupled from real platform-admin identity, so anyone who could land in (or forge) an org named "platform" read/wrote the global namespace where every org's records live (Red — privilege escalation via the empty namespace). Cross-org / superadmin datastore access is now gated EXCLUSIVELY on auth.IAMClaims.IsSuperAdmin() (owner=="admin") at the handler/middleware layer — never inferred from the org name here.

func (Organization) Namespaced

func (o Organization) Namespaced(ctx context.Context) context.Context

Namespaced returns a context scoped to this organization's namespace. When called with a gin.Context, we always detach from the HTTP request lifecycle and use context.Background() for the database context. This prevents "context canceled" errors when the browser disconnects or the upstream proxy timeout fires before the datastore query completes.

func (Organization) Pricing

func (o Organization) Pricing() (*pricing.Fees, []pricing.Partner)

func (*Organization) ResetReferenceToken

func (o *Organization) ResetReferenceToken(usr *user.User, claims oauthtoken.Claims) (*oauthtoken.Token, error)

New JWT / OAUTH

func (*Organization) RevokeReferenceToken

func (o *Organization) RevokeReferenceToken(usr *user.User) (*oauthtoken.Token, bool, error)

func (*Organization) Save

func (o *Organization) Save() (ps []datastore.Property, err error)

func (Organization) SquareConfig

func (o Organization) SquareConfig(sandbox bool) integration.SquareConnection

func (Organization) SquareEnvironment

func (o Organization) SquareEnvironment() string

SquareEnvironment returns "sandbox" or "production" — the value the Square SDK uses to select its API base URL — derived from TestMode (one authority).

func (Organization) StripeToken

func (o Organization) StripeToken() string

func (Organization) TestMode

func (o Organization) TestMode() bool

TestMode reports whether this org transacts in TEST mode on the current deployment. It is the SINGLE authority for BOTH the payment environment (Square sandbox vs production) AND the ledger (trans.Test, balance bucket, pay.Live). Keeping the charge environment and the ledger on ONE authority is what prevents a sandbox charge from crediting the live (spendable) balance and a production charge from booking test (unbilled) revenue.

SQUARE_ENVIRONMENT is the deployment authority and makes the 3-env split pure per-env config (mainnet=production, testnet/devnet=sandbox). It is fail-CLOSED: only an explicit, recognized "production" (or prod/live) selects production; anything else that is SET — sandbox/test, an empty placeholder, or a typo — selects test/sandbox, so a misconfiguration can never silently charge real cards. When SQUARE_ENVIRONMENT is UNSET, the org's own live flag decides (live→production, test→sandbox) so local and un-templated deploys still resolve.

func (*Organization) Validator

func (o *Organization) Validator() *val.Validator

type StripeAccessTokenNotFound

type StripeAccessTokenNotFound struct {
	UserId     string
	LiveUserId string
	TestUserId string
}

func (StripeAccessTokenNotFound) Error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL