Migrate profile icons from fields to list of icons

This commit is contained in:
Daniel 2023-09-12 16:11:46 +02:00
parent e81953d8f3
commit 2a5db42a66
3 changed files with 109 additions and 14 deletions

52
profile/icon.go Normal file
View file

@ -0,0 +1,52 @@
package profile
import (
"strings"
"golang.org/x/exp/slices"
)
// Icon describes an icon.
type Icon struct {
Type IconType
Value string
}
// IconType describes the type of an Icon.
type IconType string
// Supported icon types.
const (
IconTypeFile IconType = "path"
IconTypeDatabase IconType = "database"
IconTypeBlob IconType = "blob"
)
func (t IconType) sortOrder() int {
switch t {
case IconTypeFile:
return 1
case IconTypeDatabase:
return 2
case IconTypeBlob:
return 3
default:
return 100
}
}
func sortIcons(icons []Icon) {
slices.SortFunc[[]Icon, Icon](icons, func(a, b Icon) int {
aOrder := a.Type.sortOrder()
bOrder := b.Type.sortOrder()
switch {
case aOrder != bOrder:
return aOrder - bOrder
case a.Value != b.Value:
return strings.Compare(a.Value, b.Value)
default:
return 0
}
})
}

View file

@ -25,6 +25,11 @@ func registerMigrations() error {
Version: "v0.9.9",
MigrateFunc: migrateLinkedPath,
},
migration.Migration{
Description: "Migrate from Icon Fields to Icon List",
Version: "v1.5.0", // FIXME
MigrateFunc: migrateIcons,
},
)
}
@ -97,3 +102,48 @@ func migrateLinkedPath(ctx context.Context, _, to *version.Version, db *database
return nil
}
func migrateIcons(ctx context.Context, _, to *version.Version, db *database.Interface) error {
// Get iterator over all profiles.
it, err := db.Query(query.New(profilesDBPath))
if err != nil {
log.Tracer(ctx).Errorf("profile: failed to migrate from icon fields: failed to start query: %s", err)
return nil
}
// Migrate all profiles.
for r := range it.Next {
// Parse profile.
profile, err := EnsureProfile(r)
if err != nil {
log.Tracer(ctx).Debugf("profiles: failed to parse profile %s for migration: %s", r.Key(), err)
continue
}
// Skip if there is no (valid) icon defined or the icon list is already populated.
if profile.Icon == "" || profile.IconType == "" || len(profile.Icons) > 0 {
continue
}
// Migrate to icon list.
profile.Icons = []Icon{{
Type: profile.IconType,
Value: profile.Icon,
}}
// Save back to DB.
err = db.Put(profile)
if err != nil {
log.Tracer(ctx).Debugf("profiles: failed to save profile %s after migration: %s", r.Key(), err)
} else {
log.Tracer(ctx).Tracef("profiles: migrated profile %s to %s", r.Key(), to)
}
}
// Check if there was an error while iterating.
if err := it.Err(); err != nil {
log.Tracer(ctx).Errorf("profile: failed to migrate from icon fields: failed to iterate over profiles for migration: %s", err)
}
return nil
}

View file

@ -37,17 +37,6 @@ const (
DefaultActionPermit uint8 = 3
)
// iconType describes the type of the Icon property
// of a profile.
type iconType string
// Supported icon types.
const (
IconTypeFile iconType = "path"
IconTypeDatabase iconType = "database"
IconTypeBlob iconType = "blob"
)
// Profile is used to predefine a security profile for applications.
type Profile struct { //nolint:maligned // not worth the effort
record.Base
@ -73,12 +62,16 @@ type Profile struct { //nolint:maligned // not worth the effort
// Homepage may refer to the website of the application
// vendor.
Homepage string
// Icon holds the icon of the application. The value
// Deprecated: Icon holds the icon of the application. The value
// may either be a filepath, a database key or a blob URL.
// See IconType for more information.
Icon string
// IconType describes the type of the Icon property.
IconType iconType
// Deprecated: IconType describes the type of the Icon property.
IconType IconType
// Icons holds a list of icons to represent the application.
Icons []Icon
// Deprecated: LinkedPath used to point to the executableis this
// profile was created for.
// Until removed, it will be added to the Fingerprints as an exact path match.