apiclient

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Nov 12, 2026 License: AGPL-3.0 Imports: 17 Imported by: 0

Documentation

Overview

Package apiclient is how the frontend process talks to the backend process. The backend owns the database, the keys and every security decision; the frontend renders pages from what this client returns. The package must not import the store or the web package.

The wire protocol is the backend's internal API under /internal/v1. It is not a public API and may change between versions: deploy the frontend and the backend from the same release.

Index

Constants

View Source
const (
	// HeaderService carries the shared secret that proves the caller is the frontend.
	HeaderService = "X-Dexafix-Service"
	// HeaderClientIP, HeaderSecure and HeaderHost describe the visitor's own request, after the
	// frontend settled the proxy headers. The backend believes them only after the service secret
	// checked out.
	HeaderClientIP = "X-Dexafix-Client-IP"
	HeaderSecure   = "X-Dexafix-Secure"
	HeaderHost     = "X-Dexafix-Host"
	// HeaderCookie carries the visitor's Cookie header. The backend reads its session and sealed
	// state cookies from it and answers with Set-Cookie headers, which the frontend relays. The
	// sealing keys stay in the backend: the frontend only stores and returns the opaque values.
	HeaderCookie = "X-Dexafix-Cookie"
)

Header names of the internal API.

View Source
const (
	CodeNotFound     = "not_found"
	CodeInvalid      = "invalid"
	CodeExists       = "exists"
	CodeThrottled    = "throttled"
	CodeForbidden    = "forbidden"
	CodeUnauthorized = "unauthorized"
	CodeReauth       = "reauth_required"
	CodeStepUp       = "step_up_required"
	CodeUnavailable  = "unavailable"
	CodeInternal     = "internal"
)

Codes in Error.Code.

View Source
const (
	TLSOff        = "off"
	TLSUpload     = "upload"
	TLSSelfSigned = "selfsigned"
)

The values of FrontendConfig.TLSMode.

View Source
const (
	StateUp       = "up"       // works
	StateDegraded = "degraded" // works, but something is wrong; no component reports it yet, the page and Overall handle it
	StateDown     = "down"     // does not work
	StateOff      = "off"      // not in use (for example no worker has ever registered): not a fault
)

Component states.

View Source
const HeaderResetToken = "X-Dexafix-Reset-Token"

HeaderResetToken carries a password reset token. It travels in a header, never in a URL, so it does not end up in access logs.

View Source
const Prefix = "/internal/v1"

Prefix of every internal API path.

View Source
const SessionCookie = "dexafix_session"

SessionCookie is the name of the cookie that holds the session. The browser sends it to the frontend, which passes it on to the backend (HeaderCookie).

Variables

View Source
var ErrUnavailable = errors.New("the backend is not available")

ErrUnavailable is returned when the backend cannot be reached or answers with a server error. Pages render a "temporarily unavailable" notice for it.

Functions

func DefaultHTTPClient

func DefaultHTTPClient() *http.Client

DefaultHTTPClient is a client with timeouts and connection limits suited to the internal link.

func HTTPClient

func HTTPClient(tlsConfig *tls.Config) *http.Client

HTTPClient is DefaultHTTPClient with a TLS configuration for the link, such as the mutual TLS configuration of package mtls. nil means plain HTTP.

func InProcess

func InProcess(h http.Handler) http.RoundTripper

InProcess returns a transport that runs requests against h in the same process, on a goroutine of its own, so the combined `serve` mode goes through exactly the same middleware as two processes do. The body of the answer is streamed, not buffered.

func IsCode

func IsCode(err error, code string) bool

IsCode reports whether err is a backend error with the given code.

func StatusOf

func StatusOf(err error) int

StatusOf returns the HTTP status of a backend error, or 0 for any other error.

func WithRequest

func WithRequest(ctx context.Context, rq Request) context.Context

WithRequest attaches the visitor's request to ctx. Calls made with the returned context carry the visitor's cookies, address and host, and relay the backend's Set-Cookie headers to w.

Types

type AdminPage

type AdminPage struct {
	Status          AdminStatus
	Users           []AdminUser
	PasswordEnabled bool
	PasswordForced  bool
	SignupOpen      bool
	Providers       []AdminProvider
	Form            AdminProvider // the add or edit form
	Editing         bool
	Withings        AdminWithings
	Audit           []AuditLine
	Key             KeyView
	Require2FA      string // off, admins or everyone
	Server          ServerSettingsView
	Analytics       Analytics
	SMTP            SMTPView
	ResetByEmail    bool // users can ask for a reset e-mail
	TLS             TLSView
}

AdminPage is the data of the Admin page.

type AdminProvider

type AdminProvider struct {
	models.AuthProvider
	CallbackURL string
	HasSecret   bool
}

AdminProvider is a sign-in provider as the Admin page shows it. The secret is never sent.

type AdminResult

type AdminResult struct {
	Message       string     `json:"message,omitempty"`
	ConfigChanged bool       `json:"config_changed,omitempty"`
	ListenCheck   bool       `json:"listen_check,omitempty"`
	ResetLink     *ResetLink `json:"reset_link,omitempty"`
}

AdminResult is the outcome of a change. Message is the flash text for the Admin page (refusals the administrator can fix are messages too, not errors). ConfigChanged is true when the change touched the settings the frontend acts on (base URL, proxies, TLS): the frontend fetches them again before it answers. ListenCheck is true when the frontend's own listener state decides the message (HTTPS was turned on). ResetLink is set instead of a Message when a link was made.

type AdminStatus

type AdminStatus struct {
	Driver        string
	Encrypted     bool
	SchemaVersion int64
	Users         int
	Admins        int
	DexaScans     int
	ScaleReadings int
	// BodyUnavailable is set when the service that holds the scans and readings did not answer, so
	// the two counts above are unknown and not zero.
	BodyUnavailable bool
	Sessions        int
	AccessTokens    int
	TwoFactorUsers  int
}

AdminStatus is the database and usage figures of the Admin page.

type AdminUser

type AdminUser struct {
	ID        int64
	Username  string
	FirstName string
	LastName  string
	Email     string
	Admin     bool
	Self      bool
	Created   string
	SignIn    string
	// StrengthLevel is whether the user may sync to Strength Level automatically.
	StrengthLevel bool
	// StrengthLevelBulk is whether the user may also run the multi-day sync from Settings.
	StrengthLevelBulk bool
	TwoFactor         bool // two-step verification is on
	// JobPriority (1-100) orders the user's worker jobs among other users'; a higher number goes
	// first, and administrators always go before everyone.
	JobPriority int
}

type AdminWithings

type AdminWithings struct {
	Available       bool
	Configured      bool
	ClientID        string
	RedirectURL     string
	DefaultRedirect string // used when the field is left empty
	SecretSaved     bool
}

type Analytics

type Analytics struct {
	ScarfPixelID      string `json:"scarf_pixel_id,omitempty"`      // a UUID
	GoogleAnalyticsID string `json:"google_analytics_id,omitempty"` // G-XXXXXXXXXX
	AdSensePublisher  string `json:"adsense_publisher,omitempty"`   // ca-pub-0000000000000000
}

Analytics holds the identifiers of the optional services. An empty one is off.

func (Analytics) Any

func (a Analytics) Any() bool

Any reports whether at least one service is on.

type AuditLine

type AuditLine struct {
	When, Action, Detail, IP string
	Actor, Target            string
}

AuditLine is one event as shown on a page.

type Client

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

Client calls the backend. It is safe for concurrent use.

func New

func New(base string, hc *http.Client, secret string) (*Client, error)

New returns a client for the backend at base (for example http://api:8081). hc may be nil.

func (*Client) AdminAddUser

func (c *Client) AdminAddUser(ctx context.Context, username, email, password string) (AdminResult, error)

AdminAddUser creates an account with a password.

func (*Client) AdminCancelJob

func (c *Client) AdminCancelJob(ctx context.Context, id string) (AdminResult, error)

func (*Client) AdminDeleteProvider

func (c *Client) AdminDeleteProvider(ctx context.Context, slug string) (AdminResult, error)

func (*Client) AdminDeleteUser

func (c *Client) AdminDeleteUser(ctx context.Context, id int64) (AdminResult, error)

func (*Client) AdminPage

func (c *Client) AdminPage(ctx context.Context, edit string) (AdminPage, error)

AdminPage fetches the page; edit is the slug of the provider to edit, or empty.

func (*Client) AdminPasswordLogin

func (c *Client) AdminPasswordLogin(ctx context.Context, on bool) (AdminResult, error)

func (*Client) AdminRemoveTwoFactor

func (c *Client) AdminRemoveTwoFactor(ctx context.Context, id int64) (AdminResult, error)

AdminRemoveTwoFactor removes a user's second step.

func (c *Client) AdminResetLink(ctx context.Context, id int64, email bool) (AdminResult, error)

AdminResetLink makes a one-time reset link, and e-mails it too when email is set and possible.

func (*Client) AdminResumeSchedule

func (c *Client) AdminResumeSchedule(ctx context.Context, userID int64, kind string) (AdminResult, error)

AdminResumeSchedule lets the scheduler run a kind for a user again after it paused their runs.

func (*Client) AdminResumeWorkerKind

func (c *Client) AdminResumeWorkerKind(ctx context.Context, kind string) (AdminResult, error)

AdminResumeWorkerKind turns a paused kind back on, and starts counting failures afresh.

func (*Client) AdminSaveAnalytics

func (c *Client) AdminSaveAnalytics(ctx context.Context, a Analytics) (AdminResult, error)

AdminSaveAnalytics stores the identifiers of the optional analytics and ad services; an empty one turns that service off.

func (*Client) AdminSaveProvider

func (c *Client) AdminSaveProvider(ctx context.Context, f ProviderForm) (AdminResult, error)

func (*Client) AdminSaveSMTP

func (c *Client) AdminSaveSMTP(ctx context.Context, f SMTPForm) (AdminResult, error)

func (*Client) AdminSaveServer

func (c *Client) AdminSaveServer(ctx context.Context, f ServerForm) (AdminResult, error)

func (*Client) AdminSaveTLS

func (c *Client) AdminSaveTLS(ctx context.Context, f TLSForm) (AdminResult, error)

func (*Client) AdminSaveWithings

func (c *Client) AdminSaveWithings(ctx context.Context, f WithingsForm) (AdminResult, error)

func (*Client) AdminSaveWorkerKind

func (c *Client) AdminSaveWorkerKind(ctx context.Context, kind string, f WorkerKindForm) (AdminResult, error)

func (*Client) AdminSaveWorkersGlobal

func (c *Client) AdminSaveWorkersGlobal(ctx context.Context, f WorkersGlobalForm) (AdminResult, error)

func (*Client) AdminSetJobPriority

func (c *Client) AdminSetJobPriority(ctx context.Context, userID int64, priority int) (AdminResult, error)

AdminSetJobPriority sets a user's job priority, 1 to 100.

func (*Client) AdminSetPassword

func (c *Client) AdminSetPassword(ctx context.Context, id int64, password string) (AdminResult, error)

func (*Client) AdminSetRole

func (c *Client) AdminSetRole(ctx context.Context, id int64, role string) (AdminResult, error)

func (*Client) AdminSetStrengthLevel

func (c *Client) AdminSetStrengthLevel(ctx context.Context, id int64, on bool) (AdminResult, error)

func (*Client) AdminSetStrengthLevelBulk

func (c *Client) AdminSetStrengthLevelBulk(ctx context.Context, id int64, on bool) (AdminResult, error)

func (*Client) AdminSignup

func (c *Client) AdminSignup(ctx context.Context, open bool) (AdminResult, error)

func (*Client) AdminStatus

func (c *Client) AdminStatus(ctx context.Context) (*StatusDetail, error)

AdminStatus returns the detail. It needs an administrator who passed the step-up check.

func (*Client) AdminStepUp

func (c *Client) AdminStepUp(ctx context.Context) (bool, error)

AdminStepUp reports whether the signed-in administrator has to enter a code before the Admin pages. It fails with CodeUnauthorized or CodeForbidden for anyone who is not an administrator.

func (*Client) AdminTestSMTP

func (c *Client) AdminTestSMTP(ctx context.Context) (AdminResult, error)

func (*Client) AdminTwoFactorPolicy

func (c *Client) AdminTwoFactorPolicy(ctx context.Context, require string) (AdminResult, error)

AdminTwoFactorPolicy sets who must use two-step verification: off, admins or everyone.

func (*Client) AdminVerify

func (c *Client) AdminVerify(ctx context.Context, code string) (SecondStep, error)

AdminVerify checks a code for the Admin pages. On success the proof cookie is relayed and the answer redirects to /admin.

func (*Client) AdminWorkers

func (c *Client) AdminWorkers(ctx context.Context) (*WorkersPage, error)

func (*Client) ChangePassword

func (c *Client) ChangePassword(ctx context.Context, userID int64, p PasswordChange) (SettingsPage, error)

ChangePassword sets a new password. The backend signs the user in again with a new session (the Set-Cookie is relayed) and answers with the settings page data, since the old session is gone.

func (*Client) ConnectIntegration

func (c *Client) ConnectIntegration(ctx context.Context, userID int64, provider string) (string, error)

ConnectIntegration starts the OAuth flow. The backend sets the state cookie (relayed); the result is the provider's authorize URL.

func (*Client) CreateDexaScan

func (c *Client) CreateDexaScan(ctx context.Context, userID int64, sc models.DexaScan) error

func (*Client) CreateScaleReading

func (c *Client) CreateScaleReading(ctx context.Context, userID int64, rd models.ScaleReading) error

CreateScaleReading stores a manual reading. The backend checks the values again.

func (*Client) CreateToken

func (c *Client) CreateToken(ctx context.Context, userID int64, rq NewTokenRequest) (string, error)

CreateToken creates an access token and returns it. It is shown once and never stored in clear.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, path string) error

Delete is Do with DELETE and no body.

func (*Client) DeleteDexaScan

func (c *Client) DeleteDexaScan(ctx context.Context, userID, id int64) error

func (*Client) DeletePasskey

func (c *Client) DeletePasskey(ctx context.Context, userID int64, cred, current string) (string, error)

DeletePasskey removes a passkey. The answer is the message to show, whether it was removed or not.

func (*Client) DeleteScaleReading

func (c *Client) DeleteScaleReading(ctx context.Context, userID, id int64) error

func (*Client) DeleteStrengthLevelLogin

func (c *Client) DeleteStrengthLevelLogin(ctx context.Context, userID int64) (Flash, error)

DeleteStrengthLevelLogin removes the stored login and stops a running sync.

func (*Client) DeleteToken

func (c *Client) DeleteToken(ctx context.Context, userID, id int64) error

DeleteToken revokes one of the user's access tokens.

func (*Client) DexaScans

func (c *Client) DexaScans(ctx context.Context, userID int64) ([]models.DexaScan, error)

DexaScans returns all of a user's scans.

func (*Client) DisconnectIntegration

func (c *Client) DisconnectIntegration(ctx context.Context, userID int64, provider string) (Flash, error)

DisconnectIntegration removes the user's link to the provider.

func (*Client) Do

func (c *Client) Do(ctx context.Context, method, path string, in, out any) (*Result, error)

Do sends in (JSON-encoded unless nil) and decodes the answer into out (unless nil). An error status from the backend is returned as *Error; a failure to reach it as ErrUnavailable.

func (*Client) EstimatesPage

func (c *Client) EstimatesPage(ctx context.Context, userID int64, days int) (EstimatesPage, error)

EstimatesPage returns the data of the estimates page. With days > 0 the result holds only the days within that many days of the newest one (estimate.WithinDays) and all the calibrations; 0 means every day.

func (*Client) FrontendConfig

func (c *Client) FrontendConfig(ctx context.Context, etag string) (*FrontendConfig, string, error)

FrontendConfig fetches the configuration. If etag is the tag of the answer last seen and nothing changed, it returns (nil, etag, nil).

func (*Client) Get

func (c *Client) Get(ctx context.Context, path string, out any) error

Get is Do with GET and no body.

func (*Client) Health

func (c *Client) Health(ctx context.Context) error

Health asks the backend whether it is up.

func (*Client) Import

func (c *Client) Import(ctx context.Context, userID int64, provider, day string) (Flash, error)

Import fetches the provider's measurements now. day (YYYY-MM-DD) limits it to one day. The message summarises the result or the failure.

func (*Client) IntegrationCallback

func (c *Client) IntegrationCallback(ctx context.Context, provider, state, code, providerError string) (Flash, error)

IntegrationCallback completes the OAuth flow with what the provider sent back.

func (*Client) Login

func (c *Client) Login(ctx context.Context, email, password string) (SignInOutcome, error)

Login checks an e-mail address and password.

func (*Client) LoginPage

func (c *Client) LoginPage(ctx context.Context) (LoginPage, error)

LoginPage returns the data of the sign-in page.

func (*Client) LoginSecondStep

func (c *Client) LoginSecondStep(ctx context.Context, code string) (SecondStep, error)

LoginSecondStep checks the code of a sign-in.

func (*Client) LoginSecondStepPage

func (c *Client) LoginSecondStepPage(ctx context.Context) (SecondStep, error)

LoginSecondStepPage asks what the verification page shows. The sealed state cookie comes from the visitor's request.

func (*Client) LoginSetup

func (c *Client) LoginSetup(ctx context.Context, code string) (SecondStep, error)

LoginSetup confirms the required setup of two-step verification with a first code.

func (*Client) LoginSetupPage

func (c *Client) LoginSetupPage(ctx context.Context) (SecondStep, error)

LoginSetupPage asks what the required setup page shows.

func (*Client) Logout

func (c *Client) Logout(ctx context.Context) error

Logout ends the visitor's session. The cleared cookie is relayed.

func (*Client) PasskeyLoginBegin

func (c *Client) PasskeyLoginBegin(ctx context.Context) (json.RawMessage, error)

PasskeyLoginBegin starts a passkey sign-in and returns the WebAuthn options for the browser.

func (*Client) PasskeyLoginFinish

func (c *Client) PasskeyLoginFinish(ctx context.Context, body io.Reader) (SignInOutcome, error)

PasskeyLoginFinish forwards the browser's assertion unchanged. The session cookies are relayed.

func (*Client) PasskeyRegisterBegin

func (c *Client) PasskeyRegisterBegin(ctx context.Context, userID int64, name, current string) (json.RawMessage, error)

PasskeyRegisterBegin starts adding a passkey and returns the WebAuthn options. current is the password, when the account has one.

func (*Client) PasskeyRegisterFinish

func (c *Client) PasskeyRegisterFinish(ctx context.Context, userID int64, body io.Reader) (SignInOutcome, error)

PasskeyRegisterFinish forwards the browser's attestation unchanged and returns where to go.

func (*Client) Post

func (c *Client) Post(ctx context.Context, path string, in, out any) error

Post is Do with POST.

func (*Client) ProviderCallback

func (c *Client) ProviderCallback(ctx context.Context, slug string, params map[string]string) (SignInOutcome, error)

ProviderCallback finishes a sign-in or a linking with every query and form parameter the provider sent back (Apple answers with a cross-site form post).

func (*Client) ProviderStart

func (c *Client) ProviderStart(ctx context.Context, slug string, link bool, current string) (SignInOutcome, error)

ProviderStart begins a sign-in with an external provider, or (link set, for a signed-in visitor) linking it to the account, which needs the current password. The outcome's Redirect is the provider's address; the sealed state cookie travels in the relayed Set-Cookie headers.

func (*Client) Raw

func (c *Client) Raw(ctx context.Context, method, path string, body io.Reader, header http.Header) (*http.Response, error)

Raw sends a request and returns the response unread, for streamed bodies such as exports. Status codes of 400 and above are not turned into errors; the caller owns resp.Body. Set-Cookie headers are relayed.

func (*Client) RenamePasskey

func (c *Client) RenamePasskey(ctx context.Context, userID int64, cred, name string) error

RenamePasskey renames one of the user's passkeys.

func (*Client) Reset

func (c *Client) Reset(ctx context.Context, token, password, confirm, code string) (ResetStep, error)

Reset sets a new password with a reset token (and a code when the account has two-step verification).

func (*Client) ResetForgot

func (c *Client) ResetForgot(ctx context.Context, email string) (ResetStep, error)

ResetForgot asks for a reset e-mail. It answers the same whoever the address belongs to.

func (*Client) ResetForgotPage

func (c *Client) ResetForgotPage(ctx context.Context) (ResetStep, error)

ResetForgotPage reports whether people can ask for a reset e-mail (else it is a not found error).

func (*Client) ResetFormPage

func (c *Client) ResetFormPage(ctx context.Context, token string) (ResetStep, error)

ResetFormPage checks a reset token and tells which form to show.

func (*Client) SaveHiddenColumns

func (c *Client) SaveHiddenColumns(ctx context.Context, userID int64, hidden []string) error

SaveHiddenColumns stores which columns of the daily table are hidden.

func (*Client) SaveProfile

func (c *Client) SaveProfile(ctx context.Context, userID int64, p Profile) error

SaveProfile stores the profile.

func (*Client) SaveSettings

func (c *Client) SaveSettings(ctx context.Context, userID int64, s Settings) error

SaveSettings stores the estimation settings.

func (*Client) SaveStrengthLevelLogin

func (c *Client) SaveStrengthLevelLogin(ctx context.Context, userID int64, email, password string) (Flash, error)

SaveStrengthLevelLogin checks and stores the user's Strength Level login.

func (*Client) ScalePage

func (c *Client) ScalePage(ctx context.Context, userID int64, before string) (ScalePage, error)

ScalePage returns the page of readings before the cursor (empty: the newest).

func (*Client) SendStrengthLevelDay

func (c *Client) SendStrengthLevelDay(ctx context.Context, userID int64, day string) (Flash, error)

SendStrengthLevelDay sends one day's estimate to Strength Level.

func (*Client) Session

func (c *Client) Session(ctx context.Context) (*models.User, error)

Session returns the user behind the visitor's session cookie, or nil if nobody is signed in.

func (*Client) SettingsPage

func (c *Client) SettingsPage(ctx context.Context, userID int64, msg string) (SettingsPage, error)

SettingsPage returns the data of the settings page. msg is the flash message of the request; the Strength Level card shows it.

func (*Client) Signup

func (c *Client) Signup(ctx context.Context, username, email, password, confirm string) (SignInOutcome, error)

Signup creates an account with a password.

func (*Client) StartStrengthLevelSync

func (c *Client) StartStrengthLevelSync(ctx context.Context, userID int64, days string, update bool) (Flash, error)

StartStrengthLevelSync starts the multi-day sync. days is the raw form value.

func (*Client) Status

func (c *Client) Status(ctx context.Context) (*Status, error)

Status returns the summary of the backend and the parts it depends on.

func (*Client) StrengthLevelStatus

func (c *Client) StrengthLevelStatus(ctx context.Context, userID int64) (*SLJobView, error)

StrengthLevelStatus returns the latest sync job, or nil when there has been none.

func (*Client) TwoFactorBegin

func (c *Client) TwoFactorBegin(ctx context.Context, userID int64, current string) (TwoFactorChange, error)

TwoFactorBegin starts the setup and returns the secret to show. current is the password.

func (*Client) TwoFactorConfirm

func (c *Client) TwoFactorConfirm(ctx context.Context, userID int64, code string) (TwoFactorChange, error)

TwoFactorConfirm checks the first code and turns two-step verification on.

func (*Client) TwoFactorDisable

func (c *Client) TwoFactorDisable(ctx context.Context, userID int64, current, code string) error

TwoFactorDisable turns two-step verification off.

func (*Client) TwoFactorRecovery

func (c *Client) TwoFactorRecovery(ctx context.Context, userID int64, current, code string) (TwoFactorChange, error)

TwoFactorRecovery replaces the recovery codes and returns the new ones.

func (*Client) UnlinkIdentity

func (c *Client) UnlinkIdentity(ctx context.Context, userID int64, provider string) (string, error)

UnlinkIdentity unlinks a sign-in provider. The answer is the message to show, whether the account was unlinked or not.

type Error

type Error struct {
	Status  int    `json:"status"`
	Code    string `json:"code"`
	Message string `json:"message"`
}

Error is an error answered by the backend. Message is fit to show to the person.

func (*Error) Error

func (e *Error) Error() string

type EstimatesPage

type EstimatesPage struct {
	Result   estimate.Result  `json:"result"`
	Withings *IntegrationView `json:"withings"`
	SLReady  bool             `json:"sl_ready"`
}

EstimatesPage is the data the estimates page needs besides the user: the estimates, the state of the Withings integration and whether the single-day Strength Level button is shown.

type Flash

type Flash struct {
	Message string `json:"message"`
	UserID  int64  `json:"user_id,omitempty"`
}

Flash is the outcome of an action that ends with a message on a page. UserID is set where the backend, not the request path, says whose page it is (the OAuth callback).

type FrontendConfig

type FrontendConfig struct {
	// Generation changes with every change to the settings.
	Generation int64  `json:"generation"`
	Version    string `json:"version"`

	BaseURL        string   `json:"base_url,omitempty"`
	TrustedProxies []string `json:"trusted_proxies,omitempty"` // prefixes in CIDR form
	ProxyProtocol  bool     `json:"proxy_protocol"`

	TLSMode   string `json:"tls_mode"` // off, upload or selfsigned
	CertPEM   string `json:"cert_pem,omitempty"`
	KeyPEM    string `json:"key_pem,omitempty"` // only over the authenticated internal link
	HTTPSPort string `json:"https_port,omitempty"`
	HTTP3     bool   `json:"http3"`

	// Analytics are the optional measuring and ad services an administrator turned on. The frontend
	// loads them, after a visitor agrees, on the public pages only.
	Analytics Analytics `json:"analytics"`
}

FrontendConfig is what the frontend process needs from the administrator settings to serve visitors: who its trusted proxies are, its public address, and the TLS material for the HTTPS and HTTP/3 listeners it owns.

type IntegrationView

type IntegrationView struct {
	Configured bool // the server has the provider's credentials
	Connected  bool // the user has linked their account
	// AutoPaused is why automatic runs for the user were paused after repeated failures; empty when they are not.
	AutoPaused string
}

IntegrationView is the state of an OAuth integration for the current user.

type KeyView

type KeyView struct {
	Shown   bool
	ID      string
	Since   string // date the key was introduced, at least; empty when unknown
	AgeDays int
	Due     bool // older than the reminder
	Rekey   bool // the database still belongs to a previous key
}

KeyView describes the encryption key on the Admin page.

type LinkedProvider

type LinkedProvider struct {
	Slug, Label string
	Linked      bool
}

type LoginPage

type LoginPage struct {
	PasswordEnabled bool
	SignupOpen      bool
	FirstUser       bool
	Providers       []LoginProvider
	CanReset        bool // people can ask for a reset e-mail
	Passkeys        bool // the browser can use passkeys here
}

LoginPage is what the sign-in page shows.

type LoginProvider

type LoginProvider struct{ Slug, Label string }

LoginProvider is a way of signing in through an external provider.

type NewTokenRequest

type NewTokenRequest struct {
	Name    string `json:"name"`
	Expires string `json:"expires"` // days, "never" or empty
	Current string `json:"current"`
}

NewTokenRequest is the create-token form.

type PasskeyItem

type PasskeyItem struct {
	ID, Name, Created, LastUsed string
}

type PasskeysView

type PasskeysView struct {
	Ready bool // the browser can use passkeys here: HTTPS or localhost
	Items []PasskeyItem
}

PasskeysView is the passkey section of the settings page.

type PasswordChange

type PasswordChange struct {
	Current  string `json:"current"`
	Password string `json:"password"`
	Confirm  string `json:"confirm"`
}

PasswordChange is the change-password form.

type Profile

type Profile struct {
	Username  string `json:"username"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Email     string `json:"email"`
	Timezone  string `json:"timezone"`
	HeightCm  string `json:"height_cm"`
	Current   string `json:"current"`
}

Profile is the profile form of the settings page, as typed. The backend validates every field again; Current is the current password, asked for when the e-mail address changes.

type ProviderForm

type ProviderForm struct {
	Slug, Label, Kind, Issuer, AuthURL, TokenURL, UserinfoURL, ClientID, ClientSecret string
	AppleTeamID, AppleKeyID, Scopes, SubjectClaim, NameClaim                          string
	AllowSignup                                                                       bool
}

ProviderForm is the text of the provider form, as typed.

type Request

type Request struct {
	Cookie   string
	ClientIP string
	Host     string
	Secure   bool

	// Relay receives the Set-Cookie headers the backend answers with. May be nil.
	Relay http.ResponseWriter
}

Request describes the visitor's request for one call. Build it with FromRequest.

type ResetLink struct {
	For     string
	URL     string
	Expires string
	Emailed bool
	Warning bool // made from the request's host, which the request controls
}

ResetLink is the one-time link shown to the administrator who made it.

type ResetStep

type ResetStep struct {
	Redirect  string `json:"redirect,omitempty"`
	Mode      string `json:"mode,omitempty"` // "forgot", "sent", "form" or "invalid"
	Error     string `json:"error,omitempty"`
	NeedsCode bool   `json:"needs_code,omitempty"` // the account has two-step verification
	Status    int    `json:"status,omitempty"`     // HTTP status of the page; 200 when zero
}

ResetStep is what a reset page shows, or where to go on.

type Result

type Result struct {
	Status int
	Header http.Header
}

Result is a successful answer.

type SLJobView

type SLJobView struct {
	Running     bool
	Text        string
	Done, Total int
}

SLJobView is what the settings page shows about a Strength Level job.

type SLView

type SLView struct {
	UserID int64
	Saved  bool
	Email  string // the saved login's e-mail address; the password is never sent back
	Msg    string
	Bulk   bool // the multi-day sync is allowed
	// AutoPaused is why automatic syncs for the user were paused after repeated failures; empty when they are not.
	AutoPaused string
	Job        *SLJobView // the latest multi-day sync, if any
}

SLView is the Strength Level card of the settings page.

type SMTPForm

type SMTPForm struct {
	Host, Port, Username, Password, From, TLS string
	RemovePassword                            bool
}

SMTPForm is the text of the e-mail form, as typed.

type SMTPView

type SMTPView struct {
	Host, Username, From, TLS string
	Port                      int
	PasswordSaved             bool
}

SMTPView is what the Admin page shows and saves for e-mail.

type ScalePage

type ScalePage struct {
	Readings []models.ScaleReading `json:"readings"`
	// Next is the cursor of the next (older) page; empty on the last page.
	Next string `json:"next,omitempty"`
}

ScalePage is one page of a user's scale readings, newest first.

type SecondStep

type SecondStep struct {
	Redirect string   `json:"redirect,omitempty"`
	Status   int      `json:"status,omitempty"` // HTTP status of the page; 200 when zero
	Mode     string   `json:"mode,omitempty"`
	Error    string   `json:"error,omitempty"`
	QR       string   `json:"qr,omitempty"` // SVG made by the backend
	Secret   string   `json:"secret,omitempty"`
	Codes    []string `json:"codes,omitempty"` // recovery codes, shown once
	Continue string   `json:"continue,omitempty"`
}

SecondStep is the answer to a request of the second step of signing in. Either Redirect is set, or the page described by Mode ("verify", "setup" or "codes") is to be shown with Status. When a step finished a sign-in the backend already set the session cookies; the frontend relays them.

type SecurityView

type SecurityView struct {
	Activity        []AuditLine // the latest events about this account
	PasswordEnabled bool
	HasPassword     bool
	ConfirmPassword bool // sensitive changes ask for the current password
	Tokens          []TokenView
	NewToken        string // shown once, right after it was created
	Linked          []LinkedProvider
	TwoFactor       TwoFactorSettings
	Passkeys        PasskeysView
}

SecurityView is the settings page's sign-in section.

type ServerForm

type ServerForm struct {
	BaseURL, TrustedProxies, AuditDays, KeyReminderDays string
	ProxyProtocol                                       bool
	AllowPrivateProviders, AllowPrivateMail             bool
}

ServerForm is the text of the server settings form, as typed.

type ServerSettingsView

type ServerSettingsView struct {
	BaseURL               string
	TrustedProxies        string
	ProxyProtocol         bool
	AllowPrivateProviders bool // sign-in providers may be on private network addresses
	AllowPrivateMail      bool // the mail server may be on a private network address
	AuditDays             string
	KeyReminderDays       string
}

ServerSettingsView is the stored text of the network and retention settings.

type SessionUser

type SessionUser struct {
	models.User
	HiddenColumns     []string `json:"hidden_columns"`
	StrengthLevelAuto bool     `json:"strength_level_auto"`
	StrengthLevelBulk bool     `json:"strength_level_bulk"`
	DataVersion       int64    `json:"data_version"`
}

SessionUser is the signed-in user as the frontend needs it. models.User leaves some fields out of its JSON form on purpose (they are not part of the public API), so the internal API carries them here.

func NewSessionUser

func NewSessionUser(u models.User) SessionUser

NewSessionUser copies a user for the wire.

func (SessionUser) Model

func (s SessionUser) Model() models.User

Model returns the user with every field filled in again.

type Settings

type Settings struct {
	AthleteDefault bool     `json:"athlete_default"`
	MethodRanking  []string `json:"method_ranking"`
}

Settings is the estimation settings a user can save: whether new readings default to athlete mode and the method ranking, best first.

type SettingsPage

type SettingsPage struct {
	Withings      *IntegrationView
	StrengthLevel *SLView
	Security      *SecurityView
}

SettingsPage is the data the settings page needs besides the user.

type SignInOutcome

type SignInOutcome struct {
	Redirect string `json:"redirect,omitempty"`
	Error    string `json:"error,omitempty"`  // fit to show on the sign-in page
	Status   int    `json:"status,omitempty"` // HTTP status to show it with
}

SignInOutcome is the answer to a step of signing in. Exactly one of Redirect and Error is set. When the step succeeded the backend already set the session (or second-step) cookies, and the frontend relays them with the redirect.

type Status

type Status struct {
	CheckedAt  string // UTC, when the backend last checked (it keeps an answer for a few seconds)
	Components []StatusComponent
}

Status is the summary everybody may see.

func (Status) Overall

func (s Status) Overall() string

Overall is the worst state among the components, ignoring those that are off: StateDown, StateDegraded or StateUp.

type StatusComponent

type StatusComponent struct {
	Name  string // a stable key: web, api, database, body, valkey, workers.<provider>
	Label string
	State string
}

StatusComponent is one part of the deployment.

type StatusDetail

type StatusDetail struct {
	Status
	Notes   map[string]string // component name to the reason it is not up
	Workers []StatusWorker
}

StatusDetail is the summary plus what only administrators see.

type StatusWorker

type StatusWorker struct {
	ID       string
	Version  string
	Kinds    []string
	LastSeen string
	Live     bool // asked for work recently enough to count as running
}

StatusWorker is a worker process, for administrators.

type TLSForm

type TLSForm struct {
	Mode, Port, Cert, Key, Names string
	HTTP3                        bool
}

TLSForm is the text of the TLS form, as typed.

type TLSView

type TLSView struct {
	Mode        string // off, upload or selfsigned
	Names       string // names for a self-signed certificate, as typed
	Active      bool   // a certificate is in force
	Subject     string
	CertNames   string
	NotAfter    string
	Fingerprint string
	HTTP3       bool
	HTTP3Active bool
	Port        string
}

TLSView is the secure connections section, without what only the frontend knows (whether its listener could bind).

type TokenView

type TokenView struct {
	ID       int64
	Name     string
	Prefix   string
	Created  string
	LastUsed string
	Expires  string
}

type TwoFactorChange

type TwoFactorChange struct {
	Error  string          `json:"error,omitempty"`
	Status int             `json:"status,omitempty"`
	Setup  *TwoFactorSetup `json:"setup,omitempty"`
	Codes  []string        `json:"codes,omitempty"`
}

TwoFactorChange is the answer to a change of two-step verification on the settings page. A refusal that needs the setup shown again (a wrong first code) is Error with Status and Setup; other refusals are errors. Codes are the recovery codes, shown once.

type TwoFactorSettings

type TwoFactorSettings struct {
	Available    bool // the user signs in with a password, so there is something to protect
	Enabled      bool
	Required     bool // an administrator requires it for this user
	RecoveryLeft int
	Setup        *TwoFactorSetup
	NewCodes     []string // shown once
}

TwoFactorSettings is the two-step part of the settings page.

type TwoFactorSetup

type TwoFactorSetup struct {
	QR     template.HTML
	Secret string
}

TwoFactorSetup is a secret waiting to be confirmed.

type WithingsForm

type WithingsForm struct {
	ClientID, RedirectURL, ClientSecret string
	ClearSecret                         bool
}

WithingsForm is the text of the Withings credentials form.

type WorkerInstanceView

type WorkerInstanceView struct {
	ID       string
	Version  string
	Kinds    []string
	LastSeen string
}

WorkerInstanceView is a worker process that asked for work recently.

type WorkerJobView

type WorkerJobView struct {
	ID          string
	Kind        string
	User        string
	UserID      int64
	Priority    int
	UserIsAdmin bool
	State       string
	Origin      string
	Attempts    int
	MaxAttempts int
	Error       string
	Created     string
	Updated     string
	Active      bool // can still be canceled
}

WorkerJobView is a job in the list on the Admin page.

type WorkerKindForm

type WorkerKindForm struct {
	Enabled          bool
	MaxRunning       int
	MaxAttempts      int
	RetryBaseSeconds int
	TimeoutSeconds   int
	ScheduleHours    int
	PauseAfter       int
	Breaker          int
	Options          map[string]int
}

WorkerKindForm is what an administrator saves for a kind.

type WorkerKindView

type WorkerKindView struct {
	Kind  string
	Label string
	// Enabled is false when an administrator (or the circuit breaker, see PausedReason) paused it.
	Enabled      bool
	PausedReason string

	MaxRunning       int // at once in all workers together; 0 is no limit
	MaxAttempts      int
	RetryBaseSeconds int
	TimeoutSeconds   int
	ScheduleHours    int // 0: no automatic runs
	PauseAfter       int
	Breaker          int
	Schedulable      bool
	Options          []WorkerOptionView

	Queued          int
	Running         int
	Failed24h       int
	WorkersOnline   int
	PausedSchedules int // users whose automatic runs are paused
}

WorkerKindView is one kind of job: its settings and what is going on.

type WorkerOptionView

type WorkerOptionView struct {
	Name     string
	Label    string
	Value    int
	Min, Max int
	Millis   bool // shown in milliseconds
}

WorkerOptionView is a whole-number option of a kind that is sent to its workers.

type WorkerProviderView

type WorkerProviderView struct {
	Name  string
	Label string
	Kinds []WorkerKindView
}

WorkerProviderView groups the kinds of one provider.

type WorkersGlobalForm

type WorkersGlobalForm struct {
	DefaultPriority int
	KeepHistoryDays int
}

WorkersGlobalForm is what an administrator saves for all workers.

type WorkersPage

type WorkersPage struct {
	Providers       []WorkerProviderView
	Workers         []WorkerInstanceView
	Jobs            []WorkerJobView
	DefaultPriority int
	KeepHistoryDays int
}

WorkersPage is everything the workers section of the Admin page shows.

Jump to

Keyboard shortcuts

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