Documentation ¶
Index ¶
- Constants
- Variables
- func IsUserError(err error) bool
- func ListFoods() map[foods.Category][]foods.Name
- func ValidateUsername(username string) error
- type AuthorizedServer
- type AuthorizerServer
- type Date
- type FileServer
- type FoodPreferences
- type ID
- type LoginMetadata
- type LoginServer
- type Post
- type PostListing
- type PostServer
- type Self
- type Server
- type Session
- type Throttle
- type User
- type UserLikedPosts
- type UserPostPreferences
- type UserServer
Constants ¶
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.
const MaxAssetSize = 1 << 20 // 1MB
MaxAssetSize is the maximum size in bytes that an asset should be.
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 ¶
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 !".
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 ¶
IsUserError returns true if the error is a user error.
func ValidateUsername ¶
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 ¶
Date describes a Date with undefined time.
func (Date) MarshalJSON ¶
func (*Date) UnmarshalJSON ¶
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 ¶
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.
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 ¶
Throttle describes a basic rate limit throttling. It allows n bursts over a duration.
func (*Throttle) NewLimiter ¶
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.
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.