feat: batch update config endpoint
This commit is contained in:
@@ -2,6 +2,7 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"acc-server-manager/local/middleware"
|
"acc-server-manager/local/middleware"
|
||||||
|
"acc-server-manager/local/model"
|
||||||
"acc-server-manager/local/service"
|
"acc-server-manager/local/service"
|
||||||
"acc-server-manager/local/utl/common"
|
"acc-server-manager/local/utl/common"
|
||||||
"acc-server-manager/local/utl/error_handler"
|
"acc-server-manager/local/utl/error_handler"
|
||||||
@@ -34,6 +35,7 @@ func NewConfigController(as *service.ConfigService, routeGroups *common.RouteGro
|
|||||||
|
|
||||||
configGroup := routeGroups.Config
|
configGroup := routeGroups.Config
|
||||||
configGroup.Use(auth.Authenticate)
|
configGroup.Use(auth.Authenticate)
|
||||||
|
configGroup.Patch("/", ac.UpdateAllConfigs)
|
||||||
configGroup.Put("/:file", ac.UpdateConfig)
|
configGroup.Put("/:file", ac.UpdateConfig)
|
||||||
configGroup.Get("/:file", ac.GetConfig)
|
configGroup.Get("/:file", ac.GetConfig)
|
||||||
configGroup.Get("/", ac.GetConfigs)
|
configGroup.Get("/", ac.GetConfigs)
|
||||||
@@ -41,6 +43,54 @@ func NewConfigController(as *service.ConfigService, routeGroups *common.RouteGro
|
|||||||
return ac
|
return ac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateAllConfigs updates all configuration files
|
||||||
|
//
|
||||||
|
// @Summary Bulk update all server configuration files
|
||||||
|
// @Description Update multiple ACC server configuration files in one request. Null or omitted sections are skipped.
|
||||||
|
// @Tags Server Configuration
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param id path string true "Server ID (UUID format)"
|
||||||
|
// @Param restart query bool false "Restart the server after update"
|
||||||
|
// @Param override query bool false "Override instead of merging with existing config"
|
||||||
|
// @Param content body model.ConfigurationsUpdateRequest true "Configuration sections to update (null sections are skipped)"
|
||||||
|
// @Success 200 {array} model.Config "List of updated config audit records"
|
||||||
|
// @Failure 400 {object} error_handler.ErrorResponse "Invalid request or JSON format"
|
||||||
|
// @Failure 401 {object} error_handler.ErrorResponse "Unauthorized"
|
||||||
|
// @Failure 403 {object} error_handler.ErrorResponse "Insufficient permissions"
|
||||||
|
// @Failure 404 {object} error_handler.ErrorResponse "Server not found"
|
||||||
|
// @Failure 500 {object} error_handler.ErrorResponse "Internal server error"
|
||||||
|
// @Security BearerAuth
|
||||||
|
// @Router /server/{id}/config [patch]
|
||||||
|
func (ac *ConfigController) UpdateAllConfigs(c *fiber.Ctx) error {
|
||||||
|
restart := c.QueryBool("restart")
|
||||||
|
serverID := c.Params("id")
|
||||||
|
|
||||||
|
if _, err := uuid.Parse(serverID); err != nil {
|
||||||
|
return ac.errorHandler.HandleUUIDError(c, "server ID")
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Locals("serverId", serverID)
|
||||||
|
|
||||||
|
var req model.ConfigurationsUpdateRequest
|
||||||
|
if err := c.BodyParser(&req); err != nil {
|
||||||
|
return ac.errorHandler.HandleParsingError(c, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
configs, err := ac.service.UpdateAllConfigs(c, &req)
|
||||||
|
if err != nil {
|
||||||
|
return ac.errorHandler.HandleServiceError(c, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if restart {
|
||||||
|
if _, err := ac.apiService.ServiceControlRestartServer(c); err != nil {
|
||||||
|
logging.ErrorWithContext("CONFIG_RESTART", "Failed to restart server after bulk config update: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(configs)
|
||||||
|
}
|
||||||
|
|
||||||
// updateConfig returns Config
|
// updateConfig returns Config
|
||||||
//
|
//
|
||||||
// @Summary Update server configuration file
|
// @Summary Update server configuration file
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ type Configurations struct {
|
|||||||
Settings ServerSettings `json:"settings"`
|
Settings ServerSettings `json:"settings"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConfigurationsUpdateRequest struct {
|
||||||
|
Configuration *map[string]interface{} `json:"configuration"`
|
||||||
|
AssistRules *map[string]interface{} `json:"assistRules"`
|
||||||
|
Event *map[string]interface{} `json:"event"`
|
||||||
|
EventRules *map[string]interface{} `json:"eventRules"`
|
||||||
|
Settings *map[string]interface{} `json:"settings"`
|
||||||
|
}
|
||||||
|
|
||||||
type ServerSettings struct {
|
type ServerSettings struct {
|
||||||
ServerName string `json:"serverName"`
|
ServerName string `json:"serverName"`
|
||||||
AdminPassword string `json:"adminPassword"`
|
AdminPassword string `json:"adminPassword"`
|
||||||
|
|||||||
@@ -91,6 +91,62 @@ func (as *ConfigService) SetServerService(serverService *ServerService) {
|
|||||||
// context.Context: Application context
|
// context.Context: Application context
|
||||||
// Returns:
|
// Returns:
|
||||||
// string: Application version
|
// string: Application version
|
||||||
|
func (as *ConfigService) UpdateAllConfigs(ctx *fiber.Ctx, req *model.ConfigurationsUpdateRequest) ([]*model.Config, error) {
|
||||||
|
serverID := ctx.Locals("serverId").(string)
|
||||||
|
override := ctx.QueryBool("override", false)
|
||||||
|
|
||||||
|
serverUUID, err := uuid.Parse(serverID)
|
||||||
|
if err != nil {
|
||||||
|
logging.Error("Invalid server ID format: %v", err)
|
||||||
|
return nil, fmt.Errorf("invalid server ID format")
|
||||||
|
}
|
||||||
|
|
||||||
|
server, err := as.serverRepository.GetByID(ctx.UserContext(), serverUUID)
|
||||||
|
if err != nil {
|
||||||
|
logging.Error("Server not found")
|
||||||
|
return nil, fmt.Errorf("server not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
type configEntry struct {
|
||||||
|
fileName string
|
||||||
|
body *map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
entries := []configEntry{
|
||||||
|
{ConfigurationJson, req.Configuration},
|
||||||
|
{AssistRulesJson, req.AssistRules},
|
||||||
|
{EventJson, req.Event},
|
||||||
|
{EventRulesJson, req.EventRules},
|
||||||
|
{SettingsJson, req.Settings},
|
||||||
|
}
|
||||||
|
|
||||||
|
var results []*model.Config
|
||||||
|
for _, entry := range entries {
|
||||||
|
if entry.body == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
oldDataUTF8, newData, err := as.updateConfigFiles(ctx.UserContext(), server, entry.fileName, entry.body, override)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
result := as.repository.UpdateConfig(ctx.UserContext(), &model.Config{
|
||||||
|
ServerID: serverUUID,
|
||||||
|
ConfigFile: entry.fileName,
|
||||||
|
OldConfig: string(oldDataUTF8),
|
||||||
|
NewConfig: string(newData),
|
||||||
|
ChangedAt: time.Now(),
|
||||||
|
})
|
||||||
|
results = append(results, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(results) > 0 {
|
||||||
|
as.configCache.InvalidateServerCache(serverID)
|
||||||
|
as.serverService.StartAccServerRuntime(server)
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (as *ConfigService) UpdateConfig(ctx *fiber.Ctx, body *map[string]interface{}) (*model.Config, error) {
|
func (as *ConfigService) UpdateConfig(ctx *fiber.Ctx, body *map[string]interface{}) (*model.Config, error) {
|
||||||
serverID := ctx.Locals("serverId").(string)
|
serverID := ctx.Locals("serverId").(string)
|
||||||
configFile := ctx.Params("file")
|
configFile := ctx.Params("file")
|
||||||
|
|||||||
Reference in New Issue
Block a user