We are making simple blog, so first thing we have to do is to implement some way for users to create account and log in. For now, we will just make simple struct User
that will be stored in memory. Latter we will connect our application with a database so we can store our data there.
First let's create new directory inside of internal/
which we will name store/
. This package will implement logic for storing all our data. Until we connect our app to database, we will use simple slice for storing users. In internal/store/
directory, let's create new file users.go
:
package store
type User struct {
Username string
Password string
}
var Users []*User
Remove /hello
test route from router.go
file and add new routes /signup
and /signin
:
package server
import (
"github.com/gin-gonic/gin"
)
func setRouter() *gin.Engine {
// Creates default gin router with Logger and Recovery middleware already attached
router := gin.Default()
// Enables automatic redirection if the current route can't be matched but a
// handler for the path with (without) the trailing slash exists.
router.RedirectTrailingSlash = true
// Create API route group
api := router.Group("/api")
{
api.POST("/signup", signUp)
api.POST("/signin", signIn)
}
router.NoRoute(func(ctx *gin.Context) { ctx.JSON(http.StatusNotFound, gin.H{}) })
return router
}
Handlers signUp
and signIn
that we are passing to router will be implemented in internal/server/user.go
file:
package server
import (
"net/http"
"rgb/internal/store"
"github.com/gin-gonic/gin"
)
func signUp(ctx *gin.Context) {
user := new(store.User)
if err := ctx.Bind(user); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"err": err.Error()})
return
}
store.Users = append(store.Users, user)
ctx.JSON(http.StatusOK, gin.H{
"msg": "Signed up successfully.",
"jwt": "123456789",
})
}
func signIn(ctx *gin.Context) {
user := new(store.User)
if err := ctx.Bind(user); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"err": err.Error()})
return
}
for _, u := range store.Users {
if u.Username == user.Username && u.Password == user.Password {
ctx.JSON(http.StatusOK, gin.H{
"msg": "Signed in successfully.",
"jwt": "123456789",
})
return
}
}
ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"err": "Sign in failed."})
}
Let's analyze what this code does. We create new variable of type User where we will store data user provided through our frontend. After that we are calling method Bind()
which will bind this form data to our User type variable. If this binding fails we immediately set error code and error message, and return from current function. If there were no errors, we will set response code to status OK and return JWT for authentication. For now we are returning only some dummy JWT so our frontend will work correctly, but latter we will change that with real JWT implementation. Now you can try to create new account, logout and login again. As you can see on pictures below, both routes are working.
Top comments (0)