feat(boxstore): add one-time download retention mode

Introduce a `one-time` retention option and persist it on the manifest as `one_time_download`. One-time download boxes bypass retention expiry scheduling, force zip downloads, and reject download attempts until all files are complete to prevent partial retrievals.feat(boxstore): add one-time download retention mode

Introduce a `one-time` retention option and persist it on the manifest as `one_time_download`. One-time download boxes bypass retention expiry scheduling, force zip downloads, and reject download attempts until all files are complete to prevent partial retrievals.
This commit is contained in:
2026-04-28 19:41:23 +03:00
parent f1600faa8d
commit 9dececcc7d
7 changed files with 116 additions and 22 deletions

View File

@@ -24,6 +24,8 @@ import (
const (
UploadRoot = "data/uploads"
manifestFile = ".warpbox.json"
OneTimeDownloadRetentionKey = "one-time"
)
var manifestMu sync.Mutex
@@ -35,6 +37,7 @@ var retentionOptions = []models.RetentionOption{
{Key: "12h", Label: "12 hours", Seconds: 12 * 60 * 60},
{Key: "24h", Label: "24 hours", Seconds: 24 * 60 * 60},
{Key: "48h", Label: "48 hours", Seconds: 48 * 60 * 60},
{Key: OneTimeDownloadRetentionKey, Label: "One time download", Seconds: 0},
}
func NewBoxID() (string, error) {
@@ -120,14 +123,19 @@ func CreateManifest(boxID string, request models.CreateBoxRequest) ([]models.Box
if request.AllowZip != nil {
disableZip = !*request.AllowZip
}
oneTimeDownload := retention.Key == OneTimeDownloadRetentionKey
if oneTimeDownload {
disableZip = false
}
manifest := models.BoxManifest{
Files: files,
CreatedAt: now,
RetentionKey: retention.Key,
RetentionLabel: retention.Label,
RetentionSecs: retention.Seconds,
DisableZip: disableZip,
Files: files,
CreatedAt: now,
RetentionKey: retention.Key,
RetentionLabel: retention.Label,
RetentionSecs: retention.Seconds,
DisableZip: disableZip,
OneTimeDownload: oneTimeDownload,
}
if password := strings.TrimSpace(request.Password); password != "" {
@@ -479,6 +487,9 @@ func startRetentionIfTerminalUnlocked(manifest *models.BoxManifest) {
if !manifest.ExpiresAt.IsZero() || len(manifest.Files) == 0 {
return
}
if manifest.OneTimeDownload {
return
}
for _, file := range manifest.Files {
if file.Status != models.FileStatusReady && file.Status != models.FileStatusFailed {