feat(config): allow -1 to represent unlimited upload limits
Introduce support for configuring unlimited upload limits by allowing -1 as a valid value for anonymous and user upload MB limits. Changes include: - Added `envMegabytesLimitFloat` and helper functions to parse and validate limits where -1 is allowed. - Updated validation logic to accept -1 for `AnonymousMaxUploadMB`, `AnonymousDailyUploadMB`, and `UserDailyUploadMB`. - Added a test case to verify unlimited upload policy behavior.
This commit is contained in:
@@ -220,6 +220,29 @@ func TestAdminUploadBypassesMaxUploadSize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnlimitedAnonymousUploadPolicyUsesNegativeOne(t *testing.T) {
|
||||
app, cleanup := newTestApp(t)
|
||||
defer cleanup()
|
||||
|
||||
policy, err := app.settingsService.UploadPolicy()
|
||||
if err != nil {
|
||||
t.Fatalf("UploadPolicy returned error: %v", err)
|
||||
}
|
||||
policy.AnonymousMaxUploadMB = -1
|
||||
policy.AnonymousDailyUploadMB = -1
|
||||
if err := app.settingsService.UpdateUploadPolicy(policy); err != nil {
|
||||
t.Fatalf("UpdateUploadPolicy returned error: %v", err)
|
||||
}
|
||||
|
||||
request := multipartUploadRequest(t, "/api/v1/upload", "file", "large.txt", strings.Repeat("x", int(app.uploadService.MaxUploadSize())+1))
|
||||
request.Header.Set("Accept", "application/json")
|
||||
response := httptest.NewRecorder()
|
||||
app.Upload(response, request)
|
||||
if response.Code != http.StatusCreated {
|
||||
t.Fatalf("unlimited anonymous upload status = %d, body = %s", response.Code, response.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnonymousUploadDisabled(t *testing.T) {
|
||||
app, cleanup := newTestApp(t)
|
||||
defer cleanup()
|
||||
|
||||
@@ -359,15 +359,15 @@ func (a *App) AdminSettingsPost(w http.ResponseWriter, r *http.Request) {
|
||||
if value := r.FormValue("user_storage_backend"); value != "" {
|
||||
settings.UserStorageBackend = value
|
||||
}
|
||||
if settings.AnonymousMaxUploadMB, err = services.ParseMegabytesValue(r.FormValue("anonymous_max_upload_mb")); err != nil {
|
||||
if settings.AnonymousMaxUploadMB, err = services.ParseMegabytesLimitValue(r.FormValue("anonymous_max_upload_mb")); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if settings.AnonymousDailyUploadMB, err = services.ParseMegabytesValue(r.FormValue("anonymous_daily_upload_mb")); err != nil {
|
||||
if settings.AnonymousDailyUploadMB, err = services.ParseMegabytesLimitValue(r.FormValue("anonymous_daily_upload_mb")); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if settings.UserDailyUploadMB, err = services.ParseMegabytesValue(r.FormValue("user_daily_upload_mb")); err != nil {
|
||||
if settings.UserDailyUploadMB, err = services.ParseMegabytesLimitValue(r.FormValue("user_daily_upload_mb")); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -839,7 +839,7 @@ func optionalMB(value string) *float64 {
|
||||
if value == "" {
|
||||
return nil
|
||||
}
|
||||
parsed, err := services.ParseMegabytesValue(value)
|
||||
parsed, err := services.ParseMegabytesLimitValue(value)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -66,7 +66,9 @@ func (a *App) homeUploadPolicyLabels(settings services.UploadPolicySettings, use
|
||||
}
|
||||
policy := a.settingsService.EffectivePolicyForUser(settings, user)
|
||||
maxUpload := a.uploadService.MaxUploadSizeLabel()
|
||||
if policy.MaxUploadMB > 0 {
|
||||
if policy.MaxUploadMB < 0 {
|
||||
maxUpload = "unlimited"
|
||||
} else if policy.MaxUploadMB > 0 {
|
||||
maxUpload = services.FormatMegabytesLabel(policy.MaxUploadMB)
|
||||
}
|
||||
quota := "unlimited"
|
||||
|
||||
@@ -39,12 +39,14 @@ func (a *App) Upload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if !isAdminUpload {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, uploadParseLimit(effectivePolicy, loggedIn, a.uploadService.MaxUploadSize()))
|
||||
}
|
||||
parseLimit := uploadParseLimit(effectivePolicy, loggedIn, a.uploadService.MaxUploadSize())
|
||||
if !isAdminUpload && parseLimit > 0 {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, parseLimit)
|
||||
}
|
||||
if isAdminUpload {
|
||||
parseLimit = 32 << 20
|
||||
} else if parseLimit <= 0 {
|
||||
parseLimit = 32 << 20
|
||||
}
|
||||
if err := r.ParseMultipartForm(parseLimit); err != nil {
|
||||
helpers.WriteJSONError(w, http.StatusBadRequest, "upload form could not be read")
|
||||
@@ -84,7 +86,7 @@ func (a *App) Upload(w http.ResponseWriter, r *http.Request) {
|
||||
ObfuscateMetadata: r.FormValue("obfuscate_metadata") == "on",
|
||||
OwnerID: ownerID,
|
||||
CollectionID: collectionID,
|
||||
SkipSizeLimit: isAdminUpload,
|
||||
SkipSizeLimit: isAdminUpload || effectivePolicy.MaxUploadMB < 0,
|
||||
CreatorIP: uploadClientIP(r),
|
||||
StorageBackendID: effectivePolicy.StorageBackendID,
|
||||
})
|
||||
@@ -131,7 +133,7 @@ func (a *App) checkUploadPolicy(r *http.Request, user services.User, loggedIn bo
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, "upload usage could not be checked"
|
||||
}
|
||||
if usage.UploadedBytes+totalBytes > services.MegabytesToBytes(policy.DailyUploadMB) {
|
||||
if policy.DailyUploadMB > 0 && usage.UploadedBytes+totalBytes > services.MegabytesToBytes(policy.DailyUploadMB) {
|
||||
return http.StatusTooManyRequests, "anonymous daily upload limit reached"
|
||||
}
|
||||
if usage.UploadedBoxes+1 > policy.DailyBoxes {
|
||||
@@ -154,7 +156,7 @@ func (a *App) checkUploadPolicy(r *http.Request, user services.User, loggedIn bo
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, "upload usage could not be checked"
|
||||
}
|
||||
if usage.UploadedBytes+totalBytes > services.MegabytesToBytes(policy.DailyUploadMB) {
|
||||
if policy.DailyUploadMB > 0 && usage.UploadedBytes+totalBytes > services.MegabytesToBytes(policy.DailyUploadMB) {
|
||||
return http.StatusTooManyRequests, "daily upload limit reached"
|
||||
}
|
||||
if usage.UploadedBoxes+1 > policy.DailyBoxes {
|
||||
@@ -214,6 +216,9 @@ func (a *App) checkStorageBackendCapacity(backendID string, settings services.Up
|
||||
}
|
||||
|
||||
func uploadParseLimit(policy services.EffectiveUploadPolicy, loggedIn bool, fallback int64) int64 {
|
||||
if policy.MaxUploadMB < 0 {
|
||||
return -1
|
||||
}
|
||||
if loggedIn && policy.MaxUploadMB <= 0 {
|
||||
return fallback * 8
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user