215 lines
6.6 KiB
Go
215 lines
6.6 KiB
Go
package handlers
|
|
|
|
import (
|
|
"time"
|
|
"ttime/internal/types"
|
|
|
|
"github.com/gofiber/fiber/v2/log"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/golang-jwt/jwt/v5"
|
|
)
|
|
|
|
// Register is a simple handler that registers a new user
|
|
//
|
|
// @Summary Register a new user
|
|
// @Description Register a new user
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Produce plain
|
|
// @Param NewUser body types.NewUser true "User to register"
|
|
// @Success 200 {string} string "User added"
|
|
// @Failure 400 {string} string "Bad request"
|
|
// @Failure 500 {string} string "Internal server error"
|
|
// @Router /register [post]
|
|
func (gs *GState) Register(c *fiber.Ctx) error {
|
|
u := new(types.NewUser)
|
|
if err := c.BodyParser(u); err != nil {
|
|
log.Warn("Error parsing body")
|
|
return c.Status(400).SendString(err.Error())
|
|
}
|
|
|
|
log.Info("Adding user:", u.Username)
|
|
if err := gs.Db.AddUser(u.Username, u.Password); err != nil {
|
|
log.Warn("Error adding user:", err)
|
|
return c.Status(500).SendString(err.Error())
|
|
}
|
|
|
|
log.Info("User added:", u.Username)
|
|
return c.Status(200).SendString("User added")
|
|
}
|
|
|
|
// This path should obviously be protected in the future
|
|
// UserDelete deletes a user from the database
|
|
//
|
|
// @Summary Deletes a user
|
|
// @Description UserDelete deletes a user from the database
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Produce plain
|
|
// @Success 200 {string} string "User deleted"
|
|
// @Failure 403 {string} string "You can only delete yourself"
|
|
// @Failure 500 {string} string "Internal server error"
|
|
// @Failure 401 {string} string "Unauthorized"
|
|
// @Router /userdelete/{username} [delete]
|
|
func (gs *GState) UserDelete(c *fiber.Ctx) error {
|
|
// Read from path parameters
|
|
username := c.Params("username")
|
|
|
|
// Read username from Locals
|
|
auth_username := c.Locals("user").(*jwt.Token).Claims.(jwt.MapClaims)["name"].(string)
|
|
|
|
if username != auth_username {
|
|
log.Info("User tried to delete another user")
|
|
return c.Status(403).SendString("You can only delete yourself")
|
|
}
|
|
|
|
if err := gs.Db.RemoveUser(username); err != nil {
|
|
log.Warn("Error deleting user:", err)
|
|
return c.Status(500).SendString(err.Error())
|
|
}
|
|
|
|
log.Info("User deleted:", username)
|
|
return c.Status(200).SendString("User deleted")
|
|
}
|
|
|
|
// Login is a simple login handler that returns a JWT token
|
|
//
|
|
// @Summary login
|
|
// @Description logs the user in and returns a jwt token
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Param NewUser body types.NewUser true "login info"
|
|
// @Produce plain
|
|
// @Success 200 Token types.Token "Successfully signed token for user"
|
|
// @Failure 400 {string} string "Bad request"
|
|
// @Failure 401 {string} string "Unauthorized"
|
|
// @Failure 500 {string} string "Internal server error"
|
|
// @Router /login [post]
|
|
func (gs *GState) Login(c *fiber.Ctx) error {
|
|
// The body type is identical to a NewUser
|
|
|
|
u := new(types.NewUser)
|
|
if err := c.BodyParser(u); err != nil {
|
|
log.Warn("Error parsing body")
|
|
return c.Status(400).SendString(err.Error())
|
|
}
|
|
|
|
log.Info("Username logging in:", u.Username)
|
|
if !gs.Db.CheckUser(u.Username, u.Password) {
|
|
log.Info("User not found")
|
|
return c.SendStatus(fiber.StatusUnauthorized)
|
|
}
|
|
|
|
// Create the Claims
|
|
claims := jwt.MapClaims{
|
|
"name": u.Username,
|
|
"admin": false,
|
|
"exp": time.Now().Add(time.Hour * 72).Unix(),
|
|
}
|
|
|
|
// Create token
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
|
log.Info("Token created for user:", u.Username)
|
|
|
|
// Generate encoded token and send it as response.
|
|
t, err := token.SignedString([]byte("secret"))
|
|
if err != nil {
|
|
log.Warn("Error signing token")
|
|
return c.SendStatus(fiber.StatusInternalServerError)
|
|
}
|
|
|
|
println("Successfully signed token for user:", u.Username)
|
|
return c.JSON(types.Token{Token: t})
|
|
}
|
|
|
|
// LoginRenew is a simple handler that renews the token
|
|
//
|
|
// @Summary renews the users token
|
|
// @Description renews the users token
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Produce plain
|
|
// @Success 200 Token types.Token "Successfully signed token for user"
|
|
// @Failure 401 {string} string "Unauthorized"
|
|
// @Failure 500 {string} string "Internal server error"
|
|
// @Router /loginerenew [post]
|
|
func (gs *GState) LoginRenew(c *fiber.Ctx) error {
|
|
user := c.Locals("user").(*jwt.Token)
|
|
|
|
log.Info("Renewing token for user:", user.Claims.(jwt.MapClaims)["name"])
|
|
|
|
claims := user.Claims.(jwt.MapClaims)
|
|
claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
|
|
renewed := jwt.MapClaims{
|
|
"name": claims["name"],
|
|
"admin": claims["admin"],
|
|
"exp": claims["exp"],
|
|
}
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, renewed)
|
|
t, err := token.SignedString([]byte("secret"))
|
|
if err != nil {
|
|
log.Warn("Error signing token")
|
|
return c.SendStatus(fiber.StatusInternalServerError)
|
|
}
|
|
|
|
log.Info("Successfully renewed token for user:", user.Claims.(jwt.MapClaims)["name"])
|
|
return c.JSON(types.Token{Token: t})
|
|
}
|
|
|
|
// ListAllUsers is a handler that returns a list of all users in the application database
|
|
//
|
|
// @Summary Lists users
|
|
// @Description lists all users
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Produce plain
|
|
// @Success 200 {json} json "Successfully signed token for user"
|
|
// @Failure 401 {string} string "Unauthorized"
|
|
// @Failure 500 {string} string "Internal server error"
|
|
// @Router /users/all [get]
|
|
func (gs *GState) ListAllUsers(c *fiber.Ctx) error {
|
|
// Get all users from the database
|
|
users, err := gs.Db.GetAllUsersApplication()
|
|
if err != nil {
|
|
log.Info("Error getting users from db:", err) // Debug print
|
|
return c.Status(500).SendString(err.Error())
|
|
}
|
|
|
|
log.Info("Returning all users")
|
|
// Return the list of users as JSON
|
|
return c.JSON(users)
|
|
}
|
|
|
|
// @Summary promote user to admin
|
|
// @Description promote chosen user to admin
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Produce plain
|
|
// @Param NewUser body types.NewUser true "user info"
|
|
// @Success 200 {json} json "Successfully prometed user"
|
|
// @Failure 400 {string} string "bad request"
|
|
// @Failure 401 {string} string "Unauthorized"
|
|
// @Failure 500 {string} string "Internal server error"
|
|
// @Router /promoteToAdmin [post]
|
|
func (gs *GState) PromoteToAdmin(c *fiber.Ctx) error {
|
|
// Extract the username from the request body
|
|
var newUser types.NewUser
|
|
if err := c.BodyParser(&newUser); err != nil {
|
|
return c.Status(400).SendString("Bad request")
|
|
}
|
|
username := newUser.Username
|
|
|
|
log.Info("Promoting user to admin:", username) // Debug print
|
|
|
|
// Promote the user to a site admin in the database
|
|
if err := gs.Db.PromoteToAdmin(username); err != nil {
|
|
log.Info("Error promoting user to admin:", err) // Debug print
|
|
return c.Status(500).SendString(err.Error())
|
|
}
|
|
|
|
log.Info("User promoted to admin successfully:", username) // Debug print
|
|
|
|
// Return a success message
|
|
return c.SendStatus(fiber.StatusOK)
|
|
}
|