diff --git a/docs/docs.go b/docs/docs.go index 824ca81..9cd0a9c 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -33,13 +33,15 @@ const docTemplate = `{ } } } - }, + } + }, + "/v1/api/restart": { "post": { - "description": "Return API", + "description": "Restarts service", "tags": [ "api" ], - "summary": "Return API", + "summary": "Restart service", "parameters": [ { "description": "required", @@ -63,6 +65,325 @@ const docTemplate = `{ } } } + }, + "/v1/api/start": { + "post": { + "description": "Starts service", + "tags": [ + "api" + ], + "summary": "Start service", + "parameters": [ + { + "description": "required", + "name": "name", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/api/stop": { + "post": { + "description": "Stops service", + "tags": [ + "api" + ], + "summary": "Stop service", + "parameters": [ + { + "description": "required", + "name": "name", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/api/{service}": { + "get": { + "description": "Returns service status", + "tags": [ + "api" + ], + "summary": "Return service status", + "parameters": [ + { + "type": "string", + "description": "required", + "name": "service", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/car-models": { + "get": { + "description": "Return CarModels Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return CarModels Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/cup-categories": { + "get": { + "description": "Return CupCategories Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return CupCategories Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/driver-categories": { + "get": { + "description": "Return DriverCategories Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return DriverCategories Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/session-types": { + "get": { + "description": "Return SessionTypes Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return SessionTypes Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/tracks": { + "get": { + "description": "Return Tracks Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return Tracks Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/server": { + "get": { + "description": "Return Servers", + "tags": [ + "Server" + ], + "summary": "Return Servers", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/server/{id}/config": { + "get": { + "description": "Return Config files", + "tags": [ + "Config" + ], + "summary": "Return Configs", + "parameters": [ + { + "type": "number", + "description": "required", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/server/{id}/config/{file}": { + "get": { + "description": "Returns Config file", + "tags": [ + "Config" + ], + "summary": "Return Config file", + "parameters": [ + { + "type": "number", + "description": "required", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "required", + "name": "file", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "put": { + "description": "Updates config", + "tags": [ + "Config" + ], + "summary": "Update config", + "parameters": [ + { + "type": "number", + "description": "required", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "required", + "name": "file", + "in": "path", + "required": true + }, + { + "description": "required", + "name": "content", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } } } }` diff --git a/docs/swagger.json b/docs/swagger.json index 3b5c47d..64b58ca 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -22,13 +22,15 @@ } } } - }, + } + }, + "/v1/api/restart": { "post": { - "description": "Return API", + "description": "Restarts service", "tags": [ "api" ], - "summary": "Return API", + "summary": "Restart service", "parameters": [ { "description": "required", @@ -52,6 +54,325 @@ } } } + }, + "/v1/api/start": { + "post": { + "description": "Starts service", + "tags": [ + "api" + ], + "summary": "Start service", + "parameters": [ + { + "description": "required", + "name": "name", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/api/stop": { + "post": { + "description": "Stops service", + "tags": [ + "api" + ], + "summary": "Stop service", + "parameters": [ + { + "description": "required", + "name": "name", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/api/{service}": { + "get": { + "description": "Returns service status", + "tags": [ + "api" + ], + "summary": "Return service status", + "parameters": [ + { + "type": "string", + "description": "required", + "name": "service", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/car-models": { + "get": { + "description": "Return CarModels Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return CarModels Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/cup-categories": { + "get": { + "description": "Return CupCategories Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return CupCategories Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/driver-categories": { + "get": { + "description": "Return DriverCategories Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return DriverCategories Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/session-types": { + "get": { + "description": "Return SessionTypes Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return SessionTypes Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/lookup/tracks": { + "get": { + "description": "Return Tracks Lookup", + "tags": [ + "Lookup" + ], + "summary": "Return Tracks Lookup", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/server": { + "get": { + "description": "Return Servers", + "tags": [ + "Server" + ], + "summary": "Return Servers", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/server/{id}/config": { + "get": { + "description": "Return Config files", + "tags": [ + "Config" + ], + "summary": "Return Configs", + "parameters": [ + { + "type": "number", + "description": "required", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + }, + "/v1/server/{id}/config/{file}": { + "get": { + "description": "Returns Config file", + "tags": [ + "Config" + ], + "summary": "Return Config file", + "parameters": [ + { + "type": "number", + "description": "required", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "required", + "name": "file", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "put": { + "description": "Updates config", + "tags": [ + "Config" + ], + "summary": "Update config", + "parameters": [ + { + "type": "number", + "description": "required", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "required", + "name": "file", + "in": "path", + "required": true + }, + { + "description": "required", + "name": "content", + "in": "body", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } } } } \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml index ea12a0a..0624c9a 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -14,8 +14,28 @@ paths: summary: Return API tags: - api + /v1/api/{service}: + get: + description: Returns service status + parameters: + - description: required + in: path + name: service + required: true + type: string + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return service status + tags: + - api + /v1/api/restart: post: - description: Return API + description: Restarts service parameters: - description: required in: body @@ -30,7 +50,197 @@ paths: items: type: string type: array - summary: Return API + summary: Restart service tags: - api + /v1/api/start: + post: + description: Starts service + parameters: + - description: required + in: body + name: name + required: true + schema: + type: string + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Start service + tags: + - api + /v1/api/stop: + post: + description: Stops service + parameters: + - description: required + in: body + name: name + required: true + schema: + type: string + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Stop service + tags: + - api + /v1/lookup/car-models: + get: + description: Return CarModels Lookup + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return CarModels Lookup + tags: + - Lookup + /v1/lookup/cup-categories: + get: + description: Return CupCategories Lookup + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return CupCategories Lookup + tags: + - Lookup + /v1/lookup/driver-categories: + get: + description: Return DriverCategories Lookup + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return DriverCategories Lookup + tags: + - Lookup + /v1/lookup/session-types: + get: + description: Return SessionTypes Lookup + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return SessionTypes Lookup + tags: + - Lookup + /v1/lookup/tracks: + get: + description: Return Tracks Lookup + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return Tracks Lookup + tags: + - Lookup + /v1/server: + get: + description: Return Servers + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return Servers + tags: + - Server + /v1/server/{id}/config: + get: + description: Return Config files + parameters: + - description: required + in: path + name: id + required: true + type: number + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return Configs + tags: + - Config + /v1/server/{id}/config/{file}: + get: + description: Returns Config file + parameters: + - description: required + in: path + name: id + required: true + type: number + - description: required + in: path + name: file + required: true + type: string + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Return Config file + tags: + - Config + put: + description: Updates config + parameters: + - description: required + in: path + name: id + required: true + type: number + - description: required + in: path + name: file + required: true + type: string + - description: required + in: body + name: content + required: true + schema: + type: string + responses: + "200": + description: OK + schema: + items: + type: string + type: array + summary: Update config + tags: + - Config swagger: "2.0" diff --git a/local/api/api.go b/local/api/api.go index 7887b3e..2b65c16 100644 --- a/local/api/api.go +++ b/local/api/api.go @@ -26,7 +26,10 @@ func Init(di *dig.Container, app *fiber.App) { }) routeGroups := &common.RouteGroups{ - Api: groups.Group("/api"), + Api: groups.Group("/api"), + Server: groups.Group("/server"), + Config: groups.Group("/server/:id").Group("/config"), + Lookup: groups.Group("/lookup"), } routeGroups.Api.Use(basicAuthConfig) diff --git a/local/controller/api.go b/local/controller/api.go index 4e0eeb3..bddfee6 100644 --- a/local/controller/api.go +++ b/local/controller/api.go @@ -25,7 +25,10 @@ func NewApiController(as *service.ApiService, routeGroups *common.RouteGroups) * } routeGroups.Api.Get("/", ac.getFirst) - routeGroups.Api.Post("/", ac.startServer) + routeGroups.Api.Get("/:service", ac.getStatus) + routeGroups.Api.Post("/start", ac.startServer) + routeGroups.Api.Post("/stop", ac.stopServer) + routeGroups.Api.Post("/restart", ac.restartServer) return ac } @@ -42,14 +45,30 @@ func (ac *ApiController) getFirst(c *fiber.Ctx) error { return c.SendString(apiModel.Api) } -// startServer returns API +// getStatus returns service status // -// @Summary Return API -// @Description Return API +// @Summary Return service status +// @Description Returns service status +// @Param service path string true "required" +// @Tags api +// @Success 200 {array} string +// @Router /v1/api/{service} [get] +func (ac *ApiController) getStatus(c *fiber.Ctx) error { + apiModel, err := ac.service.GetStatus(c) + if err != nil { + return c.Status(400).SendString(err.Error()) + } + return c.SendString(apiModel) +} + +// startServer starts service +// +// @Summary Start service +// @Description Starts service // @Param name body string true "required" // @Tags api // @Success 200 {array} string -// @Router /v1/api [post] +// @Router /v1/api/start [post] func (ac *ApiController) startServer(c *fiber.Ctx) error { model := new(Service) if err := c.BodyParser(model); err != nil { @@ -58,7 +77,49 @@ func (ac *ApiController) startServer(c *fiber.Ctx) error { c.Locals("service", model.Name) apiModel, err := ac.service.ApiStartServer(c) if err != nil { - return c.SendStatus(400) + return c.Status(400).SendString(err.Error()) + } + return c.SendString(apiModel) +} + +// stopServer stops service +// +// @Summary Stop service +// @Description Stops service +// @Param name body string true "required" +// @Tags api +// @Success 200 {array} string +// @Router /v1/api/stop [post] +func (ac *ApiController) stopServer(c *fiber.Ctx) error { + model := new(Service) + if err := c.BodyParser(model); err != nil { + c.SendStatus(400) + } + c.Locals("service", model.Name) + apiModel, err := ac.service.ApiStopServer(c) + if err != nil { + return c.Status(400).SendString(err.Error()) + } + return c.SendString(apiModel) +} + +// restartServer returns API +// +// @Summary Restart service +// @Description Restarts service +// @Param name body string true "required" +// @Tags api +// @Success 200 {array} string +// @Router /v1/api/restart [post] +func (ac *ApiController) restartServer(c *fiber.Ctx) error { + model := new(Service) + if err := c.BodyParser(model); err != nil { + c.SendStatus(400) + } + c.Locals("service", model.Name) + apiModel, err := ac.service.ApiRestartServer(c) + if err != nil { + return c.Status(400).SendString(err.Error()) } return c.SendString(apiModel) } diff --git a/local/controller/config.go b/local/controller/config.go new file mode 100644 index 0000000..43e964b --- /dev/null +++ b/local/controller/config.go @@ -0,0 +1,89 @@ +package controller + +import ( + "acc-server-manager/local/service" + "acc-server-manager/local/utl/common" + + "github.com/gofiber/fiber/v2" +) + +type ConfigController struct { + service *service.ConfigService +} + +// NewConfigController +// Initializes ConfigController. +// +// Args: +// *services.ConfigService: Config service +// *Fiber.RouterGroup: Fiber Router Group +// Returns: +// *ConfigController: Controller for "Config" interactions +func NewConfigController(as *service.ConfigService, routeGroups *common.RouteGroups) *ConfigController { + ac := &ConfigController{ + service: as, + } + + routeGroups.Config.Put("/:file", ac.updateConfig) + routeGroups.Config.Get("/:file", ac.getConfig) + routeGroups.Config.Get("/", ac.getConfigs) + + return ac +} + +// updateConfig returns Config +// +// @Summary Update config +// @Description Updates config +// @Param id path number true "required" +// @Param file path string true "required" +// @Param content body string true "required" +// @Tags Config +// @Success 200 {array} string +// @Router /v1/server/{id}/config/{file} [put] +func (ac *ConfigController) updateConfig(c *fiber.Ctx) error { + + var config map[string]interface{} + if err := c.BodyParser(&config); err != nil { + return c.Status(400).JSON(fiber.Map{"error": "Invalid config format"}) + } + + ConfigModel, err := ac.service.UpdateConfig(c, &config) + if err != nil { + return c.Status(400).SendString(err.Error()) + } + return c.JSON(ConfigModel) +} + +// getConfig returns Config +// +// @Summary Return Config file +// @Description Returns Config file +// @Param id path number true "required" +// @Param file path string true "required" +// @Tags Config +// @Success 200 {array} string +// @Router /v1/server/{id}/config/{file} [get] +func (ac *ConfigController) getConfig(c *fiber.Ctx) error { + Model, err := ac.service.GetConfig(c) + if err != nil { + return c.Status(400).SendString(err.Error()) + } + return c.JSON(Model) +} + +// getConfigs returns Config +// +// @Summary Return Configs +// @Description Return Config files +// @Param id path number true "required" +// @Tags Config +// @Success 200 {array} string +// @Router /v1/server/{id}/config [get] +func (ac *ConfigController) getConfigs(c *fiber.Ctx) error { + Model, err := ac.service.GetConfigs(c) + if err != nil { + return c.Status(400).SendString(err.Error()) + } + return c.JSON(Model) +} diff --git a/local/controller/controller.go b/local/controller/controller.go index 2e48b00..1871830 100644 --- a/local/controller/controller.go +++ b/local/controller/controller.go @@ -24,6 +24,21 @@ func InitializeControllers(c *dig.Container) { if err != nil { panic("unable to initialize api controller") } + + err = c.Invoke(NewConfigController) + if err != nil { + panic("unable to initialize config controller") + } + + err = c.Invoke(NewServerController) + if err != nil { + panic("unable to initialize server controller") + } + + err = c.Invoke(NewLookupController) + if err != nil { + panic("unable to initialize lookup controller") + } } // FilteredResponse diff --git a/local/controller/lookup.go b/local/controller/lookup.go new file mode 100644 index 0000000..c41ea00 --- /dev/null +++ b/local/controller/lookup.go @@ -0,0 +1,93 @@ +package controller + +import ( + "acc-server-manager/local/service" + "acc-server-manager/local/utl/common" + + "github.com/gofiber/fiber/v2" +) + +type LookupController struct { + service *service.LookupService +} + +// NewLookupController +// Initializes LookupController. +// +// Args: +// *services.LookupService: Lookup service +// *Fiber.RouterGroup: Fiber Router Group +// Returns: +// *LookupController: Controller for "Lookup" interactions +func NewLookupController(as *service.LookupService, routeGroups *common.RouteGroups) *LookupController { + ac := &LookupController{ + service: as, + } + routeGroups.Lookup.Get("/tracks", ac.getTracks) + routeGroups.Lookup.Get("/car-models", ac.getCarModels) + routeGroups.Lookup.Get("/driver-categories", ac.getDriverCategories) + routeGroups.Lookup.Get("/cup-categories", ac.getCupCategories) + routeGroups.Lookup.Get("/session-types", ac.getSessionTypes) + + return ac +} + +// getTracks returns Tracks +// +// @Summary Return Tracks Lookup +// @Description Return Tracks Lookup +// @Tags Lookup +// @Success 200 {array} string +// @Router /v1/lookup/tracks [get] +func (ac *LookupController) getTracks(c *fiber.Ctx) error { + LookupModel := ac.service.GetTracks(c) + return c.JSON(LookupModel) +} + +// getCarModels returns CarModels +// +// @Summary Return CarModels Lookup +// @Description Return CarModels Lookup +// @Tags Lookup +// @Success 200 {array} string +// @Router /v1/lookup/car-models [get] +func (ac *LookupController) getCarModels(c *fiber.Ctx) error { + LookupModel := ac.service.GetCarModels(c) + return c.JSON(LookupModel) +} + +// getDriverCategories returns DriverCategories +// +// @Summary Return DriverCategories Lookup +// @Description Return DriverCategories Lookup +// @Tags Lookup +// @Success 200 {array} string +// @Router /v1/lookup/driver-categories [get] +func (ac *LookupController) getDriverCategories(c *fiber.Ctx) error { + LookupModel := ac.service.GetDriverCategories(c) + return c.JSON(LookupModel) +} + +// getCupCategories returns CupCategories +// +// @Summary Return CupCategories Lookup +// @Description Return CupCategories Lookup +// @Tags Lookup +// @Success 200 {array} string +// @Router /v1/lookup/cup-categories [get] +func (ac *LookupController) getCupCategories(c *fiber.Ctx) error { + LookupModel := ac.service.GetCupCategories(c) + return c.JSON(LookupModel) +} + +// getSessionTypes returns SessionTypes +// +// @Summary Return SessionTypes Lookup +// @Description Return SessionTypes Lookup +// @Tags Lookup +// @Success 200 {array} string +// @Router /v1/lookup/session-types [get] +func (ac *LookupController) getSessionTypes(c *fiber.Ctx) error { + LookupModel := ac.service.GetSessionTypes(c) + return c.JSON(LookupModel) +} diff --git a/local/controller/server.go b/local/controller/server.go new file mode 100644 index 0000000..99865d3 --- /dev/null +++ b/local/controller/server.go @@ -0,0 +1,42 @@ +package controller + +import ( + "acc-server-manager/local/service" + "acc-server-manager/local/utl/common" + + "github.com/gofiber/fiber/v2" +) + +type ServerController struct { + service *service.ServerService +} + +// NewServerController +// Initializes ServerController. +// +// Args: +// *services.ServerService: Server service +// *Fiber.RouterGroup: Fiber Router Group +// Returns: +// *ServerController: Controller for "Server" interactions +func NewServerController(as *service.ServerService, routeGroups *common.RouteGroups) *ServerController { + ac := &ServerController{ + service: as, + } + + routeGroups.Server.Get("/", ac.getAll) + + return ac +} + +// getAll returns Servers +// +// @Summary Return Servers +// @Description Return Servers +// @Tags Server +// @Success 200 {array} string +// @Router /v1/server [get] +func (ac *ServerController) getAll(c *fiber.Ctx) error { + ServerModel := ac.service.GetAll(c) + return c.JSON(ServerModel) +} diff --git a/local/model/api.go b/local/model/api.go index 8ce20a3..9ec7cb7 100644 --- a/local/model/api.go +++ b/local/model/api.go @@ -3,3 +3,9 @@ package model type ApiModel struct { Api string `json:"api"` } + +// ServiceStatus represents a Windows service state +type ServiceStatus struct { + Name string `json:"name"` + Status string `json:"status"` // "running", "stopped", "pending" +} diff --git a/local/model/config.go b/local/model/config.go new file mode 100644 index 0000000..22b0ef2 --- /dev/null +++ b/local/model/config.go @@ -0,0 +1,21 @@ +package model + +import "time" + +// Config tracks configuration modifications +type Config struct { + ID uint `gorm:"primaryKey"` + ServerID uint `gorm:"not null"` + ConfigFile string `gorm:"not null"` // e.g. "settings.json" + OldConfig string `gorm:"type:text"` + NewConfig string `gorm:"type:text"` + ChangedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"` +} + +type Configurations struct { + Configuration map[string]interface{} + Entrylist map[string]interface{} + Event map[string]interface{} + EventRules map[string]interface{} + Settings map[string]interface{} +} diff --git a/local/model/lookup.go b/local/model/lookup.go new file mode 100644 index 0000000..4f303cc --- /dev/null +++ b/local/model/lookup.go @@ -0,0 +1,32 @@ +package model + +// Track represents a track and its capacity +type Track struct { + Name string `json:"track" gorm:"primaryKey;size:50"` + UniquePitBoxes int `json:"unique_pit_boxes"` + PrivateServerSlots int `json:"private_server_slots"` +} + +// CarModel represents a car model mapping +type CarModel struct { + Value int `json:"value" gorm:"primaryKey"` + CarModel string `json:"car_model"` +} + +// DriverCategory represents driver skill categories +type DriverCategory struct { + Value int `json:"value" gorm:"primaryKey"` + Category string `json:"category"` +} + +// CupCategory represents championship cup categories +type CupCategory struct { + Value int `json:"value" gorm:"primaryKey"` + Category string `json:"category"` +} + +// SessionType represents session types +type SessionType struct { + Value int `json:"value" gorm:"primaryKey"` + SessionType string `json:"session_type"` +} diff --git a/local/model/server.go b/local/model/server.go new file mode 100644 index 0000000..14ed096 --- /dev/null +++ b/local/model/server.go @@ -0,0 +1,11 @@ +package model + +// Server represents an ACC server instance +type Server struct { + ID uint `gorm:"primaryKey"` + Name string `gorm:"not null"` + IP string `gorm:"not null"` + Port int `gorm:"not null"` + ConfigPath string `gorm:"not null"` // e.g. "/acc/servers/server1/" + ServiceName string `gorm:"not null"` // Windows service name +} diff --git a/local/repository/api.go b/local/repository/api.go index 4e10926..8b18138 100644 --- a/local/repository/api.go +++ b/local/repository/api.go @@ -3,6 +3,7 @@ package repository import ( "acc-server-manager/local/model" "context" + "errors" "gorm.io/gorm" ) @@ -27,6 +28,9 @@ func NewApiRepository(db *gorm.DB) *ApiRepository { func (as ApiRepository) GetFirst(ctx context.Context) *model.ApiModel { db := as.db.WithContext(ctx) apiModel := new(model.ApiModel) - db.First(&apiModel) + result := db.First(&apiModel) + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil + } return apiModel } diff --git a/local/repository/config.go b/local/repository/config.go new file mode 100644 index 0000000..2505e56 --- /dev/null +++ b/local/repository/config.go @@ -0,0 +1,66 @@ +package repository + +import ( + "acc-server-manager/local/model" + "context" + "errors" + + "gorm.io/gorm" +) + +type ConfigRepository struct { + db *gorm.DB +} + +func NewConfigRepository(db *gorm.DB) *ConfigRepository { + return &ConfigRepository{ + db: db, + } +} + +// UpdateConfig +// Updates first row from Config table. +// +// Args: +// context.Context: Application context +// Returns: +// model.ConfigModel: Config object from database. +func (as ConfigRepository) UpdateFirst(ctx context.Context) *model.Config { + db := as.db.WithContext(ctx) + ConfigModel := new(model.Config) + db.First(&ConfigModel) + return ConfigModel +} + +// UpdateAll +// Updates All rows from Config table. +// +// Args: +// context.Context: Application context +// Returns: +// model.ConfigModel: Config object from database. +func (as ConfigRepository) UpdateAll(ctx context.Context) *[]model.Config { + db := as.db.WithContext(ctx) + ConfigModel := new([]model.Config) + db.Find(&ConfigModel) + return ConfigModel +} + +// UpdateConfig +// Updates Config row from Config table. +// +// Args: +// context.Context: Application context +// Returns: +// model.ConfigModel: Config object from database. +func (as ConfigRepository) UpdateConfig(ctx context.Context, body *model.Config) *model.Config { + db := as.db.WithContext(ctx) + + existingConfig := new(model.Config) + result := db.Where("server_id=?", body.ServerID).Where("config_file=?", body.ConfigFile).First(existingConfig) + if !errors.Is(result.Error, gorm.ErrRecordNotFound) { + body.ID = existingConfig.ID + } + db.Save(body) + return body +} diff --git a/local/repository/lookup.go b/local/repository/lookup.go new file mode 100644 index 0000000..1a7c30b --- /dev/null +++ b/local/repository/lookup.go @@ -0,0 +1,88 @@ +package repository + +import ( + "acc-server-manager/local/model" + "context" + + "gorm.io/gorm" +) + +type LookupRepository struct { + db *gorm.DB +} + +func NewLookupRepository(db *gorm.DB) *LookupRepository { + return &LookupRepository{ + db: db, + } +} + +// GetTracks +// Gets Tracks rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupRepository) GetTracks(ctx context.Context) *[]model.Track { + db := as.db.WithContext(ctx) + TrackModel := new([]model.Track) + db.Find(&TrackModel) + return TrackModel +} + +// GetCarModels +// Gets CarModels rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupRepository) GetCarModels(ctx context.Context) *[]model.CarModel { + db := as.db.WithContext(ctx) + CarModelModel := new([]model.CarModel) + db.Find(&CarModelModel) + return CarModelModel +} + +// GetDriverCategories +// Gets DriverCategories rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupRepository) GetDriverCategories(ctx context.Context) *[]model.DriverCategory { + db := as.db.WithContext(ctx) + DriverCategoryModel := new([]model.DriverCategory) + db.Find(&DriverCategoryModel) + return DriverCategoryModel +} + +// GetCupCategories +// Gets CupCategories rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupRepository) GetCupCategories(ctx context.Context) *[]model.CupCategory { + db := as.db.WithContext(ctx) + CupCategoryModel := new([]model.CupCategory) + db.Find(&CupCategoryModel) + return CupCategoryModel +} + +// GetSessionTypes +// Gets SessionTypes rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupRepository) GetSessionTypes(ctx context.Context) *[]model.SessionType { + db := as.db.WithContext(ctx) + SessionTypesModel := new([]model.SessionType) + db.Find(&SessionTypesModel) + return SessionTypesModel +} diff --git a/local/repository/repository.go b/local/repository/repository.go index cc137de..d089f23 100644 --- a/local/repository/repository.go +++ b/local/repository/repository.go @@ -11,4 +11,7 @@ import ( // *dig.Container: Dig Container func InitializeRepositories(c *dig.Container) { c.Provide(NewApiRepository) + c.Provide(NewServerRepository) + c.Provide(NewConfigRepository) + c.Provide(NewLookupRepository) } diff --git a/local/repository/server.go b/local/repository/server.go new file mode 100644 index 0000000..365675f --- /dev/null +++ b/local/repository/server.go @@ -0,0 +1,64 @@ +package repository + +import ( + "acc-server-manager/local/model" + "context" + "errors" + + "gorm.io/gorm" +) + +type ServerRepository struct { + db *gorm.DB +} + +func NewServerRepository(db *gorm.DB) *ServerRepository { + return &ServerRepository{ + db: db, + } +} + +// GetFirst +// Gets first row from Server table. +// +// Args: +// context.Context: Application context +// Returns: +// model.ServerModel: Server object from database. +func (as ServerRepository) GetFirst(ctx context.Context, serverId int) *model.Server { + db := as.db.WithContext(ctx) + ServerModel := new(model.Server) + db.Where("id=?", serverId).First(&ServerModel) + return ServerModel +} + +// GetFirstByServiceName +// Gets first row from Server table. +// +// Args: +// context.Context: Application context +// Returns: +// model.ServerModel: Server object from database. +func (as ServerRepository) GetFirstByServiceName(ctx context.Context, serviceName string) *model.Server { + db := as.db.WithContext(ctx) + ServerModel := new(model.Server) + result := db.Where("service_name=?", serviceName).First(&ServerModel) + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil + } + return ServerModel +} + +// GetAll +// Gets All rows from Server table. +// +// Args: +// context.Context: Application context +// Returns: +// model.ServerModel: Server object from database. +func (as ServerRepository) GetAll(ctx context.Context) *[]model.Server { + db := as.db.WithContext(ctx) + ServerModel := new([]model.Server) + db.Find(&ServerModel) + return ServerModel +} diff --git a/local/service/api.go b/local/service/api.go index 968f243..b61c120 100644 --- a/local/service/api.go +++ b/local/service/api.go @@ -10,12 +10,15 @@ import ( ) type ApiService struct { - repository *repository.ApiRepository + repository *repository.ApiRepository + serverRepository *repository.ServerRepository } -func NewApiService(repository *repository.ApiRepository) *ApiService { +func NewApiService(repository *repository.ApiRepository, + serverRepository *repository.ServerRepository) *ApiService { return &ApiService{ - repository: repository, + repository: repository, + serverRepository: serverRepository, } } @@ -30,16 +33,17 @@ func (as ApiService) GetFirst(ctx *fiber.Ctx) *model.ApiModel { return as.repository.GetFirst(ctx.UserContext()) } +func (as ApiService) GetStatus(ctx *fiber.Ctx) (string, error) { + service := ctx.Params("service") + return as.StatusServer(ctx, service) +} + func (as ApiService) ApiStartServer(ctx *fiber.Ctx) (string, error) { service, ok := ctx.Locals("service").(string) if !ok { return "", errors.New("service name missing") } - return as.StartServer(service) -} - -func (as ApiService) StartServer(serviceName string) (string, error) { - return as.ManageService("start", serviceName) + return as.StartServer(ctx, service) } func (as ApiService) ApiStopServer(ctx *fiber.Ctx) (string, error) { @@ -47,11 +51,7 @@ func (as ApiService) ApiStopServer(ctx *fiber.Ctx) (string, error) { if !ok { return "", errors.New("service name missing") } - return as.StopServer(service) -} - -func (as ApiService) StopServer(serviceName string) (string, error) { - return as.ManageService("stop", serviceName) + return as.StopServer(ctx, service) } func (as ApiService) ApiRestartServer(ctx *fiber.Ctx) (string, error) { @@ -59,18 +59,31 @@ func (as ApiService) ApiRestartServer(ctx *fiber.Ctx) (string, error) { if !ok { return "", errors.New("service name missing") } - return as.RestartServer(service) + return as.RestartServer(ctx, service) } -func (as ApiService) RestartServer(serviceName string) (string, error) { - _, err := as.ManageService("stop", serviceName) - if err != nil { - return "", err +func (as ApiService) StatusServer(ctx *fiber.Ctx, serviceName string) (string, error) { + return as.ManageService(ctx, "status", serviceName) +} + +func (as ApiService) StartServer(ctx *fiber.Ctx, serviceName string) (string, error) { + return as.ManageService(ctx, "start", serviceName) +} + +func (as ApiService) StopServer(ctx *fiber.Ctx, serviceName string) (string, error) { + return as.ManageService(ctx, "stop", serviceName) +} + +func (as ApiService) RestartServer(ctx *fiber.Ctx, serviceName string) (string, error) { + return as.ManageService(ctx, "restart", serviceName) +} + +func (as ApiService) ManageService(ctx *fiber.Ctx, action string, serviceName string) (string, error) { + server := as.serverRepository.GetFirstByServiceName(ctx.UserContext(), serviceName) + if server == nil { + return "", fiber.NewError(404, "Server not found") } - return as.ManageService("start", serviceName) -} -func (as ApiService) ManageService(action string, serviceName string) (string, error) { output, err := common.RunElevatedCommand(action, serviceName) if err != nil { return "", err diff --git a/local/service/config.go b/local/service/config.go new file mode 100644 index 0000000..997fe0e --- /dev/null +++ b/local/service/config.go @@ -0,0 +1,238 @@ +package service + +import ( + "acc-server-manager/local/model" + "acc-server-manager/local/repository" + "bytes" + "encoding/json" + "errors" + "io" + "os" + "path/filepath" + "time" + + "github.com/gofiber/fiber/v2" + "golang.org/x/text/encoding/unicode" + "golang.org/x/text/transform" +) + +type ConfigService struct { + repository *repository.ConfigRepository + serverRepository *repository.ServerRepository +} + +func NewConfigService(repository *repository.ConfigRepository, serverRepository *repository.ServerRepository) *ConfigService { + return &ConfigService{ + repository: repository, + serverRepository: serverRepository, + } +} + +// UpdateConfig +// Updates physical config file and caches it in database. +// +// Args: +// context.Context: Application context +// Returns: +// string: Application version +func (as ConfigService) UpdateConfig(ctx *fiber.Ctx, body *map[string]interface{}) (*model.Config, error) { + serverID, _ := ctx.ParamsInt("id") + configFile := ctx.Params("file") + + server := as.serverRepository.GetFirst(ctx.UserContext(), serverID) + + if server == nil { + return nil, fiber.NewError(404, "Server not found") + } + + // Read existing config + configPath := filepath.Join(server.ConfigPath, "\\server\\cfg", configFile) + oldData, err := os.ReadFile(configPath) + if err != nil { + return nil, err + } + + oldDataUTF8, err := DecodeUTF16LEBOM(oldData) + if err != nil { + return nil, err + } + + // Write new config + newData, err := json.MarshalIndent(&body, "", " ") + if err != nil { + return nil, err + } + + newDataUTF16, err := EncodeUTF16LEBOM(newData) + if err != nil { + return nil, err + } + + if err := os.WriteFile(configPath, newDataUTF16, 0644); err != nil { + return nil, err + } + + // Log change + return as.repository.UpdateConfig(ctx.UserContext(), &model.Config{ + ServerID: uint(serverID), + ConfigFile: configFile, + OldConfig: string(oldDataUTF8), + NewConfig: string(newData), + ChangedAt: time.Now(), + }), nil +} + +// GetConfig +// Gets physical config file and caches it in database. +// +// Args: +// context.Context: Application context +// Returns: +// string: Application version +func (as ConfigService) GetConfig(ctx *fiber.Ctx) (map[string]interface{}, error) { + serverID, _ := ctx.ParamsInt("id") + configFile := ctx.Params("file") + + server := as.serverRepository.GetFirst(ctx.UserContext(), serverID) + + if server == nil { + return nil, fiber.NewError(404, "Server not found") + } + + config, err := readFile(server.ConfigPath, configFile) + + if err != nil { + return nil, err + } + + decoded, err := DecodeToMap(config) + if err != nil { + return nil, err + } + + return decoded, nil +} + +// GetConfigs +// Gets physical config file and caches it in database. +// +// Args: +// context.Context: Application context +// Returns: +// string: Application version +func (as ConfigService) GetConfigs(ctx *fiber.Ctx) (*model.Configurations, error) { + serverID, _ := ctx.ParamsInt("id") + + server := as.serverRepository.GetFirst(ctx.UserContext(), serverID) + + if server == nil { + return nil, fiber.NewError(404, "Server not found") + } + + configuration, err := readFile(server.ConfigPath, "configuration.json") + if err != nil { + return nil, err + } + decodedconfiguration, err := DecodeToMap(configuration) + if err != nil { + return nil, err + } + + entrylist, err := readFile(server.ConfigPath, "entrylist.json") + if err != nil { + return nil, err + } + decodedentrylist, err := DecodeToMap(entrylist) + if err != nil { + return nil, err + } + + event, err := readFile(server.ConfigPath, "event.json") + if err != nil { + return nil, err + } + decodedevent, err := DecodeToMap(event) + if err != nil { + return nil, err + } + + eventRules, err := readFile(server.ConfigPath, "eventRules.json") + if err != nil { + return nil, err + } + decodedeventRules, err := DecodeToMap(eventRules) + if err != nil { + return nil, err + } + + settings, err := readFile(server.ConfigPath, "settings.json") + if err != nil { + return nil, err + } + decodedsettings, err := DecodeToMap(settings) + if err != nil { + return nil, err + } + + return &model.Configurations{ + Configuration: decodedconfiguration, + Event: decodedevent, + EventRules: decodedeventRules, + Settings: decodedsettings, + Entrylist: decodedentrylist, + }, nil +} + +func readFile(path string, configFile string) ([]byte, error) { + configPath := filepath.Join(path, "\\server\\cfg", configFile) + oldData, err := os.ReadFile(configPath) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return nil, err + } else if errors.Is(err, os.ErrNotExist) { + return nil, nil + } + + return oldData, nil +} + +func EncodeUTF16LEBOM(input []byte) ([]byte, error) { + encoder := unicode.UTF16(unicode.LittleEndian, unicode.UseBOM) + return transformBytes(encoder.NewEncoder(), input) +} + +func DecodeUTF16LEBOM(input []byte) ([]byte, error) { + decoder := unicode.UTF16(unicode.LittleEndian, unicode.UseBOM) + return transformBytes(decoder.NewDecoder(), input) +} + +func DecodeToMap(input []byte) (map[string]interface{}, error) { + if input == nil { + return nil, nil + } + configUTF8 := new(map[string]interface{}) + decoded, err := DecodeUTF16LEBOM(input) + if err != nil { + return nil, err + } + + err = json.Unmarshal(decoded, configUTF8) + if err != nil { + return nil, err + } + return *configUTF8, nil +} + +func transformBytes(t transform.Transformer, input []byte) ([]byte, error) { + var buf bytes.Buffer + w := transform.NewWriter(&buf, t) + + if _, err := io.Copy(w, bytes.NewReader(input)); err != nil { + return nil, err + } + + if err := w.Close(); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} diff --git a/local/service/lookup.go b/local/service/lookup.go new file mode 100644 index 0000000..304cdcd --- /dev/null +++ b/local/service/lookup.go @@ -0,0 +1,73 @@ +package service + +import ( + "acc-server-manager/local/model" + "acc-server-manager/local/repository" + + "github.com/gofiber/fiber/v2" +) + +type LookupService struct { + repository *repository.LookupRepository +} + +func NewLookupService(repository *repository.LookupRepository) *LookupService { + return &LookupService{ + repository: repository, + } +} + +// GetTracks +// Gets Tracks rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// string: Application version +func (as LookupService) GetTracks(ctx *fiber.Ctx) *[]model.Track { + return as.repository.GetTracks(ctx.UserContext()) +} + +// GetCarModels +// Gets CarModels rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupService) GetCarModels(ctx *fiber.Ctx) *[]model.CarModel { + return as.repository.GetCarModels(ctx.UserContext()) +} + +// GetDriverCategories +// Gets DriverCategories rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupService) GetDriverCategories(ctx *fiber.Ctx) *[]model.DriverCategory { + return as.repository.GetDriverCategories(ctx.UserContext()) +} + +// GetCupCategories +// Gets CupCategories rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupService) GetCupCategories(ctx *fiber.Ctx) *[]model.CupCategory { + return as.repository.GetCupCategories(ctx.UserContext()) +} + +// GetSessionTypes +// Gets SessionTypes rows from Lookup table. +// +// Args: +// context.Context: Application context +// Returns: +// model.LookupModel: Lookup object from database. +func (as LookupService) GetSessionTypes(ctx *fiber.Ctx) *[]model.SessionType { + return as.repository.GetSessionTypes(ctx.UserContext()) +} diff --git a/local/service/server.go b/local/service/server.go new file mode 100644 index 0000000..84d847f --- /dev/null +++ b/local/service/server.go @@ -0,0 +1,29 @@ +package service + +import ( + "acc-server-manager/local/model" + "acc-server-manager/local/repository" + + "github.com/gofiber/fiber/v2" +) + +type ServerService struct { + repository *repository.ServerRepository +} + +func NewServerService(repository *repository.ServerRepository) *ServerService { + return &ServerService{ + repository: repository, + } +} + +// GetAll +// Gets All rows from Server table. +// +// Args: +// context.Context: Application context +// Returns: +// string: Application version +func (as ServerService) GetAll(ctx *fiber.Ctx) *[]model.Server { + return as.repository.GetAll(ctx.UserContext()) +} diff --git a/local/service/service.go b/local/service/service.go index 83c169d..2c75aa8 100644 --- a/local/service/service.go +++ b/local/service/service.go @@ -15,4 +15,7 @@ func InitializeServices(c *dig.Container) { repository.InitializeRepositories(c) c.Provide(NewApiService) + c.Provide(NewConfigService) + c.Provide(NewServerService) + c.Provide(NewLookupService) } diff --git a/local/utl/common/common.go b/local/utl/common/common.go index 9d540ee..127a840 100644 --- a/local/utl/common/common.go +++ b/local/utl/common/common.go @@ -13,7 +13,10 @@ import ( ) type RouteGroups struct { - Api fiber.Router + Api fiber.Router + Server fiber.Router + Config fiber.Router + Lookup fiber.Router } func CheckError(err error) { @@ -58,10 +61,10 @@ func Find[T any](lst *[]T, callback func(item *T) bool) *T { } func RunElevatedCommand(command string, service string) (string, error) { - cmd := exec.Command("powershell", "-nologo", "-noprofile", "-File", "run_sc.ps1", command, service) + cmd := exec.Command("powershell", "-nologo", "-noprofile", ".\\nssm", command, service) + // cmd := exec.Command("powershell", "-nologo", "-noprofile", "-File", "run_sc.ps1", command, service) output, err := cmd.CombinedOutput() if err != nil { - log.Panic("error: %v, output: %s", err, string(output)) return "", fmt.Errorf("error: %v, output: %s", err, string(output)) } return string(output), nil diff --git a/local/utl/db/db.go b/local/utl/db/db.go index 12190e5..7250eb6 100644 --- a/local/utl/db/db.go +++ b/local/utl/db/db.go @@ -27,5 +27,173 @@ func Migrate(db *gorm.DB) { if err != nil { panic("failed to migrate model.ApiModel") } + err = db.AutoMigrate(&model.Server{}) + if err != nil { + panic("failed to migrate model.Server") + } + err = db.AutoMigrate(&model.Config{}) + if err != nil { + panic("failed to migrate model.Config") + } + err = db.AutoMigrate(&model.Track{}) + if err != nil { + panic("failed to migrate model.Track") + } + err = db.AutoMigrate(&model.CarModel{}) + if err != nil { + panic("failed to migrate model.CarModel") + } + err = db.AutoMigrate(&model.CupCategory{}) + if err != nil { + panic("failed to migrate model.CupCategory") + } + err = db.AutoMigrate(&model.DriverCategory{}) + if err != nil { + panic("failed to migrate model.DriverCategory") + } + err = db.AutoMigrate(&model.SessionType{}) + if err != nil { + panic("failed to migrate model.SessionType") + } db.FirstOrCreate(&model.ApiModel{Api: "Works"}) + + Seed(db) + +} + +func Seed(db *gorm.DB) error { + if err := seedTracks(db); err != nil { + return err + } + if err := seedCarModels(db); err != nil { + return err + } + if err := seedDriverCategories(db); err != nil { + return err + } + if err := seedCupCategories(db); err != nil { + return err + } + if err := seedSessionTypes(db); err != nil { + return err + } + if err := seedServers(db); err != nil { + return err + } + return nil +} + +func seedServers(db *gorm.DB) error { + servers := []model.Server{ + {ID: 1, Name: "ACC Server - Barcelona", ServiceName: "ACC-Barcelona", ConfigPath: "C:\\steamcmd\\acc"}, + {ID: 2, Name: "ACC Server - Monza", ServiceName: "ACC-Monza", ConfigPath: "C:\\steamcmd\\acc2"}, + {ID: 3, Name: "ACC Server - Spa", ServiceName: "ACC-Spa", ConfigPath: "C:\\steamcmd\\acc3"}, + {ID: 4, Name: "ACC Server - League", ServiceName: "ACC-League", ConfigPath: "C:\\steamcmd\\acc-league"}, + } + + for _, track := range servers { + if err := db.FirstOrCreate(&track).Error; err != nil { + return err + } + } + return nil +} + +func seedTracks(db *gorm.DB) error { + tracks := []model.Track{ + {Name: "monza", UniquePitBoxes: 29, PrivateServerSlots: 60}, + {Name: "zolder", UniquePitBoxes: 34, PrivateServerSlots: 50}, + {Name: "brands_hatch", UniquePitBoxes: 32, PrivateServerSlots: 50}, + {Name: "silverstone", UniquePitBoxes: 36, PrivateServerSlots: 60}, + {Name: "paul_ricard", UniquePitBoxes: 33, PrivateServerSlots: 80}, + {Name: "misano", UniquePitBoxes: 30, PrivateServerSlots: 50}, + {Name: "spa", UniquePitBoxes: 82, PrivateServerSlots: 82}, + {Name: "nurburgring", UniquePitBoxes: 30, PrivateServerSlots: 50}, + {Name: "barcelona", UniquePitBoxes: 29, PrivateServerSlots: 50}, + {Name: "hungaroring", UniquePitBoxes: 27, PrivateServerSlots: 50}, + {Name: "zandvoort", UniquePitBoxes: 25, PrivateServerSlots: 50}, + {Name: "kyalami", UniquePitBoxes: 40, PrivateServerSlots: 50}, + {Name: "mount_panorama", UniquePitBoxes: 36, PrivateServerSlots: 50}, + {Name: "suzuka", UniquePitBoxes: 51, PrivateServerSlots: 105}, + {Name: "laguna_seca", UniquePitBoxes: 30, PrivateServerSlots: 50}, + {Name: "imola", UniquePitBoxes: 30, PrivateServerSlots: 50}, + {Name: "oulton_park", UniquePitBoxes: 28, PrivateServerSlots: 50}, + {Name: "donington", UniquePitBoxes: 37, PrivateServerSlots: 50}, + {Name: "snetterton", UniquePitBoxes: 26, PrivateServerSlots: 50}, + {Name: "cota", UniquePitBoxes: 30, PrivateServerSlots: 70}, + {Name: "indianapolis", UniquePitBoxes: 30, PrivateServerSlots: 60}, + {Name: "watkins_glen", UniquePitBoxes: 30, PrivateServerSlots: 60}, + {Name: "valencia", UniquePitBoxes: 29, PrivateServerSlots: 50}, + {Name: "nurburgring_24h", UniquePitBoxes: 50, PrivateServerSlots: 110}, + } + + for _, track := range tracks { + if err := db.FirstOrCreate(&track).Error; err != nil { + return err + } + } + return nil +} + +func seedCarModels(db *gorm.DB) error { + carModels := []model.CarModel{ + {Value: 0, CarModel: "Porsche 991 GT3 R"}, + {Value: 1, CarModel: "Mercedes-AMG GT3"}, + // ... Add all car models from your list + } + + for _, cm := range carModels { + if err := db.FirstOrCreate(&cm).Error; err != nil { + return err + } + } + return nil +} + +func seedDriverCategories(db *gorm.DB) error { + categories := []model.DriverCategory{ + {Value: 3, Category: "Platinum"}, + {Value: 2, Category: "Gold"}, + {Value: 1, Category: "Silver"}, + {Value: 0, Category: "Bronze"}, + } + + for _, cat := range categories { + if err := db.FirstOrCreate(&cat).Error; err != nil { + return err + } + } + return nil +} + +func seedCupCategories(db *gorm.DB) error { + categories := []model.CupCategory{ + {Value: 0, Category: "Overall"}, + {Value: 1, Category: "ProAm"}, + {Value: 2, Category: "Am"}, + {Value: 3, Category: "Silver"}, + {Value: 4, Category: "National"}, + } + + for _, cat := range categories { + if err := db.FirstOrCreate(&cat).Error; err != nil { + return err + } + } + return nil +} + +func seedSessionTypes(db *gorm.DB) error { + sessionTypes := []model.SessionType{ + {Value: 0, SessionType: "Practice"}, + {Value: 4, SessionType: "Qualifying"}, + {Value: 10, SessionType: "Race"}, + } + + for _, st := range sessionTypes { + if err := db.FirstOrCreate(&st).Error; err != nil { + return err + } + } + return nil } diff --git a/run_sc.ps1 b/run_sc.ps1 deleted file mode 100644 index e6fff33..0000000 --- a/run_sc.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -param ( - [string]$Action, - [string]$ServiceName -) - -if ($Action -eq "start") { - sc.exe start $ServiceName -} elseif ($Action -eq "stop") { - sc.exe stop $ServiceName -} elseif ($Action -eq "restart") { - sc.exe stop $ServiceName - sc.exe start $ServiceName -} else { - Write-Error "Invalid action specified. Use 'start', 'stop', or 'restart'." -} \ No newline at end of file