diff --git a/server/i18n/en.json b/server/i18n/en.json
index 789ae0a4b8..ba8723e139 100644
--- a/server/i18n/en.json
+++ b/server/i18n/en.json
@@ -9296,6 +9296,30 @@
"id": "model.config.is_valid.encrypt_sql.app_error",
"translation": "Invalid at rest encrypt key for SQL settings. Must be 32 chars or more."
},
+ {
+ "id": "model.config.is_valid.experimental_audit_settings.file_max_age_invalid",
+ "translation": "Max File Age of audit logs config must not be negative."
+ },
+ {
+ "id": "model.config.is_valid.experimental_audit_settings.file_max_backups_invalid",
+ "translation": "Maximum File Backups of audit logs config must not be negative."
+ },
+ {
+ "id": "model.config.is_valid.experimental_audit_settings.file_max_queue_size_invalid",
+ "translation": "Maximum File Queue of audit logs config must be greater than zero."
+ },
+ {
+ "id": "model.config.is_valid.experimental_audit_settings.file_max_size_invalid",
+ "translation": "Maximum File Size of audit logs config must be greater than zero."
+ },
+ {
+ "id": "model.config.is_valid.experimental_audit_settings.file_name_empty",
+ "translation": "When audit file logging is enabled, a file name must be specified."
+ },
+ {
+ "id": "model.config.is_valid.experimental_audit_settings.file_name_is_directory",
+ "translation": "The file name must not be a directory."
+ },
{
"id": "model.config.is_valid.export.directory.app_error",
"translation": "Value for Directory should not be empty."
diff --git a/server/public/model/config.go b/server/public/model/config.go
index 420273bdc1..96b54c2a23 100644
--- a/server/public/model/config.go
+++ b/server/public/model/config.go
@@ -1568,6 +1568,47 @@ type ExperimentalAuditSettings struct {
Certificate *string `access:"experimental_features"` // telemetry: none
}
+func (s *ExperimentalAuditSettings) isValid() *AppError {
+ if *s.FileEnabled {
+ if *s.FileName == "" {
+ return NewAppError("ExperimentalAuditSettings.isValid", "model.config.is_valid.experimental_audit_settings.file_name_empty", nil, "", http.StatusBadRequest)
+ }
+
+ if strings.HasSuffix(*s.FileName, `\`) {
+ return NewAppError("ExperimentalAuditSettings.isValid", "model.config.is_valid.experimental_audit_settings.file_name_is_directory", nil, "", http.StatusBadRequest)
+ }
+
+ if *s.FileMaxSizeMB <= 0 {
+ return NewAppError("ExperimentalAuditSettings.isValid", "model.config.is_valid.experimental_audit_settings.file_max_size_invalid", nil, "", http.StatusBadRequest)
+ }
+
+ if *s.FileMaxAgeDays < 0 {
+ return NewAppError("ExperimentalAuditSettings.isValid", "model.config.is_valid.experimental_audit_settings.file_max_age_invalid", nil, "", http.StatusBadRequest)
+ }
+
+ if *s.FileMaxBackups < 0 {
+ return NewAppError("ExperimentalAuditSettings.isValid", "model.config.is_valid.experimental_audit_settings.file_max_backups_invalid", nil, "", http.StatusBadRequest)
+ }
+
+ if *s.FileMaxQueueSize <= 0 {
+ return NewAppError("ExperimentalAuditSettings.isValid", "model.config.is_valid.experimental_audit_settings.file_max_queue_size_invalid", nil, "", http.StatusBadRequest)
+ }
+ }
+
+ cfg := make(mlog.LoggerConfiguration)
+ err := json.Unmarshal(s.AdvancedLoggingJSON, &cfg)
+ if err != nil {
+ return NewAppError("ExperimentalAuditSettings.isValid", "model.config.is_valid.log.advanced_logging.json", map[string]any{"Error": err}, "", http.StatusBadRequest).Wrap(err)
+ }
+
+ err = cfg.IsValid()
+ if err != nil {
+ return NewAppError("ExperimentalAuditSettings.isValid", "model.config.is_valid.log.advanced_logging.parse", map[string]any{"Error": err}, "", http.StatusBadRequest).Wrap(err)
+ }
+
+ return nil
+}
+
func (s *ExperimentalAuditSettings) SetDefaults() {
if s.FileEnabled == nil {
s.FileEnabled = NewPointer(false)
@@ -4040,6 +4081,10 @@ func (o *Config) IsValid() *AppError {
return appErr
}
+ if appErr := o.ExperimentalAuditSettings.isValid(); appErr != nil {
+ return appErr
+ }
+
if appErr := o.LocalizationSettings.isValid(); appErr != nil {
return appErr
}
diff --git a/server/public/model/config_test.go b/server/public/model/config_test.go
index b85fea15bc..809e1eb1c2 100644
--- a/server/public/model/config_test.go
+++ b/server/public/model/config_test.go
@@ -1402,6 +1402,8 @@ func TestLdapSettingsIsValid(t *testing.T) {
}
func TestLogSettingsIsValid(t *testing.T) {
+ t.Parallel()
+
for name, test := range map[string]struct {
LogSettings LogSettings
ExpectError bool
@@ -2163,6 +2165,115 @@ func TestConfigDefaultConnectedWorkspacesSettings(t *testing.T) {
})
}
+func TestExperimentalAuditSettingsIsValid(t *testing.T) {
+ t.Parallel()
+
+ for name, test := range map[string]struct {
+ ExperimentalAuditSettings ExperimentalAuditSettings
+ ExpectError bool
+ }{
+ "empty settings": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{},
+ ExpectError: false,
+ },
+ "file enabled with empty filename": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ FileEnabled: NewPointer(true),
+ FileName: NewPointer(""),
+ },
+ ExpectError: true,
+ },
+ "file enabled with valid filename": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ FileEnabled: NewPointer(true),
+ FileName: NewPointer("audit.log"),
+ FileMaxSizeMB: NewPointer(100),
+ FileMaxAgeDays: NewPointer(5),
+ FileMaxBackups: NewPointer(10),
+ FileMaxQueueSize: NewPointer(1000),
+ },
+ ExpectError: false,
+ },
+ "invalid file max size": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ FileEnabled: NewPointer(true),
+ FileName: NewPointer("audit.log"),
+ FileMaxSizeMB: NewPointer(0),
+ },
+ ExpectError: true,
+ },
+ "negative file max size": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ FileEnabled: NewPointer(true),
+ FileName: NewPointer("audit.log"),
+ FileMaxSizeMB: NewPointer(-10),
+ },
+ ExpectError: true,
+ },
+ "negative file max age": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ FileEnabled: NewPointer(true),
+ FileName: NewPointer("audit.log"),
+ FileMaxSizeMB: NewPointer(100),
+ FileMaxAgeDays: NewPointer(-5),
+ },
+ ExpectError: true,
+ },
+ "negative file max backups": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ FileEnabled: NewPointer(true),
+ FileName: NewPointer("audit.log"),
+ FileMaxSizeMB: NewPointer(100),
+ FileMaxAgeDays: NewPointer(5),
+ FileMaxBackups: NewPointer(-10),
+ },
+ ExpectError: true,
+ },
+ "zero file max queue size": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ FileEnabled: NewPointer(true),
+ FileName: NewPointer("audit.log"),
+ FileMaxSizeMB: NewPointer(100),
+ FileMaxAgeDays: NewPointer(5),
+ FileMaxBackups: NewPointer(10),
+ FileMaxQueueSize: NewPointer(0),
+ },
+ ExpectError: true,
+ },
+ "negative file max queue size": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ FileEnabled: NewPointer(true),
+ FileName: NewPointer("audit.log"),
+ FileMaxSizeMB: NewPointer(100),
+ FileMaxAgeDays: NewPointer(5),
+ FileMaxBackups: NewPointer(10),
+ FileMaxQueueSize: NewPointer(-1000),
+ },
+ ExpectError: true,
+ },
+ "AdvancedLoggingJSON has JSON error ": {
+ ExperimentalAuditSettings: ExperimentalAuditSettings{
+ AdvancedLoggingJSON: json.RawMessage(`
+ {
+ "foo": "bar",
+ `),
+ },
+ ExpectError: true,
+ },
+ } {
+ t.Run(name, func(t *testing.T) {
+ test.ExperimentalAuditSettings.SetDefaults()
+
+ appErr := test.ExperimentalAuditSettings.isValid()
+ if test.ExpectError {
+ require.NotNil(t, appErr)
+ } else {
+ require.Nil(t, appErr)
+ }
+ })
+ }
+}
+
func TestFilterConfig(t *testing.T) {
t.Run("should clear default values", func(t *testing.T) {
cfg := &Config{}
diff --git a/server/public/model/feature_flags.go b/server/public/model/feature_flags.go
index 5f67c16d95..f8acdbed0c 100644
--- a/server/public/model/feature_flags.go
+++ b/server/public/model/feature_flags.go
@@ -93,7 +93,7 @@ func (f *FeatureFlags) SetDefaults() {
f.ChannelBookmarks = true
f.WebSocketEventScope = true
f.NotificationMonitoring = true
- f.ExperimentalAuditSettingsSystemConsoleUI = false
+ f.ExperimentalAuditSettingsSystemConsoleUI = true
f.CustomProfileAttributes = true
f.AttributeBasedAccessControl = true
}
diff --git a/webapp/channels/src/components/admin_console/admin_definition.tsx b/webapp/channels/src/components/admin_console/admin_definition.tsx
index 117e0ecf4b..42b717e8d9 100644
--- a/webapp/channels/src/components/admin_console/admin_definition.tsx
+++ b/webapp/channels/src/components/admin_console/admin_definition.tsx
@@ -5613,6 +5613,149 @@ const AdminDefinition: AdminDefinitionType = {
],
},
},
+ audit_logging: {
+ url: 'compliance/audit_logging',
+ title: defineMessage({id: 'admin.sidebar.audit_logging_experimental', defaultMessage: 'Audit Logging'}),
+ isHidden: it.any(
+ it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ it.configIsFalse('FeatureFlags', 'ExperimentalAuditSettingsSystemConsoleUI'),
+ it.not(it.minLicenseTier(LicenseSkus.Enterprise)),
+ ),
+ schema: {
+ id: 'ExperimentalAuditSettings',
+ name: 'Audit logging (Beta)',
+ settings: [
+ {
+ type: 'banner',
+ label: defineMessage({id: 'admin.rate.noteDescription', defaultMessage: 'Changing properties in this section will require a server restart before taking effect.'}),
+ banner_type: 'info',
+ },
+ {
+ type: 'bool',
+ key: 'ExperimentalAuditSettings.FileEnabled',
+ label: defineMessage({id: 'admin.audit_logging_experimental.file_enabled.title', defaultMessage: 'File Enabled'}),
+ help_text: defineMessage({id: 'admin.audit_logging_experimental.file_enabled.help_text', defaultMessage: 'Choose whether audit logs are written locally to a file or not.'}),
+ isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ isHidden: it.licensedForFeature('Cloud'),
+ },
+ {
+ type: 'text',
+ key: 'ExperimentalAuditSettings.FileName',
+ label: defineMessage({id: 'admin.audit_logging_experimental.file_name.title', defaultMessage: 'File Name'}),
+ help_text: defineMessage({id: 'admin.audit_logging_experimental.file_name.help_text', defaultMessage: 'The name of the file to write to.'}),
+ isDisabled: it.any(
+ it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ it.stateIsFalse('ExperimentalAuditSettings.FileEnabled'),
+ ),
+ isHidden: it.licensedForFeature('Cloud'),
+ },
+ {
+ type: 'number',
+ key: 'ExperimentalAuditSettings.FileMaxSizeMB',
+ label: defineMessage({id: 'admin.audit_logging_experimental.file_max_size.title', defaultMessage: 'Max File Size (MB)'}),
+ help_text: defineMessage({id: 'admin.audit_logging_experimental.file_max_size.help_text', defaultMessage: 'Maximum size, in megabytes (MB), the log file can grow before it gets rotated.'}),
+ isDisabled: it.any(
+ it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ it.stateIsFalse('ExperimentalAuditSettings.FileEnabled'),
+ ),
+ isHidden: it.licensedForFeature('Cloud'),
+ },
+ {
+ type: 'number',
+ key: 'ExperimentalAuditSettings.FileMaxAgeDays',
+ label: defineMessage({id: 'admin.audit_logging_experimental.file_max_age.title', defaultMessage: 'Max File Age (Days)'}),
+ help_text: defineMessage({id: 'admin.audit_logging_experimental.file_max_age.help_text', defaultMessage: 'Maximum number of days to retain old log files. 0 disables the removal of old log files.'}),
+ isDisabled: it.any(
+ it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ it.stateIsFalse('ExperimentalAuditSettings.FileEnabled'),
+ ),
+ isHidden: it.licensedForFeature('Cloud'),
+ },
+ {
+ type: 'number',
+ key: 'ExperimentalAuditSettings.FileMaxBackups',
+ label: defineMessage({id: 'admin.audit_logging_experimental.file_max_backups.title', defaultMessage: 'Maximum File Backups'}),
+ help_text: defineMessage({id: 'admin.audit_logging_experimental.file_max_backups.help_text', defaultMessage: 'Maximum number of old log files to retain. 0 retains all old log files. Note: Configuring Max File Age can result in old log files being deleted regardless of this configuration value.'}),
+ isDisabled: it.any(
+ it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ it.stateIsFalse('ExperimentalAuditSettings.FileEnabled'),
+ ),
+ isHidden: it.licensedForFeature('Cloud'),
+ },
+ {
+ type: 'bool',
+ key: 'ExperimentalAuditSettings.FileCompress',
+ label: defineMessage({id: 'admin.audit_logging_experimental.file_compress.title', defaultMessage: 'File Compression'}),
+ help_text: defineMessage({id: 'admin.audit_logging_experimental.file_compress.help_text', defaultMessage: 'Choose whether enable or disable file compression.'}),
+ isDisabled: it.any(
+ it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ it.stateIsFalse('ExperimentalAuditSettings.FileEnabled'),
+ ),
+ isHidden: it.licensedForFeature('Cloud'),
+ },
+ {
+ type: 'number',
+ key: 'ExperimentalAuditSettings.FileMaxQueueSize',
+ label: defineMessage({id: 'admin.audit_logging_experimental.file_max_queue_size.title', defaultMessage: 'Maximum File Queue'}),
+ help_text: defineMessage({id: 'admin.audit_logging_experimental.file_max_queue_size.help_text', defaultMessage: 'The maximum number of files to be retained in the queue.'}),
+ isDisabled: it.any(
+ it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ it.stateIsFalse('ExperimentalAuditSettings.FileEnabled'),
+ ),
+ isHidden: it.licensedForFeature('Cloud'),
+ },
+ {
+ type: 'longtext',
+ key: 'ExperimentalAuditSettings.AdvancedLoggingJSON',
+ label: defineMessage({id: 'admin.log.AdvancedLoggingJSONTitle', defaultMessage: 'Advanced Logging:'}),
+ help_text: defineMessage({id: 'admin.log.AdvancedLoggingJSONDescription', defaultMessage: 'The JSON configuration for Advanced Audit Logging. Please see documentation to learn more about Advanced Logging and the JSON format it uses.'}),
+ help_text_markdown: false,
+ help_text_values: {
+ link: (msg: string) => (
+
+ {msg}
+
+ ),
+ },
+ placeholder: defineMessage({id: 'admin.log.AdvancedLoggingJSONPlaceholder', defaultMessage: 'Enter your JSON configuration'}),
+ isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ validate: (value) => {
+ const valid = new ValidationResult(true, '');
+ if (!value) {
+ return valid;
+ }
+ try {
+ JSON.parse(value);
+ return valid;
+ } catch (error) {
+ return new ValidationResult(false, error.message);
+ }
+ },
+ onConfigLoad: (configVal) => JSON.stringify(configVal, null, ' '),
+ onConfigSave: (displayVal) => {
+ // Handle case where field is empty
+ if (!displayVal) {
+ return {undefined};
+ }
+
+ return JSON.parse(displayVal);
+ },
+ },
+ {
+ type: 'custom',
+ component: AuditLoggingCertificateUploadSetting,
+ label: defineMessage({id: 'admin.audit_logging_experimental.certificate.title', defaultMessage: 'Certificate'}),
+ key: 'ExperimentalAuditSettings.Certificate',
+ help_text: defineMessage({id: 'admin.audit_logging_experimental.certificate.help_text', defaultMessage: 'The certificate file used for audit logging encryption.'}),
+ isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
+ isHidden: it.not(it.licensedForFeature('Cloud')),
+ },
+ ],
+ },
+ },
custom_terms_of_service: {
url: 'compliance/custom_terms_of_service',
title: defineMessage({id: 'admin.sidebar.customTermsOfService', defaultMessage: 'Custom Terms of Service'}),
@@ -6086,126 +6229,6 @@ const AdminDefinition: AdminDefinitionType = {
component: BleveSettings,
},
},
- audit_logging: {
- url: 'experimental/audit_logging',
- title: defineMessage({id: 'admin.sidebar.audit_logging_experimental', defaultMessage: 'Audit Logging'}),
- isHidden: it.any(
- it.not(it.userHasReadPermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- it.configIsFalse('FeatureFlags', 'ExperimentalAuditSettingsSystemConsoleUI'),
- it.not(it.minLicenseTier(LicenseSkus.Enterprise)),
- ),
- schema: {
- id: 'ExperimentalAuditSettings',
- name: 'Audit Log Settings (Experimental)',
- settings: [
- {
- type: 'bool',
- key: 'ExperimentalAuditSettings.FileEnabled',
- label: defineMessage({id: 'admin.audit_logging_experimental.file_enabled.title', defaultMessage: 'File Enabled'}),
- help_text: defineMessage({id: 'admin.audit_logging_experimental.file_enabled.help_text', defaultMessage: 'Choose whether audit logs are written locally to a file or not.'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- isHidden: it.licensedForFeature('Cloud'),
- },
- {
- type: 'text',
- key: 'ExperimentalAuditSettings.FileName',
- label: defineMessage({id: 'admin.audit_logging_experimental.file_name.title', defaultMessage: 'File Name'}),
- help_text: defineMessage({id: 'admin.audit_logging_experimental.file_name.help_text', defaultMessage: 'The name of the file to write to. NOTE: If ExperimentalAuditSettings.FileEnabled is set to TRUE, this field is required.'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- isHidden: it.licensedForFeature('Cloud'),
- },
- {
- type: 'number',
- key: 'ExperimentalAuditSettings.FileMaxSizeMB',
- label: defineMessage({id: 'admin.audit_logging_experimental.file_max_size.title', defaultMessage: 'Max File Size (MB)'}),
- help_text: defineMessage({id: 'admin.audit_logging_experimental.file_max_size.help_text', defaultMessage: 'The maximum size of a single exported file, in MB.'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- isHidden: it.licensedForFeature('Cloud'),
- },
- {
- type: 'number',
- key: 'ExperimentalAuditSettings.FileMaxAgeDays',
- label: defineMessage({id: 'admin.audit_logging_experimental.file_max_age.title', defaultMessage: 'Max File Age (Days)'}),
- help_text: defineMessage({id: 'admin.audit_logging_experimental.file_max_age.help_text', defaultMessage: 'The maximum age of an exported file, in days.'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- isHidden: it.licensedForFeature('Cloud'),
- },
- {
- type: 'number',
- key: 'ExperimentalAuditSettings.FileMaxBackups',
- label: defineMessage({id: 'admin.audit_logging_experimental.file_max_backups.title', defaultMessage: 'Maximum File Backups'}),
- help_text: defineMessage({id: 'admin.audit_logging_experimental.file_max_backups.help_text', defaultMessage: 'The maximum number of backup files to retain'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- isHidden: it.licensedForFeature('Cloud'),
- },
- {
- type: 'bool',
- key: 'ExperimentalAuditSettings.FileCompress',
- label: defineMessage({id: 'admin.audit_logging_experimental.file_compress.title', defaultMessage: 'File Compression'}),
- help_text: defineMessage({id: 'admin.audit_logging_experimental.file_compress.help_text', defaultMessage: 'Choose whether enable or disable file compression.'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- isHidden: it.licensedForFeature('Cloud'),
- },
- {
- type: 'number',
- key: 'ExperimentalAuditSettings.FileMaxQueueSize',
- label: defineMessage({id: 'admin.audit_logging_experimental.file_max_queue_size.title', defaultMessage: 'Maximum File Queue'}),
- help_text: defineMessage({id: 'admin.audit_logging_experimental.file_max_queue_size.help_text', defaultMessage: 'The maximum number of files to be retained in the queue.'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- isHidden: it.licensedForFeature('Cloud'),
- },
- {
- type: 'longtext',
- key: 'ExperimentalAuditSettings.AdvancedLoggingJSON',
- label: defineMessage({id: 'admin.log.AdvancedLoggingJSONTitle', defaultMessage: 'Advanced Logging:'}),
- help_text: defineMessage({id: 'admin.log.AdvancedLoggingJSONDescription', defaultMessage: 'The JSON configuration for Advanced Audit Logging. Please see documentation to learn more about Advanced Logging and the JSON format it uses.'}),
- help_text_markdown: false,
- help_text_values: {
- link: (msg: string) => (
-
- {msg}
-
- ),
- },
- placeholder: defineMessage({id: 'admin.log.AdvancedLoggingJSONPlaceholder', defaultMessage: 'Enter your JSON configuration'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- validate: (value) => {
- const valid = new ValidationResult(true, '');
- if (!value) {
- return valid;
- }
- try {
- JSON.parse(value);
- return valid;
- } catch (error) {
- return new ValidationResult(false, error.message);
- }
- },
- onConfigLoad: (configVal) => JSON.stringify(configVal, null, ' '),
- onConfigSave: (displayVal) => {
- // Handle case where field is empty
- if (!displayVal) {
- return {undefined};
- }
-
- return JSON.parse(displayVal);
- },
- },
- {
- type: 'custom',
- component: AuditLoggingCertificateUploadSetting,
- label: defineMessage({id: 'admin.audit_logging_experimental.certificate.title', defaultMessage: 'Certificate'}),
- key: 'ExperimentalAuditSettings.Certificate',
- help_text: defineMessage({id: 'admin.audit_logging_experimental.certificate.help_text', defaultMessage: 'The certificate file used for audit logging encryption.'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.EXPERIMENTAL.FEATURES)),
- isHidden: it.not(it.licensedForFeature('Cloud')),
- },
- ],
- },
- },
},
},
};
diff --git a/webapp/channels/src/components/admin_console/admin_sidebar/__snapshots__/admin_sidebar.test.tsx.snap b/webapp/channels/src/components/admin_console/admin_sidebar/__snapshots__/admin_sidebar.test.tsx.snap
index fa4489dc5a..4a3aef70e9 100644
--- a/webapp/channels/src/components/admin_console/admin_sidebar/__snapshots__/admin_sidebar.test.tsx.snap
+++ b/webapp/channels/src/components/admin_console/admin_sidebar/__snapshots__/admin_sidebar.test.tsx.snap
@@ -1871,6 +1871,17 @@ exports[`components/AdminSidebar should match snapshot with license with enterpr
/>
}
/>
+
+ }
+ />
}
/>
-
- }
- />
@@ -2948,6 +2948,17 @@ exports[`components/AdminSidebar should match snapshot with license with enterpr
/>
}
/>
+
+ }
+ />
}
/>
-
- }
- />
diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json
index 5d2a84cfc0..40fd83b2bc 100644
--- a/webapp/channels/src/i18n/en.json
+++ b/webapp/channels/src/i18n/en.json
@@ -362,15 +362,15 @@
"admin.audit_logging_experimental.file_compress.title": "File Compression",
"admin.audit_logging_experimental.file_enabled.help_text": "Choose whether audit logs are written locally to a file or not.",
"admin.audit_logging_experimental.file_enabled.title": "File Enabled",
- "admin.audit_logging_experimental.file_max_age.help_text": "The maximum age of an exported file, in days.",
+ "admin.audit_logging_experimental.file_max_age.help_text": "Maximum number of days to retain old log files. 0 disables the removal of old log files.",
"admin.audit_logging_experimental.file_max_age.title": "Max File Age (Days)",
- "admin.audit_logging_experimental.file_max_backups.help_text": "The maximum number of backup files to retain",
+ "admin.audit_logging_experimental.file_max_backups.help_text": "Maximum number of old log files to retain. 0 retains all old log files. Note: Configuring Max File Age can result in old log files being deleted regardless of this configuration value.",
"admin.audit_logging_experimental.file_max_backups.title": "Maximum File Backups",
"admin.audit_logging_experimental.file_max_queue_size.help_text": "The maximum number of files to be retained in the queue.",
"admin.audit_logging_experimental.file_max_queue_size.title": "Maximum File Queue",
- "admin.audit_logging_experimental.file_max_size.help_text": "The maximum size of a single exported file, in MB.",
+ "admin.audit_logging_experimental.file_max_size.help_text": "Maximum size, in megabytes (MB), the log file can grow before it gets rotated.",
"admin.audit_logging_experimental.file_max_size.title": "Max File Size (MB)",
- "admin.audit_logging_experimental.file_name.help_text": "The name of the file to write to. NOTE: If ExperimentalAuditSettings.FileEnabled is set to TRUE, this field is required.",
+ "admin.audit_logging_experimental.file_name.help_text": "The name of the file to write to.",
"admin.audit_logging_experimental.file_name.title": "File Name",
"admin.audits.reload": "Reload User Activity Logs",
"admin.authentication.email": "Email Authentication",