- Replace middle dots (·) and em-dashes (—) with pipes (|) and standard punctuation in page titles, descriptions, and image alt texts. - Shorten the homepage description to be more concise and direct. - Update file share description phrasing for better readability, changing "click to preview" to "Open to preview" and capitalizing "Expires".
190 lines
6.1 KiB
Go
190 lines
6.1 KiB
Go
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 quickly. Drop a file, get a link.",
|
|
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
|
|
}
|