nquest/pkg/controller/user.go

232 lines
5 KiB
Go

package controller
import (
"log"
"net/http"
"github.com/google/uuid"
"github.com/gorilla/sessions"
"github.com/labstack/echo-contrib/session"
"github.com/labstack/echo/v4"
"gitrepo.ru/neonxp/nquest/api"
"gitrepo.ru/neonxp/nquest/pkg/models"
"gitrepo.ru/neonxp/nquest/pkg/service"
"gitrepo.ru/neonxp/nquest/pkg/utils"
)
type User struct {
UserService *service.User
}
func (u *User) PostUserLogin(c echo.Context) error {
req := new(api.PostUserLoginJSONRequestBody)
if err := c.Bind(req); err != nil {
return err
}
user, err := u.UserService.Login(
c.Request().Context(),
req.Email,
req.Password,
)
if err != nil {
return c.JSON(http.StatusBadRequest, &api.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
}
if err := setUser(c, user); err != nil {
return c.JSON(http.StatusBadRequest, &api.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
}
return mapUser(c, user)
}
func (u *User) PostUserRegister(c echo.Context) error {
req := new(api.PostUserRegisterJSONRequestBody)
if err := c.Bind(req); err != nil {
return err
}
user, err := u.UserService.Register(
c.Request().Context(),
req.Username,
req.Email,
req.Password,
req.Password2,
)
if err != nil {
return c.JSON(http.StatusBadRequest, &api.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
}
if err := setUser(c, user); err != nil {
return c.JSON(http.StatusBadRequest, &api.ErrorResponse{
Code: http.StatusBadRequest,
Message: err.Error(),
})
}
return mapUser(c, user)
}
func (u *User) PostUserLogout(c echo.Context) error {
if err := setUser(c, nil); err != nil {
return err
}
return c.NoContent(http.StatusOK)
}
func (u *User) GetUser(c echo.Context) error {
user := u.UserService.GetUser(c)
if user == nil {
return c.JSON(http.StatusNotFound, &api.ErrorResponse{
Code: http.StatusNotFound,
Message: "User not found",
})
}
return mapUser(c, user)
}
// (GET /users)
func (u *User) GetUsers(c echo.Context) error {
list, err := u.UserService.List(c.Request().Context())
if err != nil {
return err
}
result := make(api.UsersListResponse, 0, len(list))
for _, u := range list {
level := utils.ExpToLevel(u.Experience)
finished := 0
for _, g := range u.Games {
if g.Finish {
finished++
}
}
result = append(result, api.UserShortView{
Experience: u.Experience,
GamesFinished: finished,
GamesStarted: len(u.Games),
Id: u.ID,
Level: level,
Username: u.Username,
})
}
return c.JSON(200, result)
}
// (GET /users/{uid})
func (s *User) GetUserInfo(c echo.Context, uid uuid.UUID) error {
user, err := s.UserService.GetUserByID(c.Request().Context(), uid)
if err != nil {
log.Println(err)
return echo.ErrNotFound
}
level := utils.ExpToLevel(user.Experience)
expToCur := utils.LevelToExp(level)
expToNext := utils.LevelToExp(level + 1)
games := make([]api.GameView, 0, len(user.Games))
for _, gc := range user.Games {
games = append(games, api.GameView{
Id: gc.GameID,
Title: gc.Game.Title,
Description: gc.Game.Description,
Type: api.MapGameTypeReverse(gc.Game.Type),
Icon: gc.Game.IconID,
})
}
res := &api.UserShortView{
ExpToCurrentLevel: &expToCur,
ExpToNextLevel: &expToNext,
Experience: user.Experience,
Games: &games,
GamesFinished: 0,
GamesStarted: 0,
Id: user.ID,
Level: level,
Username: user.Username,
}
return c.JSON(200, res)
}
func setUser(c echo.Context, user *models.User) error {
sess, err := session.Get("session", c)
if err != nil {
return err
}
if user == nil {
sess.Options = &sessions.Options{
Path: "/",
MaxAge: -86400 * 7,
HttpOnly: true,
}
if err := sess.Save(c.Request(), c.Response()); err != nil {
return err
}
return nil
}
sess.Options = &sessions.Options{
Path: "/",
MaxAge: 86400 * 7,
HttpOnly: true,
}
sess.Values["userID"] = user.ID.String()
if err := sess.Save(c.Request(), c.Response()); err != nil {
return err
}
return nil
}
func mapUser(c echo.Context, user *models.User) error {
games := make([]api.GameView, 0)
for _, gc := range user.Games {
games = append(games, api.GameView{
Id: gc.GameID,
Title: gc.Game.Title,
Description: gc.Game.Description,
Type: api.MapGameTypeReverse(gc.Game.Type),
Icon: gc.Game.IconID,
})
}
level := utils.ExpToLevel(user.Experience)
role := api.User
switch user.Role {
case models.RoleUser:
role = api.User
case models.RoleCreator:
role = api.Creator
case models.RoleAdmin:
role = api.Admin
}
return c.JSON(http.StatusOK, &api.UserResponse{
Id: user.ID,
Username: user.Username,
Email: user.Email,
Experience: user.Experience,
ExpToCurrentLevel: utils.LevelToExp(level),
ExpToNextLevel: utils.LevelToExp(level + 1),
Level: int(level),
Games: games,
Role: role,
})
}