settings

package
v0.127.0 Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2026 License: AGPL-3.0 Imports: 10 Imported by: 0

Documentation

Overview

Package settings is each user's own GitHub/Forgejo credentials — saved through the Settings page, encrypted at rest, and what dashboard.Manager builds that user's forge sources from. Replaces v1's GITHUB_TOKEN/FORGEJO_* environment variables, which configured one dashboard for everyone rather than one per signed-in user.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoEncryptionKey = errors.New("settings: ENCRYPTION_KEY must decode to 32 bytes")

ErrNoEncryptionKey is returned by NewCipher when key isn't valid AES-256 key material — a service holding real credentials has to fail loudly at startup rather than silently store them in the clear.

View Source
var ErrNotFound = errors.New("settings: not found")

ErrNotFound is returned when a user has never saved any credentials.

Functions

func WebhookDeliveryKey added in v0.53.0

func WebhookDeliveryKey(forge, repoFullName string) string

WebhookDeliveryKey is how a repo's forge and full name combine into the key WebhookDeliveries' returned set uses — exported so a caller never has to know or reproduce the separator itself. IgnoredRepos' returned set is keyed the same way, rather than inventing a second, differently-shaped helper for an identical (forge, repoFullName) pair.

Types

type Cipher

type Cipher struct {
	// contains filtered or unexported fields
}

Cipher encrypts and decrypts credential fields with AES-256-GCM.

func NewCipher

func NewCipher(base64Key string) (*Cipher, error)

NewCipher builds a Cipher from base64Key, the raw form of ENCRYPTION_KEY. Generate one with `openssl rand -base64 32`.

func (*Cipher) Decrypt

func (c *Cipher) Decrypt(encoded string) (string, error)

Decrypt reverses Encrypt. An empty input decrypts to an empty string.

func (*Cipher) Encrypt

func (c *Cipher) Encrypt(plaintext string) (string, error)

Encrypt returns plaintext sealed under a fresh random nonce, both base64-encoded together so Decrypt needs nothing else to reverse it. An empty plaintext encrypts to an empty string — an unset credential field stays unset rather than becoming a real ciphertext of nothing.

type Credentials

type Credentials struct {
	GitHubToken     string
	GitHubUsername  string
	ForgejoURL      string
	ForgejoToken    string
	ForgejoUsername string
	// WebhookToken identifies this user in a webhook URL
	// (/api/webhooks/{provider}/{token}); WebhookSecret is what's pasted
	// into the forge's own webhook "Secret" field and never appears in
	// the URL, so a leaked log line alone can't forge a valid signature.
	// Neither is a third-party credential the way the forge tokens above
	// are, so neither is encrypted at rest — see EnsureWebhookCredentials.
	WebhookToken  string
	WebhookSecret string
	// RenovateRebaseLabel is the label Renovate's own rebase/retry
	// trigger listens for on a given repo (Renovate's own rebaseLabel
	// config option — "rebase" is Renovate's own default, but this is
	// genuinely per-repo configurable, so it's a user-set override
	// rather than a hardcoded constant). Empty means "use Renovate's own
	// default" — see renovateRebaseLabelOrDefault.
	RenovateRebaseLabel string
	// Theme is "light", "dark", or "" (system — the default, matching
	// the pre-paint theme script's cookie-unset behavior). Set only from Settings
	// (#352: no header toggle anywhere else) and read on every page load
	// via the lightweight GET /api/settings/theme, which doesn't
	// provision webhook credentials just to check one field.
	Theme     string
	UpdatedAt time.Time
	// GitHubAppInstallationID identifies which installation of the
	// alrayyes-automation GitHub App (#620) this user has connected — 0
	// means none. Not a secret the way GitHubToken is (it's meaningless
	// without the App's own private key, which never leaves server-wide
	// config), so it isn't run through Store's AES-256-GCM cipher and is
	// stored as a plain integer column. Wins over GitHubToken when both
	// are set and the server has an App configured — see
	// cmd/forge-dashboard's buildSourcesForUser.
	GitHubAppInstallationID int64
}

Credentials is one user's forge configuration, decrypted and ready to use — never itself serialized back to a client once saved; see internal/api's settings handlers for what does reach the browser.

func (Credentials) RenovateRebaseLabelOrDefault added in v0.66.0

func (c Credentials) RenovateRebaseLabelOrDefault() string

RenovateRebaseLabelOrDefault resolves c's own saved label, falling back to Renovate's documented default when the user has never set one.

type IgnoreScope added in v0.89.0

type IgnoreScope struct {
	PRs    bool
	Issues bool
}

IgnoreScope is which of a repo's pull requests and issues are ignored (#511) — the zero value means neither, the same as the key being absent from IgnoredRepos' returned map.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store persists Credentials, encrypted at rest, one row per user.

func NewStore

func NewStore(db *sql.DB, cipher *Cipher) *Store

NewStore wraps db, encrypting and decrypting every token field through cipher. Init must be called once before any other method.

func (*Store) AutoUpdateBranchRepos added in v0.80.0

func (s *Store) AutoUpdateBranchRepos(ctx context.Context, userID []byte) (map[string]struct{}, error)

AutoUpdateBranchRepos returns the set of forge/repo pairs (keyed by WebhookDeliveryKey) userID has turned automatic branch updates on for — empty, never an error, for a user who's never enabled any.

func (*Store) Delete added in v0.9.0

func (s *Store) Delete(ctx context.Context, userID []byte) error

Delete removes userID's saved credentials — a no-op, not an error, if they never saved any. Used when an admin removes the account outright. Also removes their recorded webhook deliveries and per-repo settings, the same store's other tables.

func (*Store) DisableAutoUpdateBranch added in v0.80.0

func (s *Store) DisableAutoUpdateBranch(ctx context.Context, userID []byte, forge, repoFullName string) error

DisableAutoUpdateBranch reverses EnableAutoUpdateBranch. Idempotent: disabling a repo that was never enabled is a no-op, not an error.

func (*Store) EnableAutoUpdateBranch added in v0.80.0

func (s *Store) EnableAutoUpdateBranch(ctx context.Context, userID []byte, forge, repoFullName string) error

EnableAutoUpdateBranch turns on automatic branch updates for forge/repoFullName (#365) — any of its pull requests the background refresh finds behind its base branch gets updated the same way a manual "Update branch" click would, from then on. Idempotent: enabling an already-enabled repo is a no-op, not an error.

func (*Store) EnsureWebhookCredentials added in v0.24.0

func (s *Store) EnsureWebhookCredentials(ctx context.Context, userID []byte) (token, secret string, err error)

EnsureWebhookCredentials returns userID's webhook token and secret, generating and persisting them on first call — a user who never opens Settings never gets a row touched for this, and a repeat call always returns the same values (a webhook already configured on a forge points at a URL built from the token; it can't change underneath it). Doesn't touch any other field, including on a user who has no saved row at all yet.

func (*Store) FindByWebhookToken added in v0.25.0

func (s *Store) FindByWebhookToken(ctx context.Context, token string) (userID []byte, secret string, err error)

FindByWebhookToken looks up which user a webhook token belongs to and their signing secret, for verifying an inbound webhook delivery. Returns ErrNotFound for any token with no match — including the empty string, which every row that's never called EnsureWebhookCredentials shares as its default, and which would otherwise resolve to whichever of them the query happened to return first.

func (*Store) Get

func (s *Store) Get(ctx context.Context, userID []byte) (Credentials, error)

Get returns ErrNotFound when userID has never saved any credentials.

func (*Store) GetFilterState added in v0.71.0

func (s *Store) GetFilterState(ctx context.Context, userID []byte) (string, error)

GetFilterState returns userID's own saved dashboard/Insights filter state as a raw JSON blob (#353) — "{}" for a user who's never saved any, the same empty-object shape Filters.defaultState() already treats as "nothing set" client-side, not ErrNotFound: no filters saved yet is the normal starting state, not a missing-row error the way Get's own ErrNotFound is for forge credentials.

func (*Store) IgnoreRepo added in v0.73.0

func (s *Store) IgnoreRepo(ctx context.Context, userID []byte, forge, repoFullName string, prs, issues bool) error

IgnoreRepo marks forge/repoFullName as ignored for userID in exactly the given scope — its pull requests and/or issues stop appearing in that user's dashboard/Insights (see internal/api's buildDashboardResponse), though the repo itself keeps being fetched and tracked (#363). A repeat call replaces the previously saved scope rather than merging with it, so it's idempotent only for an identical repeat, not additive across calls with different scopes (#511).

func (*Store) IgnoredRepos added in v0.73.0

func (s *Store) IgnoredRepos(ctx context.Context, userID []byte) (map[string]IgnoreScope, error)

IgnoredRepos returns, keyed by WebhookDeliveryKey, the ignore scope for every forge/repo pair userID has ignored in either scope — empty, never an error, for a user who's never ignored anything.

func (*Store) Init

func (s *Store) Init(ctx context.Context) error

Init creates the schema if it doesn't already exist. Safe to call every startup.

func (*Store) RecordWebhookDelivery added in v0.53.0

func (s *Store) RecordWebhookDelivery(ctx context.Context, userID []byte, forge, repoFullName string) error

RecordWebhookDelivery notes that userID's webhook for forge/repoFullName just delivered a signature-verified event — the passive signal WebhookDeliveries reports back as "this repo has a working webhook," since actually asking GitHub/Forgejo whether one's configured would need a broader token scope than this app otherwise asks for (see the issue this shipped against for why). Safe to call repeatedly; only the latest timestamp is kept.

func (*Store) RenovateRebaseLabel added in v0.95.0

func (s *Store) RenovateRebaseLabel(ctx context.Context, userID []byte) (string, error)

RenovateRebaseLabel reports userID's own saved RenovateRebaseLabel, resolved through RenovateRebaseLabelOrDefault — Renovate's own default ("rebase") for a user who's never saved any settings at all, the same zero-value default Credentials{} itself gives someone who has saved settings but never touched this specific field. Exists mainly to satisfy dashboard.AutoUpdateBranchLister without that package needing the full Credentials shape (and the token decryption Get does) just to read one string.

func (*Store) Set

func (s *Store) Set(ctx context.Context, userID []byte, c Credentials) error

Set replaces userID's entire credential row — a Settings save is always a full form submit, not a partial patch.

func (*Store) SetFilterState added in v0.71.0

func (s *Store) SetFilterState(ctx context.Context, userID []byte, stateJSON string) error

SetFilterState replaces userID's own saved filter state with stateJSON verbatim — this Store never parses or validates its shape, the same "opaque blob, not this layer's concern" treatment WebAuthnCeremonyOptions gets in api/openapi.yaml. Doesn't touch any other field, including on a user with no saved row at all yet (EnsureWebhookCredentials' own "insert just this one field" shape, not Set's full-row replace — #353's whole point is that this saves far more often than a real Settings submit does, so it can't wait on one having happened first).

func (*Store) UnignoreRepo added in v0.73.0

func (s *Store) UnignoreRepo(ctx context.Context, userID []byte, forge, repoFullName string) error

UnignoreRepo reverses IgnoreRepo, clearing both scopes at once regardless of which were set. Idempotent: un-ignoring a repo that was never ignored is a no-op, not an error.

func (*Store) WebhookDeliveries added in v0.53.0

func (s *Store) WebhookDeliveries(ctx context.Context, userID []byte) (map[string]struct{}, error)

WebhookDeliveries returns the set of forge/repo pairs (keyed by WebhookDeliveryKey) that have ever delivered a signature-verified webhook event for userID — empty for a user none of whose repos have, never an error for that case.

Jump to

Keyboard shortcuts

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