docs: expand configuration docs for admin and BadgerDB
Update README to explain startup config precedence (defaults/env/admin overrides), document admin/bootstrap and feature toggles, and clarify storage locations under WARPBOX_DATA_DIR including BadgerDB metadata. Also refresh project layout to include new config and metastore packages.docs: expand configuration docs for admin and BadgerDB Update README to explain startup config precedence (defaults/env/admin overrides), document admin/bootstrap and feature toggles, and clarify storage locations under WARPBOX_DATA_DIR including BadgerDB metadata. Also refresh project layout to include new config and metastore packages.
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -22,13 +23,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
UploadRoot = "data/uploads"
|
||||
manifestFile = ".warpbox.json"
|
||||
|
||||
OneTimeDownloadRetentionKey = "one-time"
|
||||
)
|
||||
|
||||
var manifestMu sync.Mutex
|
||||
var (
|
||||
uploadRoot = filepath.Join("data", "uploads")
|
||||
manifestMu sync.Mutex
|
||||
)
|
||||
|
||||
var retentionOptions = []models.RetentionOption{
|
||||
{Key: "10s", Label: "10 seconds", Seconds: 10},
|
||||
@@ -58,8 +61,19 @@ func DefaultRetentionOption() models.RetentionOption {
|
||||
return retentionOptions[0]
|
||||
}
|
||||
|
||||
func SetUploadRoot(path string) {
|
||||
if path == "" {
|
||||
return
|
||||
}
|
||||
uploadRoot = filepath.Clean(path)
|
||||
}
|
||||
|
||||
func UploadRoot() string {
|
||||
return uploadRoot
|
||||
}
|
||||
|
||||
func BoxPath(boxID string) string {
|
||||
return filepath.Join(UploadRoot, boxID)
|
||||
return filepath.Join(uploadRoot, boxID)
|
||||
}
|
||||
|
||||
func ManifestPath(boxID string) string {
|
||||
@@ -74,6 +88,71 @@ func DeleteBox(boxID string) error {
|
||||
return os.RemoveAll(BoxPath(boxID))
|
||||
}
|
||||
|
||||
func ListBoxSummaries() ([]models.BoxSummary, error) {
|
||||
entries, err := os.ReadDir(uploadRoot)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
summaries := make([]models.BoxSummary, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() || !ValidBoxID(entry.Name()) {
|
||||
continue
|
||||
}
|
||||
|
||||
summary, err := BoxSummary(entry.Name())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
summaries = append(summaries, summary)
|
||||
}
|
||||
|
||||
sort.Slice(summaries, func(i int, j int) bool {
|
||||
return summaries[i].CreatedAt.After(summaries[j].CreatedAt)
|
||||
})
|
||||
return summaries, nil
|
||||
}
|
||||
|
||||
func BoxSummary(boxID string) (models.BoxSummary, error) {
|
||||
files, err := ListFiles(boxID)
|
||||
if err != nil {
|
||||
return models.BoxSummary{}, err
|
||||
}
|
||||
|
||||
var manifest models.BoxManifest
|
||||
hasManifest := false
|
||||
if readManifest, err := ReadManifest(boxID); err == nil {
|
||||
manifest = readManifest
|
||||
hasManifest = true
|
||||
}
|
||||
|
||||
totalSize := int64(0)
|
||||
for _, file := range files {
|
||||
totalSize += file.Size
|
||||
}
|
||||
|
||||
summary := models.BoxSummary{
|
||||
ID: boxID,
|
||||
FileCount: len(files),
|
||||
TotalSize: totalSize,
|
||||
TotalSizeLabel: helpers.FormatBytes(totalSize),
|
||||
}
|
||||
if hasManifest {
|
||||
summary.CreatedAt = manifest.CreatedAt
|
||||
summary.ExpiresAt = manifest.ExpiresAt
|
||||
summary.Expired = IsExpired(manifest)
|
||||
summary.OneTimeDownload = manifest.OneTimeDownload
|
||||
summary.PasswordProtected = IsPasswordProtected(manifest)
|
||||
} else if info, err := os.Stat(BoxPath(boxID)); err == nil {
|
||||
summary.CreatedAt = info.ModTime().UTC()
|
||||
}
|
||||
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
func ListFiles(boxID string) ([]models.BoxFile, error) {
|
||||
if manifest, err := reconcileManifest(boxID); err == nil && len(manifest.Files) > 0 {
|
||||
files := make([]models.BoxFile, 0, len(manifest.Files))
|
||||
@@ -240,6 +319,21 @@ func WriteManifest(boxID string, manifest models.BoxManifest) error {
|
||||
return writeManifestUnlocked(boxID, manifest)
|
||||
}
|
||||
|
||||
func RenewManifest(boxID string, seconds int64) (models.BoxManifest, error) {
|
||||
manifestMu.Lock()
|
||||
defer manifestMu.Unlock()
|
||||
|
||||
manifest, err := readManifestUnlocked(boxID)
|
||||
if err != nil {
|
||||
return manifest, err
|
||||
}
|
||||
if seconds <= 0 || manifest.OneTimeDownload || manifest.ExpiresAt.IsZero() {
|
||||
return manifest, nil
|
||||
}
|
||||
manifest.ExpiresAt = time.Now().UTC().Add(time.Duration(seconds) * time.Second)
|
||||
return manifest, writeManifestUnlocked(boxID, manifest)
|
||||
}
|
||||
|
||||
func AddFileToZip(zipWriter *zip.Writer, boxID string, filename string) error {
|
||||
source, err := os.Open(filepath.Join(BoxPath(boxID), filename))
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user