From 6ec77e06eaecc9b0567e1c67e9255da448fa4b2f Mon Sep 17 00:00:00 2001 From: Wim Date: Thu, 23 Jun 2016 20:28:05 +0200 Subject: Sync with mattermost 3.1.0 --- .../mattermost/platform/einterfaces/ldap.go | 2 + .../github.com/mattermost/platform/model/client.go | 244 +++++++++++++++++++-- .../mattermost/platform/model/command.go | 5 +- .../github.com/mattermost/platform/model/config.go | 152 ++++++++++--- .../github.com/mattermost/platform/model/file.go | 4 - .../mattermost/platform/model/gitlab/gitlab.go | 3 +- .../mattermost/platform/model/incoming_webhook.go | 135 +++++++++++- vendor/github.com/mattermost/platform/model/job.go | 91 ++++++++ .../mattermost/platform/model/outgoing_webhook.go | 47 ++++ .../mattermost/platform/model/preference.go | 3 + .../mattermost/platform/model/search_params.go | 8 +- .../github.com/mattermost/platform/model/user.go | 18 +- .../github.com/mattermost/platform/model/utils.go | 5 +- .../mattermost/platform/model/version.go | 2 + 14 files changed, 654 insertions(+), 65 deletions(-) create mode 100644 vendor/github.com/mattermost/platform/model/job.go (limited to 'vendor/github.com/mattermost/platform') diff --git a/vendor/github.com/mattermost/platform/einterfaces/ldap.go b/vendor/github.com/mattermost/platform/einterfaces/ldap.go index 25d591ce..4f1b5611 100644 --- a/vendor/github.com/mattermost/platform/einterfaces/ldap.go +++ b/vendor/github.com/mattermost/platform/einterfaces/ldap.go @@ -13,6 +13,8 @@ type LdapInterface interface { CheckPassword(id string, password string) *model.AppError SwitchToLdap(userId, ldapId, ldapPassword string) *model.AppError ValidateFilter(filter string) *model.AppError + Syncronize() *model.AppError + StartLdapSyncJob() } var theLdapInterface LdapInterface diff --git a/vendor/github.com/mattermost/platform/model/client.go b/vendor/github.com/mattermost/platform/model/client.go index 152aaa70..e8ce21ab 100644 --- a/vendor/github.com/mattermost/platform/model/client.go +++ b/vendor/github.com/mattermost/platform/model/client.go @@ -28,6 +28,8 @@ const ( HEADER_AUTH = "Authorization" HEADER_REQUESTED_WITH = "X-Requested-With" HEADER_REQUESTED_WITH_XML = "XMLHttpRequest" + STATUS = "status" + STATUS_OK = "OK" API_URL_SUFFIX_V1 = "/api/v1" API_URL_SUFFIX_V3 = "/api/v3" @@ -41,18 +43,28 @@ type Result struct { } type Client struct { - Url string // The location of the server like "http://localhost:8065" - ApiUrl string // The api location of the server like "http://localhost:8065/api/v3" - HttpClient *http.Client // The http client - AuthToken string - AuthType string - TeamId string + Url string // The location of the server like "http://localhost:8065" + ApiUrl string // The api location of the server like "http://localhost:8065/api/v3" + HttpClient *http.Client // The http client + AuthToken string + AuthType string + TeamId string + RequestId string + Etag string + ServerVersion string } // NewClient constructs a new client with convienence methods for talking to // the server. func NewClient(url string) *Client { - return &Client{url, url + API_URL_SUFFIX, &http.Client{}, "", "", ""} + return &Client{url, url + API_URL_SUFFIX, &http.Client{}, "", "", "", "", "", ""} +} + +func closeBody(r *http.Response) { + if r.Body != nil { + ioutil.ReadAll(r.Body) + r.Body.Close() + } } func (c *Client) SetOAuthToken(token string) { @@ -94,6 +106,10 @@ func (c *Client) GetChannelNameRoute(channelName string) string { return fmt.Sprintf("/teams/%v/channels/name/%v", c.GetTeamId(), channelName) } +func (c *Client) GetGeneralRoute() string { + return "/general" +} + func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppError) { rq, _ := http.NewRequest("POST", c.Url+url, strings.NewReader(data)) rq.Header.Set("Content-Type", contentType) @@ -101,6 +117,7 @@ func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppErro if rp, err := c.HttpClient.Do(rq); err != nil { return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error()) } else if rp.StatusCode >= 300 { + defer closeBody(rp) return nil, AppErrorFromJson(rp.Body) } else { return rp, nil @@ -117,6 +134,7 @@ func (c *Client) DoApiPost(url string, data string) (*http.Response, *AppError) if rp, err := c.HttpClient.Do(rq); err != nil { return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error()) } else if rp.StatusCode >= 300 { + defer closeBody(rp) return nil, AppErrorFromJson(rp.Body) } else { return rp, nil @@ -139,6 +157,7 @@ func (c *Client) DoApiGet(url string, data string, etag string) (*http.Response, } else if rp.StatusCode == 304 { return rp, nil } else if rp.StatusCode >= 300 { + defer closeBody(rp) return rp, AppErrorFromJson(rp.Body) } else { return rp, nil @@ -155,6 +174,7 @@ func getCookie(name string, resp *http.Response) *http.Cookie { return nil } +// Must is a convenience function used for testing. func (c *Client) Must(result *Result, err *AppError) *Result { if err != nil { l4g.Close() @@ -165,6 +185,80 @@ func (c *Client) Must(result *Result, err *AppError) *Result { return result } +// CheckStatusOK is a convenience function for checking the return of Web Service +// call that return the a map of status=OK. +func (c *Client) CheckStatusOK(r *http.Response) bool { + m := MapFromJson(r.Body) + defer closeBody(r) + + if m != nil && m[STATUS] == STATUS_OK { + return true + } + + return false +} + +func (c *Client) fillInExtraProperties(r *http.Response) { + c.RequestId = r.Header.Get(HEADER_REQUEST_ID) + c.Etag = r.Header.Get(HEADER_ETAG_SERVER) + c.ServerVersion = r.Header.Get(HEADER_VERSION_ID) +} + +func (c *Client) clearExtraProperties() { + c.RequestId = "" + c.Etag = "" + c.ServerVersion = "" +} + +// General Routes Section + +// GetClientProperties returns properties needed by the client to show/hide +// certian features. It returns a map of strings. +func (c *Client) GetClientProperties() (map[string]string, *AppError) { + c.clearExtraProperties() + if r, err := c.DoApiGet(c.GetGeneralRoute()+"/client_props", "", ""); err != nil { + return nil, err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return MapFromJson(r.Body), nil + } +} + +// LogClient is a convenience Web Service call so clients can log messages into +// the server-side logs. For example we typically log javascript error messages +// into the server-side. It returns true if the logging was successful. +func (c *Client) LogClient(message string) (bool, *AppError) { + c.clearExtraProperties() + m := make(map[string]string) + m["level"] = "ERROR" + m["message"] = message + + if r, err := c.DoApiPost(c.GetGeneralRoute()+"/log_client", MapToJson(m)); err != nil { + return false, err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return c.CheckStatusOK(r), nil + } +} + +// GetPing returns a map of strings with server time, server version, and node Id. +// Systems that want to check on health status of the server should check the +// url /api/v3/ping for a 200 status response. +func (c *Client) GetPing() (map[string]string, *AppError) { + c.clearExtraProperties() + if r, err := c.DoApiGet(c.GetGeneralRoute()+"/ping", "", ""); err != nil { + return nil, err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return MapFromJson(r.Body), nil + } +} + +// Team Routes Section + func (c *Client) SignupTeam(email string, displayName string) (*Result, *AppError) { m := make(map[string]string) m["email"] = email @@ -172,6 +266,7 @@ func (c *Client) SignupTeam(email string, displayName string) (*Result, *AppErro if r, err := c.DoApiPost("/teams/signup", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -181,6 +276,7 @@ func (c *Client) CreateTeamFromSignup(teamSignup *TeamSignup) (*Result, *AppErro if r, err := c.DoApiPost("/teams/create_from_signup", teamSignup.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), TeamSignupFromJson(r.Body)}, nil } @@ -190,6 +286,7 @@ func (c *Client) CreateTeam(team *Team) (*Result, *AppError) { if r, err := c.DoApiPost("/teams/create", team.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil } @@ -199,7 +296,7 @@ func (c *Client) GetAllTeams() (*Result, *AppError) { if r, err := c.DoApiGet("/teams/all", "", ""); err != nil { return nil, err } else { - + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), TeamMapFromJson(r.Body)}, nil } @@ -209,7 +306,7 @@ func (c *Client) GetAllTeamListings() (*Result, *AppError) { if r, err := c.DoApiGet("/teams/all_team_listings", "", ""); err != nil { return nil, err } else { - + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), TeamMapFromJson(r.Body)}, nil } @@ -225,7 +322,7 @@ func (c *Client) FindTeamByName(name string) (*Result, *AppError) { if body, _ := ioutil.ReadAll(r.Body); string(body) == "true" { val = true } - + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), val}, nil } @@ -237,6 +334,7 @@ func (c *Client) AddUserToTeam(userId string) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/add_user_to_team", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -250,6 +348,7 @@ func (c *Client) AddUserToTeamFromInvite(hash, dataToHash, inviteId string) (*Re if r, err := c.DoApiPost("/teams/add_user_to_team_from_invite", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil } @@ -259,6 +358,7 @@ func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/invite_members", invites.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), InvitesFromJson(r.Body)}, nil } @@ -268,6 +368,7 @@ func (c *Client) UpdateTeam(team *Team) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/update", team.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -277,6 +378,7 @@ func (c *Client) CreateUser(user *User, hash string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/create", user.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -289,6 +391,7 @@ func (c *Client) CreateUserWithInvite(user *User, hash string, data string, invi if r, err := c.DoApiPost(url, user.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -298,6 +401,7 @@ func (c *Client) CreateUserFromSignup(user *User, data string, hash string) (*Re if r, err := c.DoApiPost("/users/create?d="+url.QueryEscape(data)+"&h="+hash, user.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -307,6 +411,7 @@ func (c *Client) GetUser(id string, etag string) (*Result, *AppError) { if r, err := c.DoApiGet("/users/"+id+"/get", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -316,6 +421,7 @@ func (c *Client) GetMe(etag string) (*Result, *AppError) { if r, err := c.DoApiGet("/users/me", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -325,6 +431,7 @@ func (c *Client) GetProfilesForDirectMessageList(teamId string) (*Result, *AppEr if r, err := c.DoApiGet("/users/profiles_for_dm_list/"+teamId, "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil } @@ -334,6 +441,7 @@ func (c *Client) GetProfiles(teamId string, etag string) (*Result, *AppError) { if r, err := c.DoApiGet("/users/profiles/"+teamId, "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil } @@ -343,6 +451,7 @@ func (c *Client) GetDirectProfiles(etag string) (*Result, *AppError) { if r, err := c.DoApiGet("/users/direct_profiles", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil } @@ -390,6 +499,7 @@ func (c *Client) login(m map[string]string) (*Result, *AppError) { NewLocAppError("/users/login", "model.client.login.app_error", nil, "") } + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -403,6 +513,7 @@ func (c *Client) Logout() (*Result, *AppError) { c.AuthType = HEADER_BEARER c.TeamId = "" + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -415,6 +526,7 @@ func (c *Client) CheckMfa(loginId string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/mfa", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -424,6 +536,7 @@ func (c *Client) GenerateMfaQrCode() (*Result, *AppError) { if r, err := c.DoApiGet("/users/generate_mfa_qr", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), r.Body}, nil } @@ -437,6 +550,7 @@ func (c *Client) UpdateMfa(activate bool, token string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/update_mfa", StringInterfaceToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -449,6 +563,7 @@ func (c *Client) AdminResetMfa(userId string) (*Result, *AppError) { if r, err := c.DoApiPost("/admin/reset_mfa", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -461,6 +576,7 @@ func (c *Client) RevokeSession(sessionAltId string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/revoke_session", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -470,6 +586,7 @@ func (c *Client) GetSessions(id string) (*Result, *AppError) { if r, err := c.DoApiGet("/users/"+id+"/sessions", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), SessionsFromJson(r.Body)}, nil } @@ -479,6 +596,7 @@ func (c *Client) EmailToOAuth(m map[string]string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/claim/email_to_sso", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -488,6 +606,7 @@ func (c *Client) OAuthToEmail(m map[string]string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/claim/oauth_to_email", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -497,6 +616,7 @@ func (c *Client) LDAPToEmail(m map[string]string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/claim/ldap_to_email", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -506,6 +626,7 @@ func (c *Client) EmailToLDAP(m map[string]string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/claim/ldap_to_email", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -519,6 +640,7 @@ func (c *Client) Command(channelId string, command string, suggest bool) (*Resul if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/execute", MapToJson(m)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), CommandResponseFromJson(r.Body)}, nil } @@ -528,6 +650,7 @@ func (c *Client) ListCommands() (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/commands/list", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), CommandListFromJson(r.Body)}, nil } @@ -537,6 +660,7 @@ func (c *Client) ListTeamCommands() (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/commands/list_team_commands", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), CommandListFromJson(r.Body)}, nil } @@ -546,6 +670,7 @@ func (c *Client) CreateCommand(cmd *Command) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/create", cmd.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), CommandFromJson(r.Body)}, nil } @@ -555,6 +680,7 @@ func (c *Client) RegenCommandToken(data map[string]string) (*Result, *AppError) if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/regen_token", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), CommandFromJson(r.Body)}, nil } @@ -564,6 +690,7 @@ func (c *Client) DeleteCommand(data map[string]string) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/delete", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -573,6 +700,7 @@ func (c *Client) GetAudits(id string, etag string) (*Result, *AppError) { if r, err := c.DoApiGet("/users/"+id+"/audits", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), AuditsFromJson(r.Body)}, nil } @@ -582,6 +710,7 @@ func (c *Client) GetLogs() (*Result, *AppError) { if r, err := c.DoApiGet("/admin/logs", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ArrayFromJson(r.Body)}, nil } @@ -591,26 +720,33 @@ func (c *Client) GetAllAudits() (*Result, *AppError) { if r, err := c.DoApiGet("/admin/audits", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), AuditsFromJson(r.Body)}, nil } } -func (c *Client) GetClientProperties() (*Result, *AppError) { - if r, err := c.DoApiGet("/admin/client_props", "", ""); err != nil { +func (c *Client) GetConfig() (*Result, *AppError) { + if r, err := c.DoApiGet("/admin/config", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), - r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + r.Header.Get(HEADER_ETAG_SERVER), ConfigFromJson(r.Body)}, nil } } -func (c *Client) GetConfig() (*Result, *AppError) { - if r, err := c.DoApiGet("/admin/config", "", ""); err != nil { - return nil, err +// ReloadConfig will reload the config.json file from disk. Properties +// requiring a server restart will still need a server restart. You must +// have the system admin role to call this method. It will return status=OK +// if it's successfully reloaded the config file, otherwise check the returned error. +func (c *Client) ReloadConfig() (bool, *AppError) { + c.clearExtraProperties() + if r, err := c.DoApiGet("/admin/reload_config", "", ""); err != nil { + return false, err } else { - return &Result{r.Header.Get(HEADER_REQUEST_ID), - r.Header.Get(HEADER_ETAG_SERVER), ConfigFromJson(r.Body)}, nil + c.fillInExtraProperties(r) + return c.CheckStatusOK(r), nil } } @@ -618,15 +754,30 @@ func (c *Client) SaveConfig(config *Config) (*Result, *AppError) { if r, err := c.DoApiPost("/admin/save_config", config.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } } +// RecycleDatabaseConnection will attempt to recycle the database connections. +// You must have the system admin role to call this method. It will return status=OK +// if it's successfully recycled the connections, otherwise check the returned error. +func (c *Client) RecycleDatabaseConnection() (bool, *AppError) { + c.clearExtraProperties() + if r, err := c.DoApiGet("/admin/recycle_db_conn", "", ""); err != nil { + return false, err + } else { + c.fillInExtraProperties(r) + return c.CheckStatusOK(r), nil + } +} + func (c *Client) TestEmail(config *Config) (*Result, *AppError) { if r, err := c.DoApiPost("/admin/test_email", config.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -636,6 +787,7 @@ func (c *Client) GetComplianceReports() (*Result, *AppError) { if r, err := c.DoApiGet("/admin/compliance_reports", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), CompliancesFromJson(r.Body)}, nil } @@ -645,6 +797,7 @@ func (c *Client) SaveComplianceReport(job *Compliance) (*Result, *AppError) { if r, err := c.DoApiPost("/admin/save_compliance_report", job.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ComplianceFromJson(r.Body)}, nil } @@ -661,8 +814,10 @@ func (c *Client) DownloadComplianceReport(id string) (*Result, *AppError) { if rp, err := c.HttpClient.Do(rq); err != nil { return nil, NewLocAppError("/admin/download_compliance_report", "model.client.connecting.app_error", nil, err.Error()) } else if rp.StatusCode >= 300 { + defer rp.Body.Close() return nil, AppErrorFromJson(rp.Body) } else { + defer closeBody(rp) return &Result{rp.Header.Get(HEADER_REQUEST_ID), rp.Header.Get(HEADER_ETAG_SERVER), rp.Body}, nil } @@ -672,6 +827,7 @@ func (c *Client) GetTeamAnalytics(teamId, name string) (*Result, *AppError) { if r, err := c.DoApiGet("/admin/analytics/"+teamId+"/"+name, "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), AnalyticsRowsFromJson(r.Body)}, nil } @@ -681,6 +837,7 @@ func (c *Client) GetSystemAnalytics(name string) (*Result, *AppError) { if r, err := c.DoApiGet("/admin/analytics/"+name, "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), AnalyticsRowsFromJson(r.Body)}, nil } @@ -690,6 +847,7 @@ func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create", channel.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil } @@ -701,6 +859,7 @@ func (c *Client) CreateDirectChannel(userId string) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create_direct", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil } @@ -710,6 +869,7 @@ func (c *Client) UpdateChannel(channel *Channel) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update", channel.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil } @@ -719,6 +879,7 @@ func (c *Client) UpdateChannelHeader(data map[string]string) (*Result, *AppError if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_header", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil } @@ -728,6 +889,7 @@ func (c *Client) UpdateChannelPurpose(data map[string]string) (*Result, *AppErro if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_purpose", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelFromJson(r.Body)}, nil } @@ -737,6 +899,7 @@ func (c *Client) UpdateNotifyProps(data map[string]string) (*Result, *AppError) if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_notify_props", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -746,6 +909,7 @@ func (c *Client) GetChannels(etag string) (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelListFromJson(r.Body)}, nil } @@ -755,6 +919,7 @@ func (c *Client) GetChannel(id, etag string) (*Result, *AppError) { if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelDataFromJson(r.Body)}, nil } @@ -764,6 +929,7 @@ func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/more", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelListFromJson(r.Body)}, nil } @@ -773,6 +939,7 @@ func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/counts", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelCountsFromJson(r.Body)}, nil } @@ -849,6 +1016,7 @@ func (c *Client) GetChannelExtraInfo(id string, memberLimit int, etag string) (* if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/extra_info/"+strconv.FormatInt(int64(memberLimit), 10), "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), ChannelExtraFromJson(r.Body)}, nil } @@ -858,6 +1026,7 @@ func (c *Client) CreatePost(post *Post) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/create", post.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PostFromJson(r.Body)}, nil } @@ -867,6 +1036,7 @@ func (c *Client) UpdatePost(post *Post) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/update", post.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PostFromJson(r.Body)}, nil } @@ -876,6 +1046,7 @@ func (c *Client) GetPosts(channelId string, offset int, limit int, etag string) if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/page/%v/%v", offset, limit), "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil } @@ -885,6 +1056,7 @@ func (c *Client) GetPostsSince(channelId string, time int64) (*Result, *AppError if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/since/%v", time), "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil } @@ -894,6 +1066,7 @@ func (c *Client) GetPostsBefore(channelId string, postid string, offset int, lim if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/before/%v/%v", postid, offset, limit), "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil } @@ -903,6 +1076,7 @@ func (c *Client) GetPostsAfter(channelId string, postid string, offset int, limi if r, err := c.DoApiGet(fmt.Sprintf(c.GetChannelRoute(channelId)+"/posts/%v/after/%v/%v", postid, offset, limit), "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil } @@ -912,6 +1086,7 @@ func (c *Client) GetPost(channelId string, postId string, etag string) (*Result, if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/get", postId), "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil } @@ -921,6 +1096,7 @@ func (c *Client) DeletePost(channelId string, postId string) (*Result, *AppError if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/delete", postId), ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -933,6 +1109,7 @@ func (c *Client) SearchPosts(terms string, isOrSearch bool) (*Result, *AppError) if r, err := c.DoApiPost(c.GetTeamRoute()+"/posts/search", StringInterfaceToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PostListFromJson(r.Body)}, nil } @@ -959,6 +1136,7 @@ func (c *Client) uploadFile(url string, data []byte, contentType string) (*Resul } else if rp.StatusCode >= 300 { return nil, AppErrorFromJson(rp.Body) } else { + defer closeBody(rp) return &Result{rp.Header.Get(HEADER_REQUEST_ID), rp.Header.Get(HEADER_ETAG_SERVER), FileUploadResponseFromJson(rp.Body)}, nil } @@ -981,6 +1159,7 @@ func (c *Client) GetFile(url string, isFullUrl bool) (*Result, *AppError) { } else if rp.StatusCode >= 300 { return nil, AppErrorFromJson(rp.Body) } else { + defer closeBody(rp) return &Result{rp.Header.Get(HEADER_REQUEST_ID), rp.Header.Get(HEADER_ETAG_SERVER), rp.Body}, nil } @@ -999,6 +1178,7 @@ func (c *Client) GetFileInfo(url string) (*Result, *AppError) { } else if rp.StatusCode >= 300 { return nil, AppErrorFromJson(rp.Body) } else { + defer closeBody(rp) return &Result{rp.Header.Get(HEADER_REQUEST_ID), rp.Header.Get(HEADER_ETAG_SERVER), FileInfoFromJson(rp.Body)}, nil } @@ -1008,6 +1188,7 @@ func (c *Client) GetPublicLink(filename string) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/files/get_public_link", MapToJson(map[string]string{"filename": filename})); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), StringFromJson(r.Body)}, nil } @@ -1017,6 +1198,7 @@ func (c *Client) UpdateUser(user *User) (*Result, *AppError) { if r, err := c.DoApiPost("/users/update", user.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -1026,6 +1208,7 @@ func (c *Client) UpdateUserRoles(data map[string]string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/update_roles", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1037,6 +1220,7 @@ func (c *Client) AttachDeviceId(deviceId string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/attach_device", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -1049,6 +1233,7 @@ func (c *Client) UpdateActive(userId string, active bool) (*Result, *AppError) { if r, err := c.DoApiPost("/users/update_active", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -1058,6 +1243,7 @@ func (c *Client) UpdateUserNotify(data map[string]string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/update_notify", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil } @@ -1072,6 +1258,7 @@ func (c *Client) UpdateUserPassword(userId, currentPassword, newPassword string) if r, err := c.DoApiPost("/users/newpassword", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1083,6 +1270,7 @@ func (c *Client) SendPasswordReset(email string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/send_password_reset", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1095,6 +1283,7 @@ func (c *Client) ResetPassword(code, newPassword string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/reset_password", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1107,6 +1296,7 @@ func (c *Client) AdminResetPassword(userId, newPassword string) (*Result, *AppEr if r, err := c.DoApiPost("/admin/reset_password", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1116,6 +1306,7 @@ func (c *Client) GetStatuses(data []string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/status", ArrayToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1125,6 +1316,7 @@ func (c *Client) GetMyTeam(etag string) (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/me", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil } @@ -1134,6 +1326,7 @@ func (c *Client) GetTeamMembers(teamId string) (*Result, *AppError) { if r, err := c.DoApiGet("/teams/members/"+teamId, "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), TeamMembersFromJson(r.Body)}, nil } @@ -1143,6 +1336,7 @@ func (c *Client) RegisterApp(app *OAuthApp) (*Result, *AppError) { if r, err := c.DoApiPost("/oauth/register", app.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), OAuthAppFromJson(r.Body)}, nil } @@ -1152,6 +1346,7 @@ func (c *Client) AllowOAuth(rspType, clientId, redirect, scope, state string) (* if r, err := c.DoApiGet("/oauth/allow?response_type="+rspType+"&client_id="+clientId+"&redirect_uri="+url.QueryEscape(redirect)+"&scope="+scope+"&state="+url.QueryEscape(state), "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1161,6 +1356,7 @@ func (c *Client) GetAccessToken(data url.Values) (*Result, *AppError) { if r, err := c.DoApiPost("/oauth/access_token", data.Encode()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), AccessResponseFromJson(r.Body)}, nil } @@ -1170,6 +1366,7 @@ func (c *Client) CreateIncomingWebhook(hook *IncomingWebhook) (*Result, *AppErro if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/create", hook.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), IncomingWebhookFromJson(r.Body)}, nil } @@ -1190,6 +1387,7 @@ func (c *Client) DeleteIncomingWebhook(id string) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/delete", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1199,6 +1397,7 @@ func (c *Client) ListIncomingWebhooks() (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/hooks/incoming/list", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), IncomingWebhookListFromJson(r.Body)}, nil } @@ -1208,6 +1407,7 @@ func (c *Client) GetAllPreferences() (*Result, *AppError) { if r, err := c.DoApiGet("/preferences/", "", ""); err != nil { return nil, err } else { + defer closeBody(r) preferences, _ := PreferencesFromJson(r.Body) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), preferences}, nil } @@ -1226,6 +1426,7 @@ func (c *Client) GetPreference(category string, name string) (*Result, *AppError if r, err := c.DoApiGet("/preferences/"+category+"/"+name, "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), PreferenceFromJson(r.Body)}, nil } } @@ -1234,6 +1435,7 @@ func (c *Client) GetPreferenceCategory(category string) (*Result, *AppError) { if r, err := c.DoApiGet("/preferences/"+category, "", ""); err != nil { return nil, err } else { + defer closeBody(r) preferences, _ := PreferencesFromJson(r.Body) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), preferences}, nil } @@ -1243,6 +1445,7 @@ func (c *Client) CreateOutgoingWebhook(hook *OutgoingWebhook) (*Result, *AppErro if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/create", hook.ToJson()); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), OutgoingWebhookFromJson(r.Body)}, nil } @@ -1254,6 +1457,7 @@ func (c *Client) DeleteOutgoingWebhook(id string) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/delete", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1263,6 +1467,7 @@ func (c *Client) ListOutgoingWebhooks() (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/hooks/outgoing/list", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), OutgoingWebhookListFromJson(r.Body)}, nil } @@ -1274,6 +1479,7 @@ func (c *Client) RegenOutgoingWebhookToken(id string) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/regen_token", MapToJson(data)); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), OutgoingWebhookFromJson(r.Body)}, nil } @@ -1288,6 +1494,7 @@ func (c *Client) GetClientLicenceConfig(etag string) (*Result, *AppError) { if r, err := c.DoApiGet("/license/client_config", "", etag); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } @@ -1297,6 +1504,7 @@ func (c *Client) GetInitialLoad() (*Result, *AppError) { if r, err := c.DoApiGet("/users/initial_load", "", ""); err != nil { return nil, err } else { + defer closeBody(r) return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), InitialLoadFromJson(r.Body)}, nil } diff --git a/vendor/github.com/mattermost/platform/model/command.go b/vendor/github.com/mattermost/platform/model/command.go index 4d5f7ace..decb647b 100644 --- a/vendor/github.com/mattermost/platform/model/command.go +++ b/vendor/github.com/mattermost/platform/model/command.go @@ -6,11 +6,14 @@ package model import ( "encoding/json" "io" + "strings" ) const ( COMMAND_METHOD_POST = "P" COMMAND_METHOD_GET = "G" + MIN_TRIGGER_LENGTH = 1 + MAX_TRIGGER_LENGTH = 128 ) type Command struct { @@ -99,7 +102,7 @@ func (o *Command) IsValid() *AppError { return NewLocAppError("Command.IsValid", "model.command.is_valid.team_id.app_error", nil, "") } - if len(o.Trigger) == 0 || len(o.Trigger) > 128 { + if len(o.Trigger) < MIN_TRIGGER_LENGTH || len(o.Trigger) > MAX_TRIGGER_LENGTH || strings.Index(o.Trigger, "/") == 0 || strings.Contains(o.Trigger, " ") { return NewLocAppError("Command.IsValid", "model.command.is_valid.trigger.app_error", nil, "") } diff --git a/vendor/github.com/mattermost/platform/model/config.go b/vendor/github.com/mattermost/platform/model/config.go index eb25948f..55606ee8 100644 --- a/vendor/github.com/mattermost/platform/model/config.go +++ b/vendor/github.com/mattermost/platform/model/config.go @@ -6,6 +6,7 @@ package model import ( "encoding/json" "io" + "strings" ) const ( @@ -35,6 +36,15 @@ const ( FAKE_SETTING = "********************************" ) +// should match the values in webapp/i18n/i18n.jsx +var LOCALES = []string{ + "en", + "es", + "fr", + "ja", + "pt-BR", +} + type ServiceSettings struct { ListenAddress string MaximumLoginAttempts int @@ -92,6 +102,7 @@ type LogSettings struct { } type FileSettings struct { + MaxFileSize *int64 DriverName string Directory string EnablePublicLink bool @@ -189,6 +200,9 @@ type LdapSettings struct { NicknameAttribute *string IdAttribute *string + // Syncronization + SyncIntervalMinutes *int + // Advanced SkipCertificateVerification *bool QueryTimeout *int @@ -203,20 +217,27 @@ type ComplianceSettings struct { EnableDaily *bool } +type LocalizationSettings struct { + DefaultServerLocale *string + DefaultClientLocale *string + AvailableLocales *string +} + type Config struct { - ServiceSettings ServiceSettings - TeamSettings TeamSettings - SqlSettings SqlSettings - LogSettings LogSettings - FileSettings FileSettings - EmailSettings EmailSettings - RateLimitSettings RateLimitSettings - PrivacySettings PrivacySettings - SupportSettings SupportSettings - GitLabSettings SSOSettings - GoogleSettings SSOSettings - LdapSettings LdapSettings - ComplianceSettings ComplianceSettings + ServiceSettings ServiceSettings + TeamSettings TeamSettings + SqlSettings SqlSettings + LogSettings LogSettings + FileSettings FileSettings + EmailSettings EmailSettings + RateLimitSettings RateLimitSettings + PrivacySettings PrivacySettings + SupportSettings SupportSettings + GitLabSettings SSOSettings + GoogleSettings SSOSettings + LdapSettings LdapSettings + ComplianceSettings ComplianceSettings + LocalizationSettings LocalizationSettings } func (o *Config) ToJson() string { @@ -256,6 +277,11 @@ func (o *Config) SetDefaults() { o.SqlSettings.AtRestEncryptKey = NewRandomString(32) } + if o.FileSettings.MaxFileSize == nil { + o.FileSettings.MaxFileSize = new(int64) + *o.FileSettings.MaxFileSize = 52428800 // 50 MB + } + if len(o.FileSettings.PublicLinkSalt) == 0 { o.FileSettings.PublicLinkSalt = NewRandomString(32) } @@ -403,19 +429,39 @@ func (o *Config) SetDefaults() { *o.SupportSettings.SupportEmail = "feedback@mattermost.com" } + if o.LdapSettings.Enable == nil { + o.LdapSettings.Enable = new(bool) + *o.LdapSettings.Enable = false + } + + if o.LdapSettings.LdapServer == nil { + o.LdapSettings.LdapServer = new(string) + *o.LdapSettings.LdapServer = "" + } + if o.LdapSettings.LdapPort == nil { o.LdapSettings.LdapPort = new(int) *o.LdapSettings.LdapPort = 389 } - if o.LdapSettings.QueryTimeout == nil { - o.LdapSettings.QueryTimeout = new(int) - *o.LdapSettings.QueryTimeout = 60 + if o.LdapSettings.ConnectionSecurity == nil { + o.LdapSettings.ConnectionSecurity = new(string) + *o.LdapSettings.ConnectionSecurity = "" } - if o.LdapSettings.Enable == nil { - o.LdapSettings.Enable = new(bool) - *o.LdapSettings.Enable = false + if o.LdapSettings.BaseDN == nil { + o.LdapSettings.BaseDN = new(string) + *o.LdapSettings.BaseDN = "" + } + + if o.LdapSettings.BindUsername == nil { + o.LdapSettings.BindUsername = new(string) + *o.LdapSettings.BindUsername = "" + } + + if o.LdapSettings.BindPassword == nil { + o.LdapSettings.BindPassword = new(string) + *o.LdapSettings.BindPassword = "" } if o.LdapSettings.UserFilter == nil { @@ -423,6 +469,46 @@ func (o *Config) SetDefaults() { *o.LdapSettings.UserFilter = "" } + if o.LdapSettings.FirstNameAttribute == nil { + o.LdapSettings.FirstNameAttribute = new(string) + *o.LdapSettings.FirstNameAttribute = "" + } + + if o.LdapSettings.LastNameAttribute == nil { + o.LdapSettings.LastNameAttribute = new(string) + *o.LdapSettings.LastNameAttribute = "" + } + + if o.LdapSettings.EmailAttribute == nil { + o.LdapSettings.EmailAttribute = new(string) + *o.LdapSettings.EmailAttribute = "" + } + + if o.LdapSettings.NicknameAttribute == nil { + o.LdapSettings.NicknameAttribute = new(string) + *o.LdapSettings.NicknameAttribute = "" + } + + if o.LdapSettings.IdAttribute == nil { + o.LdapSettings.IdAttribute = new(string) + *o.LdapSettings.IdAttribute = "" + } + + if o.LdapSettings.SyncIntervalMinutes == nil { + o.LdapSettings.SyncIntervalMinutes = new(int) + *o.LdapSettings.SyncIntervalMinutes = 60 + } + + if o.LdapSettings.SkipCertificateVerification == nil { + o.LdapSettings.SkipCertificateVerification = new(bool) + *o.LdapSettings.SkipCertificateVerification = false + } + + if o.LdapSettings.QueryTimeout == nil { + o.LdapSettings.QueryTimeout = new(int) + *o.LdapSettings.QueryTimeout = 60 + } + if o.LdapSettings.LoginFieldName == nil { o.LdapSettings.LoginFieldName = new(string) *o.LdapSettings.LoginFieldName = "" @@ -493,19 +579,19 @@ func (o *Config) SetDefaults() { *o.ComplianceSettings.EnableDaily = false } - if o.LdapSettings.ConnectionSecurity == nil { - o.LdapSettings.ConnectionSecurity = new(string) - *o.LdapSettings.ConnectionSecurity = "" + if o.LocalizationSettings.DefaultServerLocale == nil { + o.LocalizationSettings.DefaultServerLocale = new(string) + *o.LocalizationSettings.DefaultServerLocale = DEFAULT_LOCALE } - if o.LdapSettings.SkipCertificateVerification == nil { - o.LdapSettings.SkipCertificateVerification = new(bool) - *o.LdapSettings.SkipCertificateVerification = false + if o.LocalizationSettings.DefaultClientLocale == nil { + o.LocalizationSettings.DefaultClientLocale = new(string) + *o.LocalizationSettings.DefaultClientLocale = DEFAULT_LOCALE } - if o.LdapSettings.NicknameAttribute == nil { - o.LdapSettings.NicknameAttribute = new(string) - *o.LdapSettings.NicknameAttribute = "" + if o.LocalizationSettings.AvailableLocales == nil { + o.LocalizationSettings.AvailableLocales = new(string) + *o.LocalizationSettings.AvailableLocales = strings.Join(LOCALES, ",") } } @@ -547,6 +633,10 @@ func (o *Config) IsValid() *AppError { return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_max_conn.app_error", nil, "") } + if *o.FileSettings.MaxFileSize <= 0 { + return NewLocAppError("Config.IsValid", "model.config.is_valid.max_file_size.app_error", nil, "") + } + if !(o.FileSettings.DriverName == IMAGE_DRIVER_LOCAL || o.FileSettings.DriverName == IMAGE_DRIVER_S3) { return NewLocAppError("Config.IsValid", "model.config.is_valid.file_driver.app_error", nil, "") } @@ -603,6 +693,10 @@ func (o *Config) IsValid() *AppError { return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_security.app_error", nil, "") } + if *o.LdapSettings.SyncIntervalMinutes <= 0 { + return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_sync_interval.app_error", nil, "") + } + return nil } @@ -615,7 +709,7 @@ func (o *Config) GetSanitizeOptions() map[string]bool { } func (o *Config) Sanitize() { - if &o.LdapSettings != nil && len(*o.LdapSettings.BindPassword) > 0 { + if o.LdapSettings.BindPassword != nil && len(*o.LdapSettings.BindPassword) > 0 { *o.LdapSettings.BindPassword = FAKE_SETTING } diff --git a/vendor/github.com/mattermost/platform/model/file.go b/vendor/github.com/mattermost/platform/model/file.go index b7806b3b..fa98a3b3 100644 --- a/vendor/github.com/mattermost/platform/model/file.go +++ b/vendor/github.com/mattermost/platform/model/file.go @@ -8,10 +8,6 @@ import ( "io" ) -const ( - MAX_FILE_SIZE = 50000000 // 50 MB -) - var ( IMAGE_EXTENSIONS = [5]string{".jpg", ".jpeg", ".gif", ".bmp", ".png"} IMAGE_MIME_TYPES = map[string]string{".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".gif": "image/gif", ".bmp": "image/bmp", ".png": "image/png", ".tiff": "image/tiff"} diff --git a/vendor/github.com/mattermost/platform/model/gitlab/gitlab.go b/vendor/github.com/mattermost/platform/model/gitlab/gitlab.go index fc70dd93..e189ee68 100644 --- a/vendor/github.com/mattermost/platform/model/gitlab/gitlab.go +++ b/vendor/github.com/mattermost/platform/model/gitlab/gitlab.go @@ -47,7 +47,8 @@ func userFromGitLabUser(glu *GitLabUser) *model.User { } strings.TrimSpace(user.Email) user.Email = glu.Email - *user.AuthData = strconv.FormatInt(glu.Id, 10) + userId := strconv.FormatInt(glu.Id, 10) + user.AuthData = &userId user.AuthService = model.USER_AUTH_SERVICE_GITLAB return user diff --git a/vendor/github.com/mattermost/platform/model/incoming_webhook.go b/vendor/github.com/mattermost/platform/model/incoming_webhook.go index 0763b443..c567edfd 100644 --- a/vendor/github.com/mattermost/platform/model/incoming_webhook.go +++ b/vendor/github.com/mattermost/platform/model/incoming_webhook.go @@ -4,13 +4,15 @@ package model import ( + "bytes" "encoding/json" "io" + "regexp" + "strings" ) const ( DEFAULT_WEBHOOK_USERNAME = "webhook" - DEFAULT_WEBHOOK_ICON = "/static/images/webhook_icon.jpg" ) type IncomingWebhook struct { @@ -125,13 +127,136 @@ func (o *IncomingWebhook) PreUpdate() { o.UpdateAt = GetMillis() } -func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest { - decoder := json.NewDecoder(data) +// escapeControlCharsFromPayload escapes control chars (\n, \t) from a byte slice. +// Context: +// JSON strings are not supposed to contain control characters such as \n, \t, +// ... but some incoming webhooks might still send invalid JSON and we want to +// try to handle that. An example invalid JSON string from an incoming webhook +// might look like this (strings for both "text" and "fallback" attributes are +// invalid JSON strings because they contain unescaped newlines and tabs): +// `{ +// "text": "this is a test +// that contains a newline and tabs", +// "attachments": [ +// { +// "fallback": "Required plain-text summary of the attachment +// that contains a newline and tabs", +// "color": "#36a64f", +// ... +// "text": "Optional text that appears within the attachment +// that contains a newline and tabs", +// ... +// "thumb_url": "http://example.com/path/to/thumb.png" +// } +// ] +// }` +// This function will search for `"key": "value"` pairs, and escape \n, \t +// from the value. +func escapeControlCharsFromPayload(by []byte) []byte { + // we'll search for `"text": "..."` or `"fallback": "..."`, ... + keys := "text|fallback|pretext|author_name|title|value" + + // the regexp reads like this: + // (?s): this flag let . match \n (default is false) + // "(keys)": we search for the keys defined above + // \s*:\s*: followed by 0..n spaces/tabs, a colon then 0..n spaces/tabs + // ": a double-quote + // (\\"|[^"])*: any number of times the `\"` string or any char but a double-quote + // ": a double-quote + r := `(?s)"(` + keys + `)"\s*:\s*"(\\"|[^"])*"` + re := regexp.MustCompile(r) + + // the function that will escape \n and \t on the regexp matches + repl := func(b []byte) []byte { + if bytes.Contains(b, []byte("\n")) { + b = bytes.Replace(b, []byte("\n"), []byte("\\n"), -1) + } + if bytes.Contains(b, []byte("\t")) { + b = bytes.Replace(b, []byte("\t"), []byte("\\t"), -1) + } + + return b + } + + return re.ReplaceAllFunc(by, repl) +} + +func decodeIncomingWebhookRequest(by []byte) (*IncomingWebhookRequest, error) { + decoder := json.NewDecoder(bytes.NewReader(by)) var o IncomingWebhookRequest err := decoder.Decode(&o) if err == nil { - return &o + return &o, nil } else { - return nil + return nil, err + } +} + +// To mention @channel via a webhook in Slack, the message should contain +// , as explained at the bottom of this article: +// https://get.slack.help/hc/en-us/articles/202009646-Making-announcements +func expandAnnouncement(text string) string { + c1 := "" + c2 := "@channel" + if strings.Contains(text, c1) { + return strings.Replace(text, c1, c2, -1) + } + return text +} + +// Expand announcements in incoming webhooks from Slack. Those announcements +// can be found in the text attribute, or in the pretext, text, title and value +// attributes of the attachment structure. The Slack attachment structure is +// documented here: https://api.slack.com/docs/attachments +func expandAnnouncements(i *IncomingWebhookRequest) { + i.Text = expandAnnouncement(i.Text) + + if i.Attachments != nil { + attachments := i.Attachments.([]interface{}) + for _, attachment := range attachments { + a := attachment.(map[string]interface{}) + + if a["pretext"] != nil { + a["pretext"] = expandAnnouncement(a["pretext"].(string)) + } + + if a["text"] != nil { + a["text"] = expandAnnouncement(a["text"].(string)) + } + + if a["title"] != nil { + a["title"] = expandAnnouncement(a["title"].(string)) + } + + if a["fields"] != nil { + fields := a["fields"].([]interface{}) + for _, field := range fields { + f := field.(map[string]interface{}) + if f["value"] != nil { + f["value"] = expandAnnouncement(f["value"].(string)) + } + } + } + } } } + +func IncomingWebhookRequestFromJson(data io.Reader) *IncomingWebhookRequest { + buf := new(bytes.Buffer) + buf.ReadFrom(data) + by := buf.Bytes() + + // Try to decode the JSON data. Only if it fails, try to escape control + // characters from the strings contained in the JSON data. + o, err := decodeIncomingWebhookRequest(by) + if err != nil { + o, err = decodeIncomingWebhookRequest(escapeControlCharsFromPayload(by)) + if err != nil { + return nil + } + } + + expandAnnouncements(o) + + return o +} diff --git a/vendor/github.com/mattermost/platform/model/job.go b/vendor/github.com/mattermost/platform/model/job.go new file mode 100644 index 00000000..bcae7a83 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/job.go @@ -0,0 +1,91 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "fmt" + "time" +) + +type TaskFunc func() + +type ScheduledTask struct { + Name string `json:"name"` + Interval time.Duration `json:"interval"` + Recurring bool `json:"recurring"` + function TaskFunc `json:",omitempty"` + timer *time.Timer `json:",omitempty"` +} + +var tasks = make(map[string]*ScheduledTask) + +func addTask(task *ScheduledTask) { + tasks[task.Name] = task +} + +func removeTaskByName(name string) { + delete(tasks, name) +} + +func getTaskByName(name string) *ScheduledTask { + return tasks[name] +} + +func GetAllTasks() *map[string]*ScheduledTask { + return &tasks +} + +func CreateTask(name string, function TaskFunc, timeToExecution time.Duration) *ScheduledTask { + task := &ScheduledTask{ + Name: name, + Interval: timeToExecution, + Recurring: false, + function: function, + } + + taskRunner := func() { + go task.function() + removeTaskByName(task.Name) + } + + task.timer = time.AfterFunc(timeToExecution, taskRunner) + + addTask(task) + + return task +} + +func CreateRecurringTask(name string, function TaskFunc, interval time.Duration) *ScheduledTask { + task := &ScheduledTask{ + Name: name, + Interval: interval, + Recurring: true, + function: function, + } + + taskRecurer := func() { + go task.function() + task.timer.Reset(task.Interval) + } + + task.timer = time.AfterFunc(interval, taskRecurer) + + addTask(task) + + return task +} + +func (task *ScheduledTask) Cancel() { + task.timer.Stop() + removeTaskByName(task.Name) +} + +func (task *ScheduledTask) String() string { + return fmt.Sprintf( + "%s\nInterval: %s\nRecurring: %t\n", + task.Name, + task.Interval.String(), + task.Recurring, + ) +} diff --git a/vendor/github.com/mattermost/platform/model/outgoing_webhook.go b/vendor/github.com/mattermost/platform/model/outgoing_webhook.go index ef1807e7..ee7a32f1 100644 --- a/vendor/github.com/mattermost/platform/model/outgoing_webhook.go +++ b/vendor/github.com/mattermost/platform/model/outgoing_webhook.go @@ -7,6 +7,8 @@ import ( "encoding/json" "fmt" "io" + "net/url" + "strconv" ) type OutgoingWebhook struct { @@ -22,6 +24,47 @@ type OutgoingWebhook struct { CallbackURLs StringArray `json:"callback_urls"` DisplayName string `json:"display_name"` Description string `json:"description"` + ContentType string `json:"content_type"` +} + +type OutgoingWebhookPayload struct { + Token string `json:"token"` + TeamId string `json:"team_id"` + TeamDomain string `json:"team_domain"` + ChannelId string `json:"channel_id"` + ChannelName string `json:"channel_name"` + Timestamp int64 `json:"timestamp"` + UserId string `json:"user_id"` + UserName string `json:"user_name"` + PostId string `json:"post_id"` + Text string `json:"text"` + TriggerWord string `json:"trigger_word"` +} + +func (o *OutgoingWebhookPayload) ToJSON() string { + b, err := json.Marshal(o) + if err != nil { + return "" + } else { + return string(b) + } +} + +func (o *OutgoingWebhookPayload) ToFormValues() string { + v := url.Values{} + v.Set("token", o.Token) + v.Set("team_id", o.TeamId) + v.Set("team_domain", o.TeamDomain) + v.Set("channel_id", o.ChannelId) + v.Set("channel_name", o.ChannelName) + v.Set("timestamp", strconv.FormatInt(o.Timestamp/1000, 10)) + v.Set("user_id", o.UserId) + v.Set("user_name", o.UserName) + v.Set("post_id", o.PostId) + v.Set("text", o.Text) + v.Set("trigger_word", o.TriggerWord) + + return v.Encode() } func (o *OutgoingWebhook) ToJson() string { @@ -124,6 +167,10 @@ func (o *OutgoingWebhook) IsValid() *AppError { return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.description.app_error", nil, "") } + if len(o.ContentType) > 128 { + return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.content_type.app_error", nil, "") + } + return nil } diff --git a/vendor/github.com/mattermost/platform/model/preference.go b/vendor/github.com/mattermost/platform/model/preference.go index b2ec9310..22858e04 100644 --- a/vendor/github.com/mattermost/platform/model/preference.go +++ b/vendor/github.com/mattermost/platform/model/preference.go @@ -14,6 +14,9 @@ const ( PREFERENCE_CATEGORY_TUTORIAL_STEPS = "tutorial_step" PREFERENCE_CATEGORY_ADVANCED_SETTINGS = "advanced_settings" + PREFERENCE_CATEGORY_DISPLAY_SETTINGS = "display_settings" + PREFERENCE_NAME_COLLAPSE_SETTING = "collapse_previews" + PREFERENCE_CATEGORY_LAST = "last" PREFERENCE_NAME_LAST_CHANNEL = "channel" ) diff --git a/vendor/github.com/mattermost/platform/model/search_params.go b/vendor/github.com/mattermost/platform/model/search_params.go index 250c8e1f..1772c902 100644 --- a/vendor/github.com/mattermost/platform/model/search_params.go +++ b/vendor/github.com/mattermost/platform/model/search_params.go @@ -4,9 +4,13 @@ package model import ( + "regexp" "strings" ) +var searchTermPuncStart = regexp.MustCompile(`^[^\pL\d\s#"]+`) +var searchTermPuncEnd = regexp.MustCompile(`[^\pL\d\s*"]+$`) + type SearchParams struct { Terms string IsHashtag bool @@ -91,8 +95,8 @@ func parseSearchFlags(input []string) ([]string, [][2]string) { if !isFlag { // trim off surrounding punctuation (note that we leave trailing asterisks to allow wildcards) - word = puncStart.ReplaceAllString(word, "") - word = puncEndWildcard.ReplaceAllString(word, "") + word = searchTermPuncStart.ReplaceAllString(word, "") + word = searchTermPuncEnd.ReplaceAllString(word, "") // and remove extra pound #s word = hashtagStart.ReplaceAllString(word, "#") diff --git a/vendor/github.com/mattermost/platform/model/user.go b/vendor/github.com/mattermost/platform/model/user.go index 15c28140..ab076894 100644 --- a/vendor/github.com/mattermost/platform/model/user.go +++ b/vendor/github.com/mattermost/platform/model/user.go @@ -136,7 +136,6 @@ func (u *User) PreSave() { u.Username = strings.ToLower(u.Username) u.Email = strings.ToLower(u.Email) - u.Locale = strings.ToLower(u.Locale) u.CreateAt = GetMillis() u.UpdateAt = u.CreateAt @@ -166,7 +165,6 @@ func (u *User) PreSave() { func (u *User) PreUpdate() { u.Username = strings.ToLower(u.Username) u.Email = strings.ToLower(u.Email) - u.Locale = strings.ToLower(u.Locale) u.UpdateAt = GetMillis() if u.AuthData != nil && *u.AuthData == "" { @@ -186,11 +184,27 @@ func (u *User) PreUpdate() { } u.NotifyProps["mention_keys"] = strings.Join(goodKeys, ",") } + + if u.ThemeProps != nil { + colorPattern := regexp.MustCompile(`^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$`) + + // blank out any invalid theme values + for name, value := range u.ThemeProps { + if name == "image" || name == "type" || name == "codeTheme" { + continue + } + + if !colorPattern.MatchString(value) { + u.ThemeProps[name] = "#ffffff" + } + } + } } func (u *User) SetDefaultNotifications() { u.NotifyProps = make(map[string]string) u.NotifyProps["email"] = "true" + u.NotifyProps["push"] = USER_NOTIFY_MENTION u.NotifyProps["desktop"] = USER_NOTIFY_ALL u.NotifyProps["desktop_sound"] = "true" u.NotifyProps["mention_keys"] = u.Username + ",@" + u.Username diff --git a/vendor/github.com/mattermost/platform/model/utils.go b/vendor/github.com/mattermost/platform/model/utils.go index 443a34bc..27093c09 100644 --- a/vendor/github.com/mattermost/platform/model/utils.go +++ b/vendor/github.com/mattermost/platform/model/utils.go @@ -315,10 +315,9 @@ func Etag(parts ...interface{}) string { } var validHashtag = regexp.MustCompile(`^(#[A-Za-zäöüÄÖÜß]+[A-Za-z0-9äöüÄÖÜß_\-]*[A-Za-z0-9äöüÄÖÜß])$`) -var puncStart = regexp.MustCompile(`^[.,()&$!\?\[\]{}':;\\<>\-+=%^*|]+`) +var puncStart = regexp.MustCompile(`^[^\pL\d\s#]+`) var hashtagStart = regexp.MustCompile(`^#{2,}`) -var puncEnd = regexp.MustCompile(`[.,()&$#!\?\[\]{}':;\\<>\-+=%^*|]+$`) -var puncEndWildcard = regexp.MustCompile(`[.,()&$#!\?\[\]{}':;\\<>\-+=%^|]+$`) +var puncEnd = regexp.MustCompile(`[^\pL\d\s]+$`) func ParseHashtags(text string) (string, string) { words := strings.Fields(text) diff --git a/vendor/github.com/mattermost/platform/model/version.go b/vendor/github.com/mattermost/platform/model/version.go index 4a47f06e..d486f5c5 100644 --- a/vendor/github.com/mattermost/platform/model/version.go +++ b/vendor/github.com/mattermost/platform/model/version.go @@ -13,6 +13,7 @@ import ( // It should be maitained in chronological order with most current // release at the front of the list. var versions = []string{ + "3.1.0", "3.0.0", "2.2.0", "2.1.0", @@ -33,6 +34,7 @@ var CurrentVersion string = versions[0] var BuildNumber string var BuildDate string var BuildHash string +var BuildHashEnterprise string var BuildEnterpriseReady string var versionsWithoutHotFixes []string -- cgit v1.2.3