Skip to content

Instantly share code, notes, and snippets.

@ferdiunal
Created April 4, 2022 21:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ferdiunal/8780cc38498c6745c98277ae5e8fe449 to your computer and use it in GitHub Desktop.
Save ferdiunal/8780cc38498c6745c98277ae5e8fe449 to your computer and use it in GitHub Desktop.
func (u *UserHandlers) CreateUser(c *fiber.Ctx) error {
errors := ValidateErrorResponse{}
errors.Errors = make(library.ValidateError)
user := models.User{}
v := validator.New()
body := new(CreateUserBody)
if err := c.BodyParser(body); err != nil {
return c.Status(422).JSON(
fiber.Map{
"message": err.Error(),
},
)
}
err := v.Struct(*body)
if err != nil {
errors.Errors = GetValidationErrors(err)
}
usernameCheck := user.FindBy("username", body.Username)
if usernameCheck == nil {
errors.Errors["username"] = append(errors.Errors["username"], "validation.unique")
}
emailCheck := user.FindBy("email", body.Username)
if emailCheck == nil {
errors.Errors["email"] = append(errors.Errors["email"], "validation.unique")
}
phoneCheck := user.FindBy("phone", body.Username)
if phoneCheck == nil {
errors.Errors["phone"] = append(errors.Errors["phone"], "validation.unique")
}
if len(errors.Errors) > 0 {
errors.Message = "validation error"
return c.Status(422).JSON(errors)
}
user.Username = body.Username
user.Name = body.Name
user.Phone = body.Phone
user.Email = body.Email
user.Password = library.Bcrypt(body.Password)
if err := user.Create(); err != nil {
return c.Status(422).JSON(
fiber.Map{
"message": err.Error(),
},
)
}
return c.Status(202).JSON(fiber.Map{
"message": "user created",
})
}
package main
import (
"flag"
"fmt"
"log"
"os"
"github.com/ferdiunal/moon/handlers/auth"
"github.com/ferdiunal/moon/handlers/users"
"github.com/ferdiunal/moon/library"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress"
"github.com/gofiber/fiber/v2/middleware/limiter"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/pprof"
"github.com/gofiber/fiber/v2/middleware/recover"
"github.com/gofiber/fiber/v2/middleware/requestid"
"github.com/gofiber/helmet/v2"
"github.com/joho/godotenv"
"github.com/kamva/mgm/v3"
"go.mongodb.org/mongo-driver/mongo/options"
)
var (
port = flag.String("port", ":5000", "Port to listen on")
prod = flag.Bool("prod", false, "Enable prefork in Production")
)
type ValidateError map[string][]string
type ValidateErrorResponse struct {
Errors ValidateError `json:"errors"`
Message string `json:"message"`
}
func GetValidationErrors(err error) ValidateError {
errors := make(ValidateError)
for _, err := range err.(validator.ValidationErrors) {
errors[strings.ToLower(err.Field())] = append(
errors[strings.ToLower(err.Field())],
fmt.Sprintf("validation.%v", strings.ToLower(err.Tag())),
)
}
return errors
}
func App() *fiber.App {
// Parse command-line flags
flag.Parse()
godotenv.Load()
env := os.Getenv("APP_ENV")
url := os.Getenv("MONGO_LOCAL_URL")
if env == "test" {
url = os.Getenv("MONGO_TEST_URL")
} else if env == "prod" {
url = os.Getenv("MONGO_PROD_URL")
}
fmt.Println(url)
_ = mgm.SetDefaultConfig(nil, "moon", options.Client().ApplyURI(url))
fmt.Println("database init", url)
// Create fiber app
app := fiber.New(fiber.Config{
Prefork: *prod, // go run app.go -prod
})
// Middleware
app.Use(helmet.New())
app.Use(recover.New())
app.Use(logger.New())
app.Use(pprof.New())
app.Use(compress.New(compress.Config{
Level: compress.LevelBestSpeed, // 1
}))
app.Use(limiter.New())
app.Use(requestid.New(
requestid.Config{
Header: "X-Request-Id",
Generator: func() string {
return library.GeneratePlainTextToken()
},
},
))
// Create a /v1 endpoint
v1 := app.Group("/v1")
auth.NewAuthHandlers(v1)
users.NewUserHandlers(v1)
// app.Get("/monitor", monitor.New())
// Setup static files
app.Static("/", "./static/public")
// Handle not founds
// app.Use(handlers.NotFound)
// Listen on port 3000
return app
}
func main() {
app := App()
log.Fatal(app.Listen(*port)) // go run app.go -port=:3000
}
package main
import (
"bytes"
"encoding/json"
"io"
"io/ioutil"
"net/http/httptest"
"testing"
"github.com/ferdiunal/moon/library"
)
func TestUserHandlers_CreateUser(t *testing.T) {
app := App()
body := `{
"username": "administrator",
"email": "admin@admin.com",
"name": "Administrator",
"phone": "55555555555",
"password": "admin123"
}`
req := httptest.NewRequest("POST", "/v1/users", bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
res, err := app.Test(req)
if err != nil {
t.Fatal(err)
}
if res.StatusCode == 422 {
t.Errorf("Validate status code %d, got %d", 202, res.StatusCode)
validateErrorResponse(t, res.Body)
} else if res.StatusCode != 202 {
t.Errorf("Validate status code %d, got %d", 202, res.StatusCode)
v, _ := ioutil.ReadAll(res.Body)
t.Log(string(v))
}
}
func validateErrorResponse(t *testing.T, res io.ReadCloser) {
response := new(ValidateErrorResponse)
if err := json.NewDecoder(res).Decode(response); err != nil {
t.Fatal(err)
}
if len(response.Errors) > 0 {
t.Error(response.Message)
for key, value := range response.Errors {
t.Errorf("%s: %s", key, value)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment