Skip to content
This repository has been archived by the owner on Jun 29, 2024. It is now read-only.

Commit

Permalink
Merge pull request #8 from leapkit/refining-validations
Browse files Browse the repository at this point in the history
feature: updating the validations API
  • Loading branch information
paganotoni committed May 12, 2024
2 parents 99e5268 + d808aa9 commit df595da
Show file tree
Hide file tree
Showing 14 changed files with 607 additions and 819 deletions.
100 changes: 100 additions & 0 deletions docs/features/validations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: Form Validation
index: 3
---

Leapkit provides the `form/validate` package that offers a flexible and reusable way to validate form data by defining a set of validation rules that can be applied to form fields.

### How to Use

Validations are a set of rules stablished for different fields passed in the request. You can define these Validations to be used in your http handlers by and call the `form.Validate` function passing the `req` (*http.Request) and handling the `validate.Errors` returned. Example:

```go

passwordExp := regexp.MustCompile(`^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$)`)

rules := validate.Fields(
validate.Field("email", validate.Required("email is required")),
validate.Field(
"password",
validate.Required("password is required"),
validate.MatchRegex(
passwordExp,
"Password must contain at least 8 characters, one uppercase letter, one lowercase letter, one number and one special character",
),
)

verrs := form.Validate(req, rules)
if len(verrs) > 0 {
// handle validation errors...
}
```

### Built-in Rules

You can build your set of rules for each validation by using the package's built-in functions.

```go
// General Rules:
func Required(message ...string) Rule

// String Rules:
func Matches(field string, message ...string) Rule
func MatchRegex(re *regexp.Regexp, message ...string) Rule
func MinLength(min int, message ...string) Rule
func MaxLength(max int, message ...string) Rule
func WithinOptions(options []string, message ...string) Rule

// Number Rules:
func EqualTo(value float64, message ...string) Rule
func LessThan(value float64, message ...string) Rule
func LessThanOrEqualTo(value float64, message ...string) Rule
func GreaterThan(value float64, message ...string) Rule
func GreaterThanOrEqualTo(value float64, message ...string) Rule

// UUID Rule:
func ValidUUID(message ...string) Rule

// Time Rules:
func TimeEqualTo(u time.Time, message ...string) Rule
func TimeBefore(u time.Time, message ...string) Rule
func TimeBeforeOrEqualTo(u time.Time, message ...string) Rule
func TimeAfter(u time.Time, message ...string) Rule
func TimeAfterOrEqualTo(u time.Time, message ...string) Rule
```

### Custom validation Rules

Alternatively, you can create your own validation rules. Example:

```go
func IsUnique(db *sqlx.DB ) func([]string) error {
return func(emails []string) error {
query := "SELECT EXISTS(SELECT 1 FROM users WHERE email = $1)"
stmt, err := db.Prepare(query)
if err != nil {
return err
}

for _, email := range emails {
var exists bool
if err := stmt.QueryRow(email).Scan(&exists); err != nil {
return err
}

if exists {
return fmt.Errorf("email '%s' already exists.", email)
}
}

return nil
}
}

// ...
rules := validation.Fields(
validation.Field("email", validate.Required(), IsUnique(db))
...
)
...
```
5 changes: 2 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
title: "LeapKit"
title: "About LeapKit"
index: 1
---

LeapKit is a collection of tools to help you build your next application with Go. Its main purpose is to make web development as fast and simple as possible and is targeted at web developers trying to take the leap and launch their next project.
LeapKit is a collection of packages to help you build your next application with Go. Its main purpose is to make web development as fast and simple as possible and is targeted at web developers trying to take the leap and launch their next project.

There are two main components of LeapKit, the LeapKit Core and the LeapKit Template, these two make the use of LeapKit possible.

Expand All @@ -13,5 +13,4 @@ The LeapKit Core contains the Go libraries that facilitate the web development.


## LeapKit Template

The LeapKit Template contains a starting point folder structure using the LeapKit core. It provides some CLI commands to facilitate the web development of your apps, the template can be copied and modified with the `gonew` command.
Empty file added docs/tools/gloves.md
Empty file.
107 changes: 0 additions & 107 deletions docs/validations.md

This file was deleted.

34 changes: 32 additions & 2 deletions form/form.go → form/decode.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package form

import (
"fmt"
"net/http"
"strings"

Expand All @@ -18,8 +19,8 @@ var (
func init() {
// Register custom and common type decoder
// functions.
decoder.RegisterCustomTypeFunc(DecodeUUID, uuid.UUID{})
decoder.RegisterCustomTypeFunc(DecodeUUIDSlice, []uuid.UUID{})
decoder.RegisterCustomTypeFunc(decodeUUID, uuid.UUID{})
decoder.RegisterCustomTypeFunc(decodeUUIDSlice, []uuid.UUID{})
}

// RegisterCustomTypeFunc registers a custom type decoder func for a type.
Expand Down Expand Up @@ -54,3 +55,32 @@ func Decode(r *http.Request, dst interface{}) error {
err := decoder.Decode(dst, r.Form)
return err
}

// decodeUUID a single uuid from a string
// and returns an error if there is a problem
func decodeUUID(vals []string) (interface{}, error) {
uu, err := uuid.FromString(vals[0])
if err != nil {
err = fmt.Errorf("error parsing uuid: %w", err)
}

return uu, err
}

// decodeUUIDSlice decodes a slice of uuids from a string
// and returns an error if there is a problem
func decodeUUIDSlice(vals []string) (interface{}, error) {
var uus []uuid.UUID

for _, val := range vals {
uuid, err := uuid.FromString(val)
if err != nil {
err = fmt.Errorf("error parsing uuid: %w", err)
return nil, err
}

uus = append(uus, uuid)
}

return uus, nil
}
Loading

0 comments on commit df595da

Please sign in to comment.