lith

package
v0.0.0-...-83cf971 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 22, 2022 License: LGPL-3.0 Imports: 35 Imported by: 0

Documentation

Index

Constants

View Source
const (
	PermissionGroupSystemAdmin   uint64 = 1
	PermissionGroupActiveAccount uint64 = 2
)

Certain permission groups are provided by the migration and should not be deleted.

Variables

View Source
var (
	// ErrStore is a base error for all repository specific errors.
	ErrStore = errors.New("store")

	// ErrNotFound is returned whenever a requested entity was not found.
	ErrNotFound = fmt.Errorf("%w: not found", ErrStore)

	// ErrConflict is returned whenever an operation cannot be completed
	// because it would cause data integrity violation.
	ErrConflict = fmt.Errorf("%w: conflict", ErrStore)

	// ErrPassword is returned whenever a password comparison fails.
	ErrPassword = fmt.Errorf("%s: invalid password", ErrStore)
)

Functions

func APIHandler

func APIHandler(
	conf APIConfiguration,
	store Store,
	cache cache.Store,
	events eventbus.Sink,
	queue taskqueue.Scheduler,
) http.Handler

func AccountRegisteredEvent

func AccountRegisteredEvent(accountID, email string, createdAt time.Time) eventbus.Event

AccountRegisteredEvent returns an event that represents an account registration.

func AdminHandler

func AdminHandler(
	conf AdminPanelConfiguration,
	store Store,
	cache cache.Store,
	safe secret.Safe,
	secret []byte,
	events eventbus.Sink,
) http.Handler

AdminHandler returns an HTTP handler that provides Web UI for system administration. Only system administrator is able to access any of nested endpoints.

func AuthMiddleware

func AuthMiddleware(store Store, lookups ...LookupFunc) func(http.Handler) http.Handler

AuthMiddleware read the request and injects into the context authentication information.

Session information is looked up using provided lookup functions. This way you can configure endpoints to use different session storage mechanisms and for example, avoid using cookie lookup everywhere.

Be catious when using a lookup function that checks cookie, because cookie authentication requires extra care (i.e. use CSRF protection).

This middleware is required by the CurrentAccount function.

func CurrentSessionID

func CurrentSessionID(ctx context.Context) (string, bool)

CurrentSessionID returns the session ID bound to current request.

This function requires AuthMiddleware.

func NewSendConfirmRegistrationHandler

func NewSendConfirmRegistrationHandler(s email.Server) taskqueue.Handler

func NewSendResetPasswordHandler

func NewSendResetPasswordHandler(s email.Server) taskqueue.Handler

func PublicHandler

func PublicHandler(
	conf PublicUIConfiguration,
	store Store,
	cache cache.Store,
	safe secret.Safe,
	secret []byte,
	events eventbus.Sink,
	queue taskqueue.Scheduler,
) http.Handler

func SessionCreatedEvent

func SessionCreatedEvent(accountID string, createdAt time.Time) eventbus.Event

SessionCreatedEvent returns an event that represents an authentication session creation.

func SessionFromCookie

func SessionFromCookie(r *http.Request) string

SessionFromCookie returns session ID from the "s" cookie if present.

func SessionFromHeader

func SessionFromHeader(r *http.Request) string

SessionFromHeader returns session ID from the Authorization header if present.

Types

type APIConfiguration

type APIConfiguration struct {
	// ListenHTTP defines on which address and port the public API HTTP
	// server should operate. Keep empty to disable.
	ListenHTTP string

	// PathPrefix allows to define a prefix path that each API route will
	// include.
	PathPrefix string

	// SessionMaxAge defines how long a session is present after creation.
	// This does not cover session refresh.
	SessionMaxAge time.Duration

	// SessionRefreshAge defines the expiration refresh duratoin for a used
	// session token. This value is also a hint on how and when to refresh
	// a session token. Setting it allows active sessions to not expire
	// after SessionMaxAge duration.
	SessionRefreshAge time.Duration

	// RequireTwoFactorAuth defines if user must provide two factor
	// authentication code in order to login. If false, two factor
	// authentication is optional and can be turned on by each account
	// owner.
	RequireTwoFactorAuth bool

	// CORSDomain is the domain of the API. This information is used when
	// constructing absolute URL for example inside of email messages or
	// when configuring CORS to enable access only from certain places.
	CORSDomain string

	// MinPasswordLength specifies the minimum password length requirement
	// during a new account creation.
	MinPasswordLength uint

	// AllowRegisterAccount controls if user can register a new account.
	// This flag turns on/off account registration functionality.
	AllowRegisterAccount bool

	// AllowRegisterEmail is a regular expression that validates any email
	// address before allowing to register an account.  This regexp is not
	// meant to validate correctness of an email but to provide a basic
	// mean of configuring which email addresses are allowed. For example,
	// it can ensure that only emails from a certain domain is allowed with
	// ".*@mydomain\.com"
	AllowRegisterEmail string

	// RegisterAccountCompleteURL is sent via email to a newly registered
	// account owner in order to complete registration process. In order to
	// activate an account, another endpoint call must be made.
	// RegisterAccountCompleteURL must be an absolute URL. Token
	// information is included in the URL in place of "{token}" or if
	// {token} is not present, as a GET parameter.
	RegisterAccountCompleteURL string

	// RegisteredAccountGroups controls which permission groups are
	// assigned to a newly created account.
	// Changing this configuration allows to grant additional permissions
	// for any newly created account.
	RegisteredAccountPermissionGroups []uint64

	// AllowPasswordReset controls if password reset functionality is
	// enabled.
	AllowPasswordReset bool

	// PasswordResetCompleteURL is sent via email and should display a
	// password setup form.
	// PasswordResetCompleteURL must be an absolute URL. Token information
	// is included in the URL in place of "{token}" or if {token} is not
	// present, as a GET parameter.
	PasswordResetCompleteURL string

	// FromEmail defines what address outgoing emails are send from.
	FromEmail string
}

type Account

type Account struct {
	AccountID   string
	Email       string
	CreatedAt   time.Time
	ModifiedAt  time.Time
	Permissions []string
}

func CurrentAccount

func CurrentAccount(ctx context.Context) (*Account, bool)

CurrentAccount returns the account bound to current request.

This function requires AuthMiddleware.

func (*Account) HasPermission

func (a *Account) HasPermission(permission string) bool

HasPermission returns true if this account requested permission. A nil account has no permissions.

type AdminPanelConfiguration

type AdminPanelConfiguration struct {
	// ListenHTTP defines on which address and port the admin panel HTTP
	// server should operate. Keep empty to disable.
	ListenHTTP string

	// PathPrefix allows to define a prefix path that each admin panel
	// route will include.
	PathPrefix string

	// SessionMaxAge defines how long a session is present after creation.
	// This does not cover session refresh.
	SessionMaxAge time.Duration

	// RequireTwoFactorAuth defines if user must provide two factor
	// authentication code in order to login. If false, two factor
	// authentication is optional and can be turned on by each account
	// owner.
	RequireTwoFactorAuth bool

	// AllowPasswordChange if set to true, allows to overwrite any account
	// password via the admin panel.
	AllowPasswordChange bool
}

type Changelog

type Changelog struct {
	ChangelogID  uint64
	AccountID    string
	AccountEmail string
	Operation    string
	EntityKind   string
	EntityPk     string
	CreatedAt    time.Time
}

type Configuration

type Configuration struct {
	Database             string
	TaskQueueDatabase    string
	Secret               string
	StoreVacuumFrequency time.Duration

	// Event recipient configuraiton.
	//
	// EventSinkBackend specifies which backend to use to broadcast events.
	// Choices are: dropall, fs, webhook
	EventSinkBackend    string
	EventSinkWebhook    EventSinkWebhookConfiguration
	EventSinkFilesystem EventSinkFilesystemConfiguration

	// Email configuraiton.
	//
	// EmailBackend specifies which backend to use. Choices are: smtp fs
	EmailBackend    string
	SMTP            SMTPConfiguration
	FilesystemEmail FilesystemEmailConfiguration

	// MaxCacheSize if set, defines how many bytes can be used by the
	// in-memory cache service before the LRU starts evicting entries.
	//
	// If set to 0, there is no memory limit and entries are never evicted.
	MaxCacheSize uint64

	AdminPanel AdminPanelConfiguration
	PublicUI   PublicUIConfiguration
	API        APIConfiguration
}

type EphemeralToken

type EphemeralToken struct {
	TokenID   string
	AccountID string
	Action    string
}

type EventSinkFilesystemConfiguration

type EventSinkFilesystemConfiguration struct {
	// Dir specifies a directory where all events will be written.
	Dir string
}

type EventSinkWebhookConfiguration

type EventSinkWebhookConfiguration struct {
	// URL is the address of the recipient. If not set, webhook
	// functionality is disabled.
	URL string

	// Secret is shared between client and server, used to sign the
	// request.
	Secret string
}

type FilesystemEmailConfiguration

type FilesystemEmailConfiguration struct {
	// Dir specifies a directory where all email messages will be written
	// instead of sending over the network.
	Dir string
}

type FlashMsg

type FlashMsg struct {
	Kind string `json:"k"`
	Text string `json:"t"`
}

func (FlashMsg) HTML

func (m FlashMsg) HTML() template.HTML

type LookupFunc

type LookupFunc func(*http.Request) string

type PermissionGroup

type PermissionGroup struct {
	PermissionGroupID uint64
	Permissions       []string
	Description       string
	CreatedAt         time.Time
	ModifiedAt        time.Time
}

type PublicUIConfiguration

type PublicUIConfiguration struct {
	// ListenHTTP defines on which address and port the public UI HTTP
	// server should operate. Keep empty to disable.
	ListenHTTP string

	// PathPrefix allows to define a prefix path that each public UI route
	// will include.
	PathPrefix string

	// Domain is the domain of the main website. This information is used
	// when constructing absolute URL for example inside of email messages.
	Domain string

	// DomainSSL specifies if the public UI should be served over encrypted
	// connection or not.
	DomainSSL bool

	// RequireTwoFactorAuth defines if user must provide two factor
	// authentication code in order to login. If false, two factor
	// authentication is optional and can be turned on by each account
	// owner.
	RequireTwoFactorAuth bool

	// SessionMaxAge defines how long a session is present after creation.
	// This does not cover session refresh.
	SessionMaxAge time.Duration

	// MinPasswordLength specifies the minimum password length requirement
	// during a new account creation.
	MinPasswordLength uint

	// DisableDefaultCSS allows to disable (no link) provided by default
	// CSS files in all templates.
	DisableDefaultCSS bool

	// IncludeExtraCSS allows to include/link an additional set of CSS
	// files in each public template rendered.
	IncludeExtraCSS []string

	// AllowRegisterAccount controls if user can register a new account.
	// This flag turns on/off account registration functionality.
	AllowRegisterAccount bool

	// AllowRegisterEmail is a regular expression that validates any email
	// address before allowing to register an account.  This regexp is not
	// meant to validate correctness of an email but to provide a basic
	// mean of configuring which email addresses are allowed. For example,
	// it can ensure that only emails from a certain domain is allowed with
	// ".*@mydomain\.com"
	AllowRegisterEmail string

	// RegisteredAccountGroups controls which permission groups are
	// assigned to a newly created account.
	// Changing this configuration allows to grant additional permissions
	// for any newly created account.
	RegisteredAccountPermissionGroups []uint64

	// AllowPasswordReset controls if password reset functionality is
	// enabled.
	AllowPasswordReset bool

	// FromEmail defines what address outgoing emails are send from.
	FromEmail string
}

type SMTPConfiguration

type SMTPConfiguration struct {
	Port     int
	Host     string
	Username string
	Password string

	// AllowUnencrypted allows to authenticate using an unencrypted
	// connection. This configuration is for testing purposes only, when
	// running a local cluster without certificates.
	AllowUnencrypted bool
}

type SendConfirmRegistration

type SendConfirmRegistration struct {
	Language     string
	FromEmail    string
	AccountEmail string
	Token        string
	CompleteURL  string
}

func (SendConfirmRegistration) TaskName

func (SendConfirmRegistration) TaskName() string

type SendResetPassword

type SendResetPassword struct {
	FromEmail    string
	Language     string
	AccountID    string
	AccountEmail string
	Token        string
	CompleteURL  string
}

func (SendResetPassword) TaskName

func (SendResetPassword) TaskName() string

type Store

type Store interface {
	// Session returns a new session that process all operations within a
	// translation.
	Session(context.Context) (StoreSession, error)

	// Close store and free all resources.
	Close() error
}

func OpenSQLiteStore

func OpenSQLiteStore(dbpath string, safe secret.Safe) (Store, error)

OpenSQLiteStore returns a store implementation backed by an SQLite engine.

type StoreSession

type StoreSession interface {
	// Session returns a new session that process all operations within a
	// translation. Commiting returned session merges all changes to the
	// parent and it is up to the parent to do the final commit or rollback
	// all changes.
	Session(context.Context) (StoreSession, error)

	// Commit all changes applied within given sesssion.
	Commit() error

	// Rollback all changes applied within given session.
	Rollback()

	// CreateAccount creates an account using given email and password.
	// Password must be strong enough for bcrypt to be able to hash it.
	// Email must be unique.
	CreateAccount(ctx context.Context, email, password string) (*Account, error)

	// UpdateAccountPermissionGroups updates the account permission groups.
	// Previous assignement is removed.
	UpdateAccountPermissionGroups(ctx context.Context, accountID string, permissionGroupIDs []uint64) error

	// UpdateAccountPassword updates the account password to the new value.
	// Password argument must be a plain text password.
	UpdateAccountPassword(ctx context.Context, accountID string, password string) error

	// IsAccountPassword validates if given password belongs to specified
	// account. ErrNotFound is returned if account does not exist.
	// ErrPassword is returned if account does exist but password does not
	// match.
	IsAccountPassword(ctx context.Context, accountID, password string) error

	// UpdateAccountTOTPSecret updates the account TOTP secret to given
	// value.
	UpdateAccountTOTPSecret(ctx context.Context, accountID string, totp secret.Value) error

	// AccountTOTPSecret returns TOTP secret that belongs to given account.
	AccountTOTPSecret(ctx context.Context, accountID string) (secret.Value, error)

	// AccountByID returns an account with given ID.
	// Returns ErrNotFound if account with given ID cannot be found.
	AccountByID(ctx context.Context, accountID string) (*Account, error)

	// AccountBySession
	// Returns ErrNotFound if account with given ID cannot be found.
	AccountBySession(ctx context.Context, sessionID string) (*Account, error)

	// AccountByEmail
	// Returns ErrNotFound if session with given ID cannot be found.
	AccountByEmail(ctx context.Context, email string) (*Account, error)

	// ListAccounts returns all accounts matching given filter. Filter is a
	// list of whitespace separated strings that all must be part of
	// returned account email address. Match is case insensitive.
	//
	// This method is meant for internal use only and it is not safe to
	// expose it to all/any users.
	//
	// Returns ErrNotFound if account with given email cannot be found.
	ListAccounts(ctx context.Context, filter string, limit, offset uint) ([]*Account, error)

	// CreateSession creates and returns a new session that is valid for
	// given period.
	//
	// Returns ErrNotFound if an account with given ID does not exist.
	CreateSession(ctx context.Context, accountID string, expiresIn time.Duration) (string, error)

	// DeleteSession removes session from the system. Deleted session can
	// no longer be used.
	DeleteSession(ctx context.Context, sessionID string) error

	// DeleteAccountSessions deletes all authentication sessions that
	// belong to the account with the given ID.
	DeleteAccountSessions(ctx context.Context, accountID string) error

	// RefreshSession updates a session expiration time, extending it to at
	// least given duration. If the current expiration time is greater than
	// provided duration, no update is made.
	//
	// To avoid writes, this method works with expiration approximation. If
	// expiration time is close to desired state, value might not be
	// updated.
	// This method can only extend expiration time and never shorten it.
	//
	// Returns ErrNotFound if session with given ID does not exist.
	RefreshSession(ctx context.Context, sessionID string, expiresIn time.Duration) (time.Time, error)

	// CreatePermissionGroup creates a new Permission Group.
	CreatePermissionGroup(ctx context.Context, description string, permissions []string) (*PermissionGroup, error)

	// UpdatePermissionGroup is setting attributes of a single permission
	// group to provided values.
	//
	// Returns ErrNotFound if Permission Group with given ID does not
	// exist.
	UpdatePermissionGroup(ctx context.Context, permissionGroupID uint64, description string, permissions []string) error

	// PermissionGroupsByAccount returns a list of all Permission Group
	// entities that were assigned to the account with given ID.
	PermissionGroupsByAccount(ctx context.Context, accountID string) ([]*PermissionGroup, error)

	// PermissionGroupByID returns a single Permission Group with given ID.
	// Returns ErrNotFound if Permission Group with requested ID does not
	// exist.
	PermissionGroupByID(ctx context.Context, permissiongroupID uint64) (*PermissionGroup, error)

	// ListPermissionGroups returns all existing Permission Group entities.
	// No Pagination.
	ListPermissionGroups(ctx context.Context) ([]*PermissionGroup, error)

	// ListChangelogs returns all existing Changelog entries. No pagination.
	ListChangelogs(ctx context.Context) ([]*Changelog, error)

	// AddChangelog appends a changelog entry.
	//
	// AuthenticatedAs is the ID of the user that makes the change.
	// Operation should be created, updated or deleted. Entity kind and pk
	// describes the type and primary key of the modified entity. Primary
	// key must be serialized to string.
	AddChangelog(ctx context.Context, authentitcatedAs, operation, entityKind, entityPk string) error

	// CreateEphemeralToken generates a single use, expiring token.
	// Addintional payload can be provided that will be stored within the
	// token.
	CreateEphemeralToken(ctx context.Context, action string, expireIn time.Duration, payload interface{}) (string, error)

	// EphemeralToken loads payload of a token matching given action an ID
	// into provided destination.
	// ErrNotFound is returned if token does not exists.
	EphemeralToken(ctx context.Context, action, tokenID string, payloadDest interface{}) error

	// DeleteEphemeralToken removes token with given ID.
	// ErrNotFound is returned if token does not exists.
	DeleteEphemeralToken(ctx context.Context, tokenID string) error

	// Vacuum removes stale data that is no longer requred. For example
	// expired ephemeral tokens or sessions.
	Vacuum(ctx context.Context) error
}

Jump to

Keyboard shortcuts

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