// Package classification JNX Admin-Dashboard API Documentation. // // Schemes: https // Host: jannex // BasePath: /v1 // Version: 1.0.0 // // Consumes: // - application/json // // Produces: // - application/json // // swagger:meta package main import ( "fmt" "io" "jannex/admin-dashboard-backend/modules/config" "jannex/admin-dashboard-backend/modules/database" "jannex/admin-dashboard-backend/modules/grouptasks" "jannex/admin-dashboard-backend/modules/structs" "jannex/admin-dashboard-backend/modules/systempermissions" "jannex/admin-dashboard-backend/modules/utils" "jannex/admin-dashboard-backend/routers/router" "jannex/admin-dashboard-backend/routers/router/api/v1/productpipeline" "jannex/admin-dashboard-backend/socketserver" "os" "path/filepath" "time" "git.ex.umbach.dev/Alex/roese-utils/rsconfig" "git.ex.umbach.dev/Alex/roese-utils/rslogger" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/websocket/v2" "github.com/rs/zerolog/log" adlogger "jannex/admin-dashboard-backend/modules/logger" ) func init() { fmt.Println("Server is starting...") rsconfig.CreateEnvConfigFileIfNotExists(`DEBUG=false COLORIZED_OUTPUT=true HOST=127.0.0.1 PORT=8080 LOG_MANAGER_SERVER_URL=http://localhost:50110 TELEGRAM_BOT_MANAGER_ENABLED=true TELEGRAM_BOT_MANAGER_SERVER_URL=http://localhost:50056 # Folder paths FOLDER_GROUPTASKS_GROUPS=./groupTasks/groups/ FOLDER_GROUPTASKS_RUNNINGTASKS=./groupTasks/runningTasks/ FOLDER_LOGS_GROUPTASKS=./logs/grouptasks/ FOLDER_LOGS_SYSTEM=./logs/system/ FOLDER_PUBLIC_STATIC=./public/ # MariaDB MARIADB_HOSTNAME=127.0.0.1 MARIADB_PORT=3306 MARIADB_USERNAME=db_user MARIADB_PASSWORD=db_password MARIADB_DATABASE_NAME=db_database_name # invex storage system api INVEX_API_BASE=api_url INVEX_API_TOKEN=api_token # notifications used for us admins NOTIFICATION_USER_IDS=123`) config.LoadConfig() rslogger.InitLogger(config.Cfg.Debug, config.Cfg.ColorizedOutput, config.Cfg.LogManagerServerUrl) if os.Getenv("DOCKER") != "" { fmt.Println("Waiting for mariadb docker") // waiting for the start of mariadb docker time.Sleep(10 * time.Second) copySwaggerFolder() } createServerDirectoriesIfNotExists() createGlobalRequirementsTxtIfNotExists() utils.ValidatorInit() grouptasks.InitLoadCategoryGroups() database.InitDatabase() systempermissions.CreateMasterRoleIfNotExist() productpipeline.FetchGoogleSheets() } func copySwaggerFolder() { // copied by docker build to /app/swagger srcDir := "./swagger" destDir := config.Cfg.FolderPaths.PublicStatic + "swagger/" err := copyDir(srcDir, destDir) if err != nil { panic("Failed to copy swagger folder: " + err.Error()) } log.Debug().Msgf("Copied swagger folder to %s", destDir) } func main() { app := fiber.New(fiber.Config{ BodyLimit: 100 * 1024 * 1024, }) app.Use(cors.New()) if config.Cfg.Debug { app.Use(logger.New(logger.Config{ Format: "${pid} ${locals:requestid} ${status} - ${latency} ${method} ${path}​\n", })) } router.SetupRoutes(app) app.Use("/ws", func(c *fiber.Ctx) error { // IsWebSocketUpgrade returns true if the client // requested upgrade to the WebSocket protocol. if websocket.IsWebSocketUpgrade(c) { sessionId := c.Query("auth") // needed for a user who uses multiple tabs in the browser // with the same session id because otherwise the last browser // tab would subscribe to the topic and the other tabs would // not receive any messages browserTabSession := c.Query("bts") if len(sessionId) != utils.LenHeaderXAuthorization || len(browserTabSession) != utils.LenHeaderXAuthorization { return c.SendStatus(fiber.StatusUnauthorized) } // validate ws session var userSession structs.UserSession database.DB.First(&userSession, "id = ?", sessionId) if userSession.Id != "" { var user structs.User database.DB.First(&user, "id = ?", userSession.UserId) if user.Id != "" { c.Locals("sessionId", sessionId) c.Locals("browserTabSession", browserTabSession) c.Locals("userId", user.Id) } } return c.Next() } return fiber.ErrUpgradeRequired }) go socketserver.RunHub() socketserver.WebSocketServer(app) go grouptasks.StartUnlockLockedGroupTaskStepsTicker() adlogger.AddSystemLog(rslogger.LogTypeInfo, "Server started") app.Listen(config.Cfg.Host + ":" + config.Cfg.Port) } // create global requirements.txt in cfg.PublicStatic groupTasks folder func createGlobalRequirementsTxtIfNotExists() { cfg := config.Cfg.FolderPaths filePath := cfg.GroupTasksGroups + "requirements.txt" _, err := os.Stat(filePath) if os.IsNotExist(err) { file, err := os.Create(filePath) if err != nil { log.Error().Msgf("Failed to create global requirements.txt file: %s", err.Error()) return } defer file.Close() _, err = file.WriteString("# HERE YOU CAN DEFINE GLOBAL REQUIREMENTS\n# WHICH WILL BE INSTALLED ON THE SAME WAY AS THE GROUP TASKS REQUIREMENTS,\n# BUT YOU DON'T HAVE TO DEFINE THEM IN EVERY GROUP TASK\n") if err != nil { log.Error().Msgf("Failed to write to requirements.txt file: %s", err.Error()) return } log.Info().Msgf("Created global requirements.txt file") } } func createServerDirectoriesIfNotExists() { cfg := config.Cfg.FolderPaths paths := []string{ cfg.GroupTasksGroups, cfg.GroupTasksRunningTasks, cfg.PublicStatic + "avatars/", cfg.PublicStatic + "grouptasks/", cfg.PublicStatic + "sounds/", cfg.PublicStatic + "equipmentdocumentation/"} for _, path := range paths { _, err := os.Stat(path) if os.IsNotExist(err) { if err := os.MkdirAll(path, os.ModePerm); err != nil { log.Error().Msgf("Failed to create server directory: %s", err.Error()) continue } log.Info().Msgf("Created server directory: %s", path) } } } func copyDir(srcDir, destDir string) error { err := os.MkdirAll(destDir, 0755) if err != nil { return err } files, err := filepath.Glob(filepath.Join(srcDir, "*")) if err != nil { return err } for _, file := range files { destFile := filepath.Join(destDir, filepath.Base(file)) if err := copyFile(file, destFile); err != nil { return err } } return nil } func copyFile(srcFile, destFile string) error { source, err := os.Open(srcFile) if err != nil { return err } defer source.Close() destination, err := os.Create(destFile) if err != nil { return err } defer destination.Close() _, err = io.Copy(destination, source) return err }