sqlstore

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: 34 Imported by: 0

Documentation

Overview

Package sqlstore implements store.Store on top of bun, for SQLite and PostgreSQL. Schema changes are versioned goose migrations (see migrate.go).

Index

Constants

View Source
const (
	ProvisionAppRole    = "dexafix"      // the api's role; owns the database
	ProvisionBodyRole   = "dexafix_body" // the body service's role; owns the schema "body" only
	ProvisionDatabase   = "dexafix"
	ProvisionBodySchema = "body"
)

The names Provision creates. They are fixed: the connection strings that deploy init writes and the body service's search_path refer to them.

View Source
const (
	DriverSQLite   = "sqlite"
	DriverPostgres = "postgres"
)

Supported database drivers.

View Source
const KeySize = 32

KeySize is the length of an encryption key in bytes (AES-256).

Variables

This section is empty.

Functions

func HasEncryptedBodyValues

func HasEncryptedBodyValues(ctx context.Context, driver, dsn string) (bool, error)

HasEncryptedBodyValues is HasEncryptedValues for a database that holds only the body domain.

func HasEncryptedValues

func HasEncryptedValues(ctx context.Context, driver, dsn string) (bool, error)

HasEncryptedValues reports whether the database already holds encrypted values, without migrating it. A database that does not exist yet, or has no tables, holds none. The serve command uses it to avoid inventing a new key for data that depends on an old one.

func ParseKey

func ParseKey(text string) ([]byte, error)

ParseKey decodes a key written as 64 hexadecimal characters or as base64.

func Provision

func Provision(ctx context.Context, o ProvisionOptions) error

Provision makes the PostgreSQL roles, the database and the body schema the recommended deployment runs on, so that no service runs as a superuser and a leak of one cannot read the other's data:

dexafix        owns the database, has no rights in the schema "body"
dexafix_body   owns the schema "body" and can use nothing else

It can be run again and again: what exists is kept and the passwords are set again, so a changed password file takes effect at the next run. It never drops anything.

func SequentialUserIDsForTests

func SequentialUserIDsForTests()

SequentialUserIDsForTests makes new users get the ids 1, 2, 3... instead of random ones. Call it from TestMain of a test binary, never from production code: random ids are a defence.

func SetSequentialUserIDsForTests

func SetSequentialUserIDsForTests(on bool)

SetSequentialUserIDsForTests turns the sequential ids of SequentialUserIDsForTests on or off, for the test that wants random ids in a binary that otherwise uses counted ones.

Types

type BodyRekeyStats

type BodyRekeyStats struct {
	Changed int // rows re-encrypted
	Current int // rows already under the current key
}

BodyRekeyStats counts what Rekey changed (or, in a dry run, would change) in the body data.

type BodyStore

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

BodyStore is the body domain: a user's scale readings and DEXA scans, and the counter of their changes. It has its own migrations (migrations/body, with a version table of its own), its own key check and a cipher of its own, so it can live in a database of its own, in the process of the body service. Inside a Store it shares the connection pool of the main database.

func OpenBody

func OpenBody(ctx context.Context, driver, dsn string, opts ...Option) (*BodyStore, error)

OpenBody opens a database that holds only the body domain, for the body service. The cipher option (WithCipher) is a master key: the body key derives from it, so a body process may share the key file of the main backend, or have one of its own. WithoutMigrate and RequireMigrated work as for Open.

func (*BodyStore) BodyStats

func (s *BodyStore) BodyStats(ctx context.Context) (store.BodyStats, error)

BodyStats counts the scans and readings.

func (*BodyStore) BodyUserIDs

func (s *BodyStore) BodyUserIDs(ctx context.Context) ([]int64, error)

BodyUserIDs lists the users that have a scan, a reading or a counter.

func (*BodyStore) BodyVersion

func (s *BodyStore) BodyVersion(ctx context.Context, userID int64) (int64, error)

BodyVersion returns the number of changes to the user's scans and readings so far.

func (*BodyStore) Close

func (b *BodyStore) Close() error

Close closes the connection pool when this store opened it. Inside a Store it does nothing: the Store closes the pool.

func (*BodyStore) CreateDexaScan

func (s *BodyStore) CreateDexaScan(ctx context.Context, d *models.DexaScan) error

func (*BodyStore) DeleteDexaScan

func (s *BodyStore) DeleteDexaScan(ctx context.Context, userID, id int64) error

func (*BodyStore) DeleteScaleReading

func (s *BodyStore) DeleteScaleReading(ctx context.Context, userID, id int64) error

func (*BodyStore) DeleteScaleReadings added in v0.0.2

func (s *BodyStore) DeleteScaleReadings(ctx context.Context, userID int64, ids []int64) (int, error)

func (*BodyStore) DeleteUserBodyData

func (s *BodyStore) DeleteUserBodyData(ctx context.Context, userID int64) error

DeleteUserBodyData removes the user's scans, readings and counter.

func (*BodyStore) HasEncryptedValues

func (b *BodyStore) HasEncryptedValues(ctx context.Context) (bool, error)

HasEncryptedValues reports whether the body data holds encrypted rows.

func (*BodyStore) HasPending

func (b *BodyStore) HasPending(ctx context.Context) (bool, error)

HasPending reports whether the body domain has unapplied migrations.

func (*BodyStore) ListDexaScans

func (s *BodyStore) ListDexaScans(ctx context.Context, userID int64) ([]models.DexaScan, error)

func (*BodyStore) ListDexaScansPage

func (s *BodyStore) ListDexaScansPage(ctx context.Context, userID int64, f store.ListFilter) ([]models.DexaScan, *store.Cursor, error)

func (*BodyStore) ListScaleReadings

func (s *BodyStore) ListScaleReadings(ctx context.Context, userID int64) ([]models.ScaleReading, error)

func (*BodyStore) ListScaleReadingsPage

func (s *BodyStore) ListScaleReadingsPage(ctx context.Context, userID int64, f store.ListFilter) ([]models.ScaleReading, *store.Cursor, error)

func (*BodyStore) MaxConns

func (b *BodyStore) MaxConns() int

MaxConns is the size of the connection pool.

func (*BodyStore) Migrate

func (b *BodyStore) Migrate(ctx context.Context) ([]*goose.MigrationResult, error)

Migrate applies the pending migrations of the body domain.

func (*BodyStore) Ping

func (b *BodyStore) Ping(ctx context.Context) error

Ping checks that the database answers.

func (*BodyStore) Rekey

func (b *BodyStore) Rekey(ctx context.Context, dryRun bool) (BodyRekeyStats, error)

Rekey re-encrypts every row with the current body key and writes the new check value, in one transaction: it completes or leaves the data untouched. Rows already under the current key are skipped, so a run can be repeated. With dryRun nothing is written.

func (*BodyStore) ScaleReadingsForReconcile added in v0.0.2

func (s *BodyStore) ScaleReadingsForReconcile(ctx context.Context, userID int64, f store.ListFilter, source string, externalIDs []string) ([]models.ScaleReading, error)

func (*BodyStore) SchemaVersion

func (b *BodyStore) SchemaVersion(ctx context.Context) (int64, error)

SchemaVersion is the applied migration version of the body domain (0 = none).

func (*BodyStore) UpsertScaleReadings

func (s *BodyStore) UpsertScaleReadings(ctx context.Context, userID int64, rs []models.ScaleReading) (int, error)

type Cipher

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

Cipher encrypts sensitive columns with AES-256-GCM. It seals with the current key and opens values made by the current key or by any previous one.

func NewCipher

func NewCipher(key []byte, previous ...[]byte) (*Cipher, error)

NewCipher returns a Cipher for a key of KeySize bytes. Previous keys only serve to read values that were encrypted before a rotation (see Store.Rekey).

type CopyStats

type CopyStats struct {
	Users        int
	DexaScans    int
	ScaleReads   int
	Integrations int
	Identities   int
	AccessTokens int
	Settings     int
	Providers    int
	AuditEvents  int
}

CopyStats reports how many rows Copy transferred per table.

func Copy

func Copy(ctx context.Context, src, dst *Store) (CopyStats, error)

Copy transfers every row from src to dst, preserving ids. It works between any pair of backends. Both databases must be at the same schema version and dst must be empty. The copy is a single transaction on dst, so a failure leaves it untouched.

type Option

type Option func(*openConfig)

Option customises Open.

func RequireMigrated

func RequireMigrated() Option

RequireMigrated fails Open when there are pending migrations instead of applying them.

func WithCipher

func WithCipher(c *Cipher) Option

WithCipher encrypts sensitive columns: provider secrets, integration tokens, server settings and e-mail addresses. Values stored before it was enabled are encrypted when the store opens.

func WithoutBody

func WithoutBody() Option

WithoutBody opens the main database without the body domain (scans and readings): its tables are not created or migrated, and the BodyStore methods are not available. For a backend that calls a body service of its own.

func WithoutMigrate

func WithoutMigrate() Option

WithoutMigrate opens the database without touching the schema (used by the db management commands).

type ProvisionOptions

type ProvisionOptions struct {
	AdminDSN     string
	AppPassword  string
	BodyPassword string
}

ProvisionOptions are what Provision needs. AdminDSN is a superuser's connection string (to any database, usually "postgres"); the two passwords are the ones the application roles get.

type RekeyStats

type RekeyStats struct {
	Emails       int // user e-mail addresses re-encrypted
	Integrations int
	Settings     int
	Providers    int
	TOTP         int // two-step verification secrets re-encrypted
	Jobs         int // queued or running worker jobs re-encrypted
	Body         int // scale readings and DEXA scans re-encrypted
	Lookups      int // e-mail lookup hashes recomputed
	Current      int // encrypted values already under the current key
}

RekeyStats counts what Rekey changed (or, in a dry run, would change). Current counts values that were already sealed with the current key and are left alone.

func (RekeyStats) Changed

func (r RekeyStats) Changed() int

Changed is the number of values that were or would be rewritten.

type Store

type Store struct {

	// BodyStore is the body domain (scans and readings) on the same connection pool, or nil when
	// the store was opened WithoutBody: then another process holds that data. Its methods are
	// promoted, so a combined process and the tests use one value for both domains; the main
	// backend only sees the store.Store interface, which does not have them.
	*BodyStore
	// contains filtered or unexported fields
}

Store is a bun backed store.Store.

func Open

func Open(ctx context.Context, driver, dsn string, opts ...Option) (*Store, error)

Open connects to the database and, unless told otherwise, applies pending migrations.

func (*Store) AddAuditEvent

func (s *Store) AddAuditEvent(ctx context.Context, e *models.AuditEvent) error

func (*Store) AddPasskey

func (s *Store) AddPasskey(ctx context.Context, p models.Passkey) error

AddPasskey stores a new credential. A credential id belongs to one user: a second registration of the same authenticator credential fails with ErrExists.

func (*Store) CancelJob

func (s *Store) CancelJob(ctx context.Context, publicID string, userID int64, at time.Time) (models.Job, error)

CancelJob cancels a queued job at once and asks the worker of a running one to stop. userID limits it to that user's jobs (0: any). A job that already ended is returned as it is.

func (*Store) CancelJobs

func (s *Store) CancelJobs(ctx context.Context, userID int64, kinds []string, at time.Time) error

CancelJobs cancels the active jobs of a user and kinds (for example when a login is removed).

func (*Store) ClearFailures

func (s *Store) ClearFailures(ctx context.Context, key string) error

func (*Store) Close

func (s *Store) Close() error

Close closes the database.

func (*Store) CompleteJob

func (s *Store) CompleteJob(ctx context.Context, publicID, tokenHash string, c models.Completion, at time.Time) (models.Job, error)

CompleteJob ends the attempt as the worker reports it. An OutcomeRetry requeues the job for c.RetryAt unless it ran out of attempts (it then fails for good) or was canceled. It fails with ErrLeaseLost when the job is no longer running under this token, which also makes a second completion of the same attempt harmless.

func (*Store) CompletePasswordReset

func (s *Store) CompletePasswordReset(ctx context.Context, tokenHash, passwordHash string) (int64, error)

CompletePasswordReset uses a live link: in one transaction it deletes the user's links, sets the password and signs the user out everywhere (sessions and access tokens), so a link can be used once and a changed password never leaves old sessions alive. It returns the user id, or ErrNotFound when the link is unknown or expired.

func (*Store) ConfirmTOTP

func (s *Store) ConfirmTOTP(ctx context.Context, userID, step int64) error

ConfirmTOTP turns a pending setup into a confirmed one. step is the code step the user proved the secret with; it becomes the replay guard. It fails with ErrNotFound without a pending setup.

func (*Store) CountFailures

func (s *Store) CountFailures(ctx context.Context, key string, since time.Time) (int, error)

func (*Store) CountRecoveryCodes

func (s *Store) CountRecoveryCodes(ctx context.Context, userID int64) (int, error)

CountRecoveryCodes is the number of recovery codes the user has left.

func (*Store) CreateAccessToken

func (s *Store) CreateAccessToken(ctx context.Context, t *models.AccessToken) error

func (*Store) CreatePasswordReset

func (s *Store) CreatePasswordReset(ctx context.Context, tokenHash string, userID int64, createdBy *int64, expires time.Time) error

CreatePasswordReset stores a reset link for the user. A user has at most one live link: the others, and every expired link, are removed first. createdBy is the administrator who made it, nil when the user asked for it.

func (*Store) CreateSession

func (s *Store) CreateSession(ctx context.Context, tokenHash string, userID int64, method string, expires time.Time) error

func (*Store) CreateUser

func (s *Store) CreateUser(ctx context.Context, username string) (models.User, error)

func (*Store) CreateUserWithIdentity

func (s *Store) CreateUserWithIdentity(ctx context.Context, username, email string, id models.Identity) (models.User, error)

CreateUserWithIdentity creates a user together with a way to sign in.

func (*Store) DeleteAccessToken

func (s *Store) DeleteAccessToken(ctx context.Context, userID, id int64) error

func (*Store) DeleteAuthProvider

func (s *Store) DeleteAuthProvider(ctx context.Context, slug string) error

func (*Store) DeleteIdentity

func (s *Store) DeleteIdentity(ctx context.Context, userID int64, provider string) error

func (*Store) DeleteIntegration

func (s *Store) DeleteIntegration(ctx context.Context, userID int64, provider string) error

func (*Store) DeleteJobSchedule

func (s *Store) DeleteJobSchedule(ctx context.Context, userID int64, kind string) error

DeleteJobSchedule forgets a schedule, which also resumes one that was paused.

func (*Store) DeletePasskey

func (s *Store) DeletePasskey(ctx context.Context, userID int64, credentialID string) error

func (*Store) DeletePasswordResets

func (s *Store) DeletePasswordResets(ctx context.Context, userID int64) error

DeletePasswordResets removes the user's outstanding reset links, for example after the password or the e-mail address changed.

func (*Store) DeleteSession

func (s *Store) DeleteSession(ctx context.Context, tokenHash string) error

func (*Store) DeleteSetting

func (s *Store) DeleteSetting(ctx context.Context, name string) error

func (*Store) DeleteTOTP

func (s *Store) DeleteTOTP(ctx context.Context, userID int64) error

DeleteTOTP removes the setup and the recovery codes. It succeeds when there is none.

func (*Store) DeleteUser

func (s *Store) DeleteUser(ctx context.Context, userID int64) error

DeleteUser removes the user and, with them, the IP addresses in the audit events about them. The events themselves stay, without a reference to the person (ON DELETE SET NULL).

func (*Store) DeleteUserAccessTokens

func (s *Store) DeleteUserAccessTokens(ctx context.Context, userID int64) error

func (*Store) DeleteUserSessions

func (s *Store) DeleteUserSessions(ctx context.Context, userID int64) error

func (*Store) EnqueueJob

func (s *Store) EnqueueJob(ctx context.Context, n models.NewJob) (models.Job, bool, error)

EnqueueJob queues a job. When the job has a DedupeKey and one with that key is already queued or running, nothing is added and that job is returned with created false.

func (*Store) EnsurePasskeyHandle

func (s *Store) EnsurePasskeyHandle(ctx context.Context, userID int64) (string, error)

EnsurePasskeyHandle returns the random user handle that identifies the user to their passkeys, creating it the first time. It is 64 random bytes and says nothing about the person.

func (*Store) ExecForTests

func (s *Store) ExecForTests(ctx context.Context, query string, args ...any) error

ExecForTests runs one statement for a test that has to break the database on purpose, such as renaming a table so that every query on it fails. Never call it from production code.

func (*Store) ExpireQueuedJobs

func (s *Store) ExpireQueuedJobs(ctx context.Context, at time.Time) (int64, error)

ExpireQueuedJobs ends queued jobs that were not started before their expiry.

func (*Store) GetAuthProvider

func (s *Store) GetAuthProvider(ctx context.Context, slug string) (models.AuthProvider, error)

func (*Store) GetIdentity

func (s *Store) GetIdentity(ctx context.Context, provider, subject string) (models.Identity, error)

func (*Store) GetIntegration

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

func (*Store) GetJob

func (s *Store) GetJob(ctx context.Context, publicID string) (models.Job, error)

func (*Store) GetJobSchedule

func (s *Store) GetJobSchedule(ctx context.Context, userID int64, kind string) (models.JobSchedule, error)

GetJobSchedule returns what the scheduler remembers about a user and kind, or ErrNotFound.

func (*Store) GetSession

func (s *Store) GetSession(ctx context.Context, tokenHash string) (models.Session, error)

func (*Store) GetSetting

func (s *Store) GetSetting(ctx context.Context, name string) (string, error)

func (*Store) GetTOTP

func (s *Store) GetTOTP(ctx context.Context, userID int64) (models.TOTP, error)

GetTOTP returns the user's one-time password setup, confirmed or not, or ErrNotFound.

func (*Store) GetUser

func (s *Store) GetUser(ctx context.Context, id int64) (models.User, error)

func (*Store) GetUserByEmail

func (s *Store) GetUserByEmail(ctx context.Context, email string) (models.User, error)

func (*Store) HasPending

func (s *Store) HasPending(ctx context.Context) (bool, error)

HasPending reports whether there are unapplied migrations, in the main database or the body domain.

func (*Store) HasUsers

func (s *Store) HasUsers(ctx context.Context) (bool, error)

func (*Store) HeartbeatJob

func (s *Store) HeartbeatJob(ctx context.Context, publicID, tokenHash string, extend time.Duration, progress *string, at time.Time) (cancel bool, err error)

HeartbeatJob extends the lease of a running job and stores its progress (nil leaves it). It fails with ErrLeaseLost when the token is not the leaseholder's, or the lease or the job's hard deadline has passed: the job then belongs to the reaper. cancel tells the worker to stop.

func (*Store) IdentityProviders

func (s *Store) IdentityProviders(ctx context.Context) (map[int64][]string, error)

func (*Store) JobStats

func (s *Store) JobStats(ctx context.Context, failedSince time.Time) ([]models.JobKindStats, error)

JobStats counts the jobs of every kind that are waiting or running, and those that failed since a time.

func (*Store) LastFinishedStates

func (s *Store) LastFinishedStates(ctx context.Context, kind string, n int, since time.Time) ([]string, error)

LastFinishedStates returns the states of the latest n jobs of a kind that succeeded or failed since a time, newest first. The backend watches it to notice that a provider keeps failing.

func (*Store) LeaseJob

func (s *Store) LeaseJob(ctx context.Context, req models.LeaseRequest, at time.Time) (models.Job, bool, error)

LeaseJob hands the best waiting job to a worker, or reports that there is none. The order is: administrators' jobs first, then the user's priority (higher first), then jobs somebody waits for, then the oldest. Role and priority are read now, so a change applies to jobs already queued. MaxRunning is checked when leasing, so it can be exceeded by the number of leases that happen at the very same moment; the lease itself is exact.

func (*Store) ListAccessTokens

func (s *Store) ListAccessTokens(ctx context.Context, userID int64) ([]models.AccessToken, error)

func (*Store) ListAuditEvents

func (s *Store) ListAuditEvents(ctx context.Context, f store.AuditFilter) ([]models.AuditEvent, error)

func (*Store) ListAuthProviders

func (s *Store) ListAuthProviders(ctx context.Context) ([]models.AuthProvider, error)

func (*Store) ListJobSchedules

func (s *Store) ListJobSchedules(ctx context.Context, kind string) ([]models.JobSchedule, error)

func (*Store) ListJobs

func (s *Store) ListJobs(ctx context.Context, f models.JobFilter) ([]models.Job, error)

ListJobs returns jobs newest first, without their payload and result.

func (*Store) ListPasskeys

func (s *Store) ListPasskeys(ctx context.Context, userID int64) ([]models.Passkey, error)

func (*Store) ListUserIdentities

func (s *Store) ListUserIdentities(ctx context.Context, userID int64) ([]models.Identity, error)

func (*Store) ListUsers

func (s *Store) ListUsers(ctx context.Context) ([]models.User, error)

func (*Store) ListUsersWithIntegration

func (s *Store) ListUsersWithIntegration(ctx context.Context, provider string) ([]int64, error)

ListUsersWithIntegration returns the ids of users who have stored data for a provider.

func (*Store) ListWorkers

func (s *Store) ListWorkers(ctx context.Context, since time.Time) ([]models.WorkerInstance, error)

ListWorkers returns the workers seen since a time, newest first.

func (*Store) MaxConns

func (s *Store) MaxConns() int

MaxConns is the size of the connection pool. A server uses it to keep one class of requests from taking every connection.

func (*Store) Migrate

func (s *Store) Migrate(ctx context.Context) ([]*goose.MigrationResult, error)

Migrate applies all pending migrations: the main database's, then the body domain's when this store has one (they have separate migration sets and version tables).

func (*Store) MigrateDown

func (s *Store) MigrateDown(ctx context.Context) (*goose.MigrationResult, error)

MigrateDown rolls back the most recently applied migration.

func (*Store) MigrateTo

func (s *Store) MigrateTo(ctx context.Context, version int64) ([]*goose.MigrationResult, error)

MigrateTo migrates up or down until the database is at the given version (0 = empty).

func (*Store) MigrationStatus

func (s *Store) MigrationStatus(ctx context.Context) ([]*goose.MigrationStatus, error)

MigrationStatus lists every known migration and whether it has been applied.

func (*Store) NonceSeen

func (s *Store) NonceSeen(ctx context.Context, nonce string) (bool, error)

func (*Store) PasswordResetUser

func (s *Store) PasswordResetUser(ctx context.Context, tokenHash string) (models.User, error)

PasswordResetUser returns the user a live reset link belongs to, or ErrNotFound.

func (*Store) Ping

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

Ping checks that the database answers. It is defined here and not promoted from the BodyStore, which is nil in a store opened WithoutBody.

func (*Store) PurgeAuditEvents

func (s *Store) PurgeAuditEvents(ctx context.Context, before time.Time) (int64, error)

func (*Store) PurgeFailures

func (s *Store) PurgeFailures(ctx context.Context, before time.Time) (int64, error)

func (*Store) PurgeJobs

func (s *Store) PurgeJobs(ctx context.Context, before time.Time) (int64, error)

PurgeJobs deletes jobs that ended before the cutoff.

func (*Store) PurgeNonces

func (s *Store) PurgeNonces(ctx context.Context, before time.Time) (int64, error)

func (*Store) PurgeWorkers

func (s *Store) PurgeWorkers(ctx context.Context, before time.Time) (int64, error)

PurgeWorkers forgets workers not seen since the cutoff.

func (*Store) PutAuthProvider

func (s *Store) PutAuthProvider(ctx context.Context, p models.AuthProvider) error

func (*Store) PutIdentity

func (s *Store) PutIdentity(ctx context.Context, id models.Identity) error

func (*Store) PutIntegration

func (s *Store) PutIntegration(ctx context.Context, userID int64, provider string, data []byte) error

func (*Store) PutJobSchedule

func (s *Store) PutJobSchedule(ctx context.Context, j models.JobSchedule) error

func (*Store) PutPendingTOTP

func (s *Store) PutPendingTOTP(ctx context.Context, userID int64, secret string) error

PutPendingTOTP starts (or restarts) the setup with a new secret. The setup counts only after ConfirmTOTP, and starting again discards an earlier, unconfirmed secret. A confirmed setup is never replaced: it fails with ErrExists.

func (*Store) PutSetting

func (s *Store) PutSetting(ctx context.Context, name, value string) error

func (*Store) ReapExpiredLeases

func (s *Store) ReapExpiredLeases(ctx context.Context, at time.Time, backoff func(models.Job) time.Duration) ([]models.Job, error)

ReapExpiredLeases deals with running jobs whose lease or hard deadline has passed, because the worker died, hung or lost the network: each such attempt counts as failed, and the job is requeued after backoff(job) or, when it has no attempts left, ended. It returns the jobs it changed.

func (*Store) RecordFailure

func (s *Store) RecordFailure(ctx context.Context, key string, at time.Time) error

func (*Store) Rekey

func (s *Store) Rekey(ctx context.Context, dryRun bool) (RekeyStats, error)

Rekey re-encrypts every encrypted value with the current key, recomputes the e-mail lookup hashes (they derive from the key) and writes the new key check value, all in one transaction: it completes or leaves the database untouched. Values already sealed with the current key are skipped, so a run can be repeated. Any value that no configured key can open fails the whole run. With dryRun nothing is written and the result reports what would change.

func (*Store) ReleaseJob

func (s *Store) ReleaseJob(ctx context.Context, publicID, tokenHash string, at time.Time) error

ReleaseJob gives a job back without counting the attempt, for a worker that is shutting down.

func (*Store) RenamePasskey

func (s *Store) RenamePasskey(ctx context.Context, userID int64, credentialID, name string) error

func (*Store) ReplaceRecoveryCodes

func (s *Store) ReplaceRecoveryCodes(ctx context.Context, userID int64, hashes []string) error

ReplaceRecoveryCodes stores the hashes of a new set of recovery codes and drops the old set.

func (*Store) RunningJob

func (s *Store) RunningJob(ctx context.Context, publicID, tokenHash string) (models.Job, error)

RunningJob returns a job that is running under this lease token, or ErrLeaseLost. It changes nothing; the backend uses it to find out whose call it is serving.

func (*Store) SchemaVersion

func (s *Store) SchemaVersion(ctx context.Context) (int64, error)

SchemaVersion returns the currently applied migration version (0 = none).

func (*Store) SetUserJobPriority

func (s *Store) SetUserJobPriority(ctx context.Context, userID int64, priority int) error

SetUserJobPriority sets the priority (1-100) that orders a user's jobs among other users'.

func (*Store) SetUserRole

func (s *Store) SetUserRole(ctx context.Context, userID int64, role string) error

func (*Store) SetUserStrengthLevelAuto

func (s *Store) SetUserStrengthLevelAuto(ctx context.Context, userID int64, enabled bool) error

SetUserStrengthLevelAuto allows or forbids automatic Strength Level sync for a user. Forbidding it deletes the stored login in the same transaction.

func (*Store) SetUserStrengthLevelBulk

func (s *Store) SetUserStrengthLevelBulk(ctx context.Context, userID int64, enabled bool) error

SetUserStrengthLevelBulk allows or forbids the multi-day sync for a user who may sync.

func (*Store) SettingsGeneration

func (s *Store) SettingsGeneration(ctx context.Context) (int64, error)

SettingsGeneration returns a number that grows whenever a setting is written or deleted.

func (*Store) Stats

func (s *Store) Stats(ctx context.Context) (store.Stats, error)

Stats counts the main tables.

func (*Store) TouchWorker

func (s *Store) TouchWorker(ctx context.Context, id string, kinds []string, version string, at time.Time) error

TouchWorker records that a worker process asked for work.

func (*Store) TwoFactorUsers

func (s *Store) TwoFactorUsers(ctx context.Context) (map[int64]bool, error)

TwoFactorUsers returns the ids of the users who have confirmed two-step verification.

func (*Store) UpdatePasskeyUse

func (s *Store) UpdatePasskeyUse(ctx context.Context, credentialID, credential string, signCount uint32) error

UpdatePasskeyUse records a sign-in: the new counter, the refreshed credential JSON (flags such as backup state can change) and the time.

func (*Store) UpdateUserHiddenColumns

func (s *Store) UpdateUserHiddenColumns(ctx context.Context, userID int64, keys []string) error

UpdateUserHiddenColumns stores which daily table columns the user has hidden.

func (*Store) UpdateUserProfile

func (s *Store) UpdateUserProfile(ctx context.Context, userID int64, username, firstName, lastName, email string, heightCm *float64) error

func (*Store) UpdateUserSettings

func (s *Store) UpdateUserSettings(ctx context.Context, userID int64, athleteDefault bool, ranking []string) error

UpdateUserSettings stores the athlete-mode default and the method accuracy ranking.

func (*Store) UpdateUserTimezone

func (s *Store) UpdateUserTimezone(ctx context.Context, userID int64, timezone string) error

func (*Store) UseNonce

func (s *Store) UseNonce(ctx context.Context, nonce string, expires time.Time) (bool, error)

UseNonce claims nonce until expires. The insert only succeeds, or takes over an expired row, when nobody holds it, so two processes racing for the same value cannot both win.

func (*Store) UseRecoveryCode

func (s *Store) UseRecoveryCode(ctx context.Context, userID int64, hash string) (bool, error)

UseRecoveryCode deletes the code with this hash and reports whether the user had it.

func (*Store) UseTOTPStep

func (s *Store) UseTOTPStep(ctx context.Context, userID, step int64) (bool, error)

UseTOTPStep records step as used and reports whether it was fresh. It is one conditional update, so of two requests presenting the same code only one wins.

func (*Store) UserByPasskeyHandle

func (s *Store) UserByPasskeyHandle(ctx context.Context, handle string) (models.User, error)

func (*Store) UserBySession

func (s *Store) UserBySession(ctx context.Context, tokenHash string) (models.User, error)

func (*Store) UserByTokenHash

func (s *Store) UserByTokenHash(ctx context.Context, tokenHash string) (models.User, error)

func (*Store) UserProviders

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

Jump to

Keyboard shortcuts

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