Documentation
¶
Overview ¶
Package forge holds provider-agnostic helpers shared by forge providers - Gitea/Forgejo today, GitHub Enterprise and self-managed GitLab in future: host parsing, same-origin checks, and OAuth PKCE/Link primitives. Everything here is pure and stateless; each provider keeps its own endpoints, token store, and auth flow.
Index ¶
- Constants
- func Authorization(scheme, token string) string
- func Bearer(token string) string
- func DeviceLogin(ctx context.Context, cfg DeviceConfig, host, clientID string, ...) error
- func Host(label string, d directive.Directive, defaultHost string) (string, error)
- func NormalizeHost(host string) (string, bool)
- func OwnerName(label string, d directive.Directive) (string, string, error)
- func PATHost(hostEnv, defaultHost string, pinned bool) string
- func PKCE() (string, string, error)
- func RandomState() (string, error)
- func RequireReleasesForAsset(label string, d directive.Directive, source string) error
- func SameOrigin(a, b string) bool
- func Source(label string, d directive.Directive) (string, error)
- type Code
- type DeviceConfig
- type RESTClient
- type StatusError
Constants ¶
const ( KeySource = "source" SourceTags = "tags" SourceReleases = "releases" )
KeySource selects what a forge marker discovers; SourceTags and SourceReleases are its two values. Every forge serves both.
Variables ¶
This section is empty.
Functions ¶
func Authorization ¶ added in v0.1.1
Authorization joins an auth scheme and token into an Authorization header value, or "" when the token is empty.
func Bearer ¶ added in v0.1.1
Bearer returns the Authorization value attaching token as a Bearer credential, or "" when the token is empty.
func DeviceLogin ¶ added in v0.1.1
func DeviceLogin( ctx context.Context, cfg DeviceConfig, host, clientID string, prompt func(Code), ) error
DeviceLogin runs the OAuth device flow cfg describes against host and stores the minted token: it requests a code, hands it to prompt so the caller can show it to the user, polls until the user authorises in the browser, then persists the token under the host so the credential chain finds it. It needs no client secret and binds no local port, so it works headless. host and clientID default to cfg's host and embedded app; a private instance has no embeddable app, so it requires an explicit --client-id. The context bounds the poll.
func Host ¶ added in v0.1.1
Host resolves the optional host key against a forge's default host, normalizing and validating an explicit value.
func NormalizeHost ¶
NormalizeHost parses a forge host given as a bare name (codeberg.org), a host:port, or a full URL (https://git.example.com/), returning the lowercased host[:port]. ok is false when the value is empty or carries userinfo, a path, query, or fragment - anything that is not a plain network authority - so a marker-controlled host cannot smuggle a path or credentials.
func OwnerName ¶ added in v0.1.1
OwnerName parses the required repository key as owner/name, framing errors with the provider label.
func PATHost ¶
PATHost returns the single host a host-independent personal access token may be sent to. A PAT is attached to whichever host a marker names, so a marker-controlled host= could otherwise redirect the token to an attacker; the PAT is bound to one host - the hostEnv override (normalized) when set, else defaultHost. When pinned (a test transport), ambient env is ignored and defaultHost is returned, keeping a test hermetic and its auth path deterministic.
func PKCE ¶
PKCE returns an RFC 7636 verifier (32 random bytes, 43 base64url chars) and its S256 challenge (the base64url SHA-256 of the verifier), as required by a public OAuth client.
func RandomState ¶
RandomState returns an unguessable OAuth state value (16 random bytes) binding an authorization request to its callback.
func RequireReleasesForAsset ¶ added in v0.1.1
RequireReleasesForAsset rejects asset= on a non-releases source: asset= filters on release asset filenames, which only releases publish, so a tag candidate has none and the filter would always fail later.
func SameOrigin ¶
SameOrigin reports whether two URLs share a scheme and host. It guards a paginated lookup from forwarding a credential to a different origin than the one the lookup started on.
Types ¶
type Code ¶ added in v0.1.1
Code is the user-facing half of the device flow: the one-time code to enter and the URL to enter it at.
type DeviceConfig ¶ added in v0.1.1
type DeviceConfig struct {
Label string
DefaultHost string
DefaultClientID string
ClientIDHint string
Scopes []string
DeviceCodeURL func(host string) string
AccessTokenURL func(host string) string
}
DeviceConfig describes one forge's OAuth device flow: the label framing its errors, the default host and the public client ID embedded for it, the hint shown when a private instance needs --client-id, the scopes to request, and the host-relative endpoints.
type RESTClient ¶ added in v0.1.1
type RESTClient struct {
// contains filtered or unexported fields
}
RESTClient issues a forge's REST GETs over a shared transport. It holds no host or credential: each call carries its own absolute URL and its own Authorization value, since both the host and the credential are per-marker values.
func NewRESTClient ¶ added in v0.1.1
func NewRESTClient(httpClient *http.Client, accept string) RESTClient
NewRESTClient returns a client issuing GETs through httpClient, sending accept as the Accept header on every request.
func (RESTClient) DoWithContext ¶ added in v0.1.1
func (c RESTClient) DoWithContext( ctx context.Context, url, authorization string, response any, ) (http.Header, error)
DoWithContext issues a GET against the absolute url, attaching authorization (a full header value, e.g. "Bearer <token>") when non-empty, fails on a non-2xx status, decodes the JSON body into response when non-nil, and returns the response headers (for pagination). A stored credential that has expired or been revoked would 401 every request, including public reads that work anonymously; rather than fail those outright, a 401 from a credentialed request is retried once without the credential, so a stale token degrades to anonymous access. Only nil-body GETs are issued here, so the retry is always safe.
func (RESTClient) HTTPClient ¶ added in v0.1.1
func (c RESTClient) HTTPClient() *http.Client
HTTPClient returns the underlying client, for requests that go beyond the GET-and-decode surface (e.g. an OAuth token refresh POST) but must share the same transport.
type StatusError ¶ added in v0.3.11
type StatusError struct {
Code int // the HTTP status code
Status string // the status line, e.g. "404 Not Found"
Body string // the trimmed response body
}
StatusError is the error RESTClient.DoWithContext returns for a non-2xx response, carrying the status code so a caller can branch on a specific status - e.g. a compare 404 that means two refs share no history rather than a transport failure.
func (*StatusError) Error ¶ added in v0.3.11
func (e *StatusError) Error() string