diff --git a/e2e-tests/playwright/lib/src/server/default_config.ts b/e2e-tests/playwright/lib/src/server/default_config.ts
index 9f63620d9fe..7101bf87b9d 100644
--- a/e2e-tests/playwright/lib/src/server/default_config.ts
+++ b/e2e-tests/playwright/lib/src/server/default_config.ts
@@ -804,7 +804,6 @@ const defaultServerConfig: AdminConfig = {
WysiwygEditor: false,
EnableExportDirectDownload: false,
MoveThreadsEnabled: false,
- CloudDedicatedExportUI: false,
NotificationMonitoring: true,
CustomProfileAttributes: true,
AttributeValueMasking: false,
diff --git a/server/channels/api4/system.go b/server/channels/api4/system.go
index 4b96ba5f45c..15c26b055ab 100644
--- a/server/channels/api4/system.go
+++ b/server/channels/api4/system.go
@@ -591,12 +591,10 @@ func testFileStore(c *Context, w http.ResponseWriter, r *http.Request) {
// Validate mandatory fields per driver. TestFileStoreConnectionWithConfig
// will catch missing fields by failing to construct the backend, but a
// dedicated validation step lets us surface a clearer error.
- //
- // When the dedicated export filestore is active the backend that is
- // actually built and tested is the export backend, so we have to dispatch
- // on ExportDriverName -- otherwise a primary=S3 / export=Azure deployment
- // would run the S3 field check while testing the Azure backend.
- driver := c.App.ResolvedFileStoreDriverName(&cfg.FileSettings)
+ driver := ""
+ if cfg.FileSettings.DriverName != nil {
+ driver = *cfg.FileSettings.DriverName
+ }
switch driver {
case model.ImageDriverLocal:
// Local driver has no mandatory fields beyond the directory, which has a default.
diff --git a/server/channels/api4/system_test.go b/server/channels/api4/system_test.go
index c838b79575a..4bcd37cbf8b 100644
--- a/server/channels/api4/system_test.go
+++ b/server/channels/api4/system_test.go
@@ -826,87 +826,6 @@ func TestS3TestConnection(t *testing.T) {
})
}
-func TestFileStoreTestConnection(t *testing.T) {
- mainHelper.Parallel(t)
- th := SetupConfig(t, func(cfg *model.Config) {
- cfg.FeatureFlags.CloudDedicatedExportUI = true
- cfg.FileSettings.DedicatedExportStore = model.NewPointer(true)
- })
-
- th.App.Srv().SetLicense(model.NewTestLicense("cloud"))
- t.Cleanup(func() { th.App.Srv().SetLicense(nil) })
-
- baseSettings := func(primary, export string) model.FileSettings {
- fs := model.FileSettings{}
- fs.SetDefaults(false)
- fs.DriverName = model.NewPointer(primary)
- fs.ExportDriverName = model.NewPointer(export)
- return fs
- }
-
- t.Run("primary=local, export=azure: missing ExportAzureContainer surfaces azure error", func(t *testing.T) {
- fs := baseSettings(model.ImageDriverLocal, model.ImageDriverAzure)
- fs.ExportAzureStorageAccount = model.NewPointer("acmemattermost")
- fs.ExportAzureAccessKey = model.NewPointer("secret")
- fs.ExportAzureContainer = model.NewPointer("")
-
- resp, err := th.SystemAdminClient.TestS3Connection(context.Background(), &model.Config{FileSettings: fs})
- require.Error(t, err)
- CheckErrorID(t, err, "api.admin.test_azure.missing_azure_field")
- CheckBadRequestStatus(t, resp)
- })
-
- t.Run("primary=s3, export=azure: missing ExportAzureStorageAccount surfaces azure error", func(t *testing.T) {
- fs := baseSettings(model.ImageDriverS3, model.ImageDriverAzure)
- fs.ExportAzureStorageAccount = model.NewPointer("")
- fs.ExportAzureContainer = model.NewPointer("mattermost")
- fs.ExportAzureAccessKey = model.NewPointer("secret")
-
- resp, err := th.SystemAdminClient.TestS3Connection(context.Background(), &model.Config{FileSettings: fs})
- require.Error(t, err)
- CheckErrorID(t, err, "api.admin.test_azure.missing_azure_field")
- CheckBadRequestStatus(t, resp)
- })
-
- t.Run("primary=local, export=s3: missing ExportAmazonS3Bucket surfaces s3 error", func(t *testing.T) {
- fs := baseSettings(model.ImageDriverLocal, model.ImageDriverS3)
- fs.ExportAmazonS3Bucket = model.NewPointer("")
-
- resp, err := th.SystemAdminClient.TestS3Connection(context.Background(), &model.Config{FileSettings: fs})
- require.Error(t, err)
- CheckErrorID(t, err, "api.admin.test_s3.missing_s3_bucket")
- CheckBadRequestStatus(t, resp)
- })
-
- t.Run("unsupported export driver", func(t *testing.T) {
- fs := baseSettings(model.ImageDriverS3, "bogus")
-
- resp, err := th.SystemAdminClient.TestS3Connection(context.Background(), &model.Config{FileSettings: fs})
- require.Error(t, err)
- CheckErrorID(t, err, "api.file.test_connection_unsupported_driver.app_error")
- CheckBadRequestStatus(t, resp)
- })
-
- t.Run("no license - primary dispatch", func(t *testing.T) {
- // No license is set, so UseExportFileStore() must return false. Set an
- // ExportDriverName that, if it were honored, would change the dispatch
- // outcome -- this asserts that the primary path is taken.
- appErr := th.App.Srv().RemoveLicense()
- require.Nil(t, appErr)
- fs := baseSettings(model.ImageDriverAzure, model.ImageDriverS3)
-
- // fs.AzureStorageAccount = model.NewPointer("")
- // fs.AzureContainer = model.NewPointer("mattermost")
- // fs.AzureAccessKey = model.NewPointer("secret")
- // fs.ExportAmazonS3Bucket = model.NewPointer("export-bucket")
-
- resp, err := th.SystemAdminClient.TestS3Connection(context.Background(), &model.Config{FileSettings: fs})
- require.Error(t, err)
- CheckErrorID(t, err, "api.admin.test_azure.missing_azure_field")
- CheckBadRequestStatus(t, resp)
- })
-}
-
func TestSupportedTimezones(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t)
diff --git a/server/channels/app/file.go b/server/channels/app/file.go
index 761b5d91543..0d19b456b0a 100644
--- a/server/channels/app/file.go
+++ b/server/channels/app/file.go
@@ -59,43 +59,8 @@ func (a *App) ExportFileBackend() filestore.FileBackend {
return a.ch.exportFilestore
}
-// UseExportFileStore reports whether the dedicated export filestore is
-// active. When true, callers reading the filestore configuration should
-// resolve the export-side fields (ExportDriverName, ExportAmazonS3*,
-// ExportAzure*, ...) rather than the primary fields.
-func (a *App) UseExportFileStore() bool {
- if !a.License().IsCloud() {
- return false
- }
- if !a.Config().FeatureFlags.CloudDedicatedExportUI {
- return false
- }
- dedicated := a.Config().FileSettings.DedicatedExportStore
- return dedicated != nil && *dedicated
-}
-
-// ResolvedFileStoreDriverName returns the driver name that callers should
-// read for the active filestore -- ExportDriverName when the dedicated
-// export filestore is enabled, otherwise the primary DriverName. The empty
-// string is returned when neither pointer is set so callers can produce a
-// dedicated "unsupported driver" error.
-func (a *App) ResolvedFileStoreDriverName(settings *model.FileSettings) string {
- name := settings.DriverName
- if a.UseExportFileStore() {
- name = settings.ExportDriverName
- }
-
- if name == nil {
- return ""
- }
- return *name
-}
-
func (a *App) CheckMandatoryS3Fields(settings *model.FileSettings) *model.AppError {
bucket := settings.AmazonS3Bucket
- if a.UseExportFileStore() {
- bucket = settings.ExportAmazonS3Bucket
- }
if bucket == nil || *bucket == "" {
return model.NewAppError("CheckMandatoryS3Fields", "api.admin.test_s3.missing_s3_bucket", nil, "", http.StatusBadRequest)
}
@@ -107,12 +72,6 @@ func (a *App) CheckMandatoryAzureFields(settings *model.FileSettings) *model.App
authMode := settings.AzureAuthMode
accessKey := settings.AzureAccessKey
container := settings.AzureContainer
- if a.UseExportFileStore() {
- storageAccount = settings.ExportAzureStorageAccount
- authMode = settings.ExportAzureAuthMode
- accessKey = settings.ExportAzureAccessKey
- container = settings.ExportAzureContainer
- }
if storageAccount == nil || *storageAccount == "" {
return model.NewAppError("CheckMandatoryAzureFields", "api.admin.test_azure.missing_azure_field", nil, "missing azure storage account setting", http.StatusBadRequest)
}
@@ -162,11 +121,7 @@ func (a *App) TestFileStoreConnectionWithConfig(cfg *model.FileSettings) *model.
complianceEnabled := license != nil && *license.Features.Compliance
allowInsecure := insecure != nil && *insecure
allowedUntrustedInternalConnections := model.SafeDereference(a.Config().ServiceSettings.AllowedUntrustedInternalConnections)
- if a.UseExportFileStore() {
- backend, err = filestore.NewFileBackend(filestore.NewExportFileBackendSettingsFromConfig(cfg, complianceEnabled && license.IsCloud(), allowInsecure, allowedUntrustedInternalConnections))
- } else {
- backend, err = filestore.NewFileBackend(filestore.NewFileBackendSettingsFromConfig(cfg, complianceEnabled, allowInsecure, allowedUntrustedInternalConnections))
- }
+ backend, err = filestore.NewFileBackend(filestore.NewFileBackendSettingsFromConfig(cfg, complianceEnabled, allowInsecure, allowedUntrustedInternalConnections))
if err != nil {
return model.NewAppError("FileAttachmentBackend", "api.file.no_driver.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
}
diff --git a/server/public/model/feature_flags.go b/server/public/model/feature_flags.go
index f4da2123371..80bf57bfe03 100644
--- a/server/public/model/feature_flags.go
+++ b/server/public/model/feature_flags.go
@@ -34,8 +34,6 @@ type FeatureFlags struct {
MoveThreadsEnabled bool
- CloudDedicatedExportUI bool
-
NotificationMonitoring bool
CustomProfileAttributes bool
@@ -165,7 +163,6 @@ func (f *FeatureFlags) SetDefaults() {
f.WysiwygEditor = false
f.EnableExportDirectDownload = false
f.MoveThreadsEnabled = false
- f.CloudDedicatedExportUI = false
f.NotificationMonitoring = true
f.CustomProfileAttributes = true
f.AttributeValueMasking = true
diff --git a/webapp/channels/src/components/admin_console/admin_definition.tsx b/webapp/channels/src/components/admin_console/admin_definition.tsx
index 1bf3a418954..ca4d74c0f8a 100644
--- a/webapp/channels/src/components/admin_console/admin_definition.tsx
+++ b/webapp/channels/src/components/admin_console/admin_definition.tsx
@@ -1592,352 +1592,6 @@ const AdminDefinition: AdminDefinitionType = {
],
},
},
- export_storage: {
- url: 'environment/export_storage',
- title: defineMessage({id: 'admin.sidebar.exportStorage', defaultMessage: 'Export Storage'}),
- isHidden: it.any(
- it.not(it.licensedForFeature('Cloud')),
- it.not(it.minLicenseTier(LicenseSkus.Enterprise)),
- it.configIsFalse('FeatureFlags', 'CloudDedicatedExportUI'),
- ),
- schema: {
- id: 'ExportFileSettings',
- name: defineMessage({id: 'admin.sidebar.exportStorage', defaultMessage: 'Export Storage'}),
- settings: [
- {
- type: 'bool',
- key: 'FileSettings.DedicatedExportStore',
- label: defineMessage({id: 'admin.exportStorage.dedicatedExportStore', defaultMessage: 'Enable Dedicated Export Store:'}),
- help_text: defineMessage({id: 'admin.exportStorage.dedicatedExportStoreDescription', defaultMessage: 'When enabled, Mattermost will use a dedicated export storage bucket for all export operations. This is required for Mattermost Cloud deployments.'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- },
- {
- type: 'dropdown',
- key: 'FileSettings.ExportDriverName',
- label: defineMessage({id: 'admin.exportStorage.exportDriverName', defaultMessage: 'Export Storage Driver:'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- isHidden: it.stateEquals('FileSettings.DedicatedExportStore', false),
- options: [
- {
- value: FILE_STORAGE_DRIVER_S3,
- display_name: defineMessage({id: 'admin.image.storeAmazonS3', defaultMessage: 'Amazon S3'}),
- },
- {
- value: FILE_STORAGE_DRIVER_AZURE,
- display_name: defineMessage({id: 'admin.image.storeAzureBlob', defaultMessage: 'Azure Blob Storage'}),
- },
- ],
- },
- {
- type: 'text',
- key: 'FileSettings.ExportDirectory',
- label: defineMessage({id: 'admin.exportStorage.exportDirectory', defaultMessage: 'Export Directory'}),
- help_text: defineMessage({id: 'admin.image.exportDirectoryDescription', defaultMessage: 'Directory to which files are written. If blank, defaults to ./data/.'}),
- placeholder: defineMessage({id: 'admin.image.localExample', defaultMessage: 'E.g.: "./data/"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.stateEquals('FileSettings.DedicatedExportStore', false),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAmazonS3AccessKeyId',
- label: defineMessage({id: 'admin.image.amazonS3IdTitle', defaultMessage: 'Amazon S3 Access Key ID:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3IdDescription', defaultMessage: '(Optional) Only required if you do not want to authenticate to S3 using an IAM role. Enter the Access Key ID provided by your Amazon EC2 administrator.'}), // eslint-disable-line formatjs/enforce-placeholders -- link provided via help_text_values
- help_text_values: {
- link: (msg: string) => (
-
- {msg}
-
- ),
- },
- help_text_markdown: false,
- placeholder: defineMessage({id: 'admin.image.amazonS3IdExample', defaultMessage: 'E.g.: "AKIADTOVBGERKLCBV"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAmazonS3SecretAccessKey',
- label: defineMessage({id: 'admin.image.amazonS3SecretTitle', defaultMessage: 'Amazon S3 Secret Access Key:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3SecretDescription', defaultMessage: '(Optional) The secret access key associated with your Amazon S3 Access Key ID.'}),
- placeholder: defineMessage({id: 'admin.image.amazonS3SecretExample', defaultMessage: 'E.g.: "jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAmazonS3Bucket',
- label: defineMessage({id: 'admin.image.amazonS3BucketTitle', defaultMessage: 'Amazon S3 Bucket:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3BucketDescription', defaultMessage: 'Name you selected for your S3 bucket in AWS.'}),
- placeholder: defineMessage({id: 'admin.image.amazonS3BucketExampleExport', defaultMessage: 'E.g.: "mattermost-export"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAmazonS3PathPrefix',
- label: defineMessage({id: 'admin.image.amazonS3PathPrefixTitle', defaultMessage: 'Amazon S3 Path Prefix:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3PathPrefixDescription', defaultMessage: 'Prefix you selected for your S3 bucket in AWS.'}),
- placeholder: defineMessage({id: 'admin.image.amazonS3PathPrefixExample', defaultMessage: 'E.g.: "subdir1" or you can leave it empty.'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAmazonS3Region',
- label: defineMessage({id: 'admin.image.amazonS3RegionTitle', defaultMessage: 'Amazon S3 Region:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3RegionDescription', defaultMessage: 'AWS region you selected when creating your S3 bucket. If no region is set, Mattermost attempts to get the appropriate region from AWS, or sets it to "us-east-1" if none found.'}),
- placeholder: defineMessage({id: 'admin.image.amazonS3RegionExample', defaultMessage: 'E.g.: "us-east-1"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAmazonS3Endpoint',
- label: defineMessage({id: 'admin.image.amazonS3EndpointTitle', defaultMessage: 'Amazon S3 Endpoint:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3EndpointDescription', defaultMessage: 'Hostname of your S3 Compatible Storage provider. Defaults to "s3.amazonaws.com".'}),
- placeholder: defineMessage({id: 'admin.image.amazonS3EndpointExample', defaultMessage: 'E.g.: "s3.amazonaws.com"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'bool',
- key: 'FileSettings.ExportAmazonS3SSL',
- label: defineMessage({id: 'admin.image.amazonS3SSLTitle', defaultMessage: 'Enable Secure Amazon S3 Connections:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3SSLDescription', defaultMessage: 'When false, allow insecure connections to Amazon S3. Defaults to secure connections only.'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'bool',
- key: 'FileSettings.ExportAmazonSignV2',
- label: defineMessage({id: 'admin.image.amazonS3SignV2', defaultMessage: 'Enable Sign V2'}),
- help_text: defineMessage({id: 'admin.image.amazonS3SignV2Description', defaultMessage: 'When true, use Sign V2 for Amazon S3 connections'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'bool',
- key: 'FileSettings.ExportAmazonS3SSE',
- label: defineMessage({id: 'admin.image.amazonS3SSETitle', defaultMessage: 'Enable Server-Side Encryption for Amazon S3:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3SSEDescription', defaultMessage: 'When true, encrypt files in Amazon S3 using server-side encryption with Amazon S3-managed keys. See documentation to learn more.'}), // eslint-disable-line formatjs/enforce-placeholders -- link provided via help_text_values
- help_text_values: {
- link: (msg: string) => (
-
- {msg}
-
- ),
- },
- help_text_markdown: false,
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAmazonS3StorageClass',
- label: defineMessage({id: 'admin.image.amazonS3StorageClassTitle', defaultMessage: 'Amazon S3 Storage Class:'}),
- help_text: defineMessage({id: 'admin.image.amazonS3StorageClassDescription', defaultMessage: 'Storage class for your S3 Compatible Storage provider. Defaults to empty.'}),
- placeholder: defineMessage({id: 'admin.image.amazonS3StorageClassExample', defaultMessage: 'E.g.: "STANDARD" or "STANDARD_IA"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_S3)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'dropdown',
- key: 'FileSettings.ExportAzureCloud',
- label: defineMessage({id: 'admin.image.azureCloudTitle', defaultMessage: 'Azure Cloud:'}),
- help_text: defineMessage({id: 'admin.image.azureCloudDescription', defaultMessage: 'The Azure cloud to connect to. Choose "Azure Commercial" or "Azure Government" to use the well-known endpoint for that cloud; only the storage account name is required. Choose "Custom Endpoint" to point at an arbitrary host such as Azurite, a reverse proxy, or any other Azure cloud (for example Azure China).'}),
- options: [
- {
- value: AZURE_CLOUD_COMMERCIAL,
- display_name: defineMessage({id: 'admin.image.azureCloudCommercial', defaultMessage: 'Azure Commercial'}),
- },
- {
- value: AZURE_CLOUD_GOVERNMENT,
- display_name: defineMessage({id: 'admin.image.azureCloudGovernment', defaultMessage: 'Azure Government'}),
- },
- {
- value: AZURE_CLOUD_CUSTOM,
- display_name: defineMessage({id: 'admin.image.azureCloudCustom', defaultMessage: 'Custom Endpoint'}),
- },
- ],
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAzureStorageAccount',
- label: defineMessage({id: 'admin.image.azureStorageAccountTitle', defaultMessage: 'Azure Storage Account:'}),
- help_text: defineMessage({id: 'admin.image.azureStorageAccountDescription', defaultMessage: 'The name of your Azure Storage account.'}),
- placeholder: defineMessage({id: 'admin.image.azureStorageAccountExample', defaultMessage: 'E.g.: "mattermoststorage"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAzureContainer',
- label: defineMessage({id: 'admin.image.azureContainerTitle', defaultMessage: 'Azure Container:'}),
- help_text: defineMessage({id: 'admin.image.azureContainerExportDescription', defaultMessage: 'Name of the container in your Azure Storage account.'}),
- placeholder: defineMessage({id: 'admin.image.azureContainerExportExample', defaultMessage: 'E.g.: "mattermost-export"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAzurePathPrefix',
- label: defineMessage({id: 'admin.image.azurePathPrefixTitle', defaultMessage: 'Azure Path Prefix:'}),
- help_text: defineMessage({id: 'admin.image.azurePathPrefixDescription', defaultMessage: 'Optional path prefix to use for blobs in your Azure container.'}),
- placeholder: defineMessage({id: 'admin.image.azurePathPrefixExample', defaultMessage: 'E.g.: "files/" or leave empty'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'dropdown',
- key: 'FileSettings.ExportAzureAuthMode',
- label: defineMessage({id: 'admin.image.azureAuthModeTitle', defaultMessage: 'Azure Authentication:'}),
- help_text: defineMessage({id: 'admin.image.azureAuthModeDescription', defaultMessage: '"Shared key" signs requests with the Storage Account access key.\n \n"Default credential (Microsoft Entra ID)" reads the identity from the host environment - managed identity on Azure-hosted deployments, workload identity, service principal env vars, or "az login" for local development. No access key required.'}), // eslint-disable-line formatjs/no-multiple-whitespaces
- help_text_markdown: true,
- options: [
- {
- value: AZURE_AUTH_MODE_SHARED_KEY,
- display_name: defineMessage({id: 'admin.image.azureAuthModeSharedKey', defaultMessage: 'Shared key'}),
- },
- {
- value: AZURE_AUTH_MODE_DEFAULT_CREDENTIAL,
- display_name: defineMessage({id: 'admin.image.azureAuthModeDefaultCredential', defaultMessage: 'Default credential (Microsoft Entra ID)'}),
- },
- ],
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAzureAccessKey',
- label: defineMessage({id: 'admin.image.azureAccessKeyTitle', defaultMessage: 'Azure Storage Account Key:'}),
- help_text: defineMessage({id: 'admin.image.azureAccessKeyDescription', defaultMessage: 'The shared key for your Azure Storage account.'}),
- placeholder: defineMessage({id: 'admin.image.azureAccessKeyExample', defaultMessage: 'E.g.: "9MZbtYgfq18PJ8PbRaJ5u91IH8izHvReTbcuQzMl+So="'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- it.not(it.stateEquals('FileSettings.ExportAzureAuthMode', AZURE_AUTH_MODE_SHARED_KEY)),
- ),
- isHidden: it.any(
- it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- it.not(it.stateEquals('FileSettings.ExportAzureAuthMode', AZURE_AUTH_MODE_SHARED_KEY)),
- ),
- },
- {
- type: 'text',
- key: 'FileSettings.ExportAzureEndpoint',
- label: defineMessage({id: 'admin.image.azureEndpointTitle', defaultMessage: 'Custom Azure Endpoint:'}),
- help_text: defineMessage({id: 'admin.image.azureEndpointDescription', defaultMessage: 'Full Blob service URL, including scheme and storage account. Mattermost does not modify this URL, so the storage account must already be embedded in the hostname (vhost-style, e.g. "https://acmemattermost.blob.core.chinacloudapi.cn/") or in the path (path-style, e.g. "http://localhost:10000/devstoreaccount1/"). Shared-key auth signs against the host this URL points at, so make sure it actually serves the storage account named above.'}),
- placeholder: defineMessage({id: 'admin.image.azureEndpointExample', defaultMessage: 'E.g.: "http://localhost:10000/devstoreaccount1/"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- it.not(it.stateEquals('FileSettings.ExportAzureCloud', AZURE_CLOUD_CUSTOM)),
- ),
- isHidden: it.any(
- it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- it.not(it.stateEquals('FileSettings.ExportAzureCloud', AZURE_CLOUD_CUSTOM)),
- ),
- },
- {
- type: 'bool',
- key: 'FileSettings.ExportAzureSSL',
- label: defineMessage({id: 'admin.image.azureSSLTitle', defaultMessage: 'Enable Secure Azure Blob Storage Connections:'}),
- help_text: defineMessage({id: 'admin.image.azureSSLDescription', defaultMessage: 'When false, allow insecure connections to Azure Blob Storage. Defaults to secure connections only. Ignored for the Custom Endpoint cloud (the scheme is part of the endpoint URL).'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- it.stateEquals('FileSettings.ExportAzureCloud', AZURE_CLOUD_CUSTOM),
- ),
- isHidden: it.any(
- it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- it.stateEquals('FileSettings.ExportAzureCloud', AZURE_CLOUD_CUSTOM),
- ),
- },
- {
- type: 'number',
- key: 'FileSettings.ExportAzureRequestTimeoutMilliseconds',
- label: defineMessage({id: 'admin.image.azureRequestTimeoutTitle', defaultMessage: 'Azure Request Timeout (Milliseconds):'}),
- help_text: defineMessage({id: 'admin.image.azureRequestTimeoutDescription', defaultMessage: 'Number of milliseconds to wait for a response from Azure Blob Storage before timing out.'}),
- placeholder: defineMessage({id: 'admin.image.azureRequestTimeoutExample', defaultMessage: 'E.g.: "30000"'}),
- isDisabled: it.any(
- it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- it.stateEquals('FileSettings.DedicatedExportStore', false),
- ),
- isHidden: it.any(it.not(it.stateEquals('FileSettings.ExportDriverName', FILE_STORAGE_DRIVER_AZURE)), it.stateEquals('FileSettings.DedicatedExportStore', false)),
- },
- {
- type: 'button',
- action: testFileStoreConnection,
- key: 'TestFileStoreConnection',
- label: defineMessage({id: 'admin.filestore.connectionTest', defaultMessage: 'Test Connection'}),
- loading: defineMessage({id: 'admin.filestore.testing', defaultMessage: 'Testing...'}),
- error_message: defineMessage({id: 'admin.filestore.testFail', defaultMessage: 'Connection unsuccessful: {error}'}), // eslint-disable-line formatjs/enforce-placeholders -- error provided at runtime
- success_message: defineMessage({id: 'admin.filestore.testSuccess', defaultMessage: 'Connection was successful'}),
- isDisabled: it.not(it.userHasWritePermissionOnResource(RESOURCE_KEYS.ENVIRONMENT.FILE_STORAGE)),
- isHidden: it.stateEquals('FileSettings.DedicatedExportStore', false),
- },
- ],
- },
- },
image_proxy: {
url: 'environment/image_proxy',
title: defineMessage({id: 'admin.sidebar.imageProxy', defaultMessage: 'Image Proxy'}),
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 d8abafed4e3..a14b927b97b 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
@@ -2814,25 +2814,6 @@ c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V4z M20,4v5H4V4H20z M22,15v5c0,1.1-0.9,2-2,2H
class="nav nav__sub-menu subsections"
/>
-
-