chore(avatar): decouple upload from web handler

This commit is contained in:
kolaente
2025-03-18 18:08:09 +01:00
parent 77480814fd
commit 26c7ceaed4
2 changed files with 45 additions and 46 deletions

View File

@@ -29,6 +29,7 @@ import (
"code.vikunja.io/api/pkg/user"
"github.com/disintegration/imaging"
"xorm.io/xorm"
)
// Provider represents the upload avatar provider
@@ -111,3 +112,42 @@ func InvalidateCache(u *user.User) {
log.Errorf("Could not invalidate upload avatar cache for user %d, error was %s", u.ID, err)
}
}
func StoreAvatarFile(s *xorm.Session, u *user.User, src io.Reader) (err error) {
// Remove the old file if one exists
if u.AvatarFileID != 0 {
f := &files.File{ID: u.AvatarFileID}
if err := f.Delete(s); err != nil {
if !files.IsErrFileDoesNotExist(err) {
return err
}
}
u.AvatarFileID = 0
}
// Resize the new file to a max height of 1024
img, _, err := image.Decode(src)
if err != nil {
return
}
resizedImg := imaging.Resize(img, 0, 1024, imaging.Lanczos)
buf := &bytes.Buffer{}
err = png.Encode(buf, resizedImg)
if err != nil {
return
}
InvalidateCache(u)
// Save the file
f, err := files.CreateWithMime(buf, "avatar.png", uint64(buf.Len()), u, "image/png")
if err != nil {
return err
}
u.AvatarFileID = f.ID
_, err = user.UpdateUser(s, u, false)
return
}

View File

@@ -19,27 +19,23 @@ package v1
import (
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/files"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/modules/avatar"
"code.vikunja.io/api/pkg/modules/avatar/empty"
"code.vikunja.io/api/pkg/modules/avatar/gravatar"
"code.vikunja.io/api/pkg/modules/avatar/initials"
"code.vikunja.io/api/pkg/modules/avatar/ldap"
"code.vikunja.io/api/pkg/modules/avatar/marble"
"code.vikunja.io/api/pkg/modules/avatar/upload"
"code.vikunja.io/api/pkg/user"
"code.vikunja.io/api/pkg/web/handler"
"bytes"
"image"
"image/png"
"io"
"net/http"
"strconv"
"strings"
"github.com/disintegration/imaging"
"github.com/gabriel-vasile/mimetype"
"github.com/labstack/echo/v4"
)
@@ -81,6 +77,8 @@ func GetAvatar(c echo.Context) error {
avatarProvider = &upload.Provider{}
case "marble":
avatarProvider = &marble.Provider{}
case "ldap":
avatarProvider = &ldap.Provider{}
default:
avatarProvider = &empty.Provider{}
}
@@ -164,48 +162,9 @@ func UploadAvatar(c echo.Context) (err error) {
}
_, _ = src.Seek(0, io.SeekStart)
// Remove the old file if one exists
if u.AvatarFileID != 0 {
f := &files.File{ID: u.AvatarFileID}
if err := f.Delete(s); err != nil {
if !files.IsErrFileDoesNotExist(err) {
_ = s.Rollback()
return handler.HandleHTTPError(err)
}
}
u.AvatarFileID = 0
}
// Resize the new file to a max height of 1024
img, _, err := image.Decode(src)
if err != nil {
_ = s.Rollback()
return handler.HandleHTTPError(err)
}
resizedImg := imaging.Resize(img, 0, 1024, imaging.Lanczos)
buf := &bytes.Buffer{}
if err := png.Encode(buf, resizedImg); err != nil {
_ = s.Rollback()
return handler.HandleHTTPError(err)
}
upload.InvalidateCache(u)
// Save the file
f, err := files.CreateWithMime(buf, file.Filename, uint64(file.Size), u, "image/png")
if err != nil {
_ = s.Rollback()
if files.IsErrFileIsTooLarge(err) {
return echo.ErrBadRequest
}
return handler.HandleHTTPError(err)
}
u.AvatarFileID = f.ID
u.AvatarProvider = "upload"
if _, err := user.UpdateUser(s, u, false); err != nil {
err = upload.StoreAvatarFile(s, u, src)
if err != nil {
_ = s.Rollback()
return handler.HandleHTTPError(err)
}