Use gin-gonic instead of httprouter

This commit is contained in:
nemunaire 2022-07-09 19:42:00 +02:00
parent 7c719d9fd5
commit a203cdc36a
22 changed files with 1668 additions and 1392 deletions

153
users.go
View file

@ -1,49 +1,106 @@
package main
import (
"encoding/json"
"log"
"net/http"
"strconv"
"time"
"github.com/julienschmidt/httprouter"
"github.com/gin-gonic/gin"
)
var currentPromo uint = 0
func init() {
router.GET("/api/promos", apiHandler(
func(httprouter.Params, []byte) HTTPResponse {
return formatApiResponse(getPromos())
}, adminRestricted))
router.GET("/api/users", apiHandler(
func(httprouter.Params, []byte) HTTPResponse {
return formatApiResponse(getUsers())
}, adminRestricted))
router.GET("/api/users/:uid", apiHandler(userHandler(
func(u User, _ []byte) HTTPResponse {
return APIResponse{u}
}), loggedUser))
router.PUT("/api/users/:uid", apiHandler(userHandler(updateUser), adminRestricted))
router.DELETE("/api/users/:uid", apiHandler(userHandler(
func(u User, _ []byte) HTTPResponse {
return formatApiResponse(u.Delete())
}), adminRestricted))
func declareAPIAuthUsersRoutes(router *gin.RouterGroup) {
usersRoutes := router.Group("/users/:uid")
usersRoutes.Use(userHandler)
usersRoutes.Use(sameUserMiddleware)
usersRoutes.GET("", func(c *gin.Context) {
u := c.MustGet("user").(*User)
c.JSON(http.StatusOK, u)
})
declareAPIAuthSurveysRoutes(usersRoutes)
}
func userHandler(f func(User, []byte) HTTPResponse) func(httprouter.Params, []byte) HTTPResponse {
return func(ps httprouter.Params, body []byte) HTTPResponse {
if uid, err := strconv.Atoi(string(ps.ByName("uid"))); err != nil {
if user, err := getUserByLogin(ps.ByName("uid")); err != nil {
return APIErrorResponse{err: err}
} else {
return f(user, body)
}
} else if user, err := getUser(uid); err != nil {
return APIErrorResponse{err: err}
} else {
return f(user, body)
func declareAPIAdminUsersRoutes(router *gin.RouterGroup) {
router.GET("/promos", func(c *gin.Context) {
promos, err := getPromos()
if err != nil {
log.Println("Unable to getPromos:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieve promotions. Please try again later."})
return
}
c.JSON(http.StatusOK, promos)
})
router.GET("/users", func(c *gin.Context) {
users, err := getUsers()
if err != nil {
log.Println("Unable to getUsers:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieve users. Please try again later."})
return
}
c.JSON(http.StatusOK, users)
})
usersRoutes := router.Group("/users/:uid")
usersRoutes.Use(userHandler)
usersRoutes.PUT("", updateUser)
usersRoutes.DELETE("", func(c *gin.Context) {
u := c.MustGet("user").(*User)
if _, err := u.Delete(); err != nil {
log.Println("Unable to Delete user:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to delete the user. Please try again later."})
return
}
c.JSON(http.StatusOK, nil)
})
declareAPIAdminUserCorrectionsRoutes(usersRoutes)
declareAPIAdminUserQuestionsRoutes(usersRoutes)
}
func userHandler(c *gin.Context) {
var user *User
uid, err := strconv.Atoi(string(c.Param("uid")))
if err != nil {
user, err = getUserByLogin(c.Param("uid"))
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad user identifier."})
return
}
} else {
user, err = getUser(uid)
if err != nil {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"errmsg": "User not found."})
return
}
}
c.Set("user", user)
c.Next()
}
func sameUserMiddleware(c *gin.Context) {
user := c.MustGet("user").(*User)
loggeduser := c.MustGet("LoggedUser").(*User)
if user.Id != loggeduser.Id && !loggeduser.IsAdmin {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"errmsg": "Permission denied."})
return
}
c.Next()
}
type User struct {
@ -100,12 +157,14 @@ func getPromos() (promos []uint, err error) {
}
}
func getUser(id int) (u User, err error) {
func getUser(id int) (u *User, err error) {
u = new(User)
err = DBQueryRow("SELECT id_user, login, email, firstname, lastname, time, promo, groups, is_admin FROM users WHERE id_user=?", id).Scan(&u.Id, &u.Login, &u.Email, &u.Firstname, &u.Lastname, &u.Time, &u.Promo, &u.Groups, &u.IsAdmin)
return
}
func getUserByLogin(login string) (u User, err error) {
func getUserByLogin(login string) (u *User, err error) {
u = new(User)
err = DBQueryRow("SELECT id_user, login, email, firstname, lastname, time, promo, groups, is_admin FROM users WHERE login=?", login).Scan(&u.Id, &u.Login, &u.Email, &u.Firstname, &u.Lastname, &u.Time, &u.Promo, &u.Groups, &u.IsAdmin)
return
}
@ -116,14 +175,14 @@ func userExists(login string) bool {
return err == nil && z == 1
}
func NewUser(login string, email string, firstname string, lastname string, groups string) (User, error) {
func NewUser(login string, email string, firstname string, lastname string, groups string) (*User, error) {
t := time.Now()
if res, err := DBExec("INSERT INTO users (login, email, firstname, lastname, time, promo, groups) VALUES (?, ?, ?, ?, ?, ?, ?)", login, email, firstname, lastname, t, currentPromo, groups); err != nil {
return User{}, err
return nil, err
} else if sid, err := res.LastInsertId(); err != nil {
return User{}, err
return nil, err
} else {
return User{sid, login, email, firstname, lastname, t, currentPromo, groups, false}, nil
return &User{sid, login, email, firstname, lastname, t, currentPromo, groups, false}, nil
}
}
@ -166,10 +225,13 @@ func ClearUsers() (int64, error) {
}
}
func updateUser(current User, body []byte) HTTPResponse {
func updateUser(c *gin.Context) {
current := c.MustGet("user").(*User)
var new User
if err := json.Unmarshal(body, &new); err != nil {
return APIErrorResponse{err: err}
if err := c.ShouldBindJSON(&new); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return
}
current.Login = new.Login
@ -179,5 +241,12 @@ func updateUser(current User, body []byte) HTTPResponse {
current.Time = new.Time
current.Promo = new.Promo
current.Groups = new.Groups
return formatApiResponse(current.Update())
if u, err := current.Update(); err != nil {
log.Println("Unable to Update user:", err)
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to update the given user. Please try again later."})
return
} else {
c.JSON(http.StatusOK, u)
}
}