package handlers import ( "net/http" "strconv" "warpbox.dev/backend/libs/services" "warpbox.dev/backend/libs/web" ) type homeData struct { MaxUploadSize string MaxUploadBytes int64 LimitSummary string Collections []collectionView IsAdmin bool AnonymousOpen bool ExpiryOptions []expiryOption DefaultExpiryMinutes int } type expiryOption struct { Minutes int Label string } func (a *App) Home(w http.ResponseWriter, r *http.Request) { currentUser := a.currentPublicUser(r) var collections []collectionView var isAdmin bool var user services.User var loggedIn bool if current, ok := a.currentUser(r); ok { user = current loggedIn = true isAdmin = user.Role == services.UserRoleAdmin userCollections, err := a.authService.ListCollections(user.ID) if err == nil { collections = make([]collectionView, 0, len(userCollections)) for _, collection := range userCollections { collections = append(collections, collectionView{ID: collection.ID, Name: collection.Name}) } } } settings, err := a.settingsService.UploadPolicy() if err != nil { http.Error(w, "unable to load upload policy", http.StatusInternalServerError) return } actor := "anonymous" if loggedIn { actor = "user" } a.logger.Info("upload page viewed", withRequestLogAttrs(r, "source", "page", "severity", "user_activity", "code", 2500, "actor", actor, "user_id", user.ID, )...) maxUploadSize, maxUploadBytes, limitSummary := a.homeUploadPolicyLabels(settings, user, loggedIn, isAdmin) expiryOptions, defaultExpiry := a.homeExpiryOptions(settings, user, loggedIn, isAdmin) a.renderPage(w, r, http.StatusOK, "home.html", web.PageData{ Title: "Upload your files", Description: "Upload and share files fast. Drop a file, get a link — private, temporary transfers that expire on your terms.", CanonicalURL: absoluteURL(r, "/"), ImageURL: absoluteURL(r, "/static/og-default.png"), ImageAlt: "Warp Box — simple file sharing and fast downloads", CurrentUser: currentUser, Data: homeData{ MaxUploadSize: maxUploadSize, MaxUploadBytes: maxUploadBytes, LimitSummary: limitSummary, Collections: collections, IsAdmin: isAdmin, AnonymousOpen: settings.AnonymousUploadsEnabled, ExpiryOptions: expiryOptions, DefaultExpiryMinutes: defaultExpiry, }, }) } // homeExpiryOptions builds the expiry ladder offered on the upload form, capped to // the viewer's effective maximum retention. Admins have no cap (the dropdown is // still capped at 365 days for sanity; the API accepts any value for admins). func (a *App) homeExpiryOptions(settings services.UploadPolicySettings, user services.User, loggedIn, isAdmin bool) ([]expiryOption, int) { maxDays := settings.AnonymousMaxDays unlimited := false switch { case isAdmin: unlimited = true case loggedIn: maxDays = a.settingsService.EffectivePolicyForUser(settings, user).MaxDays // A negative per-user MaxDays override means unlimited retention. if maxDays < 0 { unlimited = true } } return buildExpiryOptions(maxDays, unlimited) } func buildExpiryOptions(maxDays int, unlimited bool) ([]expiryOption, int) { ladder := []int{60, 360, 720, 1440, 2880, 4320, 7200, 10080, 14400, 20160, 43200, 86400, 129600, 259200, 525600} capMinutes := maxDays * 24 * 60 if unlimited || capMinutes <= 0 { capMinutes = 525600 } options := make([]expiryOption, 0, len(ladder)+1) seen := make(map[int]bool) for _, minutes := range ladder { if minutes > capMinutes { break } options = append(options, expiryOption{Minutes: minutes, Label: expiryLabel(minutes)}) seen[minutes] = true } // Always offer the exact cap as a final choice (e.g. a 15-day limit). if !unlimited && !seen[capMinutes] { options = append(options, expiryOption{Minutes: capMinutes, Label: expiryLabel(capMinutes)}) } if len(options) == 0 { options = append(options, expiryOption{Minutes: capMinutes, Label: expiryLabel(capMinutes)}) } // Unlimited uploaders can pick "never expires" (sentinel -1) after the ladder. if unlimited { options = append(options, expiryOption{Minutes: -1, Label: "Unlimited (never expires)"}) } // Default to 24h when available, otherwise the smallest option offered. defaultMinutes := options[0].Minutes if seen[1440] { defaultMinutes = 1440 } return options, defaultMinutes } func expiryLabel(minutes int) string { switch { case minutes < 60: return strconv.Itoa(minutes) + " minutes" case minutes < 1440: hours := minutes / 60 if hours == 1 { return "1 hour" } return strconv.Itoa(hours) + " hours" case minutes == 1440: return "24 hours" default: days := minutes / 1440 if days == 1 { return "1 day" } return strconv.Itoa(days) + " days" } } func (a *App) homeUploadPolicyLabels(settings services.UploadPolicySettings, user services.User, loggedIn, isAdmin bool) (string, int64, string) { if isAdmin { return "No file size limit", -1, "Admin uploads bypass storage and daily caps." } if !loggedIn { if !settings.AnonymousUploadsEnabled { return "Anonymous uploads disabled", 0, "Sign in to upload files." } return services.FormatMegabytesLabel(settings.AnonymousMaxUploadMB), services.MegabytesToBytes(settings.AnonymousMaxUploadMB), "Daily anonymous cap: " + services.FormatMegabytesLabel(settings.AnonymousDailyUploadMB) + " per IP · " + strconv.Itoa(settings.AnonymousMaxDays) + " day max." } policy := a.settingsService.EffectivePolicyForUser(settings, user) maxUpload := a.uploadService.MaxUploadSizeLabel() maxUploadBytes := a.uploadService.MaxUploadSize() if policy.MaxUploadMB < 0 { maxUpload = "unlimited" maxUploadBytes = -1 } else if policy.MaxUploadMB > 0 { maxUpload = services.FormatMegabytesLabel(policy.MaxUploadMB) maxUploadBytes = services.MegabytesToBytes(policy.MaxUploadMB) } quota := "unlimited" if policy.StorageQuotaSet { quota = services.FormatMegabytesLabel(policy.StorageQuotaMB) } expiryLimit := strconv.Itoa(policy.MaxDays) + " day max." if policy.MaxDays < 0 { expiryLimit = "no expiry limit." } return maxUpload, maxUploadBytes, "Daily cap: " + services.FormatMegabytesLabel(policy.DailyUploadMB) + " · Storage quota: " + quota + " · " + expiryLimit }