Skip to content

Commit

Permalink
fix: failure when config contains apps that aren't installed
Browse files Browse the repository at this point in the history
  • Loading branch information
blacktop committed Sep 8, 2023
1 parent 6a4c077 commit 9742032
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 65 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.7.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.25.4
howett.net/plist v1.0.0
Expand All @@ -29,7 +30,6 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.4 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/term v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
Expand Down
18 changes: 7 additions & 11 deletions internal/command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func DefaultOrg(c *Config) (err error) {
// Create default config file
var apps []database.App
var categories []database.Category
var dbconf database.Config
var config database.Config

page := database.Page{Number: 1}

Expand All @@ -265,7 +265,7 @@ func DefaultOrg(c *Config) (err error) {
page.Items = append(page.Items, folder)
}

dbconf.Apps.Pages = append(dbconf.Apps.Pages, page)
config.Apps.Pages = append(config.Apps.Pages, page)

////////////////////////////////////////////////////////////////////
// Place Widgets ///////////////////////////////////////////////////
Expand All @@ -283,14 +283,12 @@ func DefaultOrg(c *Config) (err error) {

/////////////////////////////////////////////////////////////////////
// Place Apps ///////////////////////////////////////////////////////
utils.Indent(log.Info)("creating App folders and adding apps to them")
missing, err := lpad.GetMissing(dbconf.Apps, database.ApplicationType)
if err != nil {
if err := lpad.GetMissing(&config.Apps, database.ApplicationType); err != nil {
return fmt.Errorf("failed to GetMissing=>Apps: %v", err)
}

dbconf.Apps.Pages = parseMissing(missing, dbconf.Apps.Pages)
groupID, err = lpad.ApplyConfig(dbconf.Apps, database.ApplicationType, groupID, 1)
utils.Indent(log.Info)("creating App folders and adding apps to them")
groupID, err = lpad.ApplyConfig(config.Apps, database.ApplicationType, groupID, 1)
if err != nil {
return fmt.Errorf("failed to ApplyConfig: %v", err)
}
Expand Down Expand Up @@ -540,13 +538,11 @@ func LoadConfig(c *Config) error {

/////////////////////////////////////////////////////////////////////
// Place Apps ///////////////////////////////////////////////////////
utils.Indent(log.Info)("creating App folders and adding apps to them")
missing, err := lpad.GetMissing(config.Apps, database.ApplicationType)
if err != nil {
if err := lpad.GetMissing(&config.Apps, database.ApplicationType); err != nil {
return fmt.Errorf("failed to GetMissing=>Apps: %v", err)
}

config.Apps.Pages = parseMissing(missing, config.Apps.Pages)
utils.Indent(log.Info)("creating App folders and adding apps to them")
groupID, err = lpad.ApplyConfig(config.Apps, database.ApplicationType, groupID, 1)
if err != nil {
return fmt.Errorf("failed to ApplyConfig=>Apps: %v", err)
Expand Down
127 changes: 74 additions & 53 deletions internal/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,113 @@
package database

import (
"crypto/rand"
"fmt"
"io"
"sort"

"github.com/apex/log"
"github.com/blacktop/lporg/internal/utils"
"github.com/google/uuid"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"golang.org/x/exp/slices"
"gorm.io/gorm"
)

// GetMissing returns a list of the rest of the apps not in the config
func (lp *LaunchPad) GetMissing(apps Apps, appType int) ([]string, error) {
func (lp *LaunchPad) GetMissing(apps *Apps, appType int) error {

missing := []string{}
appsFromConfig := []string{}
var (
dbApps []string
configApps []string
)

// get all apps from database
switch appType {
case ApplicationType:
var apps []App
err := lp.DB.Table("apps").
Select("apps.item_id, apps.title").
Joins("left join items on items.rowid = apps.item_id").
Not("items.parent_id = ?", 6).
Scan(&apps).Error
if err != nil {
return fmt.Errorf("query all apps failed: %w", err)
}
for _, app := range apps {
dbApps = append(dbApps, app.Title)
}
default:
return fmt.Errorf("GetMissing: unsupported app type: %d", appType)
}

sort.Strings(dbApps)

// get all apps from config file
for _, page := range apps.Pages {
for _, item := range page.Items {
switch item.(type) {
case string:
appsFromConfig = append(appsFromConfig, item.(string))
configApps = append(configApps, item.(string))
default:
var folder AppFolder
if err := mapstructure.Decode(item, &folder); err != nil {
return nil, errors.Wrap(err, "mapstructure unable to decode config folder")
return fmt.Errorf("mapstructure unable to decode config folder: %w", err)
}

for _, fpage := range folder.Pages {
for _, fitem := range fpage.Items {
appsFromConfig = append(appsFromConfig, fitem)
configApps = append(configApps, fitem)
}
}
}
}
}

switch appType {
case ApplicationType:
var apps []App
err := lp.DB.Table("apps").
Select("apps.item_id, apps.title").
Joins("left join items on items.rowid = apps.item_id").
Not("items.parent_id = ?", 6).
Scan(&apps).Error
if err != nil {
return nil, err
}
for _, app := range apps {
if !utils.StringInSlice(app.Title, appsFromConfig) {
missing = utils.AppendIfMissing(missing, app.Title)
}
}
case WidgetType:
var widgets []Widget
err := lp.DB.Table("widgets").Select("widgets.item_id, widgets.title").Joins("left join items on items.rowid = widgets.item_id").Scan(&widgets).Error
if err != nil {
return nil, err
}
for _, widget := range widgets {
if !utils.StringInSlice(widget.Title, appsFromConfig) {
missing = utils.AppendIfMissing(missing, widget.Title)
sort.Strings(configApps)

for _, app := range dbApps {
if !slices.Contains(configApps, app) {
utils.DoubleIndent(log.WithField("app", app).Warn)("found installed apps that are not in supplied config")
if len(apps.Pages[len(apps.Pages)-1].Items) < 35 {
apps.Pages[len(apps.Pages)-1].Items = append(apps.Pages[len(apps.Pages)-1].Items, app)
} else {
newPage := Page{
Number: len(apps.Pages) + 1,
Items: []any{app},
}
apps.Pages = append(apps.Pages, newPage)
}
}
}

sort.Strings(missing)

if len(missing) > 0 {
utils.DoubleIndent(log.WithField("count", len(missing)).Info)("found apps/widgets that are not in supplied config")
// check all apps from config file exist on system
for idx, page := range apps.Pages {
for iidx, item := range page.Items {
switch item.(type) {
case string:
if !slices.Contains(dbApps, item.(string)) {
utils.DoubleIndent(log.WithField("app", item.(string)).Warn)("found app in config that are is not on system")
apps.Pages[idx].Items = append(apps.Pages[idx].Items[:iidx], apps.Pages[idx].Items[iidx+1:]...)
}
default:
var folder AppFolder
if err := mapstructure.Decode(item, &folder); err != nil {
return fmt.Errorf("mapstructure unable to decode config folder: %w", err)
}
for fpIdx, fpage := range folder.Pages {
for fpiIdx, fitem := range fpage.Items {
if !slices.Contains(dbApps, fitem) {
utils.DoubleIndent(log.WithField("app", fitem).Warn)("found app in config that are is not on system")
apps.Pages[idx].Items[iidx].(map[string]any)["pages"].([]any)[fpIdx].(map[string]any)["items"] = append(
apps.Pages[idx].Items[iidx].(map[string]any)["pages"].([]any)[fpIdx].(map[string]any)["items"].([]any)[:fpiIdx],
apps.Pages[idx].Items[iidx].(map[string]any)["pages"].([]any)[fpIdx].(map[string]any)["items"].([]any)[fpiIdx+1:]...)
}
}
}
}
}
}

return missing, nil
return nil
}

// ClearGroups clears out items related to groups
Expand Down Expand Up @@ -122,7 +154,7 @@ func (lp *LaunchPad) createNewPage(pageNumber, groupID, pageParentID int) error

item := Item{
ID: groupID,
UUID: newUUID(),
UUID: uuid.New().String(),
Flags: 2,
Type: PageType,
ParentID: pageParentID,
Expand Down Expand Up @@ -153,7 +185,7 @@ func (lp *LaunchPad) createNewFolder(folderName string, folderNumber, groupID, f

item := Item{
ID: groupID,
UUID: newUUID(),
UUID: uuid.New().String(),
Flags: 0,
Type: FolderRootType,
ParentID: folderParentID,
Expand Down Expand Up @@ -189,7 +221,7 @@ func (lp *LaunchPad) createNewFolderPage(folderPageNumber, groupID, folderPagePa

item := Item{
ID: groupID,
UUID: newUUID(),
UUID: uuid.New().String(),
Flags: 2,
Type: PageType,
ParentID: folderPageParentID,
Expand Down Expand Up @@ -384,14 +416,3 @@ func (lp *LaunchPad) GetMaxWidgetID() int {

return maxID
}

// newUUID generates a random UUID according to RFC 4122
func newUUID() string {
uuid := make([]byte, 16)
_, _ = io.ReadFull(rand.Reader, uuid)
// variant bits; see section 4.1.1
uuid[8] = uuid[8]&^0xc0 | 0x80
// version 4 (pseudo-random); see section 4.1.3
uuid[6] = uuid[6]&^0xf0 | 0x40
return fmt.Sprintf("%x-%x-%x-%x-%x", uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:])
}

0 comments on commit 9742032

Please sign in to comment.