foodtinder

package
v0.0.0-...-381a539 Latest Latest
Warning

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

Go to latest
Published: Dec 22, 2022 License: GPL-3.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// ErrNotFound is used when a resource is not found.
	ErrNotFound = userError("not found")
	// ErrInvalidLogin is returned when a user logs in with an unknown
	// combination of username and password.
	ErrInvalidLogin = userError("invalid username or password")
	// ErrUsernameExists is returned by Register if the user tries to make an
	// account with an existing username.
	ErrUsernameExists = userError("an account with the username already exists")
	// ErrNoSession is returned on an unknown or expired token session.
	ErrNoSession = userError("no such session found, possibly expired")
)

Error constants.

View Source
const MaxAssetSize = 1 << 20 // 1MB

MaxAssetSize is the maximum size in bytes that an asset should be.

View Source
const SnowflakeEpoch = int64(1577865600 * (time.Second / time.Millisecond))

SnowflakeEpoch is the Epoch start time of a Snowflake ID used in the application. It is in milliseconds.

Variables

View Source
var AllowedUsernameRunes = []runeutil.Validator{
	unicode.IsLetter,
	unicode.IsDigit,
	runeutil.AllowRunes('_', '-', '*', '$', '!', '.'),
}

AllowedUsernameRunes is a list of validators that validate a username. Its rules can be described as "letters and digits only with ., _, -, *, $ and !".

View Source
var (
	// UserLikedThrottle throttles the number of times the user can like a post
	// over 8 hours. It's mostly to prevent the user from spamming likes.
	UserLikedThrottle = Throttle{
		Bursts:   5,
		Duration: 8 * time.Hour,
	}
)

Functions

func IsUserError

func IsUserError(err error) bool

IsUserError returns true if the error is a user error.

func ListFoods

func ListFoods() map[foods.Category][]foods.Name

ListFoods lists all valid food preferences.

func ValidateUsername

func ValidateUsername(username string) error

ValidateUsername validates the username. Usernames must be 35 characters long and only contain runes that satisfy AllowedUsernameRunes.

Types

type AuthorizedServer

type AuthorizedServer interface {
	// Logout invalidates the authorizing token.
	Logout(context.Context) error

	PostServer() PostServer
	UserServer() UserServer
}

AuthorizedServer describes a service for a specific user session.

type AuthorizerServer

type AuthorizerServer interface {
	// Authorize authorizes the user using the given session token. The session
	// is returned if the token points to a valid user.
	Authorize(ctx context.Context, token string) (*Session, error)
}

AuthorizerServer describes a service for authorizing a session.

type Date

type Date struct {
	D uint8
	M uint8
	Y uint16
}

Date describes a Date with undefined time.

func (Date) IsZero

func (d Date) IsZero() bool

IsZero returns true if Date is zero-value (is 00/00/0000).

func (Date) MarshalJSON

func (d Date) MarshalJSON() ([]byte, error)

func (Date) String

func (d Date) String() string

String formats Date in "02 January 2006" format.

func (Date) Time

func (d Date) Time() time.Time

Time returns the date in local time.

func (*Date) UnmarshalJSON

func (d *Date) UnmarshalJSON(b []byte) error

type FileServer

type FileServer interface {
	fs.FS

	// Create creates a file with the content from the given Reader. The new
	// asset hash is returned, or an error if there's one. Create may be called
	// concurrently; the implementation should guarantee that everything is
	// atomic and that there is no collision.
	Create(s *Session, src io.Reader) (string, error)
}

FileServer describes a service for serving and creating files.

TODO: consider if we should keep track of which user uploaded which asset. Otherwise, we can smartly reference-count them.

type FoodPreferences

type FoodPreferences struct {
	// Likes is a list of categories of food that the user likes.
	Likes []foods.Category
	// Prefers maps each category that the user likes to a list of specific
	// foods that they've selected.
	Prefers map[foods.Category][]foods.Name
}

FoodPreferences describes a user's food preferences.

type ID

type ID = snowflake.ID

ID is the Snowflake ID type for an entity. An inherent property of Snowflake IDs is that creation time is embedded inside the ID itself. Thus, all IDs, when sorted, will be sorted according to creation time. Its underlying type is a 64-bit signed integer.

type LoginMetadata

type LoginMetadata struct {
	// UserAgent is the user-agent that the user was on when they logged in.
	UserAgent string
}

LoginMetadata is the metadata of each login or register operation. As with all metadata, everything in this structure is optional.

type LoginServer

type LoginServer interface {
	// Login authenticates the user by a username and password and returns a new
	// session.
	Login(ctx context.Context, username, password string, m LoginMetadata) (*Session, error)
	// Register registers a new user.
	Register(ctx context.Context, username, password string, m LoginMetadata) (*Session, error)
}

LoginServer describes a service serving Sessions.

type Post

type Post struct {
	ID ID
	// Username is the username of the user who posted the food item.
	Username string
	// CoverHash is the blur hash of the cover image.
	CoverHash string
	// Images is the list of image asset hashes for this food item. The first
	// image should be used as the cover.
	Images []string
	// Description contains the description of the food item.
	Description string
	// Tags is a list of food names that this post is relevant to. It can be
	// used for the recommendation algorithm.
	Tags []foods.Name
	// Location is the location where the post was made.
	Location string
	// Likes is the number of likes of this post.
	Likes int
}

Post describes a posted food item.

func (Post) Validate

func (p Post) Validate() error

Validate validates the Post.

type PostListing

type PostListing struct {
	Post
	// Liked is whether or not the current user has liked a post.
	Liked bool
}

PostListing describes a post listing returned by NextPosts. It contains information that are specific to the current user.

type PostServer

type PostServer interface {
	// Post queries a single post.
	Post(ctx context.Context, id ID) (*PostListing, error)
	// NextPosts returns the list of posts that the user will see next
	// starting from the given previous ID. If the ID is 0, then the top is
	// assumed.
	NextPosts(ctx context.Context, previousID ID) ([]PostListing, error)
	// LikedPosts returns the list of liked posts by the user.
	LikedPosts(ctx context.Context) ([]Post, error)
	// LikePost likes or unlikes the post with the given ID. The like belongs to
	// the logged in user.
	LikePost(ctx context.Context, id ID, like bool) error
	// DeletePosts deletes the given posts. Only the posts that belong to the
	// current user can be deleted.
	DeletePost(ctx context.Context, id ID) error
	// CreatePost creates a new post. The post's ID is ignored and a new one is
	// used. That ID is returned back.
	CreatePost(ctx context.Context, post Post) (ID, error)
}

PostServer is a service serving Posts.

type Self

type Self struct {
	User
	Birthday    Date
	Preferences FoodPreferences
}

Self extends User and contains private information about that user.

type Server

type Server interface {
	FileServer() FileServer
	LoginServer() LoginServer
	AuthorizerServer() AuthorizerServer
	AuthorizedServer(s *Session) AuthorizedServer
}

Server describes the top-level server information.

type Session

type Session struct {
	// Username identifies the user that the session belongs to.
	Username string
	// Token is the token of the session.
	Token string
	// Expiry is the time that the session token expires.
	Expiry time.Time
	// Metadata is the metadata that was created when the user first logged in.
	Metadata LoginMetadata
}

Self extends User to contain personal-sensitive information.

type Throttle

type Throttle struct {
	Bursts   int
	Duration time.Duration
}

Throttle describes a basic rate limit throttling. It allows n bursts over a duration.

func (*Throttle) NewLimiter

func (t *Throttle) NewLimiter() *rate.Limiter

NewLimiter creates a new rate.Limiter with the Throttle description.

type User

type User struct {
	// Username is the username which can contain spaces. All usernames must be
	// unique.
	Username string
	// DisplayName is the visible name that users actually see.
	DisplayName string
	// Avatar is the asset hash string that can be used to create a URL.
	Avatar string
	// Bio is the user biography (or description).
	Bio string
}

User describes a user.

func (User) Validate

func (u User) Validate() error

Validate validates User.

type UserLikedPosts

type UserLikedPosts struct {
	// Posts maps post IDs to the time that the user liked.
	Posts map[ID]time.Time
	// Remaining is the number of likes allowed by the user until the Expires
	// timestamp.
	Remaining int
	// Expires is the time that the rate limiter (the Remaining field)
	// replenishes.
	Expires time.Time
}

UserLikedPosts holds the list of foods that the user liked.

type UserPostPreferences

type UserPostPreferences struct {
	Post
	// LikedAt is not nil if the user has liked the post before.
	LikedAt *time.Time
}

UserPostPreferences extends Post to add information specific to a single user.

type UserServer

type UserServer interface {
	// User fetches the user given the ID. Use this to fetch other users.
	User(ctx context.Context, username string) (*User, error)
	// Self returns the current user.
	Self(context.Context) (*Self, error)
	// UpdateSelf updates the current user. This method should change everything
	// except the Username and Password.
	UpdateSelf(context.Context, *Self) error
	// ChangePassword changes the password of the current user. All existing
	// sessions except for this one should be invalidated.
	ChangePassword(ctx context.Context, newPassword string) error
}

UserServer describes a service serving Users.

Jump to

Keyboard shortcuts

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