Skip to content

Commit

Permalink
Add updateConfig endpoint for apiV4
Browse files Browse the repository at this point in the history
  • Loading branch information
cpanato committed Mar 15, 2017
1 parent 6b208c5 commit 66d8aa4
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 24 deletions.
27 changes: 27 additions & 0 deletions api4/system.go
Expand Up @@ -18,6 +18,7 @@ func InitSystem() {
BaseRoutes.System.Handle("/ping", ApiHandler(getSystemPing)).Methods("GET")
BaseRoutes.ApiRoot.Handle("/config", ApiSessionRequired(getConfig)).Methods("GET")
BaseRoutes.ApiRoot.Handle("/config/reload", ApiSessionRequired(configReload)).Methods("POST")
BaseRoutes.ApiRoot.Handle("/config", ApiSessionRequired(updateConfig)).Methods("PUT")
BaseRoutes.ApiRoot.Handle("/email/test", ApiSessionRequired(testEmail)).Methods("POST")
BaseRoutes.ApiRoot.Handle("/database/recycle", ApiSessionRequired(databaseRecycle)).Methods("POST")
BaseRoutes.ApiRoot.Handle("/caches/invalidate", ApiSessionRequired(invalidateCaches)).Methods("POST")
Expand Down Expand Up @@ -67,6 +68,32 @@ func configReload(c *Context, w http.ResponseWriter, r *http.Request) {
ReturnStatusOK(w)
}

func updateConfig(c *Context, w http.ResponseWriter, r *http.Request) {
cfg := model.ConfigFromJson(r.Body)
if cfg == nil {
c.SetInvalidParam("config")
return
}

if !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
return
}

err := app.SaveConfig(cfg)
if err != nil {
c.Err = err
return
}

c.LogAudit("updateConfig")

cfg = app.GetConfig()

w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Write([]byte(cfg.ToJson()))
}

func databaseRecycle(c *Context, w http.ResponseWriter, r *http.Request) {

if !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
Expand Down
42 changes: 42 additions & 0 deletions api4/system_test.go
Expand Up @@ -4,6 +4,7 @@ import (
"strings"
"testing"

"github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
Expand Down Expand Up @@ -87,6 +88,47 @@ func TestReloadConfig(t *testing.T) {
*utils.Cfg.TeamSettings.EnableOpenServer = true
}

func TestUpdateConfig(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Client := th.Client

cfg := app.GetConfig()

_, resp := Client.UpdateConfig(cfg)
CheckForbiddenStatus(t, resp)

SiteName := utils.Cfg.TeamSettings.SiteName

cfg.TeamSettings.SiteName = "MyFancyName"
cfg, resp = th.SystemAdminClient.UpdateConfig(cfg)
CheckNoError(t, resp)

if len(cfg.TeamSettings.SiteName) == 0 {
t.Fatal()
} else {
if cfg.TeamSettings.SiteName != "MyFancyName" {
t.Log("It should update the SiteName")
t.Fatal()
}
}

//Revert the change
cfg.TeamSettings.SiteName = SiteName
cfg, resp = th.SystemAdminClient.UpdateConfig(cfg)
CheckNoError(t, resp)

if len(cfg.TeamSettings.SiteName) == 0 {
t.Fatal()
} else {
if cfg.TeamSettings.SiteName != SiteName {
t.Log("It should update the SiteName")
t.Fatal()
}
}

}

func TestEmailTest(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
Expand Down
2 changes: 1 addition & 1 deletion config/config.json
Expand Up @@ -260,4 +260,4 @@
"TurnUsername": "",
"TurnSharedKey": ""
}
}
}
12 changes: 12 additions & 0 deletions model/client4.go
Expand Up @@ -1149,6 +1149,7 @@ func (c *Client4) ReloadConfig() (bool, *Response) {
}
}

// DatabaseRecycle will recycle the connections. Discard current connection and get new one.
func (c *Client4) DatabaseRecycle() (bool, *Response) {
if r, err := c.DoApiPost(c.GetDatabaseRoute()+"/recycle", ""); err != nil {
return false, &Response{StatusCode: r.StatusCode, Error: err}
Expand All @@ -1158,6 +1159,7 @@ func (c *Client4) DatabaseRecycle() (bool, *Response) {
}
}

// InvalidateCaches will purge the cache and can affect the performance while is cleaning.
func (c *Client4) InvalidateCaches() (bool, *Response) {
if r, err := c.DoApiPost(c.GetCacheRoute()+"/invalidate", ""); err != nil {
return false, &Response{StatusCode: r.StatusCode, Error: err}
Expand All @@ -1167,6 +1169,16 @@ func (c *Client4) InvalidateCaches() (bool, *Response) {
}
}

// UpdateConfig will update the server configuration
func (c *Client4) UpdateConfig(config *Config) (*Config, *Response) {
if r, err := c.DoApiPut(c.GetConfigRoute(), config.ToJson()); err != nil {
return nil, &Response{StatusCode: r.StatusCode, Error: err}
} else {
defer closeBody(r)
return ConfigFromJson(r.Body), BuildResponse(r)
}
}

// Webhooks Section

// CreateIncomingWebhook creates an incoming webhook for a channel.
Expand Down
46 changes: 23 additions & 23 deletions model/config.go
Expand Up @@ -473,7 +473,7 @@ func (o *Config) SetDefaults() {
*o.FileSettings.MaxFileSize = 52428800 // 50 MB
}

if len(*o.FileSettings.PublicLinkSalt) == 0 {
if o.FileSettings.PublicLinkSalt == nil || len(*o.FileSettings.PublicLinkSalt) == 0 {
o.FileSettings.PublicLinkSalt = new(string)
*o.FileSettings.PublicLinkSalt = NewRandomString(32)
}
Expand Down Expand Up @@ -1150,7 +1150,7 @@ func (o *Config) IsValid() *AppError {
return NewLocAppError("Config.IsValid", "model.config.is_valid.login_attempts.app_error", nil, "")
}

if len(*o.ServiceSettings.SiteURL) != 0 {
if o.ServiceSettings.SiteURL != nil && len(*o.ServiceSettings.SiteURL) != 0 {
if _, err := url.ParseRequestURI(*o.ServiceSettings.SiteURL); err != nil {
return NewLocAppError("Config.IsValid", "model.config.is_valid.site_url.app_error", nil, "")
}
Expand All @@ -1160,27 +1160,27 @@ func (o *Config) IsValid() *AppError {
return NewLocAppError("Config.IsValid", "model.config.is_valid.listen_address.app_error", nil, "")
}

if *o.ClusterSettings.Enable && *o.EmailSettings.EnableEmailBatching {
if o.ClusterSettings.Enable != nil && (*o.ClusterSettings.Enable && *o.EmailSettings.EnableEmailBatching) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.cluster_email_batching.app_error", nil, "")
}

if len(*o.ServiceSettings.SiteURL) == 0 && *o.EmailSettings.EnableEmailBatching {
if (o.ServiceSettings.SiteURL != nil && o.EmailSettings.EnableEmailBatching != nil) && (len(*o.ServiceSettings.SiteURL) == 0 && *o.EmailSettings.EnableEmailBatching) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.site_url_email_batching.app_error", nil, "")
}

if o.TeamSettings.MaxUsersPerTeam <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_users.app_error", nil, "")
}

if *o.TeamSettings.MaxChannelsPerTeam <= 0 {
if o.TeamSettings.MaxChannelsPerTeam != nil && *o.TeamSettings.MaxChannelsPerTeam <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_channels.app_error", nil, "")
}

if *o.TeamSettings.MaxNotificationsPerChannel <= 0 {
if o.TeamSettings.MaxNotificationsPerChannel != nil && *o.TeamSettings.MaxNotificationsPerChannel <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_notify_per_channel.app_error", nil, "")
}

if !(*o.TeamSettings.RestrictDirectMessage == DIRECT_MESSAGE_ANY || *o.TeamSettings.RestrictDirectMessage == DIRECT_MESSAGE_TEAM) {
if o.TeamSettings.RestrictDirectMessage != nil && !(*o.TeamSettings.RestrictDirectMessage == DIRECT_MESSAGE_ANY || *o.TeamSettings.RestrictDirectMessage == DIRECT_MESSAGE_TEAM) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.restrict_direct_message.app_error", nil, "")
}

Expand All @@ -1204,7 +1204,7 @@ func (o *Config) IsValid() *AppError {
return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_max_conn.app_error", nil, "")
}

if *o.FileSettings.MaxFileSize <= 0 {
if o.FileSettings.MaxFileSize != nil && *o.FileSettings.MaxFileSize <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_file_size.app_error", nil, "")
}

Expand Down Expand Up @@ -1236,7 +1236,7 @@ func (o *Config) IsValid() *AppError {
return NewLocAppError("Config.IsValid", "model.config.is_valid.file_thumb_width.app_error", nil, "")
}

if len(*o.FileSettings.PublicLinkSalt) < 32 {
if o.FileSettings.PublicLinkSalt != nil && len(*o.FileSettings.PublicLinkSalt) < 32 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.file_salt.app_error", nil, "")
}

Expand All @@ -1252,11 +1252,11 @@ func (o *Config) IsValid() *AppError {
return NewLocAppError("Config.IsValid", "model.config.is_valid.email_reset_salt.app_error", nil, "")
}

if *o.EmailSettings.EmailBatchingBufferSize <= 0 {
if o.EmailSettings.EmailBatchingBufferSize != nil && *o.EmailSettings.EmailBatchingBufferSize <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.email_batching_buffer_size.app_error", nil, "")
}

if *o.EmailSettings.EmailBatchingInterval < 30 {
if o.EmailSettings.EmailBatchingInterval != nil && *o.EmailSettings.EmailBatchingInterval < 30 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.email_batching_interval.app_error", nil, "")
}

Expand All @@ -1268,19 +1268,19 @@ func (o *Config) IsValid() *AppError {
return NewLocAppError("Config.IsValid", "model.config.is_valid.rate_sec.app_error", nil, "")
}

if !(*o.LdapSettings.ConnectionSecurity == CONN_SECURITY_NONE || *o.LdapSettings.ConnectionSecurity == CONN_SECURITY_TLS || *o.LdapSettings.ConnectionSecurity == CONN_SECURITY_STARTTLS) {
if o.LdapSettings.ConnectionSecurity != nil && !(*o.LdapSettings.ConnectionSecurity == CONN_SECURITY_NONE || *o.LdapSettings.ConnectionSecurity == CONN_SECURITY_TLS || *o.LdapSettings.ConnectionSecurity == CONN_SECURITY_STARTTLS) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_security.app_error", nil, "")
}

if *o.LdapSettings.SyncIntervalMinutes <= 0 {
if o.LdapSettings.SyncIntervalMinutes != nil && *o.LdapSettings.SyncIntervalMinutes <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_sync_interval.app_error", nil, "")
}

if *o.LdapSettings.MaxPageSize < 0 {
if o.LdapSettings.MaxPageSize != nil && *o.LdapSettings.MaxPageSize < 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_max_page_size.app_error", nil, "")
}

if *o.LdapSettings.Enable {
if o.LdapSettings.Enable != nil && *o.LdapSettings.Enable {
if *o.LdapSettings.LdapServer == "" {
return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_server", nil, "")
}
Expand All @@ -1302,7 +1302,7 @@ func (o *Config) IsValid() *AppError {
}
}

if *o.SamlSettings.Enable {
if o.SamlSettings.Enable != nil && *o.SamlSettings.Enable {
if len(*o.SamlSettings.IdpUrl) == 0 || !IsValidHttpUrl(*o.SamlSettings.IdpUrl) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_idp_url.app_error", nil, "")
}
Expand Down Expand Up @@ -1344,35 +1344,35 @@ func (o *Config) IsValid() *AppError {
}
}

if *o.PasswordSettings.MinimumLength < PASSWORD_MINIMUM_LENGTH || *o.PasswordSettings.MinimumLength > PASSWORD_MAXIMUM_LENGTH {
if o.PasswordSettings.MinimumLength != nil && (*o.PasswordSettings.MinimumLength < PASSWORD_MINIMUM_LENGTH || *o.PasswordSettings.MinimumLength > PASSWORD_MAXIMUM_LENGTH) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.password_length.app_error", map[string]interface{}{"MinLength": PASSWORD_MINIMUM_LENGTH, "MaxLength": PASSWORD_MAXIMUM_LENGTH}, "")
}

if len(o.TeamSettings.SiteName) > SITENAME_MAX_LENGTH {
return NewLocAppError("Config.IsValid", "model.config.is_valid.sitename_length.app_error", map[string]interface{}{"MaxLength": SITENAME_MAX_LENGTH}, "")
}

if *o.RateLimitSettings.MaxBurst <= 0 {
if o.RateLimitSettings.MaxBurst != nil && *o.RateLimitSettings.MaxBurst <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_burst.app_error", nil, "")
}

if err := o.isValidWebrtcSettings(); err != nil {
return err
}

if !(*o.ServiceSettings.ConnectionSecurity == CONN_SECURITY_NONE || *o.ServiceSettings.ConnectionSecurity == CONN_SECURITY_TLS) {
if o.ServiceSettings.ConnectionSecurity != nil && !(*o.ServiceSettings.ConnectionSecurity == CONN_SECURITY_NONE || *o.ServiceSettings.ConnectionSecurity == CONN_SECURITY_TLS) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.webserver_security.app_error", nil, "")
}

if *o.ServiceSettings.ReadTimeout <= 0 {
if o.ServiceSettings.ReadTimeout != nil && *o.ServiceSettings.ReadTimeout <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.read_timeout.app_error", nil, "")
}

if *o.ServiceSettings.WriteTimeout <= 0 {
if o.ServiceSettings.WriteTimeout != nil && *o.ServiceSettings.WriteTimeout <= 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.write_timeout.app_error", nil, "")
}

if *o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds < 1000 {
if o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds != nil && *o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds < 1000 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.time_between_user_typing.app_error", nil, "")
}

Expand Down Expand Up @@ -1458,7 +1458,7 @@ func (o *Config) defaultWebrtcSettings() {
}

func (o *Config) isValidWebrtcSettings() *AppError {
if *o.WebrtcSettings.Enable {
if o.WebrtcSettings.Enable != nil && *o.WebrtcSettings.Enable {
if len(*o.WebrtcSettings.GatewayWebsocketUrl) == 0 || !IsValidWebsocketUrl(*o.WebrtcSettings.GatewayWebsocketUrl) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_ws_url.app_error", nil, "")
} else if len(*o.WebrtcSettings.GatewayAdminUrl) == 0 || !IsValidHttpUrl(*o.WebrtcSettings.GatewayAdminUrl) {
Expand Down

0 comments on commit 66d8aa4

Please sign in to comment.