Routes refactor and object removal

main
Antonio De Lucreziis 2 years ago
parent 73ec884289
commit af6e835c0c

@ -53,6 +53,8 @@ export const Bucket = () => {
if (res.ok) { if (res.ok) {
showToast('Oggetto rimosso') showToast('Oggetto rimosso')
await updateBucketObjects()
} else { } else {
showToast(`Errore "${await res.text()}"`) showToast(`Errore "${await res.text()}"`)
} }

@ -245,6 +245,10 @@ func (db *jsonDB) CreateBucket(bucket string, settings any) error {
bi.Settings = settings.(*JsonBucketSettings) bi.Settings = settings.(*JsonBucketSettings)
} }
if err := store.Create(bi.Settings.Path); err != nil {
return err
}
db.Buckets[bucket] = bi db.Buckets[bucket] = bi
return nil return nil
@ -309,7 +313,7 @@ func (db *jsonDB) CreateBucketObject(bucket string, r io.Reader) (string, error)
return "", fmt.Errorf("bucket named %q not found", bucket) return "", fmt.Errorf("bucket named %q not found", bucket)
} }
id, err := store.Create(b.Settings.Path, db.PrefixSize, r) id, err := store.CreateObject(b.Settings.Path, db.PrefixSize, r)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -327,7 +331,7 @@ func (db *jsonDB) SetBucketObject(bucket, id string, r io.Reader) error {
return fmt.Errorf("bucket named %q not found", bucket) return fmt.Errorf("bucket named %q not found", bucket)
} }
return store.Update(b.Settings.Path, db.PrefixSize, id, r) return store.UpdateObject(b.Settings.Path, db.PrefixSize, id, r)
}) })
} }
@ -338,7 +342,7 @@ func (db *jsonDB) GetBucketObject(bucket, id string, w io.Writer) error {
return fmt.Errorf("bucket named %q not found", bucket) return fmt.Errorf("bucket named %q not found", bucket)
} }
return store.Read(b.Settings.Path, db.PrefixSize, id, w) return store.ReadObject(b.Settings.Path, db.PrefixSize, id, w)
}) })
} }
@ -349,7 +353,7 @@ func (db *jsonDB) DeleteBucketObject(bucket, id string) error {
return fmt.Errorf("bucket named %q not found", bucket) return fmt.Errorf("bucket named %q not found", bucket)
} }
if err := store.Delete(b.Settings.Path, db.PrefixSize, id); err != nil { if err := store.DeleteObject(b.Settings.Path, db.PrefixSize, id); err != nil {
return err return err
} }
@ -367,7 +371,7 @@ func (db *jsonDB) AllBucketObjects(bucket string) ([]string, error) {
return nil, fmt.Errorf("bucket named %q not found", bucket) return nil, fmt.Errorf("bucket named %q not found", bucket)
} }
objects, err := store.All(b.Settings.Path) objects, err := store.AllObjects(b.Settings.Path)
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -20,30 +20,23 @@ func (r *Server) isAdminMiddleware(c *fiber.Ctx) error {
return c.Next() return c.Next()
} }
func (r *Server) Api(api fiber.Router) { func (s *Server) isAPIKeyMiddleware(c *fiber.Ctx) error {
isAPIKeyMiddleware := func(c *fiber.Ctx) error { if _, isAdmin := s.adminSessions[c.Cookies("sid")]; !isAdmin { // if admin continue
if _, isAdmin := r.adminSessions[c.Cookies("sid")]; !isAdmin { // if admin continue token := c.Cookies("token")
token := c.Cookies("token") if token == "" {
if token == "" { return fmt.Errorf("no api token")
return fmt.Errorf("no api token") }
}
if err := r.Database.CheckAPIKey(token); err != nil { // otherwise also check api token if err := s.Database.CheckAPIKey(token); err != nil { // otherwise also check api token
return err return err
}
} }
return c.Next()
} }
// return c.Next()
// TODO: Change to /server-info (also in frontend) }
// Setup "/api/monitor" routes
//
monitorRoute := api.Group("/monitor")
monitorRoute.Use(r.isAdminMiddleware)
r.ApiMonitor(monitorRoute)
api.Post("/login", func(c *fiber.Ctx) error { func (s *Server) ApiAuth(r fiber.Router) {
r.Post("/login", func(c *fiber.Ctx) error {
var form struct { var form struct {
Password string `form:"password"` Password string `form:"password"`
} }
@ -57,7 +50,7 @@ func (r *Server) Api(api fiber.Router) {
} }
token := utils.GenerateRandomString(32) token := utils.GenerateRandomString(32)
r.adminSessions[token] = struct{}{} s.adminSessions[token] = struct{}{}
c.Cookie(&fiber.Cookie{ c.Cookie(&fiber.Cookie{
Name: "sid", Name: "sid",
@ -69,23 +62,38 @@ func (r *Server) Api(api fiber.Router) {
return c.Redirect("/") return c.Redirect("/")
}) })
api.Get("/status", func(c *fiber.Ctx) error { r.Get("/current-user", func(c *fiber.Ctx) error {
return c.JSON("ok") if _, found := s.adminSessions[c.Cookies("sid")]; !found {
return c.JSON("anonymous")
}
return c.JSON("admin")
}) })
}
api.Get("/current-user", func (s *Server) Api(r fiber.Router) {
func(c *fiber.Ctx) error {
if _, found := r.adminSessions[c.Cookies("sid")]; !found {
return c.JSON("anonymous")
}
return c.JSON("admin") 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)
}
api.Get("/dashboard-state", func (s *Server) ApiDashboard(r fiber.Router) {
r.isAdminMiddleware, r.Get("/dashboard-state",
s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
state, err := r.Database.GetDashboardState() state, err := s.Database.GetDashboardState()
if err != nil { if err != nil {
return err return err
} }
@ -93,8 +101,8 @@ func (r *Server) Api(api fiber.Router) {
return c.JSON(state) return c.JSON(state)
}) })
api.Post("/dashboard-state", r.Post("/dashboard-state",
r.isAdminMiddleware, s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
var state database.DashboardState var state database.DashboardState
@ -103,17 +111,19 @@ func (r *Server) Api(api fiber.Router) {
return err return err
} }
if err := r.Database.SetDashboardState(state); err != nil { if err := s.Database.SetDashboardState(state); err != nil {
return err return err
} }
return c.JSON("ok") return c.JSON("ok")
}) })
}
api.Get("/buckets", func (s *Server) ApiBucket(r fiber.Router) {
r.isAdminMiddleware, r.Get("/",
s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
buckets, err := r.Database.AllBuckets() buckets, err := s.Database.AllBuckets()
if err != nil { if err != nil {
return err return err
} }
@ -121,8 +131,8 @@ func (r *Server) Api(api fiber.Router) {
return c.JSON(buckets) return c.JSON(buckets)
}) })
api.Post("/buckets", r.Post("/",
r.isAdminMiddleware, s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
var req struct { var req struct {
Bucket string `json:"bucket"` Bucket string `json:"bucket"`
@ -140,19 +150,21 @@ func (r *Server) Api(api fiber.Router) {
settings.Path = req.Path settings.Path = req.Path
} }
if err := r.Database.CreateBucket(req.Bucket, settings); err != nil { if err := s.Database.CreateBucket(req.Bucket, settings); err != nil {
return err return err
} }
return c.JSON("ok") return c.JSON("ok")
}) })
}
api.Get("/buckets/:bucket", func (s *Server) ApiBucketObjects(r fiber.Router) {
isAPIKeyMiddleware, r.Get("/",
s.isAPIKeyMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
bucket := c.Params("bucket") bucket := c.Params("bucket")
objects, err := r.Database.AllBucketObjects(bucket) objects, err := s.Database.AllBucketObjects(bucket)
if err != nil { if err != nil {
return err return err
} }
@ -160,12 +172,12 @@ func (r *Server) Api(api fiber.Router) {
return c.JSON(objects) return c.JSON(objects)
}) })
api.Get("/buckets/:bucket/settings", r.Get("/settings",
r.isAdminMiddleware, s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
bucket := c.Params("bucket") bucket := c.Params("bucket")
settings, err := r.Database.GetBucketSettings(bucket) settings, err := s.Database.GetBucketSettings(bucket)
if err != nil { if err != nil {
return err return err
} }
@ -173,8 +185,8 @@ func (r *Server) Api(api fiber.Router) {
return c.JSON(settings) return c.JSON(settings)
}) })
api.Post("/buckets/:bucket/settings", r.Post("/settings",
r.isAdminMiddleware, s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
bucket := c.Params("bucket") bucket := c.Params("bucket")
@ -184,15 +196,15 @@ func (r *Server) Api(api fiber.Router) {
return err return err
} }
if err := r.Database.SetBucketSettings(bucket, settings); err != nil { if err := s.Database.SetBucketSettings(bucket, settings); err != nil {
return err return err
} }
return c.JSON("ok") return c.JSON("ok")
}) })
api.Post("/buckets/:bucket", r.Post("/",
isAPIKeyMiddleware, s.isAPIKeyMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
bucket := c.Params("bucket") bucket := c.Params("bucket")
@ -206,7 +218,7 @@ func (r *Server) Api(api fiber.Router) {
return err return err
} }
id, err := r.Database.CreateBucketObject(bucket, mf) id, err := s.Database.CreateBucketObject(bucket, mf)
if err != nil { if err != nil {
return err return err
} }
@ -217,42 +229,41 @@ func (r *Server) Api(api fiber.Router) {
}) })
}) })
api.Get("/buckets/:bucket/:id", r.Get("/:id",
isAPIKeyMiddleware, s.isAPIKeyMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
bucket := c.Params("bucket") bucket := c.Params("bucket")
id := c.Params("id") id := c.Params("id")
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
if err := r.Database.GetBucketObject(bucket, id, buf); err != nil { if err := s.Database.GetBucketObject(bucket, id, buf); err != nil {
return err return err
} }
return c.SendStream(buf) return c.SendStream(buf)
}) })
api.Delete("/buckets/:bucket/:id", r.Delete("/:id",
isAPIKeyMiddleware, s.isAPIKeyMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
bucket := c.Params("bucket") bucket := c.Params("bucket")
id := c.Params("id") id := c.Params("id")
if err := r.Database.DeleteBucketObject(bucket, id); err != nil { if err := s.Database.DeleteBucketObject(bucket, id); err != nil {
return err return err
} }
return c.JSON("ok") return c.JSON("ok")
}) })
// }
// API Keys
//
api.Get("/api-keys", func (s *Server) ApiKeys(r fiber.Router) {
r.isAdminMiddleware, r.Get("/",
s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
apiKeys, err := r.Database.AllAPIKeys() apiKeys, err := s.Database.AllAPIKeys()
if err != nil { if err != nil {
return err return err
} }
@ -260,10 +271,10 @@ func (r *Server) Api(api fiber.Router) {
return c.JSON(apiKeys) return c.JSON(apiKeys)
}) })
api.Post("/api-keys", r.Post("/",
r.isAdminMiddleware, s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
key, err := r.Database.CreateAPIKey() key, err := s.Database.CreateAPIKey()
if err != nil { if err != nil {
return err return err
} }
@ -271,20 +282,20 @@ func (r *Server) Api(api fiber.Router) {
return c.JSON(key) return c.JSON(key)
}) })
api.Delete("/api-keys/:key", r.Delete("/:key",
r.isAdminMiddleware, s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
if err := r.Database.RemoveAPIKey(c.Params("key")); err != nil { if err := s.Database.RemoveAPIKey(c.Params("key")); err != nil {
return err return err
} }
return c.JSON("ok") return c.JSON("ok")
}) })
api.Get("/api-keys/:key", r.Get("/:key",
r.isAdminMiddleware, s.isAdminMiddleware,
func(c *fiber.Ctx) error { func(c *fiber.Ctx) error {
if err := r.Database.CheckAPIKey(c.Params("key")); err != nil { if err := s.Database.CheckAPIKey(c.Params("key")); err != nil {
return err return err
} }

@ -6,12 +6,12 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func (r *Server) ApiMonitor(api fiber.Router) { func (s *Server) ApiMonitor(api fiber.Router) {
// Respond to requests like // Respond to requests like
// - "/api/monitor/status?script=SCRIPT_NAME" where SCRIPT_NAME is the name of a file inside "./scripts" // - "/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 { api.Get("/status", s.isAdminMiddleware, func(c *fiber.Ctx) error {
if qScript := c.Query("script"); qScript != "" { if qScript := c.Query("script"); qScript != "" {
output, err := r.Monitor.GetOutput(qScript) output, err := s.Monitor.GetOutput(qScript)
if err != nil { if err != nil {
return err return err
} }
@ -22,8 +22,8 @@ func (r *Server) ApiMonitor(api fiber.Router) {
return fmt.Errorf("no script, device or entity provided") return fmt.Errorf("no script, device or entity provided")
}) })
api.Get("/invalidate-cache", func(c *fiber.Ctx) error { api.Get("/invalidate-cache", s.isAdminMiddleware, func(c *fiber.Ctx) error {
r.Monitor.InvalidateCache() s.Monitor.InvalidateCache()
return c.JSON("ok") return c.JSON("ok")
}) })
} }

@ -3,6 +3,7 @@ package store
import ( import (
"fmt" "fmt"
"io" "io"
"log"
"os" "os"
"path" "path"
@ -15,7 +16,11 @@ func split(baseDir string, prefixSize int, id string) (prefix, rest string) {
return id[:prefixSize], id[prefixSize:] return id[:prefixSize], id[prefixSize:]
} }
func Create(baseDir string, prefixSize int, r io.Reader) (string, error) { func Create(baseDir string) error {
return os.Mkdir(baseDir, os.ModePerm)
}
func CreateObject(baseDir string, prefixSize int, r io.Reader) (string, error) {
id := utils.GenerateRandomString(RandomIdSize) id := utils.GenerateRandomString(RandomIdSize)
prefix, rest := split(baseDir, prefixSize, id) prefix, rest := split(baseDir, prefixSize, id)
@ -33,7 +38,7 @@ func Create(baseDir string, prefixSize int, r io.Reader) (string, error) {
return id, nil return id, nil
} }
func Read(baseDir string, prefixSize int, id string, w io.Writer) error { func ReadObject(baseDir string, prefixSize int, id string, w io.Writer) error {
prefix, rest := split(baseDir, prefixSize, id) prefix, rest := split(baseDir, prefixSize, id)
f, err := os.Open(path.Join(baseDir, prefix, rest)) f, err := os.Open(path.Join(baseDir, prefix, rest))
@ -48,7 +53,7 @@ func Read(baseDir string, prefixSize int, id string, w io.Writer) error {
return nil return nil
} }
func All(baseDir string) ([]string, error) { func AllObjects(baseDir string) ([]string, error) {
entries, err := os.ReadDir(baseDir) entries, err := os.ReadDir(baseDir)
if err != nil { if err != nil {
return nil, err return nil, err
@ -78,10 +83,21 @@ func All(baseDir string) ([]string, error) {
return objects, nil return objects, nil
} }
func Update(baseDir string, prefixSize int, id string, r io.Reader) error { func UpdateObject(baseDir string, prefixSize int, id string, r io.Reader) error {
panic("TODO: Not implemented") panic("TODO: Not implemented")
} }
func Delete(baseDir string, prefixSize int, id string) error { func DeleteObject(baseDir string, prefixSize int, id string) error {
panic("TODO: Not implemented") prefix, rest := split(baseDir, prefixSize, id)
err := os.Remove(path.Join(baseDir, prefix, rest))
if err != nil {
return err
}
// Silently tries to remove the "<prefix>/" directory if empty
if err := os.Remove(path.Join(baseDir, prefix)); err != nil {
log.Panicf(`Tried to remove "%s/" folder, got: %s`, prefix, err.Error())
}
return nil
} }

Loading…
Cancel
Save