Documentation
¶
Overview ¶
Package sqlitestore implements auth's store ports on SQLite: the same ports pgstore implements, for a CLI, a single-host service or a test suite that has no Postgres to run against.
It uses modernc.org/sqlite, a pure-Go driver, so a binary embedding this package still cross-compiles with nothing but GOOS and GOARCH.
Its tables carry an auth_ prefix, since SQLite has no schemas, and migrate with their own goose version table, so an app keeping its own tables in the same file runs Migrate beside its own migrations and neither sees the other's history.
Where it differs from pgstore ¶
The ports behave the same; storetest holds both to that. What differs is what SQLite is:
- One writer at a time. Every transaction begins IMMEDIATE, taking the write lock up front, and a writer that cannot get it waits up to the busy timeout and then fails. Under sustained concurrent writes that surfaces as an error where Postgres would have queued the work.
- Ids are TEXT. Each id is parsed as a uuid and stored in its canonical lower-case form, which is what makes an upper-case id find its row as it would against a uuid column.
- Instants are TEXT in a fixed-width UTC layout, read back in UTC.
- Lists (scopes, transports, recovery-code hashes) are JSON arrays.
Index ¶
- Constants
- func DSN(path string) string
- func Migrate(ctx context.Context, db *sql.DB) error
- type Store
- func (s *Store) ClearFailedLoginAttempts(ctx context.Context, email string) error
- func (s *Store) Close() error
- func (s *Store) ConsumeRefreshToken(ctx context.Context, id string) (bool, error)
- func (s *Store) ConsumeSuperuserRefreshToken(ctx context.Context, id string) (bool, error)
- func (s *Store) ConsumeWebAuthnChallenge(ctx context.Context, tokenHash string) (*store.WebAuthnChallenge, error)
- func (s *Store) CountRecentFailedLoginAttempts(ctx context.Context, email string, since time.Time) (int, error)
- func (s *Store) CountSuperusers(ctx context.Context) (int, error)
- func (s *Store) CreateAccount(ctx context.Context, a *store.Account) error
- func (s *Store) CreateBoundDevice(ctx context.Context, d *store.BoundDevice) error
- func (s *Store) CreateDeviceAuthorization(ctx context.Context, d *store.DeviceAuthorization) error
- func (s *Store) CreateEmailLoginToken(ctx context.Context, t *store.EmailLoginToken) error
- func (s *Store) CreateEmailVerificationToken(ctx context.Context, t *store.EmailVerificationToken) error
- func (s *Store) CreateInvitation(ctx context.Context, i *store.Invitation) error
- func (s *Store) CreateMember(ctx context.Context, m *store.Member) error
- func (s *Store) CreatePasswordResetToken(ctx context.Context, t *store.PasswordResetToken) error
- func (s *Store) CreatePendingTwoFactorSession(ctx context.Context, p *store.PendingTwoFactorSession) error
- func (s *Store) CreatePersonalAccessToken(ctx context.Context, t *store.PersonalAccessToken) error
- func (s *Store) CreateRefreshToken(ctx context.Context, t *store.RefreshToken) error
- func (s *Store) CreateSuperuser(ctx context.Context, su *store.Superuser) error
- func (s *Store) CreateSuperuserPendingTwoFactorSession(ctx context.Context, p *store.PendingTwoFactorSession) error
- func (s *Store) CreateSuperuserRefreshToken(ctx context.Context, t *store.SuperuserRefreshToken) error
- func (s *Store) CreateSuperuserTOTPSettings(ctx context.Context, t *store.TOTPSettings) error
- func (s *Store) CreateTOTPSettings(ctx context.Context, t *store.TOTPSettings) error
- func (s *Store) CreateTeam(ctx context.Context, t *store.Team) error
- func (s *Store) CreateUser(ctx context.Context, u *store.User) error
- func (s *Store) CreateWebAuthnChallenge(ctx context.Context, c *store.WebAuthnChallenge) error
- func (s *Store) CreateWebAuthnCredential(ctx context.Context, c *store.WebAuthnCredential) error
- func (s *Store) DB() *sql.DB
- func (s *Store) DeleteAccount(ctx context.Context, id string) error
- func (s *Store) DeleteDeviceAuthorization(ctx context.Context, id string) error
- func (s *Store) DeleteEmailLoginTokens(ctx context.Context, email string, kind store.EmailLoginKind) error
- func (s *Store) DeleteMember(ctx context.Context, id string) error
- func (s *Store) DeletePINCredential(ctx context.Context, userID string) error
- func (s *Store) DeletePendingTwoFactorSession(ctx context.Context, id string) error
- func (s *Store) DeleteSuperuserPendingTwoFactorSession(ctx context.Context, id string) error
- func (s *Store) DeleteSuperuserTOTPSettings(ctx context.Context, superuserID string) error
- func (s *Store) DeleteTOTPSettings(ctx context.Context, userID string) error
- func (s *Store) DeleteTeam(ctx context.Context, id string) error
- func (s *Store) DeleteUserEmailVerificationTokens(ctx context.Context, userID string) error
- func (s *Store) DeleteUserPasswordResetTokens(ctx context.Context, userID string) error
- func (s *Store) DeleteWebAuthnCredential(ctx context.Context, id string) error
- func (s *Store) GetAccount(ctx context.Context, id string) (*store.Account, error)
- func (s *Store) GetAccountByProvider(ctx context.Context, provider, providerAccountID string) (*store.Account, error)
- func (s *Store) GetBoundDevice(ctx context.Context, id string) (*store.BoundDevice, error)
- func (s *Store) GetBoundDeviceByTokenHash(ctx context.Context, hash string) (*store.BoundDevice, error)
- func (s *Store) GetDeviceAuthorizationByDeviceCodeHash(ctx context.Context, hash string) (*store.DeviceAuthorization, error)
- func (s *Store) GetDeviceAuthorizationByUserCode(ctx context.Context, userCode string) (*store.DeviceAuthorization, error)
- func (s *Store) GetEmailLoginTokenByEmail(ctx context.Context, email string, kind store.EmailLoginKind) (*store.EmailLoginToken, error)
- func (s *Store) GetEmailLoginTokenByHash(ctx context.Context, hash string) (*store.EmailLoginToken, error)
- func (s *Store) GetEmailVerificationTokenByHash(ctx context.Context, hash string) (*store.EmailVerificationToken, error)
- func (s *Store) GetInvitation(ctx context.Context, id string) (*store.Invitation, error)
- func (s *Store) GetInvitationByTokenHash(ctx context.Context, hash string) (*store.Invitation, error)
- func (s *Store) GetMember(ctx context.Context, id string) (*store.Member, error)
- func (s *Store) GetMemberByUserAndTeam(ctx context.Context, userID, teamID string) (*store.Member, error)
- func (s *Store) GetPINCredential(ctx context.Context, userID string) (*store.PINCredential, error)
- func (s *Store) GetPasswordResetTokenByHash(ctx context.Context, hash string) (*store.PasswordResetToken, error)
- func (s *Store) GetPendingTwoFactorSessionByHash(ctx context.Context, hash string) (*store.PendingTwoFactorSession, error)
- func (s *Store) GetPersonalAccessToken(ctx context.Context, id string) (*store.PersonalAccessToken, error)
- func (s *Store) GetPersonalAccessTokenByHash(ctx context.Context, hash string) (*store.PersonalAccessToken, error)
- func (s *Store) GetRefreshTokenByHash(ctx context.Context, hash string) (*store.RefreshToken, error)
- func (s *Store) GetSuperuserByEmail(ctx context.Context, email string) (*store.Superuser, error)
- func (s *Store) GetSuperuserByID(ctx context.Context, id string) (*store.Superuser, error)
- func (s *Store) GetSuperuserPendingTwoFactorSessionByHash(ctx context.Context, hash string) (*store.PendingTwoFactorSession, error)
- func (s *Store) GetSuperuserRefreshTokenByHash(ctx context.Context, hash string) (*store.SuperuserRefreshToken, error)
- func (s *Store) GetSuperuserTOTPSettings(ctx context.Context, superuserID string) (*store.TOTPSettings, error)
- func (s *Store) GetTOTPSettingsByUserID(ctx context.Context, userID string) (*store.TOTPSettings, error)
- func (s *Store) GetTeam(ctx context.Context, id string) (*store.Team, error)
- func (s *Store) GetTeamBySlug(ctx context.Context, slug string) (*store.Team, error)
- func (s *Store) GetUserByEmail(ctx context.Context, email string) (*store.User, error)
- func (s *Store) GetUserByID(ctx context.Context, id string) (*store.User, error)
- func (s *Store) GetWebAuthnCredential(ctx context.Context, id string) (*store.WebAuthnCredential, error)
- func (s *Store) GetWebAuthnCredentialByCredentialID(ctx context.Context, credentialID []byte) (*store.WebAuthnCredential, error)
- func (s *Store) IncrementEmailLoginTokenAttempts(ctx context.Context, id string) (int, error)
- func (s *Store) IsAccountLocked(ctx context.Context, userID string) (bool, error)
- func (s *Store) ListAccountsByUser(ctx context.Context, userID string) ([]*store.Account, error)
- func (s *Store) ListActiveRefreshTokens(ctx context.Context, userID string) ([]*store.RefreshToken, error)
- func (s *Store) ListActiveSuperuserRefreshTokens(ctx context.Context, superuserID string) ([]*store.SuperuserRefreshToken, error)
- func (s *Store) ListBoundDevicesByUser(ctx context.Context, userID string) ([]*store.BoundDevice, error)
- func (s *Store) ListInvitationsByTeam(ctx context.Context, teamID string) ([]*store.Invitation, error)
- func (s *Store) ListMembersByTeam(ctx context.Context, teamID string) ([]*store.Member, error)
- func (s *Store) ListMembershipsByUser(ctx context.Context, userID string) ([]*store.Member, error)
- func (s *Store) ListPersonalAccessTokensByUser(ctx context.Context, userID string) ([]*store.PersonalAccessToken, error)
- func (s *Store) ListSuperusers(ctx context.Context) ([]*store.Superuser, error)
- func (s *Store) ListWebAuthnCredentialsByUser(ctx context.Context, userID string) ([]*store.WebAuthnCredential, error)
- func (s *Store) LockAccount(ctx context.Context, userID string) error
- func (s *Store) MarkEmailLoginTokenUsed(ctx context.Context, id string, usedAt time.Time) error
- func (s *Store) MarkEmailVerificationTokenUsed(ctx context.Context, id string) error
- func (s *Store) MarkPasswordResetTokenUsed(ctx context.Context, id string) error
- func (s *Store) RecordFailedLoginAttempt(ctx context.Context, a *store.FailedLoginAttempt) error
- func (s *Store) RevokeAllBoundDevices(ctx context.Context, userID string, at time.Time) (int, error)
- func (s *Store) RevokeAllSuperuserRefreshTokens(ctx context.Context, superuserID string) error
- func (s *Store) RevokeAllUserRefreshTokens(ctx context.Context, userID string) error
- func (s *Store) RevokeBoundDevice(ctx context.Context, id string, at time.Time) error
- func (s *Store) RevokeRefreshToken(ctx context.Context, id string) error
- func (s *Store) RevokeSuperuserRefreshToken(ctx context.Context, id string) error
- func (s *Store) RunInTx(ctx context.Context, fn func(ctx context.Context) error) (err error)
- func (s *Store) SetPINCredential(ctx context.Context, c *store.PINCredential) error
- func (s *Store) TouchBoundDevice(ctx context.Context, id string, at time.Time) error
- func (s *Store) TouchRefreshToken(ctx context.Context, id string, expiresAt time.Time) error
- func (s *Store) UnlockAccount(ctx context.Context, userID string) error
- func (s *Store) UpdateAccount(ctx context.Context, a *store.Account) error
- func (s *Store) UpdateDeviceAuthorization(ctx context.Context, d *store.DeviceAuthorization) error
- func (s *Store) UpdateInvitation(ctx context.Context, i *store.Invitation) error
- func (s *Store) UpdateMember(ctx context.Context, m *store.Member) error
- func (s *Store) UpdatePersonalAccessToken(ctx context.Context, t *store.PersonalAccessToken) error
- func (s *Store) UpdateSuperuser(ctx context.Context, su *store.Superuser) error
- func (s *Store) UpdateSuperuserTOTPSettings(ctx context.Context, t *store.TOTPSettings) error
- func (s *Store) UpdateTOTPSettings(ctx context.Context, t *store.TOTPSettings) error
- func (s *Store) UpdateTeam(ctx context.Context, t *store.Team) error
- func (s *Store) UpdateUser(ctx context.Context, u *store.User) error
- func (s *Store) UpdateWebAuthnCredential(ctx context.Context, c *store.WebAuthnCredential) error
Constants ¶
const VersionTable = "auth_goose_db_version"
VersionTable is goose's bookkeeping for the auth tables, kept apart from the app's own goose_db_version.
Variables ¶
This section is empty.
Functions ¶
func DSN ¶
DSN returns the modernc.org/sqlite data source name Store expects for the database file at path. A host that opens its own *sql.DB and hands it to New must open it with these settings:
- foreign_keys(1): SQLite ignores REFERENCES unless every connection asks it not to, and the cascades are part of the schema.
- busy_timeout(5000): a writer waits for the lock rather than failing at once.
- _txlock=immediate: a transaction takes the write lock when it begins, not at its first write, where SQLite would fail it without waiting.
Types ¶
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store implements every port pgstore does, and store.TxRunner, over one database.
func New ¶
New returns a Store over db, which must have been opened with DSN's settings and migrated. Open does both.
func Open ¶
Open opens (creating if needed) the SQLite database at path, configures it as Store requires and migrates it. It is the whole setup for a CLI or a small service; Close the Store when done.
path is a file. An in-memory database is refused: database/sql opens a fresh one per connection, so writes would land in databases nobody reads. A test wants a file under t.TempDir(), or memstore.
func (*Store) ClearFailedLoginAttempts ¶
func (*Store) Close ¶
Close closes the database if Open opened it, and does nothing if the host handed it to New.
func (*Store) ConsumeRefreshToken ¶ added in v0.6.0
func (*Store) ConsumeSuperuserRefreshToken ¶ added in v0.6.0
func (*Store) ConsumeWebAuthnChallenge ¶
func (s *Store) ConsumeWebAuthnChallenge(ctx context.Context, tokenHash string) (*store.WebAuthnChallenge, error)
ConsumeWebAuthnChallenge lets the DELETE decide, so two redemptions of one challenge cannot both get the row.
func (*Store) CountRecentFailedLoginAttempts ¶
func (*Store) CreateAccount ¶
func (*Store) CreateBoundDevice ¶ added in v0.7.0
func (*Store) CreateDeviceAuthorization ¶ added in v0.7.0
func (*Store) CreateEmailLoginToken ¶
func (*Store) CreateEmailVerificationToken ¶
func (*Store) CreateInvitation ¶ added in v0.7.0
func (*Store) CreateMember ¶ added in v0.7.0
func (*Store) CreatePasswordResetToken ¶
func (*Store) CreatePendingTwoFactorSession ¶
func (*Store) CreatePersonalAccessToken ¶ added in v0.7.0
func (*Store) CreateRefreshToken ¶
func (*Store) CreateSuperuser ¶
func (*Store) CreateSuperuserPendingTwoFactorSession ¶
func (*Store) CreateSuperuserRefreshToken ¶
func (*Store) CreateSuperuserTOTPSettings ¶
func (*Store) CreateTOTPSettings ¶
func (*Store) CreateTeam ¶ added in v0.7.0
func (*Store) CreateWebAuthnChallenge ¶
func (*Store) CreateWebAuthnCredential ¶
func (*Store) DeleteDeviceAuthorization ¶ added in v0.7.0
DeleteDeviceAuthorization succeeds for a row that is already gone: the device package deletes a resolved authorization and ignores the result.
func (*Store) DeleteEmailLoginTokens ¶
func (*Store) DeleteMember ¶ added in v0.7.0
func (*Store) DeletePINCredential ¶ added in v0.7.0
func (*Store) DeletePendingTwoFactorSession ¶
func (*Store) DeleteSuperuserPendingTwoFactorSession ¶
func (*Store) DeleteSuperuserTOTPSettings ¶
func (*Store) DeleteTOTPSettings ¶
func (*Store) DeleteTeam ¶ added in v0.7.0
DeleteTeam takes the team's members and invitations with it.
func (*Store) DeleteUserEmailVerificationTokens ¶
func (*Store) DeleteUserPasswordResetTokens ¶
func (*Store) DeleteWebAuthnCredential ¶
func (*Store) GetAccount ¶
func (*Store) GetAccountByProvider ¶
func (*Store) GetBoundDevice ¶ added in v0.7.0
func (*Store) GetBoundDeviceByTokenHash ¶ added in v0.7.0
func (s *Store) GetBoundDeviceByTokenHash(ctx context.Context, hash string) (*store.BoundDevice, error)
GetBoundDeviceByTokenHash returns revoked and expired devices too: the service reads both columns itself.
func (*Store) GetDeviceAuthorizationByDeviceCodeHash ¶ added in v0.7.0
func (*Store) GetDeviceAuthorizationByUserCode ¶ added in v0.7.0
func (*Store) GetEmailLoginTokenByEmail ¶
func (s *Store) GetEmailLoginTokenByEmail(ctx context.Context, email string, kind store.EmailLoginKind) (*store.EmailLoginToken, error)
func (*Store) GetEmailLoginTokenByHash ¶
func (*Store) GetEmailVerificationTokenByHash ¶
func (*Store) GetInvitation ¶ added in v0.7.0
func (*Store) GetInvitationByTokenHash ¶ added in v0.7.0
func (s *Store) GetInvitationByTokenHash(ctx context.Context, hash string) (*store.Invitation, error)
GetInvitationByTokenHash returns every status, not only pending: the service reads Status to refuse a revoked or accepted invitation.
func (*Store) GetMemberByUserAndTeam ¶ added in v0.7.0
func (s *Store) GetMemberByUserAndTeam(ctx context.Context, userID, teamID string) (*store.Member, error)
GetMemberByUserAndTeam never matches a member without a user: the equality is false against NULL.
func (*Store) GetPINCredential ¶ added in v0.7.0
func (*Store) GetPasswordResetTokenByHash ¶
func (*Store) GetPendingTwoFactorSessionByHash ¶
func (*Store) GetPersonalAccessToken ¶ added in v0.7.0
func (*Store) GetPersonalAccessTokenByHash ¶ added in v0.7.0
func (s *Store) GetPersonalAccessTokenByHash(ctx context.Context, hash string) (*store.PersonalAccessToken, error)
GetPersonalAccessTokenByHash returns revoked and expired tokens too: the service reads both columns itself.
func (*Store) GetRefreshTokenByHash ¶
func (*Store) GetSuperuserByEmail ¶
func (*Store) GetSuperuserByID ¶
func (*Store) GetSuperuserPendingTwoFactorSessionByHash ¶
func (*Store) GetSuperuserRefreshTokenByHash ¶
func (*Store) GetSuperuserTOTPSettings ¶
func (*Store) GetTOTPSettingsByUserID ¶
func (*Store) GetTeamBySlug ¶ added in v0.7.0
func (*Store) GetUserByEmail ¶
func (*Store) GetUserByID ¶
func (*Store) GetWebAuthnCredential ¶
func (*Store) GetWebAuthnCredentialByCredentialID ¶
func (*Store) IncrementEmailLoginTokenAttempts ¶
IncrementEmailLoginTokenAttempts lets the database compute the count, so parallel guesses each cost one.
func (*Store) IsAccountLocked ¶
func (*Store) ListAccountsByUser ¶
func (*Store) ListActiveRefreshTokens ¶
func (*Store) ListActiveSuperuserRefreshTokens ¶
func (*Store) ListBoundDevicesByUser ¶ added in v0.7.0
func (*Store) ListInvitationsByTeam ¶ added in v0.7.0
func (*Store) ListMembersByTeam ¶ added in v0.7.0
ListMembersByTeam lists every member, active or not, since the last-owner check reads Role and IsActive itself. Inside a transaction it needs no lock of its own: the transaction already holds SQLite's write lock, so that check and the write it guards cannot interleave with another.
func (*Store) ListMembershipsByUser ¶ added in v0.7.0
func (*Store) ListPersonalAccessTokensByUser ¶ added in v0.7.0
func (*Store) ListSuperusers ¶
func (*Store) ListWebAuthnCredentialsByUser ¶
func (*Store) MarkEmailLoginTokenUsed ¶
MarkEmailLoginTokenUsed is a compare-and-set: no row means another redemption won.
func (*Store) MarkEmailVerificationTokenUsed ¶
func (*Store) MarkPasswordResetTokenUsed ¶
func (*Store) RecordFailedLoginAttempt ¶
func (*Store) RevokeAllBoundDevices ¶ added in v0.7.0
func (*Store) RevokeAllSuperuserRefreshTokens ¶
func (*Store) RevokeAllUserRefreshTokens ¶
func (*Store) RevokeBoundDevice ¶ added in v0.7.0
func (*Store) RevokeRefreshToken ¶
func (*Store) RevokeSuperuserRefreshToken ¶
func (*Store) RunInTx ¶
RunInTx runs fn in one transaction. store.TxRunner requires every store call made with fn's context to join it, so q reads the transaction back out of the context; a call inside an open transaction joins that one.
func (*Store) SetPINCredential ¶ added in v0.7.0
SetPINCredential replaces an existing PIN in place, keeping the row's created_at.
func (*Store) TouchBoundDevice ¶ added in v0.7.0
TouchBoundDevice does not touch a revoked device, so a use racing a revocation cannot write over it.
func (*Store) TouchRefreshToken ¶
TouchRefreshToken does not extend a revoked session back to life.