Documentation
¶
Overview ¶
Package terms records which version of the terms each user accepted, and when, and lets the app refuse users who have not accepted the current one.
A sign-up form accepts in the same request by sending the version in the TermsHeader header; a data hook on user creation reads it, so every sign-up method — password, code, link, provider — records acceptance without knowing this plugin exists. Users who signed up before a new version accept it with the accept operation.
The latest acceptance sits on auth_user, for a cheap "has this user accepted" check; every acceptance is also kept, one row per version and time, in auth_terms_acceptance, read with History, for the record a regulator or a dispute asks for.
Index ¶
- Constants
- Variables
- func Bindings(c *TermsColumns) []sqlb.Binding
- func Current(version string) func(*Plugin)
- type AcceptRequest
- type Acceptance
- type Plugin
- func (p *Plugin) Accept(ctx context.Context, version string) error
- func (p *Plugin) Accepted(ctx context.Context, userID string) (bool, error)
- func (p *Plugin) Columns() []auth.ColumnExtension
- func (p *Plugin) DataHooks() auth.DataHooks
- func (p *Plugin) History(ctx context.Context, userID string) ([]Acceptance, error)
- func (p *Plugin) Init(a *auth.Auth) error
- func (p *Plugin) Name() string
- func (p *Plugin) Operations() []auth.Operation
- func (p *Plugin) RequireCurrent() func(http.Handler) http.Handler
- func (p *Plugin) Tables() []sqlb.Table
- func (p *Plugin) TypedMigrations(engine string, t auth.SQLTypes) ([]auth.Migration, error)
- func (p *Plugin) UserTables() []auth.UserTable
- func (p *Plugin) Validate(*auth.Config) error
- func (p *Plugin) Version() string
- type TermsColumns
Constants ¶
const ( ColVersion = "terms_version" ColAcceptedAt = "terms_accepted_at" )
Columns this plugin adds to auth_user.
const ( //ds:def id=terms-tablenameacceptance-8wv3kq2n owner=@khanakia stability=stable TableNameAcceptance = "auth_terms_acceptance" TableAliasAcceptance = "tma" ColAcceptanceUserID = "user_id" ColAcceptanceVer = "version" ColAcceptanceAt = "accepted_at" )
The history table: one row per acceptance. The key is user, version and time, so a version accepted again after the current one changed back to it is a second row rather than a lost one. There is no foreign key (ADR-0002); DeleteUser removes a user's rows through UserTables.
const EndpointAccept auth.EndpointID = "terms.accept"
EndpointAccept records acceptance of the current version.
const PluginName = "terms"
PluginName is the plugin's permanent identity.
const TermsHeader = "Terms-Version"
TermsHeader carries the version a sign-up form showed and the user ticked.
Variables ¶
var ( TableAcceptance = sqlb.Table{Name: TableNameAcceptance, Alias: TableAliasAcceptance} AcceptanceUserID = sqlb.Col[string](TableAcceptance, ColAcceptanceUserID) AcceptanceVersion = sqlb.Col[string](TableAcceptance, ColAcceptanceVer) AcceptanceAt = sqlb.Col[time.Time](TableAcceptance, ColAcceptanceAt) )
TableAcceptance and its typed columns, for an app that reads or joins the history (reads are open; only the plugin writes).
var ( Version = sqlb.Col[string](auth.TableUser, ColVersion) AcceptedAt = sqlb.Col[*time.Time](auth.TableUser, ColAcceptedAt) )
Typed columns on auth_user, for an app that reports on acceptance in its own queries.
var ( // ErrNotAccepted answers a user who has not accepted the current // version; its message tells the client to show the terms. ErrNotAccepted = auth.NewError("terms.not_accepted", http.StatusForbidden, "Accept the current terms to continue.") // ErrStale refuses acceptance of a version other than the current one: // the page the user read is out of date. ErrStale = auth.NewError("terms.stale_version", http.StatusConflict, "The terms changed. Read the current version and accept again.") // ErrNoVersion fails auth.New when Current was not passed: a terms // plugin with no version would accept nothing and refuse everyone. ErrNoVersion = errors.New("terms: pass terms.Current with the version users must accept") )
Errors. The first two carry stable codes a client checks for.
Functions ¶
func Bindings ¶
func Bindings(c *TermsColumns) []sqlb.Binding
Bindings binds TermsColumns, for a composite user query or LoadUserColumns.
Types ¶
type AcceptRequest ¶
type AcceptRequest struct {
Version string `json:"version"`
}
AcceptRequest names the version the user read. A version other than the current one is refused, so a stale page cannot record acceptance of terms the user never saw.
type Acceptance ¶
Acceptance is one row of a user's history: a version and when it was accepted.
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin records terms acceptance. Build it with New and Current.
func (*Plugin) Columns ¶
func (p *Plugin) Columns() []auth.ColumnExtension
Columns adds the accepted version and time to auth_user.
func (*Plugin) DataHooks ¶
DataHooks record acceptance for a user created by a request that sent the current version in TermsHeader. A stale version is not recorded: the user saw other terms than the ones in force.
func (*Plugin) History ¶
History returns every acceptance of userID, oldest first; never nil, so it encodes as []. Acceptances recorded before the history table existed are there too, copied from auth_user by the migration, but only the latest per user: earlier ones were overwritten before anything kept them.
func (*Plugin) Operations ¶
Operations lists the plugin's operation.
func (*Plugin) RequireCurrent ¶
RequireCurrent is middleware that refuses a signed-in user who has not accepted the current version with ErrNotAccepted. It must be inside authhttp.Middleware and after RequireUser.
func (*Plugin) Tables ¶
Tables declares the history table, so New can check its alias and an app can rename it.
func (*Plugin) TypedMigrations ¶
TypedMigrations creates the history table and backfills it from auth_user; the column migrations run before a plugin's own, so the columns exist by then.
func (*Plugin) UserTables ¶
UserTables tells DeleteUser which rows are a user's: every history row, by user id.
type TermsColumns ¶
TermsColumns is this plugin's flat part of a composite user. Flat because the columns live on auth_user itself (ADR-0001); an empty TermsVersion means the user never accepted any version.