270 lines
6.4 KiB
Go
Executable File
270 lines
6.4 KiB
Go
Executable File
// 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
|
||
}
|