Просмотр исходного кода

feat(policy): add policy to show/hide version number

Made-with: Cursor
jamesread 4 месяцев назад
Родитель
Сommit
aa2bd95ccb

+ 5 - 1
frontend/resources/scripts/gen/olivetin/api/v1/olivetin_pb.d.ts

@@ -210,6 +210,11 @@ export declare type EffectivePolicy = Message<"olivetin.api.v1.EffectivePolicy">
    * @generated from field: bool show_log_list = 2;
    */
   showLogList: boolean;
+
+  /**
+   * @generated from field: bool show_version_number = 3;
+   */
+  showVersionNumber: boolean;
 };
 
 /**
@@ -1853,4 +1858,3 @@ export declare const OliveTinApiService: GenService<{
     output: typeof EntitySchema;
   },
 }>;
-

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
frontend/resources/scripts/gen/olivetin/api/v1/olivetin_pb.js


+ 11 - 9
frontend/resources/vue/App.vue

@@ -31,7 +31,7 @@
             <footer title="footer" v-if="showFooter">
                 <p>
                     <img title="application icon" :src="logoUrl" alt="OliveTin logo" style="height: 1em;" class="logo" />
-                    OliveTin {{ currentVersion }}
+                    OliveTin <span v-if="showVersionNumber">{{ currentVersion }}</span>
                 </p>
                 <p>
                     <span>
@@ -52,7 +52,7 @@
 
                     <span>{{ t('connected') }}</span>
                 </p>
-                <p>
+                <p v-if="showVersionNumber">
                     <a id="available-version" href="http://olivetin.app" target="_blank" hidden>?</a>
                 </p>
             </footer>
@@ -68,7 +68,7 @@
                 </option>
             </select>
             <p class="browser-languages">
-                {{ t('language-dialog.browser-languages') }}: 
+                {{ t('language-dialog.browser-languages') }}:
                 <span v-if="browserLanguages.length > 0">{{ browserLanguages.join(', ') }}</span>
                 <span v-else>{{ t('language-dialog.not-available') }}</span>
             </p>
@@ -126,6 +126,7 @@ const showFooter = ref(true)
 const showNavigation = ref(true)
 const showLogs = ref(true)
 const showDiagnostics = ref(true)
+const showVersionNumber = ref(true)
 const showLoginLink = ref(true)
 const sectionNavigationStyle = ref('sidebar')
 
@@ -184,7 +185,7 @@ function normalizeBrowserLanguage() {
     if (navigator.languages && navigator.languages.length > 0) {
         for (const candidate of navigator.languages) {
             const lowerCandidate = candidate.toLowerCase()
-            
+
             // Try exact match (case-insensitive)
             const exact = available.find(locale => locale.toLowerCase() === lowerCandidate)
             if (exact) {
@@ -223,6 +224,7 @@ function updateHeaderFromInit() {
     showNavigation.value = window.initResponse.showNavigation
     showLogs.value = window.initResponse.showLogList
     showDiagnostics.value = window.initResponse.showDiagnostics
+    showVersionNumber.value = window.initResponse.effectivePolicy?.showVersionNumber ?? true
     sectionNavigationStyle.value = window.initResponse.sectionNavigationStyle || 'sidebar'
     availableThemes.value = window.initResponse.availableThemes || []
 
@@ -277,7 +279,7 @@ function renderNavigation() {
 
 function openLanguageDialog() {
     selectedLanguage.value = languagePreference.value
-    
+
     if (typeof navigator !== 'undefined' && Array.isArray(navigator.languages)) {
         browserLanguages.value = navigator.languages
     } else {
@@ -327,7 +329,7 @@ function handleLanguageDialogClick(event) {
 
 function openThemeDialog() {
     selectedTheme.value = themePreference.value || ''
-    
+
     if (themeDialog.value) {
         themeDialog.value.showModal()
     }
@@ -354,7 +356,7 @@ function changeTheme() {
 
 function applyTheme() {
     let themeStyle = document.getElementById('theme-style')
-    
+
     if (!themeStyle) {
         themeStyle = document.createElement('style')
         themeStyle.id = 'theme-style'
@@ -404,10 +406,10 @@ window.updateHeaderFromInit = updateHeaderFromInit
 onMounted(() => {
     serverConnection.value = true;
     updateHeaderFromInit()
-    
+
     // Initialize selected language from stored preference
     selectedLanguage.value = languagePreference.value
-    
+
     // Initialize selected theme from stored preference
     selectedTheme.value = themePreference.value || ''
 

+ 5 - 2
frontend/resources/vue/views/DiagnosticsView.vue

@@ -162,7 +162,10 @@ async function generateBrowserInfo() {
       userAgentData: userAgentData
     }
 
-    const olivetinVersion = window.initResponse?.currentVersion || t('diagnostics.unknown')
+    const showVersionNumber = window.initResponse?.effectivePolicy?.showVersionNumber ?? true
+    const olivetinVersion = showVersionNumber
+      ? (window.initResponse?.currentVersion || t('diagnostics.unknown'))
+      : '[hidden]'
     const currentLanguage = locale.value || t('diagnostics.unknown')
 
     let output = '';
@@ -300,4 +303,4 @@ onMounted(() => {
   flex-direction: column;
   gap: 1em;
 }
-</style>
+</style>

+ 1 - 0
proto/olivetin/api/v1/olivetin.proto

@@ -51,6 +51,7 @@ message GetDashboardResponse {
 message EffectivePolicy {
 	bool show_diagnostics = 1;
 	bool show_log_list = 2;
+	bool show_version_number = 3;
 }
 
 message GetDashboardRequest {

+ 16 - 7
service/gen/olivetin/api/v1/olivetin.pb.go

@@ -410,11 +410,12 @@ func (x *GetDashboardResponse) GetDashboard() *Dashboard {
 }
 
 type EffectivePolicy struct {
-	state           protoimpl.MessageState `protogen:"open.v1"`
-	ShowDiagnostics bool                   `protobuf:"varint,1,opt,name=show_diagnostics,json=showDiagnostics,proto3" json:"show_diagnostics,omitempty"`
-	ShowLogList     bool                   `protobuf:"varint,2,opt,name=show_log_list,json=showLogList,proto3" json:"show_log_list,omitempty"`
-	unknownFields   protoimpl.UnknownFields
-	sizeCache       protoimpl.SizeCache
+	state             protoimpl.MessageState `protogen:"open.v1"`
+	ShowDiagnostics   bool                   `protobuf:"varint,1,opt,name=show_diagnostics,json=showDiagnostics,proto3" json:"show_diagnostics,omitempty"`
+	ShowLogList       bool                   `protobuf:"varint,2,opt,name=show_log_list,json=showLogList,proto3" json:"show_log_list,omitempty"`
+	ShowVersionNumber bool                   `protobuf:"varint,3,opt,name=show_version_number,json=showVersionNumber,proto3" json:"show_version_number,omitempty"`
+	unknownFields     protoimpl.UnknownFields
+	sizeCache         protoimpl.SizeCache
 }
 
 func (x *EffectivePolicy) Reset() {
@@ -461,6 +462,13 @@ func (x *EffectivePolicy) GetShowLogList() bool {
 	return false
 }
 
+func (x *EffectivePolicy) GetShowVersionNumber() bool {
+	if x != nil {
+		return x.ShowVersionNumber
+	}
+	return false
+}
+
 type GetDashboardRequest struct {
 	state         protoimpl.MessageState `protogen:"open.v1"`
 	Title         string                 `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"`
@@ -3934,10 +3942,11 @@ const file_olivetin_api_v1_olivetin_proto_rawDesc = "" +
 	"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"f\n" +
 	"\x14GetDashboardResponse\x12\x14\n" +
 	"\x05title\x18\x01 \x01(\tR\x05title\x128\n" +
-	"\tdashboard\x18\x04 \x01(\v2\x1a.olivetin.api.v1.DashboardR\tdashboard\"`\n" +
+	"\tdashboard\x18\x04 \x01(\v2\x1a.olivetin.api.v1.DashboardR\tdashboard\"\x90\x01\n" +
 	"\x0fEffectivePolicy\x12)\n" +
 	"\x10show_diagnostics\x18\x01 \x01(\bR\x0fshowDiagnostics\x12\"\n" +
-	"\rshow_log_list\x18\x02 \x01(\bR\vshowLogList\"k\n" +
+	"\rshow_log_list\x18\x02 \x01(\bR\vshowLogList\x12.\n" +
+	"\x13show_version_number\x18\x03 \x01(\bR\x11showVersionNumber\"k\n" +
 	"\x13GetDashboardRequest\x12\x14\n" +
 	"\x05title\x18\x01 \x01(\tR\x05title\x12\x1f\n" +
 	"\ventity_type\x18\x02 \x01(\tR\n" +

+ 13 - 4
service/internal/api/api.go

@@ -710,7 +710,9 @@ func (api *oliveTinAPI) WhoAmI(ctx ctx.Context, req *connect.Request[apiv1.WhoAm
 }
 
 func (api *oliveTinAPI) SosReport(ctx ctx.Context, req *connect.Request[apiv1.SosReportRequest]) (*connect.Response[apiv1.SosReportResponse], error) {
-	sos := installationinfo.GetSosReport()
+	user := auth.UserFromApiCall(ctx, req, api.cfg)
+	redactVersion := !user.EffectivePolicy.ShowVersionNumber
+	sos := installationinfo.GetSosReport(redactVersion)
 
 	if !api.cfg.InsecureAllowDumpSos {
 		log.Info(sos)
@@ -914,12 +916,19 @@ func (api *oliveTinAPI) Init(ctx ctx.Context, req *connect.Request[apiv1.InitReq
 
 	loginRequired := user.IsGuest() && api.cfg.AuthRequireGuestsToLogin
 
+	showVersion := user.EffectivePolicy.ShowVersionNumber
+	currentVersion := ""
+	availableVersion := ""
+	if showVersion {
+		currentVersion = installationinfo.Build.Version
+		availableVersion = installationinfo.Runtime.AvailableVersion
+	}
 	res := &apiv1.InitResponse{
 		ShowFooter:                api.cfg.ShowFooter,
 		ShowNavigation:            api.cfg.ShowNavigation,
-		ShowNewVersions:           api.cfg.ShowNewVersions,
-		AvailableVersion:          installationinfo.Runtime.AvailableVersion,
-		CurrentVersion:            installationinfo.Build.Version,
+		ShowNewVersions:           showVersion && api.cfg.ShowNewVersions,
+		AvailableVersion:          availableVersion,
+		CurrentVersion:            currentVersion,
 		PageTitle:                 api.cfg.PageTitle,
 		SectionNavigationStyle:    api.cfg.SectionNavigationStyle,
 		DefaultIconForBack:        api.cfg.DefaultIconForBack,

+ 3 - 2
service/internal/api/apiActions.go

@@ -55,8 +55,9 @@ func matchesEntity(binding *executor.ActionBinding, entity *entities.Entity) boo
 
 func buildEffectivePolicy(policy *config.ConfigurationPolicy) *apiv1.EffectivePolicy {
 	ret := &apiv1.EffectivePolicy{
-		ShowDiagnostics: policy.ShowDiagnostics,
-		ShowLogList:     policy.ShowLogList,
+		ShowDiagnostics:   policy.ShowDiagnostics,
+		ShowLogList:       policy.ShowLogList,
+		ShowVersionNumber: policy.ShowVersionNumber,
 	}
 
 	return ret

+ 7 - 2
service/internal/auth/authpublic/authenticateduser.go

@@ -76,8 +76,9 @@ func (u *AuthenticatedUser) BuildUserAcls(cfg *config.Config) {
 
 func getEffectivePolicy(cfg *config.Config, u *AuthenticatedUser) *config.ConfigurationPolicy {
 	ret := &config.ConfigurationPolicy{
-		ShowDiagnostics: cfg.DefaultPolicy.ShowDiagnostics,
-		ShowLogList:     cfg.DefaultPolicy.ShowLogList,
+		ShowDiagnostics:   cfg.DefaultPolicy.ShowDiagnostics,
+		ShowLogList:       cfg.DefaultPolicy.ShowLogList,
+		ShowVersionNumber: cfg.DefaultPolicy.ShowVersionNumber,
 	}
 
 	for _, acl := range cfg.AccessControlLists {
@@ -98,5 +99,9 @@ func buildConfigurationPolicy(ret *config.ConfigurationPolicy, policy config.Con
 		ret.ShowLogList = policy.ShowLogList
 	}
 
+	if policy.ShowVersionNumber {
+		ret.ShowVersionNumber = policy.ShowVersionNumber
+	}
+
 	return ret
 }

+ 4 - 2
service/internal/config/config.go

@@ -98,8 +98,9 @@ type AccessControlList struct {
 
 // ConfigurationPolicy defines global settings which are overridden with an ACL.
 type ConfigurationPolicy struct {
-	ShowDiagnostics bool `koanf:"showDiagnostics"`
-	ShowLogList     bool `koanf:"showLogList"`
+	ShowDiagnostics   bool `koanf:"showDiagnostics"`
+	ShowLogList       bool `koanf:"showLogList"`
+	ShowVersionNumber bool `koanf:"showVersionNumber"`
 }
 
 type PrometheusConfig struct {
@@ -297,6 +298,7 @@ func DefaultConfigWithBasePort(basePort int) *Config {
 
 	config.DefaultPolicy.ShowDiagnostics = true
 	config.DefaultPolicy.ShowLogList = true
+	config.DefaultPolicy.ShowVersionNumber = true
 
 	return &config
 }

+ 11 - 3
service/internal/installationinfo/sosreport.go

@@ -40,15 +40,23 @@ func configToSosreport(cfg *config.Config) *sosReportConfig {
 	}
 }
 
-func GetSosReport() string {
+func GetSosReport(redactVersion bool) string {
 	ret := ""
 
 	ret += "### SOSREPORT START (copy all text to SOSREPORT END)\n"
 
-	out, _ := yaml.Marshal(Build)
+	buildForReport := *Build
+	if redactVersion {
+		buildForReport.Version = "[redacted]"
+	}
+	out, _ := yaml.Marshal(&buildForReport)
 	ret += fmt.Sprintf("# Build: \n%+v\n", string(out))
 
-	out, _ = yaml.Marshal(Runtime)
+	runtimeForReport := *Runtime
+	if redactVersion {
+		runtimeForReport.AvailableVersion = "[redacted]"
+	}
+	out, _ = yaml.Marshal(&runtimeForReport)
 	ret += fmt.Sprintf("# Runtime:\n%+v\n", string(out))
 
 	out, _ = yaml.Marshal(configToSosreport(Config))

Некоторые файлы не были показаны из-за большого количества измененных файлов