mirror of
https://github.com/pocket-id/pocket-id.git
synced 2025-12-21 09:15:55 +03:00
feat: add support for WEBP profile pictures (#1090)
This commit is contained in:
@@ -440,7 +440,7 @@ func (s *LdapService) SyncUsers(ctx context.Context, tx *gorm.DB, client *ldap.C
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *LdapService) saveProfilePicture(parentCtx context.Context, userId string, pictureString string) error {
|
func (s *LdapService) saveProfilePicture(parentCtx context.Context, userId string, pictureString string) error {
|
||||||
var reader io.Reader
|
var reader io.ReadSeeker
|
||||||
|
|
||||||
_, err := url.ParseRequestURI(pictureString)
|
_, err := url.ParseRequestURI(pictureString)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -460,7 +460,12 @@ func (s *LdapService) saveProfilePicture(parentCtx context.Context, userId strin
|
|||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
reader = res.Body
|
data, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read profile picture: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
reader = bytes.NewReader(data)
|
||||||
} else if decodedPhoto, err := base64.StdEncoding.DecodeString(pictureString); err == nil {
|
} else if decodedPhoto, err := base64.StdEncoding.DecodeString(pictureString); err == nil {
|
||||||
// If the photo is a base64 encoded string, decode it
|
// If the photo is a base64 encoded string, decode it
|
||||||
reader = bytes.NewReader(decodedPhoto)
|
reader = bytes.NewReader(decodedPhoto)
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ func (s *UserService) GetUserGroups(ctx context.Context, userID string) ([]model
|
|||||||
return user.UserGroups, nil
|
return user.UserGroups, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *UserService) UpdateProfilePicture(ctx context.Context, userID string, file io.Reader) error {
|
func (s *UserService) UpdateProfilePicture(ctx context.Context, userID string, file io.ReadSeeker) error {
|
||||||
// Validate the user ID to prevent directory traversal
|
// Validate the user ID to prevent directory traversal
|
||||||
err := uuid.Validate(userID)
|
err := uuid.Validate(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -12,24 +12,36 @@ import (
|
|||||||
"golang.org/x/image/font"
|
"golang.org/x/image/font"
|
||||||
"golang.org/x/image/font/opentype"
|
"golang.org/x/image/font/opentype"
|
||||||
"golang.org/x/image/math/fixed"
|
"golang.org/x/image/math/fixed"
|
||||||
|
"golang.org/x/image/webp"
|
||||||
|
|
||||||
"github.com/pocket-id/pocket-id/backend/resources"
|
"github.com/pocket-id/pocket-id/backend/resources"
|
||||||
)
|
)
|
||||||
|
|
||||||
const profilePictureSize = 300
|
const profilePictureSize = 300
|
||||||
|
|
||||||
// CreateProfilePicture resizes the profile picture to a square
|
// CreateProfilePicture resizes the profile picture to a square and encodes it as PNG
|
||||||
func CreateProfilePicture(file io.Reader) (io.ReadSeeker, error) {
|
func CreateProfilePicture(file io.ReadSeeker) (io.ReadSeeker, error) {
|
||||||
|
// Attempt standard formats first
|
||||||
img, _, err := imageorient.Decode(file)
|
img, _, err := imageorient.Decode(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to decode image: %w", err)
|
if _, seekErr := file.Seek(0, io.SeekStart); seekErr != nil {
|
||||||
|
return nil, fmt.Errorf("failed to seek file: %w", seekErr)
|
||||||
|
}
|
||||||
|
// Try WebP
|
||||||
|
webpImg, webpErr := webp.Decode(file)
|
||||||
|
if webpErr != nil {
|
||||||
|
return nil, fmt.Errorf("failed to decode image: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
img = webpImg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resize to square
|
||||||
img = imaging.Fill(img, profilePictureSize, profilePictureSize, imaging.Center, imaging.Lanczos)
|
img = imaging.Fill(img, profilePictureSize, profilePictureSize, imaging.Center, imaging.Lanczos)
|
||||||
|
|
||||||
|
// Encode back to PNG
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
err = imaging.Encode(&buf, img, imaging.PNG)
|
if err := imaging.Encode(&buf, img, imaging.PNG); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to encode image: %w", err)
|
return nil, fmt.Errorf("failed to encode image: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user