Add support for import/export of profile icon

This commit is contained in:
Daniel
2023-11-22 13:40:36 +01:00
parent 58443631c4
commit bd988724c4
8 changed files with 219 additions and 70 deletions

View File

@@ -1,9 +1,16 @@
package profile
import (
"errors"
"fmt"
"strings"
"sync"
"github.com/vincent-petithory/dataurl"
"golang.org/x/exp/slices"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/record"
)
// Icon describes an icon.
@@ -58,3 +65,68 @@ func sortAndCompactIcons(icons []Icon) []Icon {
return icons
}
// GetIconAsDataURL returns the icon data as a data URL.
func (icon *Icon) GetIconAsDataURL() (bloburl string, err error) {
switch icon.Type {
case IconTypeFile:
return "", errors.New("getting icon from file is not supported")
case IconTypeDatabase:
if !strings.HasPrefix(icon.Value, "cache:icons/") {
return "", errors.New("invalid icon db key")
}
r, err := iconDB.Get(icon.Value)
if err != nil {
return "", err
}
dbIcon, err := EnsureIconInDatabase(r)
if err != nil {
return "", err
}
return dbIcon.IconData, nil
case IconTypeAPI:
data, err := GetProfileIcon(icon.Value)
if err != nil {
return "", err
}
return dataurl.EncodeBytes(data), nil
default:
return "", errors.New("unknown icon type")
}
}
var iconDB = database.NewInterface(&database.Options{
Local: true,
Internal: true,
})
type IconInDatabase struct {
sync.Mutex
record.Base
IconData string `json:"iconData,omitempty"` // DataURL
}
// EnsureIconInDatabase ensures that the given record is a *IconInDatabase, and returns it.
func EnsureIconInDatabase(r record.Record) (*IconInDatabase, error) {
// unwrap
if r.IsWrapped() {
// only allocate a new struct, if we need it
newIcon := &IconInDatabase{}
err := record.Unwrap(r, newIcon)
if err != nil {
return nil, err
}
return newIcon, nil
}
// or adjust type
newIcon, ok := r.(*IconInDatabase)
if !ok {
return nil, fmt.Errorf("record not of type *IconInDatabase, but %T", r)
}
return newIcon, nil
}

View File

@@ -17,6 +17,11 @@ var profileIconStoragePath = ""
// GetProfileIcon returns the profile icon with the given ID and extension.
func GetProfileIcon(name string) (data []byte, err error) {
// Check if enabled.
if profileIconStoragePath == "" {
return nil, errors.New("api icon storage not configured")
}
// Build storage path.
iconPath := filepath.Clean(
filepath.Join(profileIconStoragePath, name),