api with functioning managment

This commit is contained in:
Fran Jurmanović
2025-02-05 00:26:12 +01:00
parent 954fe0ae82
commit 9118574203
26 changed files with 2017 additions and 55 deletions

View File

@@ -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

238
local/service/config.go Normal file
View File

@@ -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
}

73
local/service/lookup.go Normal file
View File

@@ -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())
}

29
local/service/server.go Normal file
View File

@@ -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())
}

View File

@@ -15,4 +15,7 @@ func InitializeServices(c *dig.Container) {
repository.InitializeRepositories(c)
c.Provide(NewApiService)
c.Provide(NewConfigService)
c.Provide(NewServerService)
c.Provide(NewLookupService)
}