package server 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 *Server) isAdminMiddleware(c *fiber.Ctx) error { if _, found := r.adminSessions[c.Cookies("sid")]; !found { return fmt.Errorf("invalid session token") } return c.Next() } func (s *Server) isAPIKeyMiddleware(c *fiber.Ctx) error { if _, isAdmin := s.adminSessions[c.Cookies("sid")]; !isAdmin { // if admin continue token := c.Cookies("token") if token == "" { return fmt.Errorf("no api token") } if err := s.Database.CheckAPIKey(token); err != nil { // otherwise also check api token return err } } return c.Next() } func (s *Server) ApiAuth(r fiber.Router) { r.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) s.adminSessions[token] = struct{}{} c.Cookie(&fiber.Cookie{ Name: "sid", Value: token, Path: "/", Expires: time.Now().Add(3 * 24 * time.Hour), }) return c.Redirect("/") }) r.Get("/current-user", func(c *fiber.Ctx) error { if _, found := s.adminSessions[c.Cookies("sid")]; !found { return c.JSON("anonymous") } return c.JSON("admin") }) } func (s *Server) Api(r fiber.Router) { r.Get("/status", func(c *fiber.Ctx) error { return c.JSON("ok") }) // // TODO: Change "/monitor" to "/server-info" (also in frontend) // Setup "/api/monitor" routes // r.Route("/", s.ApiAuth) r.Route("/", s.ApiDashboard) r.Route("/monitor", s.ApiMonitor) r.Route("/buckets", s.ApiBucket) r.Route("/buckets/:bucket", s.ApiBucketObjects) r.Route("/api-keys", s.ApiKeys) } func (s *Server) ApiDashboard(r fiber.Router) { r.Get("/dashboard-state", s.isAdminMiddleware, func(c *fiber.Ctx) error { state, err := s.Database.GetDashboardState() if err != nil { return err } return c.JSON(state) }) r.Post("/dashboard-state", s.isAdminMiddleware, func(c *fiber.Ctx) error { var state database.DashboardState if err := c.BodyParser(&state); err != nil { return err } if err := s.Database.SetDashboardState(state); err != nil { return err } return c.JSON("ok") }) } func (s *Server) ApiBucket(r fiber.Router) { r.Get("/", s.isAdminMiddleware, func(c *fiber.Ctx) error { buckets, err := s.Database.AllBuckets() if err != nil { return err } return c.JSON(buckets) }) r.Post("/", s.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 := s.Database.CreateBucket(req.Bucket, settings); err != nil { return err } return c.JSON("ok") }) } func (s *Server) ApiBucketObjects(r fiber.Router) { r.Get("/", s.isAPIKeyMiddleware, func(c *fiber.Ctx) error { bucket := c.Params("bucket") objects, err := s.Database.AllBucketObjects(bucket) if err != nil { return err } return c.JSON(objects) }) r.Get("/settings", s.isAdminMiddleware, func(c *fiber.Ctx) error { bucket := c.Params("bucket") settings, err := s.Database.GetBucketSettings(bucket) if err != nil { return err } return c.JSON(settings) }) r.Post("/settings", s.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 := s.Database.SetBucketSettings(bucket, settings); err != nil { return err } return c.JSON("ok") }) r.Post("/", s.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 := s.Database.CreateBucketObject(bucket, mf) if err != nil { return err } return c.JSON(fiber.Map{ "bucket": bucket, "id": id, }) }) r.Get("/:id", s.isAPIKeyMiddleware, func(c *fiber.Ctx) error { bucket := c.Params("bucket") id := c.Params("id") buf := &bytes.Buffer{} if err := s.Database.GetBucketObject(bucket, id, buf); err != nil { return err } return c.SendStream(buf) }) r.Delete("/:id", s.isAPIKeyMiddleware, func(c *fiber.Ctx) error { bucket := c.Params("bucket") id := c.Params("id") if err := s.Database.DeleteBucketObject(bucket, id); err != nil { return err } return c.JSON("ok") }) } func (s *Server) ApiKeys(r fiber.Router) { r.Get("/", s.isAdminMiddleware, func(c *fiber.Ctx) error { apiKeys, err := s.Database.AllAPIKeys() if err != nil { return err } return c.JSON(apiKeys) }) r.Post("/", s.isAdminMiddleware, func(c *fiber.Ctx) error { key, err := s.Database.CreateAPIKey() if err != nil { return err } return c.JSON(key) }) r.Delete("/:key", s.isAdminMiddleware, func(c *fiber.Ctx) error { if err := s.Database.RemoveAPIKey(c.Params("key")); err != nil { return err } return c.JSON("ok") }) r.Get("/:key", s.isAdminMiddleware, func(c *fiber.Ctx) error { if err := s.Database.CheckAPIKey(c.Params("key")); err != nil { return err } return c.JSON("valid") }) }