mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
Fix corrupted frontPageContent keys during migration (#4870)
* Add NestedMap.Delete * Migrate corrupt frontPageContent keys
This commit is contained in:
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/stashapp/stash/internal/manager/config"
|
"github.com/stashapp/stash/internal/manager/config"
|
||||||
"github.com/stashapp/stash/pkg/logger"
|
"github.com/stashapp/stash/pkg/logger"
|
||||||
"github.com/stashapp/stash/pkg/sqlite"
|
"github.com/stashapp/stash/pkg/sqlite"
|
||||||
|
"github.com/stashapp/stash/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type schema58Migrator struct {
|
type schema58Migrator struct {
|
||||||
@@ -93,6 +94,31 @@ func (m *schema58Migrator) fromSnakeCaseValue(val interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renameKey renames a fully qualified key name in a map
|
||||||
|
func (m *schema58Migrator) renameKey(mm map[string]interface{}, from, to string) {
|
||||||
|
nm := utils.NestedMap(mm)
|
||||||
|
v, found := nm.Get(from)
|
||||||
|
if !found {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nm.Delete(from)
|
||||||
|
nm.Set(to, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *schema58Migrator) renameFrontPageContentKeys(ui map[string]interface{}) {
|
||||||
|
frontPageContent, found := ui["frontPageContent"].([]interface{})
|
||||||
|
if !found {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range frontPageContent {
|
||||||
|
vm := v.(map[string]interface{})
|
||||||
|
m.renameKey(vm, "savedfilterid", "savedFilterId")
|
||||||
|
m.renameKey(vm, "sortby", "sortBy")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (m *schema58Migrator) migrateConfig() error {
|
func (m *schema58Migrator) migrateConfig() error {
|
||||||
c := config.GetInstance()
|
c := config.GetInstance()
|
||||||
|
|
||||||
@@ -120,6 +146,10 @@ func (m *schema58Migrator) migrateConfig() error {
|
|||||||
ui := c.GetUIConfiguration()
|
ui := c.GetUIConfiguration()
|
||||||
if ui != nil {
|
if ui != nil {
|
||||||
ui = m.fromSnakeCaseMap(ui)
|
ui = m.fromSnakeCaseMap(ui)
|
||||||
|
|
||||||
|
// find and rename specific frontEndPage keys
|
||||||
|
m.renameFrontPageContentKeys(ui)
|
||||||
|
|
||||||
c.SetUIConfiguration(ui)
|
c.SetUIConfiguration(ui)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,23 @@ func (m NestedMap) Set(key string, value interface{}) {
|
|||||||
current[fields[len(fields)-1]] = value
|
current[fields[len(fields)-1]] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m NestedMap) Delete(key string) {
|
||||||
|
fields := strings.Split(key, ".")
|
||||||
|
|
||||||
|
current := m
|
||||||
|
|
||||||
|
for _, f := range fields[:len(fields)-1] {
|
||||||
|
v, ok := current[f].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
current = v
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(current, fields[len(fields)-1])
|
||||||
|
}
|
||||||
|
|
||||||
// MergeMaps merges src into dest. If a key exists in both maps, the value from src is used.
|
// MergeMaps merges src into dest. If a key exists in both maps, the value from src is used.
|
||||||
func MergeMaps(dest map[string]interface{}, src map[string]interface{}) {
|
func MergeMaps(dest map[string]interface{}, src map[string]interface{}) {
|
||||||
for k, v := range src {
|
for k, v := range src {
|
||||||
|
|||||||
@@ -122,6 +122,69 @@ func TestNestedMapSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNestedMapDelete(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
key string
|
||||||
|
existing NestedMap
|
||||||
|
want NestedMap
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Delete non existing value",
|
||||||
|
key: "foo.bar.baa",
|
||||||
|
existing: NestedMap{
|
||||||
|
"foo": map[string]interface{}{
|
||||||
|
"bar": map[string]interface{}{
|
||||||
|
"baz": "qux",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: NestedMap{
|
||||||
|
"foo": map[string]interface{}{
|
||||||
|
"bar": map[string]interface{}{
|
||||||
|
"baz": "qux",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Delete existing value",
|
||||||
|
key: "foo.bar",
|
||||||
|
existing: NestedMap{
|
||||||
|
"foo": map[string]interface{}{
|
||||||
|
"bar": "old",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: NestedMap{
|
||||||
|
"foo": map[string]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Delete existing map",
|
||||||
|
key: "foo.bar",
|
||||||
|
existing: NestedMap{
|
||||||
|
"foo": map[string]interface{}{
|
||||||
|
"bar": map[string]interface{}{
|
||||||
|
"baz": "qux",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: NestedMap{
|
||||||
|
"foo": map[string]interface{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
tt.existing.Delete(tt.key)
|
||||||
|
if !reflect.DeepEqual(tt.existing, tt.want) {
|
||||||
|
t.Errorf("NestedMap.Set() got = %v, want %v", tt.existing, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeMaps(t *testing.T) {
|
func TestMergeMaps(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Reference in New Issue
Block a user