[bugfix] fix media limit reader check (#3363)

* return nicer errors for frontend when media / emoji upload limit reached

* fix reader limit check

* add code comment
This commit is contained in:
kim 2024-09-27 11:15:53 +00:00 committed by GitHub
parent c1c8849322
commit 497ebd8c4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 37 additions and 7 deletions

View file

@ -40,8 +40,22 @@ const (
notRelevantKey notRelevantKey
spamKey spamKey
notPermittedKey notPermittedKey
limitReachedKey
) )
// LimitReached indicates that this error was caused by
// some kind of limit being reached, e.g. media upload limit.
func LimitReached(err error) bool {
_, ok := errors.Value(err, limitReachedKey).(struct{})
return ok
}
// SetLimitReached will wrap the given error to store a "limit reached"
// flag, returning wrapped error. See LimitReached() for example use-cases.
func SetLimitReached(err error) error {
return errors.WithValue(err, limitReachedKey, struct{}{})
}
// IsUnretrievable indicates that a call to retrieve a resource // IsUnretrievable indicates that a call to retrieve a resource
// (account, status, attachment, etc) could not be fulfilled, either // (account, status, attachment, etc) could not be fulfilled, either
// because it was not found locally, or because some prerequisite // because it was not found locally, or because some prerequisite

View file

@ -29,6 +29,7 @@ import (
"codeberg.org/gruf/go-bytesize" "codeberg.org/gruf/go-bytesize"
"codeberg.org/gruf/go-iotools" "codeberg.org/gruf/go-iotools"
"codeberg.org/gruf/go-mimetypes" "codeberg.org/gruf/go-mimetypes"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
) )
// file represents one file // file represents one file
@ -143,8 +144,9 @@ func drainToTmp(rc io.ReadCloser) (string, error) {
// Check to see if limit was reached, // Check to see if limit was reached,
// (produces more useful error messages). // (produces more useful error messages).
if lr != nil && !iotools.AtEOF(lr.R) { if lr != nil && lr.N <= 0 {
return path, fmt.Errorf("reached read limit %s", bytesize.Size(limit)) err := fmt.Errorf("reached read limit %s", bytesize.Size(limit))
return path, gtserror.SetLimitReached(err)
} }
return path, nil return path, nil

View file

@ -22,6 +22,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/media" "github.com/superseriousbusiness/gotosocial/internal/media"
@ -51,11 +52,18 @@ func (p *Processor) StoreLocalMedia(
// Immediately trigger write to storage. // Immediately trigger write to storage.
attachment, err := processing.Load(ctx) attachment, err := processing.Load(ctx)
if err != nil { switch {
const text = "error processing emoji" case gtserror.LimitReached(err):
limit := config.GetMediaLocalMaxSize()
text := fmt.Sprintf("local media size limit reached: %s", limit)
return nil, gtserror.NewErrorUnprocessableEntity(err, text)
case err != nil:
const text = "error processing media"
err := gtserror.Newf("error processing media: %w", err) err := gtserror.Newf("error processing media: %w", err)
return nil, gtserror.NewErrorUnprocessableEntity(err, text) return nil, gtserror.NewErrorUnprocessableEntity(err, text)
} else if attachment.Type == gtsmodel.FileTypeUnknown {
case attachment.Type == gtsmodel.FileTypeUnknown:
text := fmt.Sprintf("could not process %s type media", attachment.File.ContentType) text := fmt.Sprintf("could not process %s type media", attachment.File.ContentType)
return nil, gtserror.NewErrorUnprocessableEntity(errors.New(text), text) return nil, gtserror.NewErrorUnprocessableEntity(errors.New(text), text)
} }
@ -86,9 +94,15 @@ func (p *Processor) StoreLocalEmoji(
return nil, gtserror.NewErrorInternalError(err) return nil, gtserror.NewErrorInternalError(err)
} }
// Immediately write to storage. // Immediately trigger write to storage.
emoji, err := processing.Load(ctx) emoji, err := processing.Load(ctx)
if err != nil { switch {
case gtserror.LimitReached(err):
limit := config.GetMediaEmojiLocalMaxSize()
text := fmt.Sprintf("local emoji size limit reached: %s", limit)
return nil, gtserror.NewErrorUnprocessableEntity(err, text)
case err != nil:
const text = "error processing emoji" const text = "error processing emoji"
err := gtserror.Newf("error processing emoji %s: %w", shortcode, err) err := gtserror.Newf("error processing emoji %s: %w", shortcode, err)
return nil, gtserror.NewErrorUnprocessableEntity(err, text) return nil, gtserror.NewErrorUnprocessableEntity(err, text)