[MM-28841] Filter settings sent to the client based on tag (#15578)

* Filter settings sent to the client based on tag

Right now we're filtering in client the sections based on the
RestrictSystemAdmin setting but we're still sending those
settings through the API call.

In this PR we include a new tag cloud_restrictable and some
method to remove those settings/fields from the final JSON
sent to the client
This commit is contained in:
Mario de Frutos Dieguez
2020-09-30 21:09:56 +02:00
committed by GitHub
parent 886c4898d8
commit ab816b18ce
3 changed files with 342 additions and 203 deletions

View File

@@ -65,7 +65,11 @@ func getConfig(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec.Success()
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Write([]byte(cfg.ToJson()))
if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud && *cfg.ExperimentalSettings.RestrictSystemAdmin {
w.Write([]byte(cfg.ToJsonFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable)))
} else {
w.Write([]byte(cfg.ToJson()))
}
}
func configReload(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -156,7 +160,11 @@ func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("updateConfig")
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Write([]byte(cfg.ToJson()))
if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud && *cfg.ExperimentalSettings.RestrictSystemAdmin {
w.Write([]byte(cfg.ToJsonFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable)))
} else {
w.Write([]byte(cfg.ToJson()))
}
}
func getClientConfig(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -259,7 +267,11 @@ func patchConfig(c *Context, w http.ResponseWriter, r *http.Request) {
}
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Write([]byte(cfg.ToJson()))
if c.App.Srv().License() != nil && *c.App.Srv().License().Features.Cloud && *cfg.ExperimentalSettings.RestrictSystemAdmin {
w.Write([]byte(cfg.ToJsonFiltered(model.ConfigAccessTagType, model.ConfigAccessTagCloudRestrictable)))
} else {
w.Write([]byte(cfg.ToJson()))
}
}
func makeFilterConfigByPermission(accessType filterType) func(c *Context, structField reflect.StructField) bool {
@@ -285,7 +297,7 @@ func makeFilterConfigByPermission(accessType filterType) func(c *Context, struct
continue
}
// ConfigAccessTagWriteRestrictable trumps all other permissions
if tagValue == model.ConfigAccessTagWriteRestrictable {
if tagValue == model.ConfigAccessTagWriteRestrictable || tagValue == model.ConfigAccessTagCloudRestrictable {
if *c.App.Config().ExperimentalSettings.RestrictSystemAdmin && accessType == filterTypeWrite {
return false
}
@@ -302,6 +314,9 @@ func makeFilterConfigByPermission(accessType filterType) func(c *Context, struct
if tagValue == model.ConfigAccessTagWriteRestrictable {
continue
}
if tagValue == model.ConfigAccessTagCloudRestrictable {
continue
}
permissionID := fmt.Sprintf("sysconsole_%s_%s", accessType, tagValue)
if permission, ok := permissionMap[permissionID]; ok {
if c.App.SessionHasPermissionTo(*c.App.Session(), permission) {

View File

@@ -12,12 +12,14 @@ import (
"net/http"
"net/url"
"os"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/mattermost/ldap"
"github.com/mattermost/mattermost-server/v5/mlog"
)
const (
@@ -252,26 +254,26 @@ var ServerTLSSupportedCiphers = map[string]uint16{
type ServiceSettings struct {
SiteURL *string `access:"environment,authentication,write_restrictable"`
WebsocketURL *string `access:"write_restrictable"`
LicenseFileLocation *string `access:"write_restrictable"`
ListenAddress *string `access:"environment,write_restrictable"`
ConnectionSecurity *string `access:"environment,write_restrictable"`
TLSCertFile *string `access:"environment,write_restrictable"`
TLSKeyFile *string `access:"environment,write_restrictable"`
TLSMinVer *string `access:"write_restrictable"`
TLSStrictTransport *bool `access:"write_restrictable"`
TLSStrictTransportMaxAge *int64 `access:"write_restrictable"`
TLSOverwriteCiphers []string `access:"write_restrictable"`
UseLetsEncrypt *bool `access:"environment,write_restrictable"`
LetsEncryptCertificateCacheFile *string `access:"environment,write_restrictable"`
Forward80To443 *bool `access:"environment,write_restrictable"`
TrustedProxyIPHeader []string `access:"write_restrictable"`
ReadTimeout *int `access:"environment,write_restrictable"`
WriteTimeout *int `access:"environment,write_restrictable"`
IdleTimeout *int `access:"write_restrictable"`
MaximumLoginAttempts *int `access:"authentication,write_restrictable"`
GoroutineHealthThreshold *int `access:"write_restrictable"`
GoogleDeveloperKey *string `access:"site,write_restrictable"`
WebsocketURL *string `access:"write_restrictable,cloud_restrictable"`
LicenseFileLocation *string `access:"write_restrictable,cloud_restrictable"`
ListenAddress *string `access:"environment,write_restrictable,cloud_restrictable"`
ConnectionSecurity *string `access:"environment,write_restrictable,cloud_restrictable"`
TLSCertFile *string `access:"environment,write_restrictable,cloud_restrictable"`
TLSKeyFile *string `access:"environment,write_restrictable,cloud_restrictable"`
TLSMinVer *string `access:"write_restrictable,cloud_restrictable"`
TLSStrictTransport *bool `access:"write_restrictable,cloud_restrictable"`
TLSStrictTransportMaxAge *int64 `access:"write_restrictable,cloud_restrictable"`
TLSOverwriteCiphers []string `access:"write_restrictable,cloud_restrictable"`
UseLetsEncrypt *bool `access:"environment,write_restrictable,cloud_restrictable"`
LetsEncryptCertificateCacheFile *string `access:"environment,write_restrictable,cloud_restrictable"`
Forward80To443 *bool `access:"environment,write_restrictable,cloud_restrictable"`
TrustedProxyIPHeader []string `access:"write_restrictable,cloud_restrictable"`
ReadTimeout *int `access:"environment,write_restrictable,cloud_restrictable"`
WriteTimeout *int `access:"environment,write_restrictable,cloud_restrictable"`
IdleTimeout *int `access:"write_restrictable,cloud_restrictable"`
MaximumLoginAttempts *int `access:"authentication,write_restrictable,cloud_restrictable"`
GoroutineHealthThreshold *int `access:"write_restrictable,cloud_restrictable"`
GoogleDeveloperKey *string `access:"site,write_restrictable,cloud_restrictable"`
EnableOAuthServiceProvider *bool `access:"integrations"`
EnableIncomingWebhooks *bool `access:"integrations"`
EnableOutgoingWebhooks *bool `access:"integrations"`
@@ -280,29 +282,29 @@ type ServiceSettings struct {
EnablePostUsernameOverride *bool `access:"integrations"`
EnablePostIconOverride *bool `access:"integrations"`
EnableLinkPreviews *bool `access:"site"`
EnableTesting *bool `access:"environment,write_restrictable"`
EnableDeveloper *bool `access:"environment,write_restrictable"`
EnableOpenTracing *bool `access:"write_restrictable"`
EnableSecurityFixAlert *bool `access:"environment,write_restrictable"`
EnableInsecureOutgoingConnections *bool `access:"environment,write_restrictable"`
AllowedUntrustedInternalConnections *string `access:"environment,write_restrictable"`
EnableTesting *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableDeveloper *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableOpenTracing *bool `access:"write_restrictable,cloud_restrictable"`
EnableSecurityFixAlert *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableInsecureOutgoingConnections *bool `access:"environment,write_restrictable,cloud_restrictable"`
AllowedUntrustedInternalConnections *string `access:"environment,write_restrictable,cloud_restrictable"`
EnableMultifactorAuthentication *bool `access:"authentication"`
EnforceMultifactorAuthentication *bool `access:"authentication"`
EnableUserAccessTokens *bool `access:"integrations"`
AllowCorsFrom *string `access:"integrations,write_restrictable"`
CorsExposedHeaders *string `access:"integrations,write_restrictable"`
CorsAllowCredentials *bool `access:"integrations,write_restrictable"`
CorsDebug *bool `access:"integrations,write_restrictable"`
AllowCookiesForSubdomains *bool `access:"write_restrictable"`
ExtendSessionLengthWithActivity *bool `access:"environment,write_restrictable"`
SessionLengthWebInDays *int `access:"environment,write_restrictable"`
SessionLengthMobileInDays *int `access:"environment,write_restrictable"`
SessionLengthSSOInDays *int `access:"environment,write_restrictable"`
SessionCacheInMinutes *int `access:"environment,write_restrictable"`
SessionIdleTimeoutInMinutes *int `access:"environment,write_restrictable"`
WebsocketSecurePort *int `access:"write_restrictable"`
WebsocketPort *int `access:"write_restrictable"`
WebserverMode *string `access:"environment,write_restrictable"`
AllowCorsFrom *string `access:"integrations,write_restrictable,cloud_restrictable"`
CorsExposedHeaders *string `access:"integrations,write_restrictable,cloud_restrictable"`
CorsAllowCredentials *bool `access:"integrations,write_restrictable,cloud_restrictable"`
CorsDebug *bool `access:"integrations,write_restrictable,cloud_restrictable"`
AllowCookiesForSubdomains *bool `access:"write_restrictable,cloud_restrictable"`
ExtendSessionLengthWithActivity *bool `access:"environment,write_restrictable,cloud_restrictable"`
SessionLengthWebInDays *int `access:"environment,write_restrictable,cloud_restrictable"`
SessionLengthMobileInDays *int `access:"environment,write_restrictable,cloud_restrictable"`
SessionLengthSSOInDays *int `access:"environment,write_restrictable,cloud_restrictable"`
SessionCacheInMinutes *int `access:"environment,write_restrictable,cloud_restrictable"`
SessionIdleTimeoutInMinutes *int `access:"environment,write_restrictable,cloud_restrictable"`
WebsocketSecurePort *int `access:"write_restrictable,cloud_restrictable"`
WebsocketPort *int `access:"write_restrictable,cloud_restrictable"`
WebserverMode *string `access:"environment,write_restrictable,cloud_restrictable"`
EnableCustomEmoji *bool `access:"site"`
EnableEmojiPicker *bool `access:"site"`
EnableGifPicker *bool `access:"integrations"`
@@ -312,14 +314,14 @@ type ServiceSettings struct {
DEPRECATED_DO_NOT_USE_RestrictPostDelete *string `json:"RestrictPostDelete" mapstructure:"RestrictPostDelete"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_AllowEditPost *string `json:"AllowEditPost" mapstructure:"AllowEditPost"` // This field is deprecated and must not be used.
PostEditTimeLimit *int `access:"user_management_permissions"`
TimeBetweenUserTypingUpdatesMilliseconds *int64 `access:"experimental,write_restrictable"`
EnablePostSearch *bool `access:"write_restrictable"`
MinimumHashtagLength *int `access:"environment,write_restrictable"`
EnableUserTypingMessages *bool `access:"experimental,write_restrictable"`
EnableChannelViewedMessages *bool `access:"experimental,write_restrictable"`
EnableUserStatuses *bool `access:"write_restrictable"`
ExperimentalEnableAuthenticationTransfer *bool `access:"experimental,write_restrictable"`
ClusterLogTimeoutMilliseconds *int `access:"write_restrictable"`
TimeBetweenUserTypingUpdatesMilliseconds *int64 `access:"experimental,write_restrictable,cloud_restrictable"`
EnablePostSearch *bool `access:"write_restrictable,cloud_restrictable"`
MinimumHashtagLength *int `access:"environment,write_restrictable,cloud_restrictable"`
EnableUserTypingMessages *bool `access:"experimental,write_restrictable,cloud_restrictable"`
EnableChannelViewedMessages *bool `access:"experimental,write_restrictable,cloud_restrictable"`
EnableUserStatuses *bool `access:"write_restrictable,cloud_restrictable"`
ExperimentalEnableAuthenticationTransfer *bool `access:"experimental,write_restrictable,cloud_restrictable"`
ClusterLogTimeoutMilliseconds *int `access:"write_restrictable,cloud_restrictable"`
CloseUnusedDirectMessages *bool `access:"experimental"`
EnablePreviewFeatures *bool `access:"experimental"`
EnableTutorial *bool `access:"experimental"`
@@ -334,10 +336,10 @@ type ServiceSettings struct {
EnableAPITeamDeletion *bool
EnableAPIUserDeletion *bool
ExperimentalEnableHardenedMode *bool `access:"experimental"`
DisableLegacyMFA *bool `access:"write_restrictable"`
ExperimentalStrictCSRFEnforcement *bool `access:"experimental,write_restrictable"`
DisableLegacyMFA *bool `access:"write_restrictable,cloud_restrictable"`
ExperimentalStrictCSRFEnforcement *bool `access:"experimental,write_restrictable,cloud_restrictable"`
EnableEmailInvitations *bool `access:"authentication"`
DisableBotsWhenOwnerIsDeactivated *bool `access:"integrations,write_restrictable"`
DisableBotsWhenOwnerIsDeactivated *bool `access:"integrations,write_restrictable,cloud_restrictable"`
EnableBotAccountCreation *bool `access:"integrations"`
EnableSVGs *bool `access:"site"`
EnableLatex *bool `access:"site"`
@@ -766,20 +768,20 @@ func (s *ServiceSettings) SetDefaults(isUpdate bool) {
type ClusterSettings struct {
Enable *bool `access:"environment,write_restrictable"`
ClusterName *string `access:"environment,write_restrictable"`
OverrideHostname *string `access:"environment,write_restrictable"`
NetworkInterface *string `access:"environment,write_restrictable"`
BindAddress *string `access:"environment,write_restrictable"`
AdvertiseAddress *string `access:"environment,write_restrictable"`
UseIpAddress *bool `access:"environment,write_restrictable"`
UseExperimentalGossip *bool `access:"environment,write_restrictable"`
EnableExperimentalGossipEncryption *bool `access:"environment,write_restrictable"`
ReadOnlyConfig *bool `access:"environment,write_restrictable"`
GossipPort *int `access:"environment,write_restrictable"`
StreamingPort *int `access:"environment,write_restrictable"`
MaxIdleConns *int `access:"environment,write_restrictable"`
MaxIdleConnsPerHost *int `access:"environment,write_restrictable"`
IdleConnTimeoutMilliseconds *int `access:"environment,write_restrictable"`
ClusterName *string `access:"environment,write_restrictable,cloud_restrictable"`
OverrideHostname *string `access:"environment,write_restrictable,cloud_restrictable"`
NetworkInterface *string `access:"environment,write_restrictable,cloud_restrictable"`
BindAddress *string `access:"environment,write_restrictable,cloud_restrictable"`
AdvertiseAddress *string `access:"environment,write_restrictable,cloud_restrictable"`
UseIpAddress *bool `access:"environment,write_restrictable,cloud_restrictable"`
UseExperimentalGossip *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableExperimentalGossipEncryption *bool `access:"environment,write_restrictable,cloud_restrictable"`
ReadOnlyConfig *bool `access:"environment,write_restrictable,cloud_restrictable"`
GossipPort *int `access:"environment,write_restrictable,cloud_restrictable"`
StreamingPort *int `access:"environment,write_restrictable,cloud_restrictable"`
MaxIdleConns *int `access:"environment,write_restrictable,cloud_restrictable"`
MaxIdleConnsPerHost *int `access:"environment,write_restrictable,cloud_restrictable"`
IdleConnTimeoutMilliseconds *int `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *ClusterSettings) SetDefaults() {
@@ -845,9 +847,9 @@ func (s *ClusterSettings) SetDefaults() {
}
type MetricsSettings struct {
Enable *bool `access:"environment,write_restrictable"`
BlockProfileRate *int `access:"environment,write_restrictable"`
ListenAddress *string `access:"environment,write_restrictable"`
Enable *bool `access:"environment,write_restrictable,cloud_restrictable"`
BlockProfileRate *int `access:"environment,write_restrictable,cloud_restrictable"`
ListenAddress *string `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *MetricsSettings) SetDefaults() {
@@ -865,14 +867,14 @@ func (s *MetricsSettings) SetDefaults() {
}
type ExperimentalSettings struct {
ClientSideCertEnable *bool `access:"experimental"`
ClientSideCertCheck *string `access:"experimental"`
EnableClickToReply *bool `access:"experimental,write_restrictable"`
LinkMetadataTimeoutMilliseconds *int64 `access:"experimental,write_restrictable"`
ClientSideCertEnable *bool `access:"experimental,cloud_restrictable"`
ClientSideCertCheck *string `access:"experimental,cloud_restrictable"`
EnableClickToReply *bool `access:"experimental,write_restrictable,cloud_restrictable"`
LinkMetadataTimeoutMilliseconds *int64 `access:"experimental,write_restrictable,cloud_restrictable"`
RestrictSystemAdmin *bool `access:"experimental,write_restrictable"`
UseNewSAMLLibrary *bool `access:"experimental"`
CloudUserLimit *int64 `access:"experimental,write_restrictable"`
CloudBilling *bool `access:"experimental,write_restrictable"`
UseNewSAMLLibrary *bool `access:"experimental,cloud_restrictable"`
CloudUserLimit *int64 `access:"experimental,write_restrictable,cloud_restrictable"`
CloudBilling *bool `access:"experimental,write_restrictable,cloud_restrictable"`
}
func (s *ExperimentalSettings) SetDefaults() {
@@ -911,7 +913,7 @@ func (s *ExperimentalSettings) SetDefaults() {
}
type AnalyticsSettings struct {
MaxUsersForStatistics *int `access:"write_restrictable"`
MaxUsersForStatistics *int `access:"write_restrictable,cloud_restrictable"`
}
func (s *AnalyticsSettings) SetDefaults() {
@@ -1018,17 +1020,17 @@ func (s *Office365Settings) SSOSettings() *SSOSettings {
}
type SqlSettings struct {
DriverName *string `access:"environment,write_restrictable"`
DataSource *string `access:"environment,write_restrictable"`
DataSourceReplicas []string `access:"environment,write_restrictable"`
DataSourceSearchReplicas []string `access:"environment,write_restrictable"`
MaxIdleConns *int `access:"environment,write_restrictable"`
ConnMaxLifetimeMilliseconds *int `access:"environment,write_restrictable"`
MaxOpenConns *int `access:"environment,write_restrictable"`
Trace *bool `access:"environment,write_restrictable"`
AtRestEncryptKey *string `access:"environment,write_restrictable"`
QueryTimeout *int `access:"environment,write_restrictable"`
DisableDatabaseSearch *bool `access:"environment,write_restrictable"`
DriverName *string `access:"environment,write_restrictable,cloud_restrictable"`
DataSource *string `access:"environment,write_restrictable,cloud_restrictable"`
DataSourceReplicas []string `access:"environment,write_restrictable,cloud_restrictable"`
DataSourceSearchReplicas []string `access:"environment,write_restrictable,cloud_restrictable"`
MaxIdleConns *int `access:"environment,write_restrictable,cloud_restrictable"`
ConnMaxLifetimeMilliseconds *int `access:"environment,write_restrictable,cloud_restrictable"`
MaxOpenConns *int `access:"environment,write_restrictable,cloud_restrictable"`
Trace *bool `access:"environment,write_restrictable,cloud_restrictable"`
AtRestEncryptKey *string `access:"environment,write_restrictable,cloud_restrictable"`
QueryTimeout *int `access:"environment,write_restrictable,cloud_restrictable"`
DisableDatabaseSearch *bool `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *SqlSettings) SetDefaults(isUpdate bool) {
@@ -1084,17 +1086,17 @@ func (s *SqlSettings) SetDefaults(isUpdate bool) {
}
type LogSettings struct {
EnableConsole *bool `access:"environment,write_restrictable"`
ConsoleLevel *string `access:"environment,write_restrictable"`
ConsoleJson *bool `access:"environment,write_restrictable"`
EnableFile *bool `access:"environment,write_restrictable"`
FileLevel *string `access:"environment,write_restrictable"`
FileJson *bool `access:"environment,write_restrictable"`
FileLocation *string `access:"environment,write_restrictable"`
EnableWebhookDebugging *bool `access:"environment,write_restrictable"`
EnableDiagnostics *bool `access:"environment,write_restrictable"`
EnableSentry *bool `access:"environment,write_restrictable"`
AdvancedLoggingConfig *string `access:"environment,write_restrictable"`
EnableConsole *bool `access:"environment,write_restrictable,cloud_restrictable"`
ConsoleLevel *string `access:"environment,write_restrictable,cloud_restrictable"`
ConsoleJson *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableFile *bool `access:"environment,write_restrictable,cloud_restrictable"`
FileLevel *string `access:"environment,write_restrictable,cloud_restrictable"`
FileJson *bool `access:"environment,write_restrictable,cloud_restrictable"`
FileLocation *string `access:"environment,write_restrictable,cloud_restrictable"`
EnableWebhookDebugging *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableDiagnostics *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableSentry *bool `access:"environment,write_restrictable,cloud_restrictable"`
AdvancedLoggingConfig *string `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *LogSettings) SetDefaults() {
@@ -1144,14 +1146,14 @@ func (s *LogSettings) SetDefaults() {
}
type ExperimentalAuditSettings struct {
FileEnabled *bool `access:"experimental,write_restrictable"`
FileName *string `access:"experimental,write_restrictable"`
FileMaxSizeMB *int `access:"experimental,write_restrictable"`
FileMaxAgeDays *int `access:"experimental,write_restrictable"`
FileMaxBackups *int `access:"experimental,write_restrictable"`
FileCompress *bool `access:"experimental,write_restrictable"`
FileMaxQueueSize *int `access:"experimental,write_restrictable"`
AdvancedLoggingConfig *string `access:"experimental,write_restrictable"`
FileEnabled *bool `access:"experimental,write_restrictable,cloud_restrictable"`
FileName *string `access:"experimental,write_restrictable,cloud_restrictable"`
FileMaxSizeMB *int `access:"experimental,write_restrictable,cloud_restrictable"`
FileMaxAgeDays *int `access:"experimental,write_restrictable,cloud_restrictable"`
FileMaxBackups *int `access:"experimental,write_restrictable,cloud_restrictable"`
FileCompress *bool `access:"experimental,write_restrictable,cloud_restrictable"`
FileMaxQueueSize *int `access:"experimental,write_restrictable,cloud_restrictable"`
AdvancedLoggingConfig *string `access:"experimental,write_restrictable,cloud_restrictable"`
}
func (s *ExperimentalAuditSettings) SetDefaults() {
@@ -1189,14 +1191,14 @@ func (s *ExperimentalAuditSettings) SetDefaults() {
}
type NotificationLogSettings struct {
EnableConsole *bool `access:"write_restrictable"`
ConsoleLevel *string `access:"write_restrictable"`
ConsoleJson *bool `access:"write_restrictable"`
EnableFile *bool `access:"write_restrictable"`
FileLevel *string `access:"write_restrictable"`
FileJson *bool `access:"write_restrictable"`
FileLocation *string `access:"write_restrictable"`
AdvancedLoggingConfig *string `access:"write_restrictable"`
EnableConsole *bool `access:"write_restrictable,cloud_restrictable"`
ConsoleLevel *string `access:"write_restrictable,cloud_restrictable"`
ConsoleJson *bool `access:"write_restrictable,cloud_restrictable"`
EnableFile *bool `access:"write_restrictable,cloud_restrictable"`
FileLevel *string `access:"write_restrictable,cloud_restrictable"`
FileJson *bool `access:"write_restrictable,cloud_restrictable"`
FileLocation *string `access:"write_restrictable,cloud_restrictable"`
AdvancedLoggingConfig *string `access:"write_restrictable,cloud_restrictable"`
}
func (s *NotificationLogSettings) SetDefaults() {
@@ -1264,25 +1266,25 @@ func (s *PasswordSettings) SetDefaults() {
}
type FileSettings struct {
EnableFileAttachments *bool `access:"site"`
EnableMobileUpload *bool `access:"site"`
EnableMobileDownload *bool `access:"site"`
MaxFileSize *int64 `access:"environment"`
DriverName *string `access:"environment,write_restrictable"`
Directory *string `access:"environment,write_restrictable"`
EnablePublicLink *bool `access:"site"`
PublicLinkSalt *string `access:"site"`
InitialFont *string `access:"environment"`
AmazonS3AccessKeyId *string `access:"environment,write_restrictable"`
AmazonS3SecretAccessKey *string `access:"environment,write_restrictable"`
AmazonS3Bucket *string `access:"environment,write_restrictable"`
AmazonS3PathPrefix *string `access:"environment,write_restrictable"`
AmazonS3Region *string `access:"environment,write_restrictable"`
AmazonS3Endpoint *string `access:"environment,write_restrictable"`
AmazonS3SSL *bool `access:"environment,write_restrictable"`
AmazonS3SignV2 *bool `access:"environment,write_restrictable"`
AmazonS3SSE *bool `access:"environment,write_restrictable"`
AmazonS3Trace *bool `access:"environment,write_restrictable"`
EnableFileAttachments *bool `access:"site,cloud_restrictable"`
EnableMobileUpload *bool `access:"site,cloud_restrictable"`
EnableMobileDownload *bool `access:"site,cloud_restrictable"`
MaxFileSize *int64 `access:"environment,cloud_restrictable"`
DriverName *string `access:"environment,write_restrictable,cloud_restrictable"`
Directory *string `access:"environment,write_restrictable,cloud_restrictable"`
EnablePublicLink *bool `access:"site,cloud_restrictable"`
PublicLinkSalt *string `access:"site,cloud_restrictable"`
InitialFont *string `access:"environment,cloud_restrictable"`
AmazonS3AccessKeyId *string `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3SecretAccessKey *string `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3Bucket *string `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3PathPrefix *string `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3Region *string `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3Endpoint *string `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3SSL *bool `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3SignV2 *bool `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3SSE *bool `access:"environment,write_restrictable,cloud_restrictable"`
AmazonS3Trace *bool `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *FileSettings) SetDefaults(isUpdate bool) {
@@ -1380,16 +1382,16 @@ type EmailSettings struct {
UseChannelInEmailNotifications *bool `access:"experimental"`
RequireEmailVerification *bool `access:"authentication"`
FeedbackName *string `access:"site"`
FeedbackEmail *string `access:"site"`
ReplyToAddress *string `access:"site"`
FeedbackEmail *string `access:"site,cloud_restrictable"`
ReplyToAddress *string `access:"site,cloud_restrictable"`
FeedbackOrganization *string `access:"site"`
EnableSMTPAuth *bool `access:"environment,write_restrictable"`
SMTPUsername *string `access:"environment,write_restrictable"`
SMTPPassword *string `access:"environment,write_restrictable"`
SMTPServer *string `access:"environment,write_restrictable"`
SMTPPort *string `access:"environment,write_restrictable"`
SMTPServerTimeout *int
ConnectionSecurity *string `access:"environment,write_restrictable"`
EnableSMTPAuth *bool `access:"environment,write_restrictable,cloud_restrictable"`
SMTPUsername *string `access:"environment,write_restrictable,cloud_restrictable"`
SMTPPassword *string `access:"environment,write_restrictable,cloud_restrictable"`
SMTPServer *string `access:"environment,write_restrictable,cloud_restrictable"`
SMTPPort *string `access:"environment,write_restrictable,cloud_restrictable"`
SMTPServerTimeout *int `access:"cloud_restrictable"`
ConnectionSecurity *string `access:"environment,write_restrictable,cloud_restrictable"`
SendPushNotifications *bool `access:"environment"`
PushNotificationServer *string `access:"environment"`
PushNotificationContents *string `access:"site"`
@@ -1398,7 +1400,7 @@ type EmailSettings struct {
EmailBatchingBufferSize *int `access:"experimental"`
EmailBatchingInterval *int `access:"experimental"`
EnablePreviewModeBanner *bool `access:"site"`
SkipServerCertificateVerification *bool `access:"environment,write_restrictable"`
SkipServerCertificateVerification *bool `access:"environment,write_restrictable,cloud_restrictable"`
EmailNotificationContentsType *string `access:"site"`
LoginButtonColor *string `access:"experimental"`
LoginButtonBorderColor *string `access:"experimental"`
@@ -1548,13 +1550,13 @@ func (s *EmailSettings) SetDefaults(isUpdate bool) {
}
type RateLimitSettings struct {
Enable *bool `access:"environment,write_restrictable"`
PerSec *int `access:"environment,write_restrictable"`
MaxBurst *int `access:"environment,write_restrictable"`
MemoryStoreSize *int `access:"environment,write_restrictable"`
VaryByRemoteAddr *bool `access:"environment,write_restrictable"`
VaryByUser *bool `access:"environment,write_restrictable"`
VaryByHeader string `access:"environment,write_restrictable"`
Enable *bool `access:"environment,write_restrictable,cloud_restrictable"`
PerSec *int `access:"environment,write_restrictable,cloud_restrictable"`
MaxBurst *int `access:"environment,write_restrictable,cloud_restrictable"`
MemoryStoreSize *int `access:"environment,write_restrictable,cloud_restrictable"`
VaryByRemoteAddr *bool `access:"environment,write_restrictable,cloud_restrictable"`
VaryByUser *bool `access:"environment,write_restrictable,cloud_restrictable"`
VaryByHeader string `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *RateLimitSettings) SetDefaults() {
@@ -1599,11 +1601,11 @@ func (s *PrivacySettings) setDefaults() {
}
type SupportSettings struct {
TermsOfServiceLink *string `access:"site,write_restrictable"`
PrivacyPolicyLink *string `access:"site,write_restrictable"`
AboutLink *string `access:"site,write_restrictable"`
HelpLink *string `access:"site,write_restrictable"`
ReportAProblemLink *string `access:"site,write_restrictable"`
TermsOfServiceLink *string `access:"site,write_restrictable,cloud_restrictable"`
PrivacyPolicyLink *string `access:"site,write_restrictable,cloud_restrictable"`
AboutLink *string `access:"site,write_restrictable,cloud_restrictable"`
HelpLink *string `access:"site,write_restrictable,cloud_restrictable"`
ReportAProblemLink *string `access:"site,write_restrictable,cloud_restrictable"`
SupportEmail *string `access:"site"`
CustomTermsOfServiceEnabled *bool `access:"compliance"`
CustomTermsOfServiceReAcceptancePeriod *int `access:"compliance"`
@@ -1930,12 +1932,12 @@ func (s *TeamSettings) SetDefaults() {
}
type ClientRequirements struct {
AndroidLatestVersion string `access:"write_restrictable"`
AndroidMinVersion string `access:"write_restrictable"`
DesktopLatestVersion string `access:"write_restrictable"`
DesktopMinVersion string `access:"write_restrictable"`
IosLatestVersion string `access:"write_restrictable"`
IosMinVersion string `access:"write_restrictable"`
AndroidLatestVersion string `access:"write_restrictable,cloud_restrictable"`
AndroidMinVersion string `access:"write_restrictable,cloud_restrictable"`
DesktopLatestVersion string `access:"write_restrictable,cloud_restrictable"`
DesktopMinVersion string `access:"write_restrictable,cloud_restrictable"`
IosLatestVersion string `access:"write_restrictable,cloud_restrictable"`
IosMinVersion string `access:"write_restrictable,cloud_restrictable"`
}
type LdapSettings struct {
@@ -2359,9 +2361,9 @@ func (s *SamlSettings) SetDefaults() {
}
type NativeAppSettings struct {
AppDownloadLink *string `access:"site,write_restrictable"`
AndroidAppDownloadLink *string `access:"site,write_restrictable"`
IosAppDownloadLink *string `access:"site,write_restrictable"`
AppDownloadLink *string `access:"site,write_restrictable,cloud_restrictable"`
AndroidAppDownloadLink *string `access:"site,write_restrictable,cloud_restrictable"`
IosAppDownloadLink *string `access:"site,write_restrictable,cloud_restrictable"`
}
func (s *NativeAppSettings) SetDefaults() {
@@ -2379,27 +2381,27 @@ func (s *NativeAppSettings) SetDefaults() {
}
type ElasticsearchSettings struct {
ConnectionUrl *string `access:"environment,write_restrictable"`
Username *string `access:"environment,write_restrictable"`
Password *string `access:"environment,write_restrictable"`
EnableIndexing *bool `access:"environment,write_restrictable"`
EnableSearching *bool `access:"environment,write_restrictable"`
EnableAutocomplete *bool `access:"environment,write_restrictable"`
Sniff *bool `access:"environment,write_restrictable"`
PostIndexReplicas *int `access:"environment,write_restrictable"`
PostIndexShards *int `access:"environment,write_restrictable"`
ChannelIndexReplicas *int `access:"environment,write_restrictable"`
ChannelIndexShards *int `access:"environment,write_restrictable"`
UserIndexReplicas *int `access:"environment,write_restrictable"`
UserIndexShards *int `access:"environment,write_restrictable"`
AggregatePostsAfterDays *int `access:"environment,write_restrictable"`
PostsAggregatorJobStartTime *string `access:"environment,write_restrictable"`
IndexPrefix *string `access:"environment,write_restrictable"`
LiveIndexingBatchSize *int `access:"environment,write_restrictable"`
BulkIndexingTimeWindowSeconds *int `access:"environment,write_restrictable"`
RequestTimeoutSeconds *int `access:"environment,write_restrictable"`
SkipTLSVerification *bool `access:"environment,write_restrictable"`
Trace *string `access:"environment,write_restrictable"`
ConnectionUrl *string `access:"environment,write_restrictable,cloud_restrictable"`
Username *string `access:"environment,write_restrictable,cloud_restrictable"`
Password *string `access:"environment,write_restrictable,cloud_restrictable"`
EnableIndexing *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableSearching *bool `access:"environment,write_restrictable,cloud_restrictable"`
EnableAutocomplete *bool `access:"environment,write_restrictable,cloud_restrictable"`
Sniff *bool `access:"environment,write_restrictable,cloud_restrictable"`
PostIndexReplicas *int `access:"environment,write_restrictable,cloud_restrictable"`
PostIndexShards *int `access:"environment,write_restrictable,cloud_restrictable"`
ChannelIndexReplicas *int `access:"environment,write_restrictable,cloud_restrictable"`
ChannelIndexShards *int `access:"environment,write_restrictable,cloud_restrictable"`
UserIndexReplicas *int `access:"environment,write_restrictable,cloud_restrictable"`
UserIndexShards *int `access:"environment,write_restrictable,cloud_restrictable"`
AggregatePostsAfterDays *int `access:"environment,write_restrictable,cloud_restrictable"`
PostsAggregatorJobStartTime *string `access:"environment,write_restrictable,cloud_restrictable"`
IndexPrefix *string `access:"environment,write_restrictable,cloud_restrictable"`
LiveIndexingBatchSize *int `access:"environment,write_restrictable,cloud_restrictable"`
BulkIndexingTimeWindowSeconds *int `access:"environment,write_restrictable,cloud_restrictable"`
RequestTimeoutSeconds *int `access:"environment,write_restrictable,cloud_restrictable"`
SkipTLSVerification *bool `access:"environment,write_restrictable,cloud_restrictable"`
Trace *string `access:"environment,write_restrictable,cloud_restrictable"`
}
func (s *ElasticsearchSettings) SetDefaults() {
@@ -2549,8 +2551,8 @@ func (s *DataRetentionSettings) SetDefaults() {
}
type JobSettings struct {
RunJobs *bool `access:"write_restrictable"`
RunScheduler *bool `access:"write_restrictable"`
RunJobs *bool `access:"write_restrictable,cloud_restrictable"`
RunScheduler *bool `access:"write_restrictable,cloud_restrictable"`
}
func (s *JobSettings) SetDefaults() {
@@ -2578,20 +2580,20 @@ type PluginState struct {
}
type PluginSettings struct {
Enable *bool `access:"plugins,write_restrictable"`
EnableUploads *bool `access:"plugins,write_restrictable"`
AllowInsecureDownloadUrl *bool `access:"plugins,write_restrictable"`
EnableHealthCheck *bool `access:"plugins,write_restrictable"`
Directory *string `access:"plugins,write_restrictable"`
ClientDirectory *string `access:"plugins,write_restrictable"`
Enable *bool `access:"plugins,write_restrictable,cloud_restrictable"`
EnableUploads *bool `access:"plugins,write_restrictable,cloud_restrictable"`
AllowInsecureDownloadUrl *bool `access:"plugins,write_restrictable,cloud_restrictable"`
EnableHealthCheck *bool `access:"plugins,write_restrictable,cloud_restrictable"`
Directory *string `access:"plugins,write_restrictable,cloud_restrictable"`
ClientDirectory *string `access:"plugins,write_restrictable,cloud_restrictable"`
Plugins map[string]map[string]interface{} `access:"plugins"`
PluginStates map[string]*PluginState `access:"plugins"`
EnableMarketplace *bool `access:"plugins,write_restrictable"`
EnableRemoteMarketplace *bool `access:"plugins,write_restrictable"`
AutomaticPrepackagedPlugins *bool `access:"plugins,write_restrictable"`
RequirePluginSignature *bool `access:"plugins,write_restrictable"`
MarketplaceUrl *string `access:"plugins,write_restrictable"`
SignaturePublicKeyFiles []string `access:"plugins,write_restrictable"`
EnableMarketplace *bool `access:"plugins,write_restrictable,cloud_restrictable"`
EnableRemoteMarketplace *bool `access:"plugins,write_restrictable,cloud_restrictable"`
AutomaticPrepackagedPlugins *bool `access:"plugins,write_restrictable,cloud_restrictable"`
RequirePluginSignature *bool `access:"plugins,write_restrictable,cloud_restrictable"`
MarketplaceUrl *string `access:"plugins,write_restrictable,cloud_restrictable"`
SignaturePublicKeyFiles []string `access:"plugins,write_restrictable,cloud_restrictable"`
}
func (s *PluginSettings) SetDefaults(ls LogSettings) {
@@ -2815,7 +2817,9 @@ func (s *ImageProxySettings) SetDefaults(ss ServiceSettings) {
type ConfigFunc func() *Config
const ConfigAccessTagType = "access"
const ConfigAccessTagWriteRestrictable = "write_restrictable"
const ConfigAccessTagCloudRestrictable = "cloud_restrictable"
// Config fields support the 'access' tag with the following values corresponding to the suffix of the associated
// PERMISSION_SYSCONSOLE_*_* permission Id: 'about', 'reporting', 'user_management_users',
@@ -2829,6 +2833,9 @@ const ConfigAccessTagWriteRestrictable = "write_restrictable"
//
// PERMISSION_MANAGE_SYSTEM always grants read access.
//
// Config values with the access tag 'cloud_restrictable' mean that are marked to be filtered when it's used in a cloud licensed
// environment with ExperimentalSettings.RestrictedSystemAdmin set to true.
//
// Example:
// type HairSettings struct {
// // Colour is writeable with either PERMISSION_SYSCONSOLE_WRITE_REPORTING or PERMISSION_SYSCONSOLE_WRITE_USER_MANAGEMENT_GROUPS.
@@ -2898,6 +2905,18 @@ func (o *Config) ToJson() string {
return string(b)
}
func (o *Config) ToJsonFiltered(tagType, tagValue string) string {
filteredConfigMap := structToMapFilteredByTag(*o, tagType, tagValue)
for key, value := range filteredConfigMap {
v, ok := value.(map[string]interface{})
if ok && len(v) == 0 {
delete(filteredConfigMap, key)
}
}
b, _ := json.Marshal(filteredConfigMap)
return string(b)
}
func (o *Config) GetSSOService(service string) *SSOSettings {
switch service {
case SERVICE_GITLAB:
@@ -3603,3 +3622,63 @@ func (o *Config) Sanitize() {
*o.ServiceSettings.GfycatApiSecret = FAKE_SETTING
}
}
// structToMapFilteredByTag converts a struct into a map removing those fields that has the tag passed
// as argument
func structToMapFilteredByTag(t interface{}, typeOfTag, filterTag string) map[string]interface{} {
defer func() {
if r := recover(); r != nil {
mlog.Error("Panicked in structToMapFilteredByTag. This should never happen.", mlog.Any("recover", r))
}
}()
val := reflect.ValueOf(t)
elemField := reflect.TypeOf(t)
if val.Kind() != reflect.Struct {
return nil
}
out := map[string]interface{}{}
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
structField := elemField.Field(i)
tagPermissions := strings.Split(structField.Tag.Get(typeOfTag), ",")
if isTagPresent(filterTag, tagPermissions) {
continue
}
var value interface{}
switch field.Kind() {
case reflect.Struct:
value = structToMapFilteredByTag(field.Interface(), typeOfTag, filterTag)
case reflect.Ptr:
indirectType := field.Elem()
if indirectType.Kind() == reflect.Struct {
value = structToMapFilteredByTag(indirectType.Interface(), typeOfTag, filterTag)
} else if indirectType.Kind() != reflect.Invalid {
value = indirectType.Interface()
}
default:
value = field.Interface()
}
out[val.Type().Field(i).Name] = value
}
return out
}
func isTagPresent(tag string, tags []string) bool {
for _, val := range tags {
tagValue := strings.TrimSpace(val)
if tagValue != "" && tagValue == tag {
return true
}
}
return false
}

View File

@@ -4,6 +4,7 @@
package model
import (
"encoding/json"
"fmt"
"reflect"
"testing"
@@ -1293,6 +1294,50 @@ func TestConfigSanitize(t *testing.T) {
assert.Equal(t, FAKE_SETTING, c.SqlSettings.DataSourceSearchReplicas[0])
}
func TestConfigFilteredByTag(t *testing.T) {
c := Config{}
c.SetDefaults()
cfgMap := structToMapFilteredByTag(c, ConfigAccessTagType, ConfigAccessTagCloudRestrictable)
// Remove entire sections but the map is still there
clusterSettings, ok := cfgMap["SqlSettings"].(map[string]interface{})
require.True(t, ok)
require.Equal(t, 0, len(clusterSettings))
// Some fields are removed if they have the filtering tag
serviceSettings, ok := cfgMap["ServiceSettings"].(map[string]interface{})
require.True(t, ok)
_, ok = serviceSettings["ListenAddress"]
require.False(t, ok)
}
func TestConfigToJSONFiltered(t *testing.T) {
c := Config{}
c.SetDefaults()
jsonCfgFiltered := c.ToJsonFiltered(ConfigAccessTagType, ConfigAccessTagCloudRestrictable)
unmarshaledCfg := make(map[string]json.RawMessage)
err := json.Unmarshal([]byte(jsonCfgFiltered), &unmarshaledCfg)
require.NoError(t, err)
_, ok := unmarshaledCfg["SqlSettings"]
require.False(t, ok)
serviceSettingsRaw, ok := unmarshaledCfg["ServiceSettings"]
require.True(t, ok)
unmarshaledServiceSettings := make(map[string]json.RawMessage)
err = json.Unmarshal([]byte(serviceSettingsRaw), &unmarshaledServiceSettings)
require.NoError(t, err)
_, ok = unmarshaledServiceSettings["ListenAddress"]
require.False(t, ok)
_, ok = unmarshaledServiceSettings["SiteURL"]
require.True(t, ok)
}
func TestConfigMarketplaceDefaults(t *testing.T) {
t.Parallel()