app

package
v0.0.0-...-3c0424e Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2021 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// CentsPerDollar describes the number of cents in a US Dollar.
	CentsPerDollar int = 100

	// MaxDollarAmount is the maximum dollar amount a Money can store.
	MaxDollarAmount int = math.MaxInt64 / CentsPerDollar
	// MinDollarAmount is the minimum dollar amount a Money can store.
	MinDollarAmount int = math.MinInt64 / CentsPerDollar

	// MaxCentAmount is the maximum number of *fractional* cents in a US Dollar.
	MaxCentAmount int = 99
	// MinCentAmount is the minimum number of *fractional* cents in a US Dollar.
	MinCentAmount int = -99
)
View Source
const SessionLength = 6 * time.Hour

SessionLength defines how long a login session for this app will last, at a MAXIMUM. Sessions may be revoked prior.

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound may be returned by a DataStore implementation when the requested data could not be found inside the store.

Suggested check for users of DataStore:

if errors.Is(err, app.ErrNotFound) {
    // do something for the special not found case
}

Suggested use by DataStore implementors:

return errors.Wrapf(app.ErrNotFound, "book #%d", id)

Functions

This section is empty.

Types

type Affiliation

type Affiliation struct {
	PersonID       int `db:"person_id"`
	OrganizationID int `db:"organization_id"`
	// Points is the quantity of points this person has with this Organization,
	// will be null for non-drivers.
	Points null.Int `db:"points"`
}

An Affiliation describes a person's relationship with an organization.

type AffiliationStore

type AffiliationStore interface {
	AddPersonAffiliation(
		ctx context.Context,
		personID, orgID int,
		role Role,
	) error
	RemovePersonAffiliation(
		ctx context.Context,
		personID, orgID int,
	) error
	SetPointsForAffiliation(
		ctx context.Context,
		personID, orgID int,
		points null.Int,
	) error
	GetBalancesForPerson(ctx context.Context, personID int) ([]Balance, error)
}

AffiliationStore defines methods for interacting with affiliations between Persons and Organizations, with Points.

type Application

type Application struct {
	// ID uniquely identifies this application.
	ID int `db:"application_id" json:"id"`
	// ApplicantID is the person ID of the driver applying to be sponsored.
	ApplicantID int `db:"applicant_id" json:"applicant_id"`

	// OrganizationID is the ID of the organization the driver would like to be
	// sponsored by.
	OrganizationID    int    `db:"organization_id" json:"organization_id"`
	OrganizationTitle string `db:"name" json:"organization_name"`
	// Comment is a driver-supplied comment to go with their application.
	Comment string `db:"comment" json:"comment"`
	// Approved specifies whether or not the organization has approved this
	// application or not. Will be null if no decision has been made.
	Approved null.Bool `db:"approved" json:"approved"`
	// Reason is the reason the organization accepted/rejected this application.
	Reason null.String `db:"reason" json:"reason"`
	// CreatedAt is the timestamp of when the driver submitted this application.
	CreatedAt time.Time `db:"created_at" json:"created_at"`
	// ApprovedAt is the timestamp of when the organization approved or rejected
	// this application.
	ApprovedAt null.Time `db:"approved_at" json:"approved_at"`
}

Application represents a driver application to be sponsored by an organization.

type ApplicationStore

type ApplicationStore interface {
	GetApplicationByID(
		ctx context.Context,
		appID int,
	) (Application, error)
	GetApplicationsForPerson(
		ctx context.Context,
		personID int,
	) ([]Application, error)
	GetApplicationsForOrganization(
		ctx context.Context,
		orgID int,
	) ([]Application, error)

	CreateApplication(ctx context.Context, a Application) (int, error)

	UpdateApplicationApproval(
		ctx context.Context,
		appID int,
		status bool,
		reason string,
	) error
}

ApplicationStore defines methods for working with app.Application objects in the database.

type Balance

type Balance struct {
	PersonID         int    `db:"person_id" json:"person_id"`
	PersonFirstName  string `db:"first_name" json:"person_first_name"`
	PersonLastName   string `db:"last_name" json:"person_last_name"`
	OrganizationID   int    `db:"organization_id" json:"organization_id"`
	OrganizationName string `db:"name" json:"organization_name"`
	Points           int    `db:"points" json:"balance"`
}

A Balance describes the number of points that a person has within a given Organization.

type CatalogProduct

type CatalogProduct struct {
	ID          int         `json:"id"`
	Title       string      `json:"title"`
	Description string      `json:"description"`
	ImageURL    null.String `json:"image_url"`
	Points      Points      `json:"points"`
}

A CatalogProduct is a product affiliated with an organization, with its cost measured in Points.

type CatalogStore

type CatalogStore interface {
	GetProductsForOrganization(
		ctx context.Context,
		orgID int,
	) ([]CatalogProduct, error)
	SearchProductCatalog(
		ctx context.Context,
		orgID int,
		keywords string,
	) ([]CatalogProduct, error)
	GetProductByID(
		ctx context.Context,
		productID, orgID int,
	) (CatalogProduct, error)

	AddProduct(ctx context.Context, p Product) (int, error)
	MakeProductUnavailable(ctx context.Context, productID, orgID int) error
}

CatalogStore defines methods for working with app.Product and app.CatalogProduct objects.

type CommerceProduct

type CommerceProduct struct {
	ID          int         `json:"id"`
	Title       string      `json:"title"`
	Description string      `json:"description"`
	ImageURL    null.String `json:"image_url"`
	Price       Money       `json:"price"`
}

A CommerceProduct describes a product of a third-party vendor.

func (*CommerceProduct) ToProduct

func (cp *CommerceProduct) ToProduct(orgID int) Product

ToProduct converts this commerce product to a Product, given the associated Organization's ID number.

type CommerceQuery

type CommerceQuery struct {
	Keywords string
	Sort     CommerceSort
	Limit    null.Int
	PageNo   null.Int
}

A CommerceQuery desceribes a search query for products.

type CommerceSort

type CommerceSort struct {
	// By controls which field results are sorted by.
	By CommerceSortBy
	// Direction controls which direction results are sorted.
	Direction CommerceSortDirection
	// Valid controls whether or not results are sorted.
	Valid bool
}

CommerceSort controls sorting of search results.

type CommerceSortBy

type CommerceSortBy string

CommerceSortBy is a pseudo-enumeration of fields on which products may be sorted in search.

const (
	CommerceSortByCreated CommerceSortBy = "created"
	CommerceSortByPrice   CommerceSortBy = "price"
	CommerceSortByRating  CommerceSortBy = "score"
)

CommerceSortBy options control the field by which search results are sorted.

type CommerceSortDirection

type CommerceSortDirection string

CommerceSortDirection is a pseudo-enumeration of directions for sorting search results.

const (
	CommerceSortDirectionAscending  CommerceSortDirection = "up"
	CommerceSortDirectionDescending CommerceSortDirection = "down"
)

CommerceSearchDirection options control the direction search results are sorted.

type CommerceVendor

type CommerceVendor interface {
	Search(ctx context.Context, q CommerceQuery) ([]CommerceProduct, error)
	GetProductByID(ctx context.Context, productID int) (CommerceProduct, error)
}

CommerceVendor describes a common interface for dealing with third-party eCommerce vendors.

type DataStore

DataStore is the common interface for durable data storage.

type Money

type Money int

Money provides an abstraction layer around monetary values stored as an integer count of cents.

func MakeMoneyFromComponents

func MakeMoneyFromComponents(dollars, cents int) (Money, error)

MakeMoneyFromComponents makes a Money from its dollar and cent component values. Both component values must be within their respective ranges and have matching signs (unless either is zero).

func MakeMoneyFromFloat

func MakeMoneyFromFloat(f float64) Money

MakeMoneyFromFloat makes a Money from a floating point integer. The decimal will be truncated at two places (floored).

func MustMakeMoneyFromComponents

func MustMakeMoneyFromComponents(dollars, cents int) Money

MustMakeMoneyFromComponents runs MakeMoneyFromComponents and follows the same constraints. HOWEVER, when any precondition fails and an error occurs, this function shall panic.

It is intended for this function only to be used by tests and constants where error checking often is impractical. All other use cases should use MakeMoneyFromComponents and check the error.

func ParseMoneyFromString

func ParseMoneyFromString(s string) (Money, error)

ParseMoneyFromString attempts to parse Money from a string.

This string must follow these rules:

  • if there is a negative sign, it must be the first character
  • the dollar sign is optional
  • the commas separating thousands in the dollar amount are optional
  • the cents are optional, but if present must have two decimal places

Examples of accepted strings:

  • "-$40,324,921.76"
  • "$503"
  • "504.32"
  • "-30"
  • "$3202.32"
  • "8,108.31"
  • "244,422"

func (Money) Components

func (m Money) Components() (dollars, cents int)

Components breaks a Money down into its dollar and cent components.

func (Money) ConvertToPoints

func (m Money) ConvertToPoints(org Organization) Points

ConvertToPoints converts this Money value into points of the given organization based on the point value.

func (Money) String

func (m Money) String() string

String returns a string representation of this Money value. Will have a leading dollar sign and use thousands separators for human readability.

This returned value is compatible with ParseMoneyFromString.

type Organization

type Organization struct {
	// ID uniquely identifies this organization.
	ID int `db:"organization_id" json:"id"`
	// Name is a human-readable alias for this organization.
	Name string `db:"name" json:"name"`
	// PointValue describes the ratio between points and real dollars.
	// Each point is worth a PointValue amount of Money.
	PointValue Money `db:"point_value" json:"point_value"`
}

An Organization contains information about a particular sponsor organization.

type OrganizationStore

type OrganizationStore interface {
	GetAllOrganizations(ctx context.Context) ([]Organization, error)
	GetOrganizationByID(ctx context.Context, orgID int) (Organization, error)

	CreateOrganization(ctx context.Context, org Organization) (int, error)
	UpdateOrganization(ctx context.Context, org Organization) error
	DeleteOrganization(ctx context.Context, orgID int) error
}

OrganizationStore defines methods for working with app.Organization objects.

type Password

type Password string

A Password is a wrapper type for bcrypt password hashes.

func NewPassword

func NewPassword(plaintext string) (Password, error)

NewPassword creates a new hashed Password given its plaintext.

func (Password) Verify

func (p Password) Verify(plaintext string) bool

Verify verifies a hashed Password against a given plaintext.

type Person

type Person struct {
	// ID is the uniquely identifying number for this person's account.
	ID int `db:"person_id" json:"id"`
	// FirstName is the person's first name.
	FirstName string `db:"first_name" json:"first_name"`
	// LastName is the person's last name.
	LastName string `db:"last_name" json:"last_name"`
	// Email is the person's email address. May be changed.
	Email string `db:"email" json:"email"`
	// Role is the person's current role. May be changed.
	Role Role `db:"role_id" json:"role_id"`
	// Password is the person's current hashed password.
	Password Password `db:"pass_hash" json:"-"`
	// IsDeactivated is true when a person's account is deactivated and
	// therefore cannot be authenticated against.
	IsDeactivated bool `db:"is_deactivated" json:"is_deactivated"`
	// Affiliations is a list of organization IDs that this user is
	// associated with.
	Affiliations []int `json:"affiliations"`
}

A Person represents a user of our app.

type PersonStore

type PersonStore interface {
	GetAllPeople(ctx context.Context) ([]Person, error)
	GetPersonByID(
		ctx context.Context,
		personID int,
	) (Person, error)
	GetPersonByEmail(ctx context.Context, email string) (Person, error)

	CreatePerson(ctx context.Context, p Person) (int, error)

	UpdatePersonName(
		ctx context.Context,
		personID int,
		firstName, lastName string,
	) error
	UpdatePersonEmail(ctx context.Context, personID int, email string) error
	UpdatePersonRole(ctx context.Context, personID int, roleType Role) error
	UpdatePersonPassword(ctx context.Context, personID int, p Password) error
	ActivatePerson(ctx context.Context, personID int) error
	DeactivatePerson(ctx context.Context, personID int) error
}

PersonStore defines methods for working with app.Person objects in the database.

type Points

type Points struct {
	// Amount describes the quantity of points.
	Amount int `json:"amount"`
	// OrganizationID is the identifier of the organization that the points
	// originated from.
	OrganizationID int `json:"organization_id"`
	// PointValue describes the amount of Money that each point is worth.
	PointValue Money `json:"point_value"`
}

Points describes a particular amount of points, the value of each point, and the organization those points are associated with.

type Product

type Product struct {
	ID             int         `db:"product_id"`
	VendorID       int         `db:"vendor_id"`
	OrganizationID int         `db:"organization_id"`
	Title          string      `db:"title"`
	Description    string      `db:"description"`
	ImageURL       null.String `db:"image_url"`
	Price          Money       `db:"price"`
	IsAvailable    bool        `db:"is_available"`
}

A Product represents an entry in the product table.

func (*Product) ToCatalogProduct

func (p *Product) ToCatalogProduct(org Organization) CatalogProduct

ToCatalogProduct converts this Product to a CatalogProduct.

type Role

type Role int

A Role specifies what role a user has in our app and therefore what permissions they might have.

const (
	// RoleAdmin users can access all parts of the system, even content that is
	// not owned by their user.
	RoleAdmin Role = 1
	// RoleSponsor can access sponsor control panels for their organization as
	// well as all driver information for their affiliated drivers.
	RoleSponsor Role = 2
	// RoleUser can access the application system only, since they are not
	// affiliated with any organization.
	RoleUser Role = 3
	// RoleDriver can access the ordering system and view their point balance,
	// as they are affiliated with a sponsor organization.
	RoleDriver Role = 4
)

type Session

type Session struct {
	// Person holds the user that this session belongs to.
	Person
	// ID is the session's identifying number. It is not secret.
	ID int `db:"session_id"`
	// Token is a unique, securely random generated UUIDv4 that also uniquely
	// identifies this session. It must be kept secret between our API server
	// and the web browser for the session.
	Token uuid.UUID `db:"token"`
	// CreatedAt is the timestamp that this session was started at.
	CreatedAt time.Time `db:"created_at"`
	// ExpiresAt is the timestamp when this session will expire permanently.
	ExpiresAt time.Time `db:"expires_at"`
	// IsRevoked is true when the session was manually revoked.
	IsRevoked bool `db:"is_revoked"`
}

A Session represents an individual user session with our app.

func NewSession

func NewSession(p Person) (*Session, error)

NewSession creates a new login session with a secure random token for a given person. It shall expire after SessionLength time has passed.

func (*Session) IsValid

func (s *Session) IsValid() bool

IsValid determines whether or not a session is still valid.

type SessionStore

type SessionStore interface {
	GetSessionsForPerson(
		ctx context.Context,
		personID int,
		includeInvalid bool,
	) ([]Session, error)
	GetSessionByToken(ctx context.Context, token uuid.UUID) (Session, error)

	CreateSession(ctx context.Context, s Session) (int, error)

	RevokeSession(ctx context.Context, sessionID int) error
	RevokeSessionsForPersonExcept(
		ctx context.Context,
		personID, sessionID int,
	) error
}

SessionStore defines methods for working with app.Session objects in the database.

Directories

Path Synopsis
cmd
api

Jump to

Keyboard shortcuts

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