diff --git a/.dockerignore b/.dockerignore index e7eb592..26a0780 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,13 +1,6 @@ # NodeJS node_modules/ -# Server -server - -# Local Files -.env -*.local* - # Itself Dockerfile .dockerignore \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 7ebead9..4f06b3a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,8 @@ RUN npm run build FROM golang:1.18-alpine AS server-builder WORKDIR /server +COPY go.mod go.sum ./ +RUN go mod download -x COPY . . RUN go build -buildvcs=false -o storage-server -v . diff --git a/main.go b/main.go index 7df1e2e..3ce326b 100644 --- a/main.go +++ b/main.go @@ -8,8 +8,8 @@ import ( "git.phc.dm.unipi.it/phc/storage/config" "git.phc.dm.unipi.it/phc/storage/database" - "git.phc.dm.unipi.it/phc/storage/monitor" - "git.phc.dm.unipi.it/phc/storage/routes" + "git.phc.dm.unipi.it/phc/storage/server" + "git.phc.dm.unipi.it/phc/storage/serverinfo" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" @@ -17,24 +17,27 @@ import ( ) func main() { - // Setup services + // + // Setup main services + // db := database.NewJSON("database.local.json") - monitorService := monitor.NewService(&monitor.Config{ + serverinfoService := serverinfo.NewService(&serverinfo.Config{ ScriptsDir: "./scripts", CacheTimeout: config.MonitorCacheTimeout, }) - if err := monitorService.LoadScripts(); err != nil { + if err := serverinfoService.LoadScripts(); err != nil { panic(err) } - // The router wraps all application dependencies and provides "routing" methods - router := &routes.Router{ - Database: db, - Monitor: monitorService, - } + // + // Setup server + // + + // The server wraps all application dependencies and provides "routing" methods + server := server.New(db, serverinfoService) // We use go-fiber as the HTTP framework app := fiber.New() @@ -60,7 +63,13 @@ func main() { }) } - app.Route("/api", router.Api) + // Setup server routes + + app.Route("/api", server.Api) + + // + // ViteJS development server + // if strings.HasPrefix(config.Mode, "dev") { log.Printf(`Running dev server for frontend: "npm run dev"`) @@ -83,5 +92,6 @@ func main() { } } + // Start backend the server log.Fatal(app.Listen(config.Host)) } diff --git a/routes/api.go b/routes/api.go deleted file mode 100644 index 3e791c9..0000000 --- a/routes/api.go +++ /dev/null @@ -1,294 +0,0 @@ -package routes - -import ( - "bytes" - "fmt" - "log" - "time" - - "git.phc.dm.unipi.it/phc/storage/config" - "git.phc.dm.unipi.it/phc/storage/database" - "git.phc.dm.unipi.it/phc/storage/utils" - "github.com/gofiber/fiber/v2" -) - -func (r *Router) Api(api fiber.Router) { - adminSessions := map[string]struct{}{} - - isAdminMiddleware := func(c *fiber.Ctx) error { - if _, found := adminSessions[c.Cookies("sid")]; !found { - return fmt.Errorf("invalid session token") - } - - return c.Next() - } - - isAPIKeyMiddleware := func(c *fiber.Ctx) error { - if _, isAdmin := adminSessions[c.Cookies("sid")]; !isAdmin { // if admin continue - token := c.Cookies("token") - if token == "" { - return fmt.Errorf("no api token") - } - - if err := r.Database.CheckAPIKey(token); err != nil { // otherwise also check api token - return err - } - } - return c.Next() - } - - // - // Setup "/api/monitor" routes - // - monitorRoute := api.Group("/monitor") - monitorRoute.Use(isAdminMiddleware) - r.ApiMonitor(monitorRoute) - - api.Post("/login", func(c *fiber.Ctx) error { - var form struct { - Password string `form:"password"` - } - - if err := c.BodyParser(&form); err != nil { - return err - } - - if form.Password != config.AdminPassword { - return c.JSON("invalid credentials") - } - - token := utils.GenerateRandomString(32) - adminSessions[token] = struct{}{} - - c.Cookie(&fiber.Cookie{ - Name: "sid", - Value: token, - Path: "/", - Expires: time.Now().Add(3 * 24 * time.Hour), - }) - - return c.Redirect("/") - }) - - api.Get("/status", func(c *fiber.Ctx) error { - return c.JSON("ok") - }) - - api.Get("/current-user", - func(c *fiber.Ctx) error { - if _, found := adminSessions[c.Cookies("sid")]; !found { - return c.JSON("anonymous") - } - - return c.JSON("admin") - }) - - api.Get("/dashboard-state", - isAdminMiddleware, - func(c *fiber.Ctx) error { - state, err := r.Database.GetDashboardState() - if err != nil { - return err - } - - return c.JSON(state) - }) - - api.Post("/dashboard-state", - isAdminMiddleware, - func(c *fiber.Ctx) error { - - var state database.DashboardState - - if err := c.BodyParser(&state); err != nil { - return err - } - - if err := r.Database.SetDashboardState(state); err != nil { - return err - } - - return c.JSON("ok") - }) - - api.Get("/buckets", - isAdminMiddleware, - func(c *fiber.Ctx) error { - buckets, err := r.Database.AllBuckets() - if err != nil { - return err - } - - return c.JSON(buckets) - }) - - api.Post("/buckets", - isAdminMiddleware, - func(c *fiber.Ctx) error { - var req struct { - Bucket string `json:"bucket"` - Path string `json:"path"` - } - - log.Printf("%v", string(c.Body())) - - if err := c.BodyParser(&req); err != nil { - return err - } - - settings := &database.JsonBucketSettings{} - if req.Path != "" { - settings.Path = req.Path - } - - if err := r.Database.CreateBucket(req.Bucket, settings); err != nil { - return err - } - - return c.JSON("ok") - }) - - api.Get("/buckets/:bucket", - isAPIKeyMiddleware, - func(c *fiber.Ctx) error { - bucket := c.Params("bucket") - - objects, err := r.Database.AllBucketObjects(bucket) - if err != nil { - return err - } - - return c.JSON(objects) - }) - - api.Get("/buckets/:bucket/settings", - isAdminMiddleware, - func(c *fiber.Ctx) error { - bucket := c.Params("bucket") - - settings, err := r.Database.GetBucketSettings(bucket) - if err != nil { - return err - } - - return c.JSON(settings) - }) - - api.Post("/buckets/:bucket/settings", - isAdminMiddleware, - func(c *fiber.Ctx) error { - bucket := c.Params("bucket") - - var settings *database.JsonBucketSettings - - if err := c.BodyParser(&settings); err != nil { - return err - } - - if err := r.Database.SetBucketSettings(bucket, settings); err != nil { - return err - } - - return c.JSON("ok") - }) - - api.Post("/buckets/:bucket", - isAPIKeyMiddleware, - func(c *fiber.Ctx) error { - bucket := c.Params("bucket") - - ff, err := c.FormFile("file") - if err != nil { - return err - } - - mf, err := ff.Open() - if err != nil { - return err - } - - id, err := r.Database.CreateBucketObject(bucket, mf) - if err != nil { - return err - } - - return c.JSON(fiber.Map{ - "bucket": bucket, - "id": id, - }) - }) - - api.Get("/buckets/:bucket/:id", - isAPIKeyMiddleware, - func(c *fiber.Ctx) error { - bucket := c.Params("bucket") - id := c.Params("id") - - buf := &bytes.Buffer{} - - if err := r.Database.GetBucketObject(bucket, id, buf); err != nil { - return err - } - - return c.SendStream(buf) - }) - - api.Delete("/buckets/:bucket/:id", - isAPIKeyMiddleware, - func(c *fiber.Ctx) error { - bucket := c.Params("bucket") - id := c.Params("id") - - if err := r.Database.DeleteBucketObject(bucket, id); err != nil { - return err - } - - return c.JSON("ok") - }) - - // - // API Keys - // - - api.Get("/api-keys", - isAdminMiddleware, - func(c *fiber.Ctx) error { - apiKeys, err := r.Database.AllAPIKeys() - if err != nil { - return err - } - - return c.JSON(apiKeys) - }) - - api.Post("/api-keys", - isAdminMiddleware, - func(c *fiber.Ctx) error { - key, err := r.Database.CreateAPIKey() - if err != nil { - return err - } - - return c.JSON(key) - }) - - api.Delete("/api-keys/:key", - isAdminMiddleware, - func(c *fiber.Ctx) error { - if err := r.Database.RemoveAPIKey(c.Params("key")); err != nil { - return err - } - - return c.JSON("ok") - }) - - api.Get("/api-keys/:key", - isAdminMiddleware, - func(c *fiber.Ctx) error { - if err := r.Database.CheckAPIKey(c.Params("key")); err != nil { - return err - } - - return c.JSON("valid") - }) -} diff --git a/routes/monitor.go b/routes/monitor.go deleted file mode 100644 index e4376c1..0000000 --- a/routes/monitor.go +++ /dev/null @@ -1,29 +0,0 @@ -package routes - -import ( - "fmt" - - "github.com/gofiber/fiber/v2" -) - -func (r *Router) ApiMonitor(api fiber.Router) { - // Respond to requests like - // - "/api/monitor/status?script=SCRIPT_NAME" where SCRIPT_NAME is the name of a file inside "./scripts" - api.Get("/status", func(c *fiber.Ctx) error { - if qScript := c.Query("script"); qScript != "" { - output, err := r.Monitor.GetOutput(qScript) - if err != nil { - return err - } - - return c.JSON(output) - } - - return fmt.Errorf("no script, device or entity provided") - }) - - api.Get("/invalidate-cache", func(c *fiber.Ctx) error { - r.Monitor.InvalidateCache() - return c.JSON("ok") - }) -} diff --git a/routes/router.go b/routes/router.go deleted file mode 100644 index 898aec3..0000000 --- a/routes/router.go +++ /dev/null @@ -1,11 +0,0 @@ -package routes - -import ( - "git.phc.dm.unipi.it/phc/storage/database" - "git.phc.dm.unipi.it/phc/storage/monitor" -) - -type Router struct { - Database database.Database - Monitor *monitor.Service -} diff --git a/monitor/service.go b/serverinfo/service.go similarity index 98% rename from monitor/service.go rename to serverinfo/service.go index 4b62a02..416d93b 100644 --- a/monitor/service.go +++ b/serverinfo/service.go @@ -1,4 +1,4 @@ -package monitor +package serverinfo import ( "log"