admin-dashboard-backend/main.go

270 lines
6.4 KiB
Go
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

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