Documentation
¶
Overview ¶
contract.go: Wires the waitlist plugin into the forge-dashboard contract surface via plugin.ContractContributor. The subpackage declares its own EntryRow / EntryQuery / EntryListRows / WaitlistStore interface (cycle avoidance); this file adapts the plugin's concrete Store via a small shim.
Package waitlist provides a pre-launch waitlist gate for AuthSome.
The waitlist plugin allows administrators to gate sign-ups behind an approval process. Users join the waitlist with their email address and are assigned a "pending" status. Administrators can approve or reject entries. Only approved users are allowed to complete the sign-up flow.
Usage:
eng, _ := authsome.NewEngine(
authsome.WithStore(store),
authsome.WithPlugin(waitlist.New()),
)
Index ¶
- Variables
- type ApproveRequest
- type Config
- type DeleteRequest
- type JoinRequest
- type ListRequest
- type MemoryStore
- func (s *MemoryStore) CountByStatus(_ context.Context, appID id.AppID) (pending, approved, rejected int, err error)
- func (s *MemoryStore) CreateEntry(_ context.Context, e *WaitlistEntry) error
- func (s *MemoryStore) DeleteEntry(_ context.Context, entryID id.WaitlistID) error
- func (s *MemoryStore) GetEntry(_ context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
- func (s *MemoryStore) GetEntryByEmail(_ context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
- func (s *MemoryStore) ListEntries(_ context.Context, q *WaitlistQuery) (*WaitlistList, error)
- func (s *MemoryStore) UpdateEntryStatus(_ context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
- type MongoStore
- func (s *MongoStore) CountByStatus(ctx context.Context, appID id.AppID) (pending, approved, rejected int, err error)
- func (s *MongoStore) CreateEntry(ctx context.Context, e *WaitlistEntry) error
- func (s *MongoStore) DeleteEntry(ctx context.Context, entryID id.WaitlistID) error
- func (s *MongoStore) GetEntry(ctx context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
- func (s *MongoStore) GetEntryByEmail(ctx context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
- func (s *MongoStore) ListEntries(ctx context.Context, q *WaitlistQuery) (*WaitlistList, error)
- func (s *MongoStore) UpdateEntryStatus(ctx context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
- type Plugin
- func (p *Plugin) MigrationGroups(driverName string) []*migrate.Group
- func (p *Plugin) Name() string
- func (p *Plugin) NotificationMappings() map[string]*plugin.NotificationMapping
- func (p *Plugin) OnBeforeSignUp(ctx context.Context, req *account.SignUpRequest) error
- func (p *Plugin) OnInit(_ context.Context, engine plugin.Engine) error
- func (p *Plugin) RegisterContract(d *dispatcher.Dispatcher, reg contract.Registry, wreg contract.WardenRegistry, ...) error
- func (p *Plugin) RegisterRoutes(router forge.Router) error
- func (p *Plugin) SetWaitlistStore(s Store)
- type PostgresStore
- func (s *PostgresStore) CountByStatus(ctx context.Context, appID id.AppID) (pending, approved, rejected int, err error)
- func (s *PostgresStore) CreateEntry(ctx context.Context, e *WaitlistEntry) error
- func (s *PostgresStore) DeleteEntry(ctx context.Context, entryID id.WaitlistID) error
- func (s *PostgresStore) GetEntry(ctx context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
- func (s *PostgresStore) GetEntryByEmail(ctx context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
- func (s *PostgresStore) ListEntries(ctx context.Context, q *WaitlistQuery) (*WaitlistList, error)
- func (s *PostgresStore) UpdateEntryStatus(ctx context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
- type RejectRequest
- type SqliteStore
- func (s *SqliteStore) CountByStatus(ctx context.Context, appID id.AppID) (pending, approved, rejected int, err error)
- func (s *SqliteStore) CreateEntry(ctx context.Context, e *WaitlistEntry) error
- func (s *SqliteStore) DeleteEntry(ctx context.Context, entryID id.WaitlistID) error
- func (s *SqliteStore) GetEntry(ctx context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
- func (s *SqliteStore) GetEntryByEmail(ctx context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
- func (s *SqliteStore) ListEntries(ctx context.Context, q *WaitlistQuery) (*WaitlistList, error)
- func (s *SqliteStore) UpdateEntryStatus(ctx context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
- type StatsRequest
- type StatsResponse
- type StatusRequest
- type StatusResponse
- type Store
- type WaitlistEntry
- type WaitlistList
- type WaitlistQuery
- type WaitlistStatus
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotFound is returned when a waitlist entry is not found. ErrNotFound = errors.New("waitlist: entry not found") // ErrDuplicateEmail is returned when the email is already on the waitlist. ErrDuplicateEmail = errors.New("waitlist: email already on waitlist") )
Sentinel errors.
var MongoMigrations = migrate.NewGroup("authsome-waitlist", migrate.DependsOn("authsome"))
MongoMigrations is the MongoDB migration group for the waitlist plugin. MongoDB is schemaless so no actual migrations are needed.
var PostgresMigrations = migrate.NewGroup("authsome-waitlist", migrate.DependsOn("authsome"))
PostgresMigrations is the postgres migration group for the waitlist plugin.
var SqliteMigrations = migrate.NewGroup("authsome-waitlist", migrate.DependsOn("authsome"))
SqliteMigrations is the SQLite migration group for the waitlist plugin.
Functions ¶
This section is empty.
Types ¶
type ApproveRequest ¶
type ApproveRequest struct {
EntryID string `path:"entryId" description:"Waitlist entry ID"`
Note string `json:"note,omitempty" description:"Optional admin note"`
}
ApproveRequest binds the path + body for POST /admin/waitlist/:entryId/approve.
type Config ¶
type Config struct {
// Enabled controls whether the waitlist gate is active.
// When true, sign-ups require a prior approved waitlist entry.
Enabled bool
}
Config configures the waitlist plugin.
type DeleteRequest ¶
type DeleteRequest struct {
EntryID string `path:"entryId" description:"Waitlist entry ID"`
}
DeleteRequest binds the path param for DELETE /admin/waitlist/:entryId.
type JoinRequest ¶
type JoinRequest struct {
Email string `json:"email" description:"Email address to add to the waitlist"`
Name string `json:"name,omitempty" description:"Display name (optional)"`
AppID string `json:"app_id,omitempty" description:"Application ID (optional, resolved from context if absent)"`
}
JoinRequest binds the body for POST /waitlist/join.
type ListRequest ¶
type ListRequest struct {
AppID string `query:"app_id" description:"Filter by application ID"`
Email string `query:"email" description:"Filter by email address"`
Status string `query:"status" description:"Filter by status (pending, approved, rejected)"`
Cursor string `query:"cursor" description:"Pagination cursor"`
Limit int `query:"limit" description:"Maximum number of results (default 50, max 200)"`
}
ListRequest binds query params for GET /admin/waitlist.
type MemoryStore ¶
type MemoryStore struct {
// contains filtered or unexported fields
}
MemoryStore is an in-memory waitlist store for development and testing.
func NewMemoryStore ¶
func NewMemoryStore() *MemoryStore
NewMemoryStore creates an in-memory waitlist store.
func (*MemoryStore) CountByStatus ¶
func (*MemoryStore) CreateEntry ¶
func (s *MemoryStore) CreateEntry(_ context.Context, e *WaitlistEntry) error
func (*MemoryStore) DeleteEntry ¶
func (s *MemoryStore) DeleteEntry(_ context.Context, entryID id.WaitlistID) error
func (*MemoryStore) GetEntry ¶
func (s *MemoryStore) GetEntry(_ context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
func (*MemoryStore) GetEntryByEmail ¶
func (s *MemoryStore) GetEntryByEmail(_ context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
func (*MemoryStore) ListEntries ¶
func (s *MemoryStore) ListEntries(_ context.Context, q *WaitlistQuery) (*WaitlistList, error)
func (*MemoryStore) UpdateEntryStatus ¶
func (s *MemoryStore) UpdateEntryStatus(_ context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
type MongoStore ¶
type MongoStore struct {
// contains filtered or unexported fields
}
MongoStore implements waitlist.Store using the Grove MongoDB driver.
func NewMongoStore ¶
func NewMongoStore(db *grove.DB) *MongoStore
NewMongoStore creates a new MongoDB-backed waitlist store.
func (*MongoStore) CountByStatus ¶
func (*MongoStore) CreateEntry ¶
func (s *MongoStore) CreateEntry(ctx context.Context, e *WaitlistEntry) error
func (*MongoStore) DeleteEntry ¶
func (s *MongoStore) DeleteEntry(ctx context.Context, entryID id.WaitlistID) error
func (*MongoStore) GetEntry ¶
func (s *MongoStore) GetEntry(ctx context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
func (*MongoStore) GetEntryByEmail ¶
func (s *MongoStore) GetEntryByEmail(ctx context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
func (*MongoStore) ListEntries ¶
func (s *MongoStore) ListEntries(ctx context.Context, q *WaitlistQuery) (*WaitlistList, error)
func (*MongoStore) UpdateEntryStatus ¶
func (s *MongoStore) UpdateEntryStatus(ctx context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin is the waitlist management plugin.
func New ¶
New creates a new waitlist plugin. An in-memory store is used by default. Use SetWaitlistStore to inject a persistent store.
func (*Plugin) MigrationGroups ¶
MigrationGroups returns the waitlist migration groups for the given driver.
func (*Plugin) NotificationMappings ¶
func (p *Plugin) NotificationMappings() map[string]*plugin.NotificationMapping
NotificationMappings contributes waitlist notification templates.
func (*Plugin) OnBeforeSignUp ¶
OnBeforeSignUp implements plugin.BeforeSignUp. When the waitlist is enabled, it blocks sign-ups unless the email has an approved entry on the waitlist.
func (*Plugin) RegisterContract ¶
func (p *Plugin) RegisterContract( d *dispatcher.Dispatcher, reg contract.Registry, wreg contract.WardenRegistry, engine plugin.Engine, ) error
func (*Plugin) RegisterRoutes ¶
RegisterRoutes registers waitlist HTTP routes.
func (*Plugin) SetWaitlistStore ¶
SetWaitlistStore allows direct waitlist store injection.
type PostgresStore ¶
type PostgresStore struct {
// contains filtered or unexported fields
}
PostgresStore implements waitlist.Store using the Grove ORM with PostgreSQL.
func NewPostgresStore ¶
func NewPostgresStore(db *grove.DB) *PostgresStore
NewPostgresStore creates a new PostgreSQL-backed waitlist store.
func (*PostgresStore) CountByStatus ¶
func (*PostgresStore) CreateEntry ¶
func (s *PostgresStore) CreateEntry(ctx context.Context, e *WaitlistEntry) error
func (*PostgresStore) DeleteEntry ¶
func (s *PostgresStore) DeleteEntry(ctx context.Context, entryID id.WaitlistID) error
func (*PostgresStore) GetEntry ¶
func (s *PostgresStore) GetEntry(ctx context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
func (*PostgresStore) GetEntryByEmail ¶
func (s *PostgresStore) GetEntryByEmail(ctx context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
func (*PostgresStore) ListEntries ¶
func (s *PostgresStore) ListEntries(ctx context.Context, q *WaitlistQuery) (*WaitlistList, error)
func (*PostgresStore) UpdateEntryStatus ¶
func (s *PostgresStore) UpdateEntryStatus(ctx context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
type RejectRequest ¶
type RejectRequest struct {
EntryID string `path:"entryId" description:"Waitlist entry ID"`
Note string `json:"note,omitempty" description:"Optional admin note"`
}
RejectRequest binds the path + body for POST /admin/waitlist/:entryId/reject.
type SqliteStore ¶
type SqliteStore struct {
// contains filtered or unexported fields
}
SqliteStore implements waitlist.Store using the Grove ORM with SQLite.
func NewSqliteStore ¶
func NewSqliteStore(db *grove.DB) *SqliteStore
NewSqliteStore creates a new SQLite-backed waitlist store.
func (*SqliteStore) CountByStatus ¶
func (*SqliteStore) CreateEntry ¶
func (s *SqliteStore) CreateEntry(ctx context.Context, e *WaitlistEntry) error
func (*SqliteStore) DeleteEntry ¶
func (s *SqliteStore) DeleteEntry(ctx context.Context, entryID id.WaitlistID) error
func (*SqliteStore) GetEntry ¶
func (s *SqliteStore) GetEntry(ctx context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
func (*SqliteStore) GetEntryByEmail ¶
func (s *SqliteStore) GetEntryByEmail(ctx context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
func (*SqliteStore) ListEntries ¶
func (s *SqliteStore) ListEntries(ctx context.Context, q *WaitlistQuery) (*WaitlistList, error)
func (*SqliteStore) UpdateEntryStatus ¶
func (s *SqliteStore) UpdateEntryStatus(ctx context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
type StatsRequest ¶
type StatsRequest struct {
AppID string `query:"app_id" description:"Application ID"`
}
StatsRequest binds query params for GET /admin/waitlist/stats.
type StatsResponse ¶
type StatsResponse struct {
Pending int `json:"pending" description:"Number of pending entries"`
Approved int `json:"approved" description:"Number of approved entries"`
Rejected int `json:"rejected" description:"Number of rejected entries"`
Total int `json:"total" description:"Total number of entries"`
}
StatsResponse holds waitlist entry counts by status.
type StatusRequest ¶
type StatusRequest struct {
Email string `query:"email" description:"Email address to check"`
AppID string `query:"app_id" description:"Application ID (optional)"`
}
StatusRequest binds query params for GET /waitlist/status.
type StatusResponse ¶
type StatusResponse struct {
Email string `json:"email" description:"Email address"`
Status WaitlistStatus `json:"status" description:"Waitlist status (pending, approved, rejected)"`
}
StatusResponse is returned when checking waitlist status.
type Store ¶
type Store interface {
// CreateEntry adds a new waitlist entry.
CreateEntry(ctx context.Context, e *WaitlistEntry) error
// GetEntry returns a waitlist entry by ID.
GetEntry(ctx context.Context, entryID id.WaitlistID) (*WaitlistEntry, error)
// GetEntryByEmail returns a waitlist entry by app and email.
GetEntryByEmail(ctx context.Context, appID id.AppID, email string) (*WaitlistEntry, error)
// UpdateEntryStatus changes the status and optionally sets a note.
UpdateEntryStatus(ctx context.Context, entryID id.WaitlistID, status WaitlistStatus, note string) error
// ListEntries returns waitlist entries matching the query.
ListEntries(ctx context.Context, q *WaitlistQuery) (*WaitlistList, error)
// CountByStatus returns counts of entries grouped by status for an app.
CountByStatus(ctx context.Context, appID id.AppID) (pending, approved, rejected int, err error)
// DeleteEntry permanently removes a waitlist entry.
DeleteEntry(ctx context.Context, entryID id.WaitlistID) error
}
Store persists and queries waitlist entries.
type WaitlistEntry ¶
type WaitlistEntry struct {
ID id.WaitlistID `json:"id"`
AppID id.AppID `json:"app_id"`
Email string `json:"email"`
Name string `json:"name"`
Status WaitlistStatus `json:"status"`
UserID *id.UserID `json:"user_id,omitempty"` // set after sign-up
IPAddress string `json:"ip_address"`
Note string `json:"note"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
WaitlistEntry is a single record on the waitlist.
type WaitlistList ¶
type WaitlistList struct {
Entries []*WaitlistEntry `json:"entries"`
Total int `json:"total"`
NextCursor string `json:"next_cursor,omitempty"`
}
WaitlistList wraps a paginated list of waitlist entries.
type WaitlistQuery ¶
type WaitlistQuery struct {
AppID id.AppID `json:"app_id"`
Email string `json:"email,omitempty"`
Status WaitlistStatus `json:"status,omitempty"`
Cursor string `json:"cursor,omitempty"`
Limit int `json:"limit,omitempty"`
}
WaitlistQuery holds filters for listing waitlist entries.
type WaitlistStatus ¶
type WaitlistStatus string //nolint:revive // exported name stutter is intentional for clarity
WaitlistStatus represents the approval state of a waitlist entry.
const ( // StatusPending means the entry is awaiting review. StatusPending WaitlistStatus = "pending" // StatusApproved means the entry has been approved for sign-up. StatusApproved WaitlistStatus = "approved" // StatusRejected means the entry has been rejected. StatusRejected WaitlistStatus = "rejected" )
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package contract is the waitlist plugin's forge-dashboard contract surface.
|
Package contract is the waitlist plugin's forge-dashboard contract surface. |
|
Package waitlisttest provides a backend-agnostic conformance suite for the waitlist.Store interface.
|
Package waitlisttest provides a backend-agnostic conformance suite for the waitlist.Store interface. |