You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

305 lines
5.6 KiB
Go

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")
})
}