fix: respect allow_icon_changes config on web and desktop

The `service.allowiconchanges` config option was ignored. On the web ui the
value injected into index.html by the api was immediately overwritten by a
hardcoded `window.ALLOW_ICON_CHANGES = true` in a later inline script, so the
configured value never took effect. The desktop app never received the
injected value at all, since it serves the bundled frontend from its own local
server and only talks to the api for data.

Expose the option via the /info endpoint and read it from the config store,
which is the only channel that reaches both the web ui and the desktop app.
The brittle window injection and its hardcoded default are removed in favor of
this single source of truth.

https://claude.ai/code/session_01HAXTJNsDcfsB4hwDNKTECb
This commit is contained in:
Tink bot 2026-06-01 09:26:09 +00:00 committed by kolaente
parent 9bf19e4dc5
commit fb6f16adde
6 changed files with 7 additions and 8 deletions

View File

@ -23,7 +23,6 @@
// It has to be the full url, including the last /api/v1 part and port.
// You can change this if your api is not reachable on the same port as the frontend.
window.API_URL = '/api/v1'
window.ALLOW_ICON_CHANGES = true
</script>
</body>
</html>

View File

@ -2,6 +2,7 @@
import { computed } from 'vue'
import { useNow } from '@vueuse/core'
import { useAuthStore } from '@/stores/auth'
import { useConfigStore } from '@/stores/config'
import { useColorScheme } from '@/composables/useColorScheme'
import LogoFull from '@/assets/logo-full.svg?component'
@ -13,9 +14,10 @@ const now = useNow({
})
const authStore = useAuthStore()
const configStore = useConfigStore()
const { isDark } = useColorScheme()
const Logo = computed(() => window.ALLOW_ICON_CHANGES
const Logo = computed(() => configStore.allowIconChanges
&& authStore.settings.frontendSettings.allowIconChanges
&& now.value.getMonth() === 5
? LogoFullPride

View File

@ -19,7 +19,6 @@ declare global {
API_URL: string;
SENTRY_ENABLED?: boolean;
SENTRY_DSN?: string;
ALLOW_ICON_CHANGES: boolean;
CUSTOM_LOGO_URL?: string;
CUSTOM_LOGO_URL_DARK?: string;
}

View File

@ -44,6 +44,7 @@ export interface ConfigState {
},
},
publicTeamsEnabled: boolean,
allowIconChanges: boolean,
enabledProFeatures: string[],
}
@ -84,6 +85,7 @@ export const useConfigStore = defineStore('config', () => {
},
},
publicTeamsEnabled: false,
allowIconChanges: true,
enabledProFeatures: [],
})

View File

@ -55,6 +55,7 @@ type vikunjaInfos struct {
DemoModeEnabled bool `json:"demo_mode_enabled"`
WebhooksEnabled bool `json:"webhooks_enabled"`
PublicTeamsEnabled bool `json:"public_teams_enabled"`
AllowIconChanges bool `json:"allow_icon_changes"`
EnabledProFeatures []license.Feature `json:"enabled_pro_features"`
}
@ -107,6 +108,7 @@ func Info(c *echo.Context) error {
DemoModeEnabled: config.ServiceDemoMode.GetBool(),
WebhooksEnabled: config.WebhooksEnabled.GetBool(),
PublicTeamsEnabled: config.ServiceEnablePublicTeams.GetBool(),
AllowIconChanges: config.ServiceAllowIconChanges.GetBool(),
EnabledProFeatures: license.EnabledProFeatures(),
AvailableMigrators: []string{
(&vikunja_file.FileMigrator{}).Name(),

View File

@ -48,7 +48,6 @@ const (
<script>
window.SENTRY_ENABLED = {{ .SENTRY_ENABLED }}
window.SENTRY_DSN = '{{ .SENTRY_DSN }}'
window.ALLOW_ICON_CHANGES = {{ .ALLOW_ICON_CHANGES }}
window.CUSTOM_LOGO_URL = '{{ .CUSTOM_LOGO_URL }}'
window.CUSTOM_LOGO_URL_DARK = '{{ .CUSTOM_LOGO_URL_DARK }}'
</script>`
@ -92,10 +91,6 @@ func serveIndexFile(c *echo.Context, assetFs http.FileSystem) (err error) {
data["SENTRY_ENABLED"] = "true"
}
data["SENTRY_DSN"] = config.SentryFrontendDsn.GetString()
data["ALLOW_ICON_CHANGES"] = "false"
if config.ServiceAllowIconChanges.GetBool() {
data["ALLOW_ICON_CHANGES"] = "true"
}
data["CUSTOM_LOGO_URL"] = config.ServiceCustomLogoURL.GetString()
data["CUSTOM_LOGO_URL_DARK"] = config.ServiceCustomLogoURLDark.GetString()