Documentation
¶
Overview ¶
Package user deals with authentication and authorization against topics
Index ¶
- Constants
- Variables
- func AllowedRole(role Role) bool
- func AllowedTier(tier string) bool
- func AllowedTopic(topic string) bool
- func AllowedTopicPattern(topic string) bool
- func AllowedUsername(username string) bool
- type Auther
- type Billing
- type Grant
- type Manager
- func (a *Manager) AddPhoneNumber(userID string, phoneNumber string) error
- func (a *Manager) AddReservation(username string, topic string, everyone Permission) error
- func (a *Manager) AddTier(tier *Tier) error
- func (a *Manager) AddUser(username, password string, role Role) error
- func (a *Manager) AllGrants() (map[string][]Grant, error)
- func (a *Manager) AllowAccess(username string, topicPattern string, permission Permission) error
- func (a *Manager) AllowReservation(username string, topic string) error
- func (a *Manager) Authenticate(username, password string) (*User, error)
- func (a *Manager) AuthenticateToken(token string) (*User, error)
- func (a *Manager) Authorize(user *User, topic string, perm Permission) error
- func (a *Manager) ChangeBilling(username string, billing *Billing) error
- func (a *Manager) ChangePassword(username, password string) error
- func (a *Manager) ChangeRole(username string, role Role) error
- func (a *Manager) ChangeSettings(userID string, prefs *Prefs) error
- func (a *Manager) ChangeTier(username, tier string) error
- func (a *Manager) ChangeToken(userID, token string, label *string, expires *time.Time) (*Token, error)
- func (a *Manager) Close() error
- func (a *Manager) CreateToken(userID, label string, expires time.Time, origin netip.Addr) (*Token, error)
- func (a *Manager) DefaultAccess() Permission
- func (a *Manager) EnqueueTokenUpdate(tokenID string, update *TokenUpdate)
- func (a *Manager) EnqueueUserStats(userID string, stats *Stats)
- func (a *Manager) Grants(username string) ([]Grant, error)
- func (a *Manager) HasReservation(username, topic string) (bool, error)
- func (a *Manager) MarkUserRemoved(user *User) error
- func (a *Manager) PhoneNumbers(userID string) ([]string, error)
- func (a *Manager) RemoveDeletedUsers() error
- func (a *Manager) RemoveExpiredTokens() error
- func (a *Manager) RemovePhoneNumber(userID string, phoneNumber string) error
- func (a *Manager) RemoveReservations(username string, topics ...string) error
- func (a *Manager) RemoveTier(code string) error
- func (a *Manager) RemoveToken(userID, token string) error
- func (a *Manager) RemoveUser(username string) error
- func (a *Manager) ReservationOwner(topic string) (string, error)
- func (a *Manager) Reservations(username string) ([]Reservation, error)
- func (a *Manager) ReservationsCount(username string) (int64, error)
- func (a *Manager) ResetAccess(username string, topicPattern string) error
- func (a *Manager) ResetStats() error
- func (a *Manager) ResetTier(username string) error
- func (a *Manager) Tier(code string) (*Tier, error)
- func (a *Manager) TierByStripePrice(priceID string) (*Tier, error)
- func (a *Manager) Tiers() ([]*Tier, error)
- func (a *Manager) Token(userID, token string) (*Token, error)
- func (a *Manager) Tokens(userID string) ([]*Token, error)
- func (a *Manager) UpdateTier(tier *Tier) error
- func (a *Manager) User(username string) (*User, error)
- func (a *Manager) UserByID(id string) (*User, error)
- func (a *Manager) UserByStripeCustomer(stripeCustomerID string) (*User, error)
- func (a *Manager) Users() ([]*User, error)
- func (a *Manager) UsersCount() (int64, error)
- type NotificationPrefs
- type Permission
- type Prefs
- type Reservation
- type Role
- type Stats
- type Subscription
- type Tier
- type Token
- type TokenUpdate
- type User
Constants ¶
const ( DefaultUserStatsQueueWriterInterval = 33 * time.Second DefaultUserPasswordBcryptCost = 10 )
Default constants that may be overridden by configs
const ( RoleAdmin = Role("admin") // Some queries have these values hardcoded! RoleUser = Role("user") RoleAnonymous = Role("anonymous") )
User roles
const (
Everyone = "*"
)
Everyone is a special username representing anonymous users
Variables ¶
var ( ErrUnauthenticated = errors.New("unauthenticated") ErrInvalidArgument = errors.New("invalid argument") ErrUserNotFound = errors.New("user not found") ErrUserExists = errors.New("user already exists") ErrTierNotFound = errors.New("tier not found") ErrTokenNotFound = errors.New("token not found") ErrPhoneNumberNotFound = errors.New("phone number not found") ErrTooManyReservations = errors.New("new tier has lower reservation limit") ErrPhoneNumberExists = errors.New("phone number already exists") )
Error constants used by the package
Functions ¶
func AllowedRole ¶
AllowedRole returns true if the given role can be used for new users
func AllowedTier ¶
AllowedTier returns true if the given tier name is valid
func AllowedTopic ¶
AllowedTopic returns true if the given topic name is valid
func AllowedTopicPattern ¶
AllowedTopicPattern returns true if the given topic pattern is valid; this includes the wildcard character (*)
func AllowedUsername ¶
AllowedUsername returns true if the given username is valid
Types ¶
type Auther ¶
type Auther interface { // Authenticate checks username and password and returns a user if correct. The method // returns in constant-ish time, regardless of whether the user exists or the password is // correct or incorrect. Authenticate(username, password string) (*User, error) // Authorize returns nil if the given user has access to the given topic using the desired // permission. The user param may be nil to signal an anonymous user. Authorize(user *User, topic string, perm Permission) error }
Auther is an interface for authentication and authorization
type Billing ¶
type Billing struct { StripeCustomerID string StripeSubscriptionID string StripeSubscriptionStatus stripe.SubscriptionStatus StripeSubscriptionInterval stripe.PriceRecurringInterval StripeSubscriptionPaidUntil time.Time StripeSubscriptionCancelAt time.Time }
Billing is a struct holding a user's billing information
type Grant ¶
type Grant struct { TopicPattern string // May include wildcard (*) Allow Permission }
Grant is a struct that represents an access control entry to a topic by a user
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager is an implementation of Manager. It stores users and access control list in a SQLite database.
func NewManager ¶
func NewManager(filename, startupQueries string, defaultAccess Permission, bcryptCost int, queueWriterInterval time.Duration) (*Manager, error)
NewManager creates a new Manager instance
func (*Manager) AddPhoneNumber ¶
AddPhoneNumber adds a phone number to the user with the given user ID
func (*Manager) AddReservation ¶
func (a *Manager) AddReservation(username string, topic string, everyone Permission) error
AddReservation creates two access control entries for the given topic: one with full read/write access for the given user, and one for Everyone with the permission passed as everyone. The user also owns the entries, and can modify or delete them.
func (*Manager) AllGrants ¶
AllGrants returns all user-specific access control entries, mapped to their respective user IDs
func (*Manager) AllowAccess ¶
func (a *Manager) AllowAccess(username string, topicPattern string, permission Permission) error
AllowAccess adds or updates an entry in th access control list for a specific user. It controls read/write access to a topic. The parameter topicPattern may include wildcards (*). The ACL entry owner may either be a user (username), or the system (empty).
func (*Manager) AllowReservation ¶
AllowReservation tests if a user may create an access control entry for the given topic. If there are any ACL entries that are not owned by the user, an error is returned.
func (*Manager) Authenticate ¶
Authenticate checks username and password and returns a User if correct, and the user has not been marked as deleted. The method returns in constant-ish time, regardless of whether the user exists or the password is correct or incorrect.
func (*Manager) AuthenticateToken ¶
AuthenticateToken checks if the token exists and returns the associated User if it does. The method sets the User.Token value to the token that was used for authentication.
func (*Manager) Authorize ¶
func (a *Manager) Authorize(user *User, topic string, perm Permission) error
Authorize returns nil if the given user has access to the given topic using the desired permission. The user param may be nil to signal an anonymous user.
func (*Manager) ChangeBilling ¶
ChangeBilling updates a user's billing fields, namely the Stripe customer ID, and subscription information
func (*Manager) ChangePassword ¶
ChangePassword changes a user's password
func (*Manager) ChangeRole ¶
ChangeRole changes a user's role. When a role is changed from RoleUser to RoleAdmin, all existing access control entries (Grant) are removed, since they are no longer needed.
func (*Manager) ChangeSettings ¶
ChangeSettings persists the user settings
func (*Manager) ChangeTier ¶
ChangeTier changes a user's tier using the tier code. This function does not delete reservations, messages, or attachments, even if the new tier has lower limits in this regard. That has to be done elsewhere.
func (*Manager) ChangeToken ¶
func (a *Manager) ChangeToken(userID, token string, label *string, expires *time.Time) (*Token, error)
ChangeToken updates a token's label and/or expiry date
func (*Manager) CreateToken ¶
func (a *Manager) CreateToken(userID, label string, expires time.Time, origin netip.Addr) (*Token, error)
CreateToken generates a random token for the given user and returns it. The token expires after a fixed duration unless ChangeToken is called. This function also prunes tokens for the given user, if there are too many of them.
func (*Manager) DefaultAccess ¶
func (a *Manager) DefaultAccess() Permission
DefaultAccess returns the default read/write access if no access control entry matches
func (*Manager) EnqueueTokenUpdate ¶
func (a *Manager) EnqueueTokenUpdate(tokenID string, update *TokenUpdate)
EnqueueTokenUpdate adds the token update to a queue which writes out token access times in batches at a regular interval
func (*Manager) EnqueueUserStats ¶
EnqueueUserStats adds the user to a queue which writes out user stats (messages, emails, ..) in batches at a regular interval
func (*Manager) HasReservation ¶
HasReservation returns true if the given topic access is owned by the user
func (*Manager) MarkUserRemoved ¶
MarkUserRemoved sets the deleted flag on the user, and deletes all access tokens. This prevents successful auth via Authenticate. A background process will delete the user at a later date.
func (*Manager) PhoneNumbers ¶
PhoneNumbers returns all phone numbers for the user with the given user ID
func (*Manager) RemoveDeletedUsers ¶
RemoveDeletedUsers deletes all users that have been marked deleted for
func (*Manager) RemoveExpiredTokens ¶
RemoveExpiredTokens deletes all expired tokens from the database
func (*Manager) RemovePhoneNumber ¶
RemovePhoneNumber deletes a phone number from the user with the given user ID
func (*Manager) RemoveReservations ¶
RemoveReservations deletes the access control entries associated with the given username/topic, as well as all entries with Everyone/topic. This is the counterpart for AddReservation.
func (*Manager) RemoveTier ¶
RemoveTier deletes the tier with the given code
func (*Manager) RemoveToken ¶
RemoveToken deletes the token defined in User.Token
func (*Manager) RemoveUser ¶
RemoveUser deletes the user with the given username. The function returns nil on success, even if the user did not exist in the first place.
func (*Manager) ReservationOwner ¶
ReservationOwner returns user ID of the user that owns this topic, or an empty string if it's not owned by anyone
func (*Manager) Reservations ¶
func (a *Manager) Reservations(username string) ([]Reservation, error)
Reservations returns all user-owned topics, and the associated everyone-access
func (*Manager) ReservationsCount ¶
ReservationsCount returns the number of reservations owned by this user
func (*Manager) ResetAccess ¶
ResetAccess removes an access control list entry for a specific username/topic, or (if topic is empty) for an entire user. The parameter topicPattern may include wildcards (*).
func (*Manager) ResetStats ¶
ResetStats resets all user stats in the user database. This touches all users.
func (*Manager) Tier ¶
Tier returns a Tier based on the code, or ErrTierNotFound if it does not exist
func (*Manager) TierByStripePrice ¶
TierByStripePrice returns a Tier based on the Stripe price ID, or ErrTierNotFound if it does not exist
func (*Manager) UpdateTier ¶
UpdateTier updates a tier's properties in the database
func (*Manager) User ¶
User returns the user with the given username if it exists, or ErrUserNotFound otherwise. You may also pass Everyone to retrieve the anonymous user and its Grant list.
func (*Manager) UserByID ¶
UserByID returns the user with the given ID if it exists, or ErrUserNotFound otherwise
func (*Manager) UserByStripeCustomer ¶
UserByStripeCustomer returns the user with the given Stripe customer ID if it exists, or ErrUserNotFound otherwise.
func (*Manager) Users ¶
Users returns a list of users. It always also returns the Everyone user ("*").
func (*Manager) UsersCount ¶
UsersCount returns the number of users in the databsae
type NotificationPrefs ¶
type NotificationPrefs struct { Sound *string `json:"sound,omitempty"` MinPriority *int `json:"min_priority,omitempty"` DeleteAfter *int `json:"delete_after,omitempty"` }
NotificationPrefs represents the user's notification settings
type Permission ¶
type Permission uint8
Permission represents a read or write permission to a topic
const ( PermissionDenyAll Permission = iota PermissionRead PermissionWrite PermissionReadWrite // 3! )
Permissions to a topic
func NewPermission ¶
func NewPermission(read, write bool) Permission
NewPermission is a helper to create a Permission based on read/write bool values
func ParsePermission ¶
func ParsePermission(s string) (Permission, error)
ParsePermission parses the string representation and returns a Permission
func (Permission) IsReadWrite ¶
func (p Permission) IsReadWrite() bool
IsReadWrite returns true if readable and writable
func (Permission) String ¶
func (p Permission) String() string
String returns a string representation of the permission
type Prefs ¶
type Prefs struct { Language *string `json:"language,omitempty"` Notification *NotificationPrefs `json:"notification,omitempty"` Subscriptions []*Subscription `json:"subscriptions,omitempty"` }
Prefs represents a user's configuration settings
type Reservation ¶
type Reservation struct { Topic string Owner Permission Everyone Permission }
Reservation is a struct that represents the ownership over a topic by a user
type Subscription ¶
type Subscription struct { BaseURL string `json:"base_url"` Topic string `json:"topic"` DisplayName *string `json:"display_name"` }
Subscription represents a user's topic subscription
func (*Subscription) Context ¶
func (s *Subscription) Context() log.Context
Context returns fields for the log
type Tier ¶
type Tier struct { ID string // Tier identifier (ti_...) Code string // Code of the tier Name string // Name of the tier MessageLimit int64 // Daily message limit MessageExpiryDuration time.Duration // Cache duration for messages EmailLimit int64 // Daily email limit CallLimit int64 // Daily phone call limit ReservationLimit int64 // Number of topic reservations allowed by user AttachmentFileSizeLimit int64 // Max file size per file (bytes) AttachmentTotalSizeLimit int64 // Total file size for all files of this user (bytes) AttachmentExpiryDuration time.Duration // Duration after which attachments will be deleted AttachmentBandwidthLimit int64 // Daily bandwidth limit for the user StripeMonthlyPriceID string // Monthly price ID for paid tiers (price_...) StripeYearlyPriceID string // Yearly price ID for paid tiers (price_...) }
Tier represents a user's account type, including its account limits
type Token ¶
type Token struct { Value string Label string LastAccess time.Time LastOrigin netip.Addr Expires time.Time }
Token represents a user token, including expiry date
type TokenUpdate ¶
TokenUpdate holds information about the last access time and origin IP address of a token
type User ¶
type User struct { ID string Name string Hash string // password hash (bcrypt) Token string // Only set if token was used to log in Role Role Prefs *Prefs Tier *Tier Stats *Stats Billing *Billing SyncTopic string Deleted bool }
User is a struct that represents a user