data

package
v0.0.0-...-f79a1d3 Latest Latest
Warning

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

Go to latest
Published: May 12, 2024 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ScopeActivation     = "activation"
	ScopeAuthentication = "authentication"
	ScopePasswordReset  = "password-reset"
)

ScopeActivation defines the scope of the token: 'activation', 'authentication', 'password-reset'

Variables

View Source
var (
	// ErrRecordNotFound is returned when a movie record doesn't exist in database.
	ErrRecordNotFound = errors.New("record not found")

	// ErrEditConflict is returned when a there is a data race, and we have an edit conflict.
	ErrEditConflict = errors.New("edit conflict")
)
View Source
var AnonymousUser = &User{}

We've created a new AnonymousUser variable, which holds a pointer to an empty User truct representing an inactivated user with no ID, name, email or password.

View Source
var (
	ErrDuplicateEmail = errors.New("duplicate email")
)
View Source
var ErrInvalidRuntimeFormat = errors.New("invalid runtime format")

ErrInvalidRuntimeFormat returns error when we are unable to parse or convert a JSON string successfully. This is used in our Runtime.UnmarshalJSON() method.

Functions

func ValidateEmail

func ValidateEmail(v *validator.Validator, email string)

ValidateEmail checks that the Email field is not an empty string and that it matches the regex for email addresses, validator.EmailRX.

func ValidateFilters

func ValidateFilters(v *validator.Validator, f Filters)

ValidateFilters runs validation checks on the Filters type.

func ValidateMovie

func ValidateMovie(v *validator.Validator, movie *Movie)

ValidateMovie runs validation checks on the Movie type.

func ValidatePasswordPlaintext

func ValidatePasswordPlaintext(v *validator.Validator, password string)

ValidatePasswordPlaintext validtes that the password is not an empty string and is between 8 and 72 bytes long.

func ValidateTokenPlaintext

func ValidateTokenPlaintext(v *validator.Validator, tokenPlaintext string)

func ValidateUser

func ValidateUser(v *validator.Validator, user *User)

Types

type Filters

type Filters struct {
	Page         int
	PageSize     int
	Sort         string
	SortSafeList []string // A list of allowed values for the Sort field:

}

type Metadata

type Metadata struct {
	CurrentPage  int `json:"current_page,omitempty"`
	PageSize     int `json:"page_size,omitempty"`
	FirstPage    int `json:"first_page,omitempty"`
	LastPage     int `json:"last_page,omitempty"`
	TotalRecords int `json:"total_records,omitempty"`
}

Metadata holds pagination metadata.

type MockMovieModel

type MockMovieModel struct{}

func (MockMovieModel) Delete

func (m MockMovieModel) Delete(id int64) error

func (MockMovieModel) Get

func (m MockMovieModel) Get(id int64) (*Movie, error)

func (MockMovieModel) Insert

func (m MockMovieModel) Insert(movie *Movie) error

func (MockMovieModel) Update

func (m MockMovieModel) Update(movie *Movie) error

type Models

type Models struct {
	Movies      MovieModel
	Users       UserModel
	Tokens      TokenModel
	Permissions PermissionModel
}

Models struct is a single convenient container to hold and represent all our database models.

func NewModels

func NewModels(db *sql.DB) Models

type Models2

type Models2 struct {
	// Set the Movies field to be an interface containing the methods that both the
	// 'real' model and mock model need to support.
	Movies interface {
		Insert(movie *Movie) error
		Get(id int64) (*Movie, error)
		Update(movie *Movie) error
		Delete(id int64) error
	}
}

func NewMockModels

func NewMockModels() Models2

Create a helper function which returns a Models instance containing the mock models // only.

type Movie

type Movie struct {
	ID        int64     `json:"id"` // Unique integer ID for the movie
	CreatedAt time.Time `json:"-"`  // Use the - directive to never export in JSON output
	Title     string    `json:"title"`
	Year      int32     `json:"year,omitempty"` // Movie release year0
	Runtime   Runtime   `json:"runtime,omitempty"`
	Genres    []string  `json:"genres,omitempty"`
	Version   int32     `json:"version"` // The version number starts at 1 and is incremented each

}

Movie type whose fields describe the movie. Note that the Runtime type uses a custom Runtime type instead of int32. Furthermore, the omitempty directive on the Runtime type will still work on this: if the Runtime field has the underlying value 0, then it will be considered empty and omitted -- and the MarshalJSON() method won't be called.

type Movie2

type Movie2 struct {
	ID        int64     `json:"id"`
	CreatedAt time.Time `json:"-"`
	Title     string    `json:"title"`
	Year      int32     `json:"year,omitempty"`
	Runtime   int32     `json:"-"`
	Genres    []string  `json:"genres,omitempty"`
	Version   int32     `json:"version"`
}

Notice that we use the - directive on the Runtime field, so that it never appears in the JSON output.

func (Movie2) MarshalJSON

func (m Movie2) MarshalJSON() ([]byte, error)

type MovieModel

type MovieModel struct {
	DB       *sql.DB
	InfoLog  *log.Logger
	ErrorLog *log.Logger
}

MovieModel struct wraps a sql.DB connection pool and allows us to work with Movie struct type and the movies table in our database.

func (MovieModel) Delete

func (m MovieModel) Delete(id int64) error

Delete is a placeholder method for deleting a specific record in the movies table.

func (MovieModel) Get

func (m MovieModel) Get(id int64) (*Movie, error)

Get fetches a record from the movies table and returns the corresponding Movie struct. It cancels the query call if the SQL query does not finish within 3 seconds.

func (MovieModel) GetAll

func (m MovieModel) GetAll(title string, genres []string, filters Filters) ([]*Movie, Metadata, error)

GetAll returns a list of movies in the form of a string of Movie type based on a set of provided filters.

func (MovieModel) Insert

func (m MovieModel) Insert(movie *Movie) error

Insert accepts a pointer to a movie struct, which should contain the data for the new record and inserts the record into the movies table.

func (MovieModel) Update

func (m MovieModel) Update(movie *Movie) error

Update updates a specific movie in the movies table.

type PermissionModel

type PermissionModel struct {
	DB       *sql.DB
	InfoLog  *log.Logger
	ErrorLog *log.Logger
}

func (PermissionModel) AddForUser

func (m PermissionModel) AddForUser(userID int64, codes ...string) error

AddForUser adds the permissions with the provided codes for a specific user. We're using a variadic parameter for the codes so that we can assign multiple permissions in a single call.

func (PermissionModel) GetAllForUser

func (m PermissionModel) GetAllForUser(userID int64) (Permissions, error)

GetAllForUser returns all permission codes for a specific user in a Permissions slice.

type Permissions

type Permissions []string

Permissions holds the permission codes for a single user.

func (Permissions) Include

func (p Permissions) Include(code string) bool

Include checks whether the Permissions slice contains a specific permission code.

type Runtime

type Runtime int32

func (Runtime) MarshalJSON

func (r Runtime) MarshalJSON() ([]byte, error)

We’re deliberately using a value receiver for our MarshalJSON() method rather than a pointerreceiverlikefunc (r *Runtime) MarshalJSON(). This gives us more flexibility because it means that our custom JSON encoding will work on both Runtime values and pointers to Runtime values.

func (*Runtime) UnmarshalJSON

func (r *Runtime) UnmarshalJSON(jsonValue []byte) error

UnmarshalJSON ensures that Runtime satisfies the json.Unmarshaler interface. IMPORTANT: because UnmarshalJSON() needs to modify the receiver (our Runtime type), we must use a pointer receiver for this to work correctly. Otherwise, we will only be modifying a copy (which is then discarded when this method returns).

type Token

type Token struct {
	// PLain text is the cryptographically-secure random token string before it is hashed.
	Plaintext string `json:"token"`
	/*
		The hash column will contain a SHA-256 hash of the activation token.
		We will only store a hash of the activation token in our database — not the
		activation token itself. Because our activation token is going to be a
		high-entropy random string (128 bits) — rather than something low entropy
		like a typical user password — it is sufficient to use a fast algorithm
		like SHA-256 to create the hash, instead of a slow algorithm like bcrypt.
	*/
	Hash   []byte    `json:"-"`
	UserID int64     `json:"-"`      // UserID is the ID of the user this token belongs to.
	Expiry time.Time `json:"expiry"` // Expiry is the time when the token will expire(3 days after creation).

	// Scope is the scope of the token. This will be used to differentiate between
	// activation tokens and authentication tokens.
	Scope string `json:"-"`
}

Token represents a token record in our tokens table. Note, it includes plaintext and hashed version of the token.

type TokenModel

type TokenModel struct {
	DB       *sql.DB
	InfoLog  *log.Logger
	ErrorLog *log.Logger
}

TokenModel struct wraps a sql.DB connection pool and allows us to work with the Token struct type and the tokens table in our database.

func (TokenModel) DeleteAllForUser

func (m TokenModel) DeleteAllForUser(scope string, userID int64) error

DeleteAllForUser deletes all tokens for a specific user and scope.

func (TokenModel) Insert

func (m TokenModel) Insert(token *Token) error

Insert inserts a new token record into the tokens table.

func (TokenModel) New

func (m TokenModel) New(userID int64, ttl time.Duration, scope string) (*Token, error)

New creates a new token and inserts the token record into the tokens table.

type User

type User struct {
	ID        int64     `json:"id"`
	CreatedAt time.Time `json:"created_at"`
	Name      string    `json:"name"`
	Email     string    `json:"email"`
	Password  password  `json:"-"`
	Activated bool      `json:"activated"`
	Version   int       `json:"-"`
}

User type whose fields describe a user. Note, that we use the json:"-" struct tag to prevent the Password and Version fields from appearing in any output when we encode it to JSON. Also, notice that the Password field uses the custom password type defined below.

func (*User) IsAnonymous

func (u *User) IsAnonymous() bool

Check if a User instance is the AnonymousUser.

type UserModel

type UserModel struct {
	DB       *sql.DB
	InfoLog  *log.Logger
	ErrorLog *log.Logger
}

UserModel struct wraps a sql.DB connection pool and allows us to work with the User struct type and the users table in our database.

func (UserModel) GetByEmail

func (m UserModel) GetByEmail(email string) (*User, error)

GetByEmail retrieves the User details from the database based on the user's email address. Because we have a UNIQUE constraint on the email column, this query will only return one record, or none at all, upon which we return a ErrRecordNotFound error).

func (UserModel) GetForToken

func (m UserModel) GetForToken(tokenScope, tokenPlaintext string) (*User, error)

Retrieve the user associated with a token GetForToken retrieves a user record from the users table for an associated token and token scope in the tokens table.

func (UserModel) Insert

func (m UserModel) Insert(user *User) error

Insert inserts a new record in the users table in our database for the user. Note, that the id, created_at, and version fields are all automatically generated by our database, so we use use the RETURNING clause to read them into the User struct after the insert. Also, we check if our table already contains the same email address and if so return ErrDuplicateEmail error.

func (UserModel) Update

func (m UserModel) Update(user *User) error

Update updates the details for a specific user in the users table. Note, we check against the version field to help prevent any race conditions during the request cycle. Also, we check for a violation of the "user_email_key" constraint.

Jump to

Keyboard shortcuts

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