alter primary keys to uuids and adjust the membership system

This commit is contained in:
Fran Jurmanović
2025-06-30 22:50:52 +02:00
parent caba5bae70
commit c17e7742ee
53 changed files with 12641 additions and 805 deletions

View File

@@ -3,14 +3,15 @@ package controller
import (
"acc-server-manager/local/service"
"acc-server-manager/local/utl/common"
"acc-server-manager/local/utl/logging"
"strings"
"acc-server-manager/local/utl/error_handler"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
)
type ApiController struct {
service *service.ApiService
service *service.ApiService
errorHandler *error_handler.ControllerErrorHandler
}
// NewApiController
@@ -23,7 +24,8 @@ type ApiController struct {
// *ApiController: Controller for "api" interactions
func NewApiController(as *service.ApiService, routeGroups *common.RouteGroups) *ApiController {
ac := &ApiController{
service: as,
service: as,
errorHandler: error_handler.NewControllerErrorHandler(),
}
routeGroups.Api.Get("/", ac.getFirst)
@@ -57,9 +59,9 @@ func (ac *ApiController) getFirst(c *fiber.Ctx) error {
func (ac *ApiController) getStatus(c *fiber.Ctx) error {
service := c.Params("service")
if service == "" {
serverId, err := c.ParamsInt("service")
if err != nil {
return c.Status(400).SendString(err.Error())
serverId := c.Params("service")
if _, err := uuid.Parse(serverId); err != nil {
return ac.errorHandler.HandleUUIDError(c, "server ID")
}
c.Locals("serverId", serverId)
} else {
@@ -67,7 +69,7 @@ func (ac *ApiController) getStatus(c *fiber.Ctx) error {
}
apiModel, err := ac.service.GetStatus(c)
if err != nil {
return c.Status(400).SendString(strings.ReplaceAll(err.Error(), "\x00", ""))
return ac.errorHandler.HandleServiceError(c, err)
}
return c.SendString(string(apiModel))
}
@@ -83,14 +85,13 @@ func (ac *ApiController) getStatus(c *fiber.Ctx) error {
func (ac *ApiController) startServer(c *fiber.Ctx) error {
model := new(Service)
if err := c.BodyParser(model); err != nil {
c.SendStatus(400)
return ac.errorHandler.HandleParsingError(c, err)
}
c.Locals("service", model.Name)
c.Locals("serverId", model.ServerId)
apiModel, err := ac.service.ApiStartServer(c)
if err != nil {
logging.Error(strings.ReplaceAll(err.Error(), "\x00", ""))
return c.Status(400).SendString(strings.ReplaceAll(err.Error(), "\x00", ""))
return ac.errorHandler.HandleServiceError(c, err)
}
return c.SendString(apiModel)
}
@@ -106,14 +107,13 @@ func (ac *ApiController) startServer(c *fiber.Ctx) error {
func (ac *ApiController) stopServer(c *fiber.Ctx) error {
model := new(Service)
if err := c.BodyParser(model); err != nil {
c.SendStatus(400)
return ac.errorHandler.HandleParsingError(c, err)
}
c.Locals("service", model.Name)
c.Locals("serverId", model.ServerId)
apiModel, err := ac.service.ApiStopServer(c)
if err != nil {
logging.Error(strings.ReplaceAll(err.Error(), "\x00", ""))
return c.Status(400).SendString(strings.ReplaceAll(err.Error(), "\x00", ""))
return ac.errorHandler.HandleServiceError(c, err)
}
return c.SendString(apiModel)
}
@@ -129,19 +129,18 @@ func (ac *ApiController) stopServer(c *fiber.Ctx) error {
func (ac *ApiController) restartServer(c *fiber.Ctx) error {
model := new(Service)
if err := c.BodyParser(model); err != nil {
c.SendStatus(400)
return ac.errorHandler.HandleParsingError(c, err)
}
c.Locals("service", model.Name)
c.Locals("serverId", model.ServerId)
apiModel, err := ac.service.ApiRestartServer(c)
if err != nil {
logging.Error(strings.ReplaceAll(err.Error(), "\x00", ""))
return c.Status(400).SendString(strings.ReplaceAll(err.Error(), "\x00", ""))
return ac.errorHandler.HandleServiceError(c, err)
}
return c.SendString(apiModel)
}
type Service struct {
Name string `json:"name" xml:"name" form:"name"`
ServerId int `json:"serverId" xml:"serverId" form:"serverId"`
ServerId string `json:"serverId" xml:"serverId" form:"serverId"`
}

View File

@@ -3,14 +3,17 @@ package controller
import (
"acc-server-manager/local/service"
"acc-server-manager/local/utl/common"
"acc-server-manager/local/utl/error_handler"
"acc-server-manager/local/utl/logging"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
)
type ConfigController struct {
service *service.ConfigService
apiService *service.ApiService
service *service.ConfigService
apiService *service.ApiService
errorHandler *error_handler.ControllerErrorHandler
}
// NewConfigController
@@ -23,8 +26,9 @@ type ConfigController struct {
// *ConfigController: Controller for "Config" interactions
func NewConfigController(as *service.ConfigService, routeGroups *common.RouteGroups, as2 *service.ApiService) *ConfigController {
ac := &ConfigController{
service: as,
apiService: as2,
service: as,
apiService: as2,
errorHandler: error_handler.NewControllerErrorHandler(),
}
routeGroups.Config.Put("/:file", ac.UpdateConfig)
@@ -46,24 +50,29 @@ func NewConfigController(as *service.ConfigService, routeGroups *common.RouteGro
// @Router /v1/server/{id}/config/{file} [put]
func (ac *ConfigController) UpdateConfig(c *fiber.Ctx) error {
restart := c.QueryBool("restart")
serverID, _ := c.ParamsInt("id")
serverID := c.Params("id")
// Validate UUID format
if _, err := uuid.Parse(serverID); err != nil {
return ac.errorHandler.HandleUUIDError(c, "server ID")
}
c.Locals("serverId", serverID)
var config map[string]interface{}
if err := c.BodyParser(&config); err != nil {
logging.Error("Invalid config format")
return c.Status(400).JSON(fiber.Map{"error": "Invalid config format"})
return ac.errorHandler.HandleParsingError(c, err)
}
ConfigModel, err := ac.service.UpdateConfig(c, &config)
if err != nil {
return c.Status(400).SendString(err.Error())
return ac.errorHandler.HandleServiceError(c, err)
}
logging.Info("restart: %v", restart)
if restart {
_, err := ac.apiService.ApiRestartServer(c)
if err != nil {
logging.Error(err.Error())
logging.ErrorWithContext("CONFIG_RESTART", "Failed to restart server after config update: %v", err)
}
}
@@ -82,8 +91,7 @@ func (ac *ConfigController) UpdateConfig(c *fiber.Ctx) error {
func (ac *ConfigController) GetConfig(c *fiber.Ctx) error {
Model, err := ac.service.GetConfig(c)
if err != nil {
logging.Error(err.Error())
return c.Status(400).SendString(err.Error())
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(Model)
}
@@ -99,8 +107,7 @@ func (ac *ConfigController) GetConfig(c *fiber.Ctx) error {
func (ac *ConfigController) GetConfigs(c *fiber.Ctx) error {
Model, err := ac.service.GetConfigs(c)
if err != nil {
logging.Error(err.Error())
return c.Status(400).SendString(err.Error())
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(Model)
}

View File

@@ -3,12 +3,14 @@ package controller
import (
"acc-server-manager/local/service"
"acc-server-manager/local/utl/common"
"acc-server-manager/local/utl/error_handler"
"github.com/gofiber/fiber/v2"
)
type LookupController struct {
service *service.LookupService
service *service.LookupService
errorHandler *error_handler.ControllerErrorHandler
}
// NewLookupController
@@ -21,7 +23,8 @@ type LookupController struct {
// *LookupController: Controller for "Lookup" interactions
func NewLookupController(as *service.LookupService, routeGroups *common.RouteGroups) *LookupController {
ac := &LookupController{
service: as,
service: as,
errorHandler: error_handler.NewControllerErrorHandler(),
}
routeGroups.Lookup.Get("/tracks", ac.GetTracks)
routeGroups.Lookup.Get("/car-models", ac.GetCarModels)
@@ -42,9 +45,7 @@ func NewLookupController(as *service.LookupService, routeGroups *common.RouteGro
func (ac *LookupController) GetTracks(c *fiber.Ctx) error {
result, err := ac.service.GetTracks(c)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error fetching tracks",
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(result)
}
@@ -59,9 +60,7 @@ func (ac *LookupController) GetTracks(c *fiber.Ctx) error {
func (ac *LookupController) GetCarModels(c *fiber.Ctx) error {
result, err := ac.service.GetCarModels(c)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error fetching car models",
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(result)
}
@@ -76,9 +75,7 @@ func (ac *LookupController) GetCarModels(c *fiber.Ctx) error {
func (ac *LookupController) GetDriverCategories(c *fiber.Ctx) error {
result, err := ac.service.GetDriverCategories(c)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error fetching driver categories",
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(result)
}
@@ -93,9 +90,7 @@ func (ac *LookupController) GetDriverCategories(c *fiber.Ctx) error {
func (ac *LookupController) GetCupCategories(c *fiber.Ctx) error {
result, err := ac.service.GetCupCategories(c)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error fetching cup categories",
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(result)
}
@@ -110,9 +105,7 @@ func (ac *LookupController) GetCupCategories(c *fiber.Ctx) error {
func (ac *LookupController) GetSessionTypes(c *fiber.Ctx) error {
result, err := ac.service.GetSessionTypes(c)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error fetching session types",
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(result)
}

View File

@@ -5,6 +5,7 @@ import (
"acc-server-manager/local/model"
"acc-server-manager/local/service"
"acc-server-manager/local/utl/common"
"acc-server-manager/local/utl/error_handler"
"acc-server-manager/local/utl/logging"
"context"
"fmt"
@@ -15,15 +16,17 @@ import (
// MembershipController handles API requests for membership.
type MembershipController struct {
service *service.MembershipService
auth *middleware.AuthMiddleware
service *service.MembershipService
auth *middleware.AuthMiddleware
errorHandler *error_handler.ControllerErrorHandler
}
// NewMembershipController creates a new MembershipController.
func NewMembershipController(service *service.MembershipService, auth *middleware.AuthMiddleware, routeGroups *common.RouteGroups) *MembershipController {
mc := &MembershipController{
service: service,
auth: auth,
service: service,
auth: auth,
errorHandler: error_handler.NewControllerErrorHandler(),
}
// Setup initial data for membership
if err := service.SetupInitialData(context.Background()); err != nil {
@@ -32,11 +35,15 @@ func NewMembershipController(service *service.MembershipService, auth *middlewar
routeGroups.Auth.Post("/login", mc.Login)
usersGroup := routeGroups.Api.Group("/users", mc.auth.Authenticate)
usersGroup := routeGroups.Membership
usersGroup.Use(mc.auth.Authenticate)
usersGroup.Post("/", mc.auth.HasPermission(model.MembershipCreate), mc.CreateUser)
usersGroup.Get("/", mc.auth.HasPermission(model.MembershipView), mc.ListUsers)
usersGroup.Get("/roles", mc.auth.HasPermission(model.RoleView), mc.GetRoles)
usersGroup.Get("/:id", mc.auth.HasPermission(model.MembershipView), mc.GetUser)
usersGroup.Put("/:id", mc.auth.HasPermission(model.MembershipEdit), mc.UpdateUser)
usersGroup.Delete("/:id", mc.auth.HasPermission(model.MembershipEdit), mc.DeleteUser)
routeGroups.Auth.Get("/me", mc.auth.Authenticate, mc.GetMe)
@@ -52,13 +59,13 @@ func (c *MembershipController) Login(ctx *fiber.Ctx) error {
var req request
if err := ctx.BodyParser(&req); err != nil {
return ctx.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request"})
return c.errorHandler.HandleParsingError(ctx, err)
}
logging.Debug("Login request received")
token, err := c.service.Login(ctx.UserContext(), req.Username, req.Password)
if err != nil {
return ctx.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": err.Error()})
return c.errorHandler.HandleAuthError(ctx, err)
}
return ctx.JSON(fiber.Map{"token": token})
@@ -74,12 +81,12 @@ func (mc *MembershipController) CreateUser(c *fiber.Ctx) error {
var req request
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request"})
return mc.errorHandler.HandleParsingError(c, err)
}
user, err := mc.service.CreateUser(c.UserContext(), req.Username, req.Password, req.Role)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return mc.errorHandler.HandleServiceError(c, err)
}
return c.JSON(user)
@@ -89,7 +96,7 @@ func (mc *MembershipController) CreateUser(c *fiber.Ctx) error {
func (mc *MembershipController) ListUsers(c *fiber.Ctx) error {
users, err := mc.service.ListUsers(c.UserContext())
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return mc.errorHandler.HandleServiceError(c, err)
}
return c.JSON(users)
@@ -99,12 +106,12 @@ func (mc *MembershipController) ListUsers(c *fiber.Ctx) error {
func (mc *MembershipController) GetUser(c *fiber.Ctx) error {
id, err := uuid.Parse(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid user ID"})
return mc.errorHandler.HandleUUIDError(c, "user ID")
}
user, err := mc.service.GetUser(c.UserContext(), id)
if err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
return mc.errorHandler.HandleNotFoundError(c, "User")
}
return c.JSON(user)
@@ -114,12 +121,12 @@ func (mc *MembershipController) GetUser(c *fiber.Ctx) error {
func (mc *MembershipController) GetMe(c *fiber.Ctx) error {
userID, ok := c.Locals("userID").(string)
if !ok || userID == "" {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Unauthorized"})
return mc.errorHandler.HandleAuthError(c, fmt.Errorf("unauthorized: user ID not found in context"))
}
user, err := mc.service.GetUserWithPermissions(c.UserContext(), userID)
if err != nil {
return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "User not found"})
return mc.errorHandler.HandleNotFoundError(c, "User")
}
// Sanitize the user object to not expose password
@@ -128,22 +135,47 @@ func (mc *MembershipController) GetMe(c *fiber.Ctx) error {
return c.JSON(user)
}
// DeleteUser deletes a user.
func (mc *MembershipController) DeleteUser(c *fiber.Ctx) error {
id, err := uuid.Parse(c.Params("id"))
if err != nil {
return mc.errorHandler.HandleUUIDError(c, "user ID")
}
err = mc.service.DeleteUser(c.UserContext(), id)
if err != nil {
return mc.errorHandler.HandleServiceError(c, err)
}
return c.SendStatus(fiber.StatusNoContent)
}
// UpdateUser updates a user.
func (mc *MembershipController) UpdateUser(c *fiber.Ctx) error {
id, err := uuid.Parse(c.Params("id"))
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid user ID"})
return mc.errorHandler.HandleUUIDError(c, "user ID")
}
var req service.UpdateUserRequest
if err := c.BodyParser(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request"})
return mc.errorHandler.HandleParsingError(c, err)
}
user, err := mc.service.UpdateUser(c.UserContext(), id, req)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return mc.errorHandler.HandleServiceError(c, err)
}
return c.JSON(user)
}
// GetRoles returns all available roles.
func (mc *MembershipController) GetRoles(c *fiber.Ctx) error {
roles, err := mc.service.GetAllRoles(c.UserContext())
if err != nil {
return mc.errorHandler.HandleServiceError(c, err)
}
return c.JSON(roles)
}

View File

@@ -5,18 +5,22 @@ import (
"acc-server-manager/local/model"
"acc-server-manager/local/service"
"acc-server-manager/local/utl/common"
"acc-server-manager/local/utl/error_handler"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
)
type ServerController struct {
service *service.ServerService
service *service.ServerService
errorHandler *error_handler.ControllerErrorHandler
}
// NewServerController initializes ServerController.
func NewServerController(ss *service.ServerService, routeGroups *common.RouteGroups, auth *middleware.AuthMiddleware) *ServerController {
ac := &ServerController{
service: ss,
service: ss,
errorHandler: error_handler.NewControllerErrorHandler(),
}
serverRoutes := routeGroups.Server
@@ -34,23 +38,26 @@ func NewServerController(ss *service.ServerService, routeGroups *common.RouteGro
func (ac *ServerController) GetAll(c *fiber.Ctx) error {
var filter model.ServerFilter
if err := common.ParseQueryFilter(c, &filter); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
})
return ac.errorHandler.HandleValidationError(c, err, "query_filter")
}
ServerModel, err := ac.service.GetAll(c, &filter)
if err != nil {
return c.Status(400).SendString(err.Error())
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(ServerModel)
}
// GetById returns a single server by its ID
func (ac *ServerController) GetById(c *fiber.Ctx) error {
serverID, _ := c.ParamsInt("id")
serverIDStr := c.Params("id")
serverID, err := uuid.Parse(serverIDStr)
if err != nil {
return ac.errorHandler.HandleUUIDError(c, "server ID")
}
ServerModel, err := ac.service.GetById(c, serverID)
if err != nil {
return c.Status(400).SendString(err.Error())
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(ServerModel)
}
@@ -59,48 +66,46 @@ func (ac *ServerController) GetById(c *fiber.Ctx) error {
func (ac *ServerController) CreateServer(c *fiber.Ctx) error {
server := new(model.Server)
if err := c.BodyParser(server); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
})
return ac.errorHandler.HandleParsingError(c, err)
}
ac.service.GenerateServerPath(server)
if err := ac.service.CreateServer(c, server); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(server)
}
// UpdateServer updates an existing server
func (ac *ServerController) UpdateServer(c *fiber.Ctx) error {
serverID, _ := c.ParamsInt("id")
serverIDStr := c.Params("id")
serverID, err := uuid.Parse(serverIDStr)
if err != nil {
return ac.errorHandler.HandleUUIDError(c, "server ID")
}
server := new(model.Server)
if err := c.BodyParser(server); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
})
return ac.errorHandler.HandleParsingError(c, err)
}
server.ID = uint(serverID)
server.ID = serverID
if err := ac.service.UpdateServer(c, server); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(server)
}
// DeleteServer deletes a server
func (ac *ServerController) DeleteServer(c *fiber.Ctx) error {
serverID, err := c.ParamsInt("id")
serverIDStr := c.Params("id")
serverID, err := uuid.Parse(serverIDStr)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid server ID"})
return ac.errorHandler.HandleUUIDError(c, "server ID")
}
if err := ac.service.DeleteServer(c, serverID); err != nil {
return c.Status(500).SendString(err.Error())
return ac.errorHandler.HandleServiceError(c, err)
}
return c.SendStatus(204)
}
}

View File

@@ -5,12 +5,14 @@ import (
"acc-server-manager/local/model"
"acc-server-manager/local/service"
"acc-server-manager/local/utl/common"
"acc-server-manager/local/utl/error_handler"
"github.com/gofiber/fiber/v2"
)
type StateHistoryController struct {
service *service.StateHistoryService
service *service.StateHistoryService
errorHandler *error_handler.ControllerErrorHandler
}
// NewStateHistoryController
@@ -23,7 +25,8 @@ type StateHistoryController struct {
// *StateHistoryController: Controller for "StateHistory" interactions
func NewStateHistoryController(as *service.StateHistoryService, routeGroups *common.RouteGroups, auth *middleware.AuthMiddleware) *StateHistoryController {
ac := &StateHistoryController{
service: as,
service: as,
errorHandler: error_handler.NewControllerErrorHandler(),
}
routeGroups.StateHistory.Use(auth.Authenticate)
@@ -43,16 +46,12 @@ func NewStateHistoryController(as *service.StateHistoryService, routeGroups *com
func (ac *StateHistoryController) GetAll(c *fiber.Ctx) error {
var filter model.StateHistoryFilter
if err := common.ParseQueryFilter(c, &filter); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
})
return ac.errorHandler.HandleValidationError(c, err, "query_filter")
}
result, err := ac.service.GetAll(c, &filter)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error retrieving state history",
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(result)
@@ -68,17 +67,13 @@ func (ac *StateHistoryController) GetAll(c *fiber.Ctx) error {
func (ac *StateHistoryController) GetStatistics(c *fiber.Ctx) error {
var filter model.StateHistoryFilter
if err := common.ParseQueryFilter(c, &filter); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": err.Error(),
})
return ac.errorHandler.HandleValidationError(c, err, "query_filter")
}
result, err := ac.service.GetStatistics(c, &filter)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"error": "Error retrieving state history statistics",
})
return ac.errorHandler.HandleServiceError(c, err)
}
return c.JSON(result)
}
}