From 2a5db42a66693b5dced31ffb1bb3b4095ab0eb92 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 12 Sep 2023 16:11:46 +0200 Subject: [PATCH] Migrate profile icons from fields to list of icons --- profile/icon.go | 52 +++++++++++++++++++++++++++++++++++++++++++ profile/migrations.go | 50 +++++++++++++++++++++++++++++++++++++++++ profile/profile.go | 21 ++++++----------- 3 files changed, 109 insertions(+), 14 deletions(-) create mode 100644 profile/icon.go diff --git a/profile/icon.go b/profile/icon.go new file mode 100644 index 00000000..7ced8a33 --- /dev/null +++ b/profile/icon.go @@ -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 + } + }) +} diff --git a/profile/migrations.go b/profile/migrations.go index 5db78958..aed22fc4 100644 --- a/profile/migrations.go +++ b/profile/migrations.go @@ -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 +} diff --git a/profile/profile.go b/profile/profile.go index 0ef7e9f5..c57c52d7 100644 --- a/profile/profile.go +++ b/profile/profile.go @@ -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.