persistence

package
v0.0.0-...-2205d8a Latest Latest
Warning

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

Go to latest
Published: Apr 4, 2024 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrBadQuery = errors.New("persistence: could not match query")

ErrBadQuery is returned when a DAL method cannot handle the given query

Functions

func EventIDAt

func EventIDAt(t time.Time) (string, error)

EventIDAt creates a new ULID based on the given timestamp

func NewULID

func NewULID() (string, error)

NewULID wraps the creation of a new ULID. These values are supposed to be used as the primary key for looking up events as it can be used as a `since` parameter without explicitly providing information about the actual timestamp like a `created_at` value would do.

Types

type Account

type Account struct {
	AccountID           string
	Name                string
	PublicKey           string
	EncryptedPrivateKey string
	UserSalt            string
	Retired             bool
	AccountStyles       string
	Created             time.Time
	Events              []Event
}

Account stores information about an account.

func (*Account) HashUserID

func (a *Account) HashUserID(userID string) (string, error)

HashUserID uses the account's `UserSalt` to create a hashed version of a user identifier that is unique per account.

func (*Account) WrapPublicKey

func (a *Account) WrapPublicKey() (jwk.Key, error)

WrapPublicKey returns the public key of an account's keypair in JSON WebKey format.

type AccountResult

type AccountResult struct {
	AccountID           string                `json:"accountId"`
	Name                string                `json:"name"`
	PublicKey           interface{}           `json:"publicKey,omitempty"`
	EncryptedPrivateKey string                `json:"encryptedPrivateKey,omitempty"`
	Events              *EventsByAccountID    `json:"events,omitempty"`
	DeletedEvents       []string              `json:"deletedEvents,omitempty"`
	Sequence            string                `json:"sequence,omitempty"`
	Secrets             *EncryptedSecretsByID `json:"secrets,omitempty"`
	AccountStyles       string                `json:"accountStyles,omitempty"`
	Created             time.Time             `json:"created,omitempty"`
	RetentionPeriod     string                `json:"retentionPeriod,omitempty"`
}

AccountResult is the data returned from looking up an account by id

type AccountUser

type AccountUser struct {
	AccountUserID  string
	HashedEmail    string
	HashedPassword string
	Salt           string
	AdminLevel     AccountUserAdminLevel
	Relationships  []AccountUserRelationship
}

AccountUser is a person that can log in and access data related to all associated accounts.

type AccountUserAdminLevel

type AccountUserAdminLevel int

AccountUserAdminLevel is used to describe the privileges granted to an account user. If zero, no admin privileges are given.

const (
	AccountUserAdminLevelSuperAdmin AccountUserAdminLevel = 1
)

A SuperAdmin is the only level currently used. It is granted any possible privilege.

type AccountUserRelationship

type AccountUserRelationship struct {
	RelationshipID                    string
	AccountUserID                     string
	AccountID                         string
	PasswordEncryptedKeyEncryptionKey string
	EmailEncryptedKeyEncryptionKey    string
	OneTimeEncryptedKeyEncryptionKey  string
	// contains filtered or unexported fields
}

AccountUserRelationship contains the encrypted KeyEncryptionKeys needed for an AccountUser to access the data of the account it links to.

type BootstrapAccount

type BootstrapAccount struct {
	AccountID string `yaml:"id"`
	Name      string `yaml:"name"`
}

BootstrapAccount contains the information needed for creating an account at bootstrap time.

type BootstrapAccountUser

type BootstrapAccountUser struct {
	Email                 string                `yaml:"email"`
	Password              string                `yaml:"password"`
	Accounts              []string              `yaml:"accounts"`
	AdminLevel            AccountUserAdminLevel `yaml:"admin_level"`
	AllowInsecurePassword bool
}

BootstrapAccountUser contains the information needed for creating an account user at bootstrap time.

type BootstrapConfig

type BootstrapConfig struct {
	Accounts     []BootstrapAccount     `yaml:"accounts"`
	AccountUsers []BootstrapAccountUser `yaml:"account_users"`
	Force        bool
}

BootstrapConfig contains data about accounts and account users that is used to seed an application database from scratch.

type Config

type Config func(*persistenceLayer)

Config is a function that adds a configuration option to the constructor

type DataAccessLayer

type DataAccessLayer interface {
	CreateEvent(*Event) error
	FindEvents(interface{}) ([]Event, error)
	DeleteEvents(interface{}) (int64, error)
	CreateSecret(*Secret) error
	FindSecret(interface{}) (Secret, error)
	DeleteSecret(interface{}) error
	CreateAccount(*Account) error
	UpdateAccount(*Account) error
	FindAccount(interface{}) (Account, error)
	FindAccounts(interface{}) ([]Account, error)
	CreateAccountUser(*AccountUser) error
	FindAccountUser(interface{}) (AccountUser, error)
	FindAccountUsers(interface{}) ([]AccountUser, error)
	UpdateAccountUser(*AccountUser) error
	CreateAccountUserRelationship(*AccountUserRelationship) error
	UpdateAccountUserRelationship(*AccountUserRelationship) error
	FindAccountUserRelationships(interface{}) ([]AccountUserRelationship, error)
	DeleteAccountUserRelationships(interface{}) error
	CreateTombstone(*Tombstone) error
	FindTombstones(interface{}) ([]Tombstone, error)
	Transaction() (Transaction, error)
	ApplyMigrations() error
	DropAll() error
	ProbeEmpty() bool
	Ping() error
}

DataAccessLayer provides a database agnostic interface for storing data. All query methods expect certain types to be passed. In case a unknown query is passed, an error can be returned early.

type DeleteAccountUserRelationshipsQueryByAccountID

type DeleteAccountUserRelationshipsQueryByAccountID string

DeleteAccountUserRelationshipsQueryByAccountID requests deletion of all relationships with the given account id.

type DeleteEventsQueryByEventIDs

type DeleteEventsQueryByEventIDs []string

DeleteEventsQueryByEventIDs requests deletion of all events contained in the given set.

type DeleteEventsQueryBySecretIDs

type DeleteEventsQueryBySecretIDs []string

DeleteEventsQueryBySecretIDs requests deletion of all events that match the given identifiers.

type DeleteEventsQueryOlderThan

type DeleteEventsQueryOlderThan string

DeleteEventsQueryOlderThan requests deletion of all events older than the given deadline

type DeleteSecretQueryBySecretID

type DeleteSecretQueryBySecretID string

DeleteSecretQueryBySecretID requests deletion of the secret record with the given secret id.

type EncryptedSecretsByID

type EncryptedSecretsByID map[string]string

EncryptedSecretsByID is a map of secret IDs and their respective encrypted user secrets

type ErrUnknownAccount

type ErrUnknownAccount string

ErrUnknownAccount will be returned when an insert call tries to create an event for an account ID that does not exist in the database

func (ErrUnknownAccount) Error

func (e ErrUnknownAccount) Error() string

type ErrUnknownSecret

type ErrUnknownSecret string

ErrUnknownSecret will be returned when a given SecretID is not found in the database

func (ErrUnknownSecret) Error

func (e ErrUnknownSecret) Error() string

type Event

type Event struct {
	EventID   string
	Sequence  string
	AccountID string
	// the secret id is nullable for anonymous events
	SecretID *string
	Payload  string
	Secret   Secret
}

Event is any analytics event that will be stored in the database. It is uniquely tied to an Account and a Secret model.

type EventResult

type EventResult struct {
	AccountID string  `json:"accountId,omitempty"`
	SecretID  *string `json:"secretId,omitempty"`
	EventID   string  `json:"eventId"`
	Payload   string  `json:"payload"`
}

EventResult is an element returned from a query. It contains all data that is stored about an atomic event.

type EventsByAccountID

type EventsByAccountID map[string][]EventResult

EventsByAccountID groups a list of events by AccountID in a response

type EventsResult

type EventsResult struct {
	Events          *EventsByAccountID `json:"events,omitempty"`
	DeletedEvents   []string           `json:"deletedEvents,omitempty"`
	Sequence        string             `json:"sequence,omitempty"`
	RetentionPeriod string             `json:"retentionPeriod,omitempty"`
}

EventsResult contains all data that is returned to a user requesting their data

type FindAccountQueryActiveByID

type FindAccountQueryActiveByID string

FindAccountQueryActiveByID requests a non-retired account of the given ID

type FindAccountQueryByID

type FindAccountQueryByID string

FindAccountQueryByID requests the account of the given id.

type FindAccountQueryIncludeEvents

type FindAccountQueryIncludeEvents struct {
	AccountID string
	Since     string
}

FindAccountQueryIncludeEvents requests the account of the given id including all of the associated events. In case the value for Since is non-zero, only events newer than the given value should be considered.

type FindAccountUserQueryByAccountUserIDIncludeRelationships

type FindAccountUserQueryByAccountUserIDIncludeRelationships string

FindAccountUserQueryByAccountUserIDIncludeRelationships requests the account user of the given id and all of its relationships.

type FindAccountUserRelationshipsQueryByAccountUserID

type FindAccountUserRelationshipsQueryByAccountUserID string

FindAccountUserRelationshipsQueryByAccountUserID requests all relationships for the user with the given account user ID.

type FindAccountUsersQueryAllAccountUsers

type FindAccountUsersQueryAllAccountUsers struct {
	IncludeRelationships bool
	IncludeInvitations   bool
}

FindAccountUsersQueryAllAccountUsers requests all account users.

type FindAccountsQueryAllAccounts

type FindAccountsQueryAllAccounts struct{}

FindAccountsQueryAllAccounts requests all known accounts to be returned.

type FindEventsQueryByEventIDs

type FindEventsQueryByEventIDs []string

FindEventsQueryByEventIDs requests all events that match the given list of identifiers.

type FindEventsQueryForSecretIDs

type FindEventsQueryForSecretIDs struct {
	SecretIDs []string
	Since     string
}

FindEventsQueryForSecretIDs requests all events that match the list of secret identifiers. In case the Since value is non-zero it will be used to request only events that are newer than the given ULID.

type FindEventsQueryOlderThan

type FindEventsQueryOlderThan string

FindEventsQueryOlderThan looks up all events older than the given event id

type FindSecretQueryBySecretID

type FindSecretQueryBySecretID string

FindSecretQueryBySecretID requests the secret of the given ID

type FindTombstonesQueryByAccounts

type FindTombstonesQueryByAccounts struct {
	Since      string
	AccountIDs []string
}

FindTombstonesQueryByAccounts requests all tombstones for an account id that are newer than the given sequence

type FindTombstonesQueryBySecrets

type FindTombstonesQueryBySecrets struct {
	Since     string
	SecretIDs []string
}

FindTombstonesQueryBySecrets requests all tombstones for an account id that are newer than the given sequence

type LoginAccountResult

type LoginAccountResult struct {
	AccountName      string      `json:"accountName"`
	AccountID        string      `json:"accountId"`
	KeyEncryptionKey interface{} `json:"keyEncryptionKey"`
	Created          time.Time   `json:"created"`
}

LoginAccountResult contains information for the client to handle an account in the client at runtime.

type LoginResult

type LoginResult struct {
	AccountUserID string                `json:"accountUserId"`
	AdminLevel    AccountUserAdminLevel `json:"adminLevel"`
	Accounts      []LoginAccountResult  `json:"accounts"`
}

LoginResult is a successful account user authentication response.

func (*LoginResult) CanAccessAccount

func (l *LoginResult) CanAccessAccount(accountID string) bool

CanAccessAccount checks whether the login result is allowed to access the account of the given identifier.

func (*LoginResult) IsSuperAdmin

func (l *LoginResult) IsSuperAdmin() bool

IsSuperAdmin checks whether the login result is a SuperAdmin.

type Query

type Query struct {
	UserID string
	Since  string
}

Query defines a set of filters to limit the set of results to be returned In case a field has the zero value, its filter will not be applied.

type RetireAccountQueryByID

type RetireAccountQueryByID string

RetireAccountQueryByID requests the account of the given id to be retired.

type Secret

type Secret struct {
	SecretID        string
	EncryptedSecret string
}

Secret associates a hashed user id - which ties a user and account together uniquely - with the encrypted user secret the account owner can use to decrypt events stored for that user.

type SecretResult

type SecretResult struct {
	SecretID        string `json:"secretId"`
	EncryptedSecret string `json:"encryptedSecret"`
}

SecretResult contains information about a single secret record

type Service

type Service interface {
	Insert(userID, accountID, payload string, eventID *string) error
	Query(Query) (EventsResult, error)
	GetAccount(accountID string, styles, events bool, eventsSince string) (AccountResult, error)
	CreateAccount(name, creatorEmailAddress, creatorPassword string) error
	RetireAccount(accountID string) error
	AssociateUserSecret(accountID, userID, encryptedUserSecret string) error
	Purge(userID string) error
	Login(email, password string) (LoginResult, error)
	LookupAccountUser(userID string) (LoginResult, error)
	ChangePassword(userID, currentPassword, changedPassword string) error
	ChangeEmail(userID, emailAddress, emailCurrent, password string) error
	GenerateOneTimeKey(emailAddress string) ([]byte, error)
	ResetPassword(emailAddress, password string, oneTimeKey []byte) error
	ShareAccount(inviteeEmailAddress, providerEmailAddress, providerPassword, accountID string, grantAdminPrivileges bool) (ShareAccountResult, error)
	UpdateAccountStyles(accountID, styles string) error
	Join(emailAddress, password string) error
	Expire(retention time.Duration) (int, error)
	Bootstrap(data BootstrapConfig) error
	ProbeEmpty() bool
	CheckHealth() error
	Migrate() error
}

Service is a backend-agnostic wrapper for interacting with a persistence layer. It does not make any assumptions about how data is being modelled and stored.

func New

func New(dal DataAccessLayer, configs ...Config) (Service, error)

New creates a persistence service that connects to any database using the given access layer.

type ShareAccountResult

type ShareAccountResult struct {
	UserExistsWithPassword bool
	AccountNames           []string
}

ShareAccountResult is a successful invitation of a user

type Tombstone

type Tombstone struct {
	EventID   string
	AccountID string
	SecretID  *string
	Sequence  string
}

A Tombstone replaces an event on its deletion

type Transaction

type Transaction interface {
	DataAccessLayer
	Rollback() error
	Commit() error
}

Transaction is a data access layer that does not persist data until commit is called. In case rollback is called before, the underlying database will remain in the same state as before.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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