chore: Missed a couple of files in the last commit

This commit is contained in:
jamesread 2026-07-28 13:23:19 +01:00
parent d3ebcac391
commit c7646166f2
4 changed files with 156 additions and 12 deletions

View File

@ -0,0 +1,21 @@
export const LOGS_FILTER_STORAGE_KEY = 'olivetin-logs-filter'
export function loadStoredLogsFilter () {
try {
return sessionStorage.getItem(LOGS_FILTER_STORAGE_KEY) || ''
} catch {
return ''
}
}
export function storeLogsFilter (value) {
try {
if (value) {
sessionStorage.setItem(LOGS_FILTER_STORAGE_KEY, value)
} else {
sessionStorage.removeItem(LOGS_FILTER_STORAGE_KEY)
}
} catch {
// Ignore storage failures (private mode, quota, etc.)
}
}

View File

@ -1217,6 +1217,9 @@ func (api *oliveTinAPI) Init(ctx ctx.Context, req *connect.Request[apiv1.InitReq
currentVersion = installationinfo.Build.Version currentVersion = installationinfo.Build.Version
availableVersion = installationinfo.Runtime.AvailableVersion availableVersion = installationinfo.Runtime.AvailableVersion
} }
rootDashboardEntries := api.buildRootDashboardEntries(user, api.cfg.Dashboards)
res := &apiv1.InitResponse{ res := &apiv1.InitResponse{
ShowFooter: api.cfg.ShowFooter, ShowFooter: api.cfg.ShowFooter,
ShowNavigation: api.cfg.ShowNavigation, ShowNavigation: api.cfg.ShowNavigation,
@ -1232,7 +1235,8 @@ func (api *oliveTinAPI) Init(ctx ctx.Context, req *connect.Request[apiv1.InitReq
OAuth2Providers: buildPublicOAuth2ProvidersList(api.cfg), OAuth2Providers: buildPublicOAuth2ProvidersList(api.cfg),
AdditionalLinks: buildAdditionalLinks(api.cfg.AdditionalNavigationLinks), AdditionalLinks: buildAdditionalLinks(api.cfg.AdditionalNavigationLinks),
StyleMods: api.cfg.StyleMods, StyleMods: api.cfg.StyleMods,
RootDashboards: api.buildRootDashboards(user, api.cfg.Dashboards), RootDashboards: rootDashboardTitles(rootDashboardEntries),
RootDashboardEntries: rootDashboardEntries,
AuthenticatedUser: user.Username, AuthenticatedUser: user.Username,
AuthenticatedUserProvider: user.Provider, AuthenticatedUserProvider: user.Provider,
EffectivePolicy: buildEffectivePolicy(user.EffectivePolicy), EffectivePolicy: buildEffectivePolicy(user.EffectivePolicy),
@ -1300,30 +1304,47 @@ func getValidThemeName(themesDir string, entry os.DirEntry) string {
} }
func (api *oliveTinAPI) buildRootDashboards(user *authpublic.AuthenticatedUser, dashboards []*config.DashboardComponent) []string { func (api *oliveTinAPI) buildRootDashboards(user *authpublic.AuthenticatedUser, dashboards []*config.DashboardComponent) []string {
var rootDashboards []string return rootDashboardTitles(api.buildRootDashboardEntries(user, dashboards))
dashboardRenderRequest := api.createDashboardRenderRequest(user, "", "")
api.addDefaultDashboardIfNeeded(&rootDashboards, dashboardRenderRequest)
api.addCustomDashboards(&rootDashboards, dashboards, dashboardRenderRequest)
return rootDashboards
} }
func (api *oliveTinAPI) addDefaultDashboardIfNeeded(rootDashboards *[]string, rr *DashboardRenderRequest) { func rootDashboardTitles(entries []*apiv1.RootDashboard) []string {
titles := make([]string, 0, len(entries))
for _, entry := range entries {
titles = append(titles, entry.Title)
}
return titles
}
func (api *oliveTinAPI) buildRootDashboardEntries(user *authpublic.AuthenticatedUser, dashboards []*config.DashboardComponent) []*apiv1.RootDashboard {
var entries []*apiv1.RootDashboard
dashboardRenderRequest := api.createDashboardRenderRequest(user, "", "")
api.addDefaultDashboardEntryIfNeeded(&entries, dashboardRenderRequest)
api.addCustomDashboardEntries(&entries, dashboards, dashboardRenderRequest)
return entries
}
func (api *oliveTinAPI) addDefaultDashboardEntryIfNeeded(entries *[]*apiv1.RootDashboard, rr *DashboardRenderRequest) {
defaultDashboard := buildDefaultDashboard(rr) defaultDashboard := buildDefaultDashboard(rr)
if defaultDashboard != nil && len(defaultDashboard.Contents) > 0 { if defaultDashboard != nil && len(defaultDashboard.Contents) > 0 {
log.Tracef("defaultDashboard: %+v", defaultDashboard.Contents) log.Tracef("defaultDashboard: %+v", defaultDashboard.Contents)
*rootDashboards = append(*rootDashboards, "Actions") *entries = append(*entries, &apiv1.RootDashboard{Title: "Actions"})
} }
} }
func (api *oliveTinAPI) addCustomDashboards(rootDashboards *[]string, dashboards []*config.DashboardComponent, rr *DashboardRenderRequest) { func (api *oliveTinAPI) addCustomDashboardEntries(entries *[]*apiv1.RootDashboard, dashboards []*config.DashboardComponent, rr *DashboardRenderRequest) {
for _, dashboard := range dashboards { for _, dashboard := range dashboards {
// We have to build the dashboard response instead of just looping over config.dashboards, // We have to build the dashboard response instead of just looping over config.dashboards,
// because we need to check if the user has access to the dashboard // because we need to check if the user has access to the dashboard
db := renderDashboard(rr, dashboard.Title) db := renderDashboard(rr, dashboard.Title)
if db != nil { if db != nil {
*rootDashboards = append(*rootDashboards, dashboard.Title) *entries = append(*entries, &apiv1.RootDashboard{
Title: dashboard.Title,
Category: dashboard.Category,
})
} }
} }
} }

View File

@ -68,6 +68,61 @@ func TestDashboardAclsRootNavAndGetDashboard(t *testing.T) {
assert.Equal(t, "Services", db.Title) assert.Equal(t, "Services", db.Title)
} }
func TestRootDashboardEntriesIncludeCategory(t *testing.T) {
cfg := config.DefaultConfig()
cfg.Dashboards = []*config.DashboardComponent{
{
Title: "Misc Tools",
Contents: []*config.DashboardComponent{{Title: "Hello", Type: "display"}},
},
{
Title: "My Servers",
Category: "Infrastructure",
Contents: []*config.DashboardComponent{{Title: "Ping", Type: "display"}},
},
{
Title: "Status Board",
Category: "Monitoring",
Contents: []*config.DashboardComponent{{Title: "Uptime", Type: "display"}},
},
{
Title: "My Containers",
Category: "Infrastructure",
Contents: []*config.DashboardComponent{{Title: "Restart", Type: "display"}},
},
}
ex := executor.DefaultExecutor(cfg)
api := newServer(ex)
user := &authpublic.AuthenticatedUser{Username: "guest", Provider: "system"}
user.BuildUserAcls(cfg)
entries := api.buildRootDashboardEntries(user, cfg.Dashboards)
require.Len(t, entries, 4)
assert.Equal(t, []string{"Misc Tools", "My Servers", "Status Board", "My Containers"}, rootDashboardTitles(entries))
assert.Equal(t, "", entries[0].Category)
assert.Equal(t, "Infrastructure", entries[1].Category)
assert.Equal(t, "Monitoring", entries[2].Category)
assert.Equal(t, "Infrastructure", entries[3].Category)
}
func TestRootDashboardEntriesOmitAclHiddenCategories(t *testing.T) {
cfg := buildDashboardAclTestConfig()
cfg.Dashboards[0].Category = "Public"
cfg.Dashboards[1].Category = "Admin only"
ex := executor.DefaultExecutor(cfg)
api := newServer(ex)
guest := &authpublic.AuthenticatedUser{Username: "guest", Provider: "system"}
guest.BuildUserAcls(cfg)
entries := api.buildRootDashboardEntries(guest, cfg.Dashboards)
require.Len(t, entries, 1)
assert.Equal(t, "Public tools", entries[0].Title)
assert.Equal(t, "Public", entries[0].Category)
}
func TestDashboardAclsNestedDirectoryDeepLink(t *testing.T) { func TestDashboardAclsNestedDirectoryDeepLink(t *testing.T) {
cfg := buildDashboardAclTestConfig() cfg := buildDashboardAclTestConfig()
cfg.Dashboards = []*config.DashboardComponent{ cfg.Dashboards = []*config.DashboardComponent{

View File

@ -0,0 +1,47 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestApplyPortEnvironmentOverride(t *testing.T) {
t.Setenv("PORT", "8080")
cfg := DefaultConfig()
cfg.ListenAddressSingleHTTPFrontend = "0.0.0.0:1337"
applyPortEnvironmentOverride(cfg)
assert.Equal(t, "0.0.0.0:8080", cfg.ListenAddressSingleHTTPFrontend)
}
func TestApplyPortEnvironmentOverridePreservesHost(t *testing.T) {
t.Setenv("PORT", "9000")
cfg := DefaultConfig()
cfg.ListenAddressSingleHTTPFrontend = "127.0.0.1:1337"
applyPortEnvironmentOverride(cfg)
assert.Equal(t, "127.0.0.1:9000", cfg.ListenAddressSingleHTTPFrontend)
}
func TestApplyPortEnvironmentOverrideUnsetLeavesConfig(t *testing.T) {
t.Setenv("PORT", "")
cfg := DefaultConfig()
cfg.ListenAddressSingleHTTPFrontend = "0.0.0.0:2337"
applyPortEnvironmentOverride(cfg)
assert.Equal(t, "0.0.0.0:2337", cfg.ListenAddressSingleHTTPFrontend)
}
func TestApplyPortEnvironmentOverrideIgnoresInvalid(t *testing.T) {
t.Setenv("PORT", "not-a-port")
cfg := DefaultConfig()
cfg.ListenAddressSingleHTTPFrontend = "0.0.0.0:1337"
applyPortEnvironmentOverride(cfg)
assert.Equal(t, "0.0.0.0:1337", cfg.ListenAddressSingleHTTPFrontend)
}