From 93114b76828357644afb22f7359c0ba185719478 Mon Sep 17 00:00:00 2001 From: Wim Date: Mon, 16 Jan 2017 23:59:50 +0100 Subject: [PATCH] Sync with mattermost 3.6.0 --- .../platform/einterfaces/cluster.go | 4 + .../platform/einterfaces/metrics.go | 41 +++ .../platform/model/channel_member.go | 8 + .../platform/model/channel_search.go | 35 +++ .../mattermost/platform/model/channel_view.go | 34 +++ .../mattermost/platform/model/client.go | 279 +++++++++++++++--- .../platform/model/cluster_stats.go | 36 +++ .../mattermost/platform/model/command_args.go | 36 +++ .../platform/model/command_response.go | 2 + .../mattermost/platform/model/config.go | 104 ++++++- .../platform/model/incoming_webhook.go | 3 +- .../mattermost/platform/model/license.go | 7 + .../mattermost/platform/model/post.go | 21 +- .../mattermost/platform/model/preference.go | 1 + .../platform/model/push_notification.go | 1 + .../mattermost/platform/model/reaction.go | 78 +++++ .../mattermost/platform/model/status.go | 13 +- .../mattermost/platform/model/team.go | 5 + .../mattermost/platform/model/team_member.go | 25 ++ .../mattermost/platform/model/team_signup.go | 40 --- .../mattermost/platform/model/user.go | 5 + .../{autocomplete.go => user_autocomplete.go} | 0 .../mattermost/platform/model/utils.go | 2 +- .../mattermost/platform/model/version.go | 1 + .../platform/model/websocket_message.go | 12 + vendor/manifest | 8 +- 26 files changed, 710 insertions(+), 91 deletions(-) create mode 100644 vendor/github.com/mattermost/platform/einterfaces/metrics.go create mode 100644 vendor/github.com/mattermost/platform/model/channel_search.go create mode 100644 vendor/github.com/mattermost/platform/model/channel_view.go create mode 100644 vendor/github.com/mattermost/platform/model/cluster_stats.go create mode 100644 vendor/github.com/mattermost/platform/model/command_args.go create mode 100644 vendor/github.com/mattermost/platform/model/reaction.go delete mode 100644 vendor/github.com/mattermost/platform/model/team_signup.go rename vendor/github.com/mattermost/platform/model/{autocomplete.go => user_autocomplete.go} (100%) diff --git a/vendor/github.com/mattermost/platform/einterfaces/cluster.go b/vendor/github.com/mattermost/platform/einterfaces/cluster.go index 6b439539..0d7bf7e8 100644 --- a/vendor/github.com/mattermost/platform/einterfaces/cluster.go +++ b/vendor/github.com/mattermost/platform/einterfaces/cluster.go @@ -11,13 +11,17 @@ type ClusterInterface interface { StartInterNodeCommunication() StopInterNodeCommunication() GetClusterInfos() []*model.ClusterInfo + GetClusterStats() ([]*model.ClusterStats, *model.AppError) RemoveAllSessionsForUserId(userId string) InvalidateCacheForUser(userId string) + InvalidateCacheForChannel(channelId string) + InvalidateCacheForChannelPosts(channelId string) Publish(event *model.WebSocketEvent) UpdateStatus(status *model.Status) GetLogs() ([]string, *model.AppError) GetClusterId() string ConfigChanged(previousConfig *model.Config, newConfig *model.Config, sendToOtherServer bool) *model.AppError + InvalidateAllCaches() *model.AppError } var theClusterInterface ClusterInterface diff --git a/vendor/github.com/mattermost/platform/einterfaces/metrics.go b/vendor/github.com/mattermost/platform/einterfaces/metrics.go new file mode 100644 index 00000000..f7d660da --- /dev/null +++ b/vendor/github.com/mattermost/platform/einterfaces/metrics.go @@ -0,0 +1,41 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package einterfaces + +type MetricsInterface interface { + StartServer() + StopServer() + + IncrementPostCreate() + IncrementPostSentEmail() + IncrementPostSentPush() + IncrementPostBroadcast() + IncrementPostFileAttachment(count int) + + IncrementHttpRequest() + IncrementHttpError() + ObserveHttpRequestDuration(elapsed float64) + + IncrementLogin() + IncrementLoginFail() + + IncrementEtagHitCounter(route string) + IncrementEtagMissCounter(route string) + + IncrementMemCacheHitCounter(cacheName string) + IncrementMemCacheMissCounter(cacheName string) + + AddMemCacheHitCounter(cacheName string, amount float64) + AddMemCacheMissCounter(cacheName string, amount float64) +} + +var theMetricsInterface MetricsInterface + +func RegisterMetricsInterface(newInterface MetricsInterface) { + theMetricsInterface = newInterface +} + +func GetMetricsInterface() MetricsInterface { + return theMetricsInterface +} diff --git a/vendor/github.com/mattermost/platform/model/channel_member.go b/vendor/github.com/mattermost/platform/model/channel_member.go index 4180bb8e..a607a505 100644 --- a/vendor/github.com/mattermost/platform/model/channel_member.go +++ b/vendor/github.com/mattermost/platform/model/channel_member.go @@ -18,6 +18,14 @@ const ( CHANNEL_MARK_UNREAD_MENTION = "mention" ) +type ChannelUnread struct { + TeamId string + TotalMsgCount int64 + MsgCount int64 + MentionCount int64 + NotifyProps StringMap +} + type ChannelMember struct { ChannelId string `json:"channel_id"` UserId string `json:"user_id"` diff --git a/vendor/github.com/mattermost/platform/model/channel_search.go b/vendor/github.com/mattermost/platform/model/channel_search.go new file mode 100644 index 00000000..2c041503 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/channel_search.go @@ -0,0 +1,35 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type ChannelSearch struct { + Term string `json:"term"` +} + +// ToJson convert a Channel to a json string +func (c *ChannelSearch) ToJson() string { + b, err := json.Marshal(c) + if err != nil { + return "" + } else { + return string(b) + } +} + +// ChannelSearchFromJson will decode the input and return a Channel +func ChannelSearchFromJson(data io.Reader) *ChannelSearch { + decoder := json.NewDecoder(data) + var cs ChannelSearch + err := decoder.Decode(&cs) + if err == nil { + return &cs + } else { + return nil + } +} diff --git a/vendor/github.com/mattermost/platform/model/channel_view.go b/vendor/github.com/mattermost/platform/model/channel_view.go new file mode 100644 index 00000000..8be7af17 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/channel_view.go @@ -0,0 +1,34 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type ChannelView struct { + ChannelId string `json:"channel_id"` + PrevChannelId string `json:"prev_channel_id"` +} + +func (o *ChannelView) ToJson() string { + b, err := json.Marshal(o) + if err != nil { + return "" + } else { + return string(b) + } +} + +func ChannelViewFromJson(data io.Reader) *ChannelView { + decoder := json.NewDecoder(data) + var o ChannelView + err := decoder.Decode(&o) + if err == nil { + return &o + } else { + return nil + } +} diff --git a/vendor/github.com/mattermost/platform/model/client.go b/vendor/github.com/mattermost/platform/model/client.go index 8a361c17..540bc747 100644 --- a/vendor/github.com/mattermost/platform/model/client.go +++ b/vendor/github.com/mattermost/platform/model/client.go @@ -6,7 +6,6 @@ package model import ( "bytes" "fmt" - l4g "github.com/alecthomas/log4go" "io" "io/ioutil" "mime/multipart" @@ -15,6 +14,8 @@ import ( "strconv" "strings" "time" + + l4g "github.com/alecthomas/log4go" ) const ( @@ -48,6 +49,13 @@ type Result struct { Data interface{} } +type ResponseMetadata struct { + StatusCode int + Error *AppError + RequestId string + Etag string +} + 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" @@ -291,34 +299,6 @@ func (c *Client) GetPing() (map[string]string, *AppError) { // Team Routes Section -// SignupTeam sends an email with a team sign-up link to the provided address if email -// verification is enabled, otherwise it returns a map with a "follow_link" entry -// containing the team sign-up link. -func (c *Client) SignupTeam(email string, displayName string) (*Result, *AppError) { - m := make(map[string]string) - m["email"] = email - m["display_name"] = displayName - 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 - } -} - -// CreateTeamFromSignup creates a team based on the provided TeamSignup struct. On success -// it returns the TeamSignup struct. -func (c *Client) CreateTeamFromSignup(teamSignup *TeamSignup) (*Result, *AppError) { - 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 - } -} - // CreateTeam creates a team based on the provided Team struct. On success it returns // the Team struct with the Id, CreateAt and other server-decided fields populated. func (c *Client) CreateTeam(team *Team) (*Result, *AppError) { @@ -500,6 +480,32 @@ func (c *Client) GetUser(id string, etag string) (*Result, *AppError) { } } +// getByUsername returns a user based on a provided username string. Must be authenticated. +func (c *Client) GetByUsername(username string, etag string) (*Result, *AppError) { + if r, err := c.DoApiGet(fmt.Sprintf("/users/name/%v", username), "", 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 + } +} + +// getByEmail returns a user based on a provided username string. Must be authenticated. +func (c *Client) GetByEmail(email string, etag string) (*User, *ResponseMetadata) { + if r, err := c.DoApiGet(fmt.Sprintf("/users/email/%v", email), "", etag); err != nil { + return nil, &ResponseMetadata{StatusCode: r.StatusCode, Error: err} + } else { + defer closeBody(r) + return UserFromJson(r.Body), + &ResponseMetadata{ + StatusCode: r.StatusCode, + RequestId: r.Header.Get(HEADER_REQUEST_ID), + Etag: r.Header.Get(HEADER_ETAG_SERVER), + } + } +} + // GetMe returns the current user. func (c *Client) GetMe(etag string) (*Result, *AppError) { if r, err := c.DoApiGet("/users/me", "", etag); err != nil { @@ -610,6 +616,19 @@ func (c *Client) AutocompleteUsersInTeam(term string) (*Result, *AppError) { } } +// AutocompleteUsers returns a list for autocompletion of users on the system that match the provided term, +// matching against username, full name and nickname. Must be authenticated. +func (c *Client) AutocompleteUsers(term string) (*Result, *AppError) { + url := fmt.Sprintf("/users/autocomplete?term=%s", url.QueryEscape(term)) + if r, err := c.DoApiGet(url, "", ""); err != nil { + return nil, err + } else { + defer closeBody(r) + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), UserListFromJson(r.Body)}, nil + } +} + // LoginById authenticates a user by user id and password. func (c *Client) LoginById(id string, password string) (*Result, *AppError) { m := make(map[string]string) @@ -802,12 +821,9 @@ func (c *Client) EmailToLDAP(m map[string]string) (*Result, *AppError) { } } -func (c *Client) Command(channelId string, command string, suggest bool) (*Result, *AppError) { - m := make(map[string]string) - m["command"] = command - m["channelId"] = channelId - m["suggest"] = strconv.FormatBool(suggest) - if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/execute", MapToJson(m)); err != nil { +func (c *Client) Command(channelId string, command string) (*Result, *AppError) { + args := &CommandArgs{ChannelId: channelId, Command: command} + if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/execute", args.ToJson()); err != nil { return nil, err } else { defer closeBody(r) @@ -846,6 +862,16 @@ func (c *Client) CreateCommand(cmd *Command) (*Result, *AppError) { } } +func (c *Client) UpdateCommand(cmd *Command) (*Result, *AppError) { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/update", 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 + } +} + 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 @@ -940,6 +966,16 @@ func (c *Client) ReloadConfig() (bool, *AppError) { } } +func (c *Client) InvalidateAllCaches() (bool, *AppError) { + c.clearExtraProperties() + if r, err := c.DoApiGet("/admin/invalidate_all_caches", "", ""); err != nil { + return false, err + } else { + c.fillInExtraProperties(r) + return c.CheckStatusOK(r), nil + } +} + func (c *Client) SaveConfig(config *Config) (*Result, *AppError) { if r, err := c.DoApiPost("/admin/save_config", config.ToJson()); err != nil { return nil, err @@ -1143,6 +1179,7 @@ func (c *Client) GetChannel(id, etag string) (*Result, *AppError) { } } +// SCHEDULED FOR DEPRECATION IN 3.7 - use GetMoreChannelsPage instead func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/more", "", etag); err != nil { return nil, err @@ -1153,6 +1190,43 @@ func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) { } } +// GetMoreChannelsPage will return a page of open channels the user is not in based on +// the provided offset and limit. Must be authenticated. +func (c *Client) GetMoreChannelsPage(offset int, limit int) (*Result, *AppError) { + if r, err := c.DoApiGet(fmt.Sprintf(c.GetTeamRoute()+"/channels/more/%v/%v", offset, limit), "", ""); 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 + } +} + +// SearchMoreChannels will return a list of open channels the user is not in, that matches +// the search criteria provided. Must be authenticated. +func (c *Client) SearchMoreChannels(channelSearch ChannelSearch) (*Result, *AppError) { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/more/search", channelSearch.ToJson()); 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 + } +} + +// AutocompleteChannels will return a list of open channels that match the provided +// string. Must be authenticated. +func (c *Client) AutocompleteChannels(term string) (*Result, *AppError) { + url := fmt.Sprintf("%s/channels/autocomplete?term=%s", c.GetTeamRoute(), url.QueryEscape(term)) + if r, err := c.DoApiGet(url, "", ""); 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 + } +} + func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) { if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/counts", "", etag); err != nil { return nil, err @@ -1173,6 +1247,16 @@ func (c *Client) GetChannels(etag string) (*Result, *AppError) { } } +func (c *Client) GetChannelByName(channelName string) (*Result, *AppError) { + if r, err := c.DoApiGet(c.GetChannelNameRoute(channelName), "", ""); 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 + } +} + func (c *Client) JoinChannel(id string) (*Result, *AppError) { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil { return nil, err @@ -1240,6 +1324,7 @@ func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) { // UpdateLastViewedAt will mark a channel as read. // The channelId indicates the channel to mark as read. If active is true, push notifications // will be cleared if there are unread messages. The default for active is true. +// SCHEDULED FOR DEPRECATION IN 3.8 - use ViewChannel instead func (c *Client) UpdateLastViewedAt(channelId string, active bool) (*Result, *AppError) { data := make(map[string]interface{}) data["active"] = active @@ -1252,6 +1337,23 @@ func (c *Client) UpdateLastViewedAt(channelId string, active bool) (*Result, *Ap } } +// ViewChannel performs all the actions related to viewing a channel. This includes marking +// the channel and the previous one as read, and marking the channel as being actively viewed. +// ChannelId is required but may be blank to indicate no channel is being viewed. +// PrevChannelId is optional, populate to indicate a channel switch occurred. +func (c *Client) ViewChannel(params ChannelView) (bool, *ResponseMetadata) { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/view", params.ToJson()); err != nil { + return false, &ResponseMetadata{StatusCode: r.StatusCode, Error: err} + } else { + return c.CheckStatusOK(r), + &ResponseMetadata{ + StatusCode: r.StatusCode, + RequestId: r.Header.Get(HEADER_REQUEST_ID), + Etag: r.Header.Get(HEADER_ETAG_SERVER), + } + } +} + func (c *Client) GetChannelStats(id string, etag string) (*Result, *AppError) { if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/stats", "", etag); err != nil { return nil, err @@ -1272,6 +1374,18 @@ func (c *Client) GetChannelMember(channelId string, userId string) (*Result, *Ap } } +// GetChannelMembersByIds will return channel member objects as an array based on the +// channel id and a list of user ids provided. Must be authenticated. +func (c *Client) GetChannelMembersByIds(channelId string, userIds []string) (*Result, *AppError) { + if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/members/ids", ArrayToJson(userIds)); err != nil { + return nil, err + } else { + defer closeBody(r) + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), ChannelMembersFromJson(r.Body)}, nil + } +} + 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 @@ -1342,6 +1456,21 @@ func (c *Client) GetPost(channelId string, postId string, etag string) (*Result, } } +// GetPostById returns a post and any posts in the same thread by post id +func (c *Client) GetPostById(postId string, etag string) (*PostList, *ResponseMetadata) { + if r, err := c.DoApiGet(c.GetTeamRoute()+fmt.Sprintf("/posts/%v", postId), "", etag); err != nil { + return nil, &ResponseMetadata{StatusCode: r.StatusCode, Error: err} + } else { + defer closeBody(r) + return PostListFromJson(r.Body), + &ResponseMetadata{ + StatusCode: r.StatusCode, + RequestId: r.Header.Get(HEADER_REQUEST_ID), + Etag: r.Header.Get(HEADER_ETAG_SERVER), + } + } +} + 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 @@ -1629,6 +1758,7 @@ func (c *Client) GetStatusesByIds(userIds []string) (*Result, *AppError) { // SetActiveChannel sets the the channel id the user is currently viewing. // The channelId key is required but the value can be blank. Returns standard // response. +// SCHEDULED FOR DEPRECATION IN 3.8 - use ViewChannel instead func (c *Client) SetActiveChannel(channelId string) (*Result, *AppError) { data := map[string]string{} data["channel_id"] = channelId @@ -1663,6 +1793,36 @@ func (c *Client) GetTeamMembers(teamId string, offset int, limit int) (*Result, } } +// GetMyTeamMembers will return an array with team member objects that the current user +// is a member of. Must be authenticated. +func (c *Client) GetMyTeamMembers() (*Result, *AppError) { + if r, err := c.DoApiGet("/teams/members", "", ""); 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 + } +} + +// GetMyTeamsUnread will return an array with TeamUnread objects that contain the amount of +// unread messages and mentions the current user has for the teams it belongs to. +// An optional team ID can be set to exclude that team from the results. Must be authenticated. +func (c *Client) GetMyTeamsUnread(teamId string) (*Result, *AppError) { + endpoint := "/teams/unread" + + if teamId != "" { + endpoint += fmt.Sprintf("?id=%s", url.QueryEscape(teamId)) + } + if r, err := c.DoApiGet(endpoint, "", ""); err != nil { + return nil, err + } else { + defer closeBody(r) + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), TeamsUnreadFromJson(r.Body)}, nil + } +} + // GetTeamMember will return a team member object based on the team id and user id provided. // Must be authenticated. func (c *Client) GetTeamMember(teamId string, userId string) (*Result, *AppError) { @@ -1687,6 +1847,18 @@ func (c *Client) GetTeamStats(teamId string) (*Result, *AppError) { } } +// GetTeamStats will return a team stats object containing the number of users on the team +// based on the team id provided. Must be authenticated. +func (c *Client) GetTeamByName(teamName string) (*Result, *AppError) { + if r, err := c.DoApiGet(fmt.Sprintf("/teams/name/%v", teamName), "", ""); err != nil { + return nil, err + } else { + defer closeBody(r) + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), TeamStatsFromJson(r.Body)}, nil + } +} + // GetTeamMembersByIds will return team member objects as an array based on the // team id and a list of user ids provided. Must be authenticated. func (c *Client) GetTeamMembersByIds(teamId string, userIds []string) (*Result, *AppError) { @@ -2030,6 +2202,7 @@ func (c *Client) DeleteEmoji(id string) (bool, *AppError) { if r, err := c.DoApiPost(c.GetEmojiRoute()+"/delete", MapToJson(data)); err != nil { return false, err } else { + defer closeBody(r) c.fillInExtraProperties(r) return c.CheckStatusOK(r), nil } @@ -2060,6 +2233,7 @@ func (c *Client) UploadCertificateFile(data []byte, contentType string) *AppErro return AppErrorFromJson(rp.Body) } else { defer closeBody(rp) + c.fillInExtraProperties(rp) return nil } } @@ -2071,6 +2245,7 @@ func (c *Client) RemoveCertificateFile(filename string) *AppError { return err } else { defer closeBody(r) + c.fillInExtraProperties(r) return nil } } @@ -2082,6 +2257,7 @@ func (c *Client) SamlCertificateStatus(filename string) (map[string]interface{}, return nil, err } else { defer closeBody(r) + c.fillInExtraProperties(r) return StringInterfaceFromJson(r.Body), nil } } @@ -2110,3 +2286,36 @@ func (c *Client) GetFileInfosForPost(channelId string, postId string, etag strin return FileInfosFromJson(r.Body), nil } } + +// Saves an emoji reaction for a post in the given channel. Returns the saved reaction if successful, otherwise returns an AppError. +func (c *Client) SaveReaction(channelId string, reaction *Reaction) (*Reaction, *AppError) { + if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions/save", reaction.PostId), reaction.ToJson()); err != nil { + return nil, err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return ReactionFromJson(r.Body), nil + } +} + +// Removes an emoji reaction for a post in the given channel. Returns nil if successful, otherwise returns an AppError. +func (c *Client) DeleteReaction(channelId string, reaction *Reaction) *AppError { + if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions/delete", reaction.PostId), reaction.ToJson()); err != nil { + return err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return nil + } +} + +// Lists all emoji reactions made for the given post in the given channel. Returns a list of Reactions if successful, otherwise returns an AppError. +func (c *Client) ListReactions(channelId string, postId string) ([]*Reaction, *AppError) { + if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/reactions", postId), "", ""); err != nil { + return nil, err + } else { + defer closeBody(r) + c.fillInExtraProperties(r) + return ReactionsFromJson(r.Body), nil + } +} diff --git a/vendor/github.com/mattermost/platform/model/cluster_stats.go b/vendor/github.com/mattermost/platform/model/cluster_stats.go new file mode 100644 index 00000000..f2efa323 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/cluster_stats.go @@ -0,0 +1,36 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type ClusterStats struct { + Id string `json:"id"` + TotalWebsocketConnections int `json:"total_websocket_connections"` + TotalReadDbConnections int `json:"total_read_db_connections"` + TotalMasterDbConnections int `json:"total_master_db_connections"` +} + +func (me *ClusterStats) ToJson() string { + b, err := json.Marshal(me) + if err != nil { + return "" + } else { + return string(b) + } +} + +func ClusterStatsFromJson(data io.Reader) *ClusterStats { + decoder := json.NewDecoder(data) + var me ClusterStats + err := decoder.Decode(&me) + if err == nil { + return &me + } else { + return nil + } +} diff --git a/vendor/github.com/mattermost/platform/model/command_args.go b/vendor/github.com/mattermost/platform/model/command_args.go new file mode 100644 index 00000000..4da5dc76 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/command_args.go @@ -0,0 +1,36 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type CommandArgs struct { + ChannelId string `json:"channel_id"` + RootId string `json:"root_id"` + ParentId string `json:"parent_id"` + Command string `json:"command"` +} + +func (o *CommandArgs) ToJson() string { + b, err := json.Marshal(o) + if err != nil { + return "" + } else { + return string(b) + } +} + +func CommandArgsFromJson(data io.Reader) *CommandArgs { + decoder := json.NewDecoder(data) + var o CommandArgs + err := decoder.Decode(&o) + if err == nil { + return &o + } else { + return nil + } +} diff --git a/vendor/github.com/mattermost/platform/model/command_response.go b/vendor/github.com/mattermost/platform/model/command_response.go index 9314f38e..bbb70418 100644 --- a/vendor/github.com/mattermost/platform/model/command_response.go +++ b/vendor/github.com/mattermost/platform/model/command_response.go @@ -16,6 +16,8 @@ const ( type CommandResponse struct { ResponseType string `json:"response_type"` Text string `json:"text"` + Username string `json:"username"` + IconURL string `json:"icon_url"` GotoLocation string `json:"goto_location"` Attachments interface{} `json:"attachments"` } diff --git a/vendor/github.com/mattermost/platform/model/config.go b/vendor/github.com/mattermost/platform/model/config.go index f2ff788d..0134e1a3 100644 --- a/vendor/github.com/mattermost/platform/model/config.go +++ b/vendor/github.com/mattermost/platform/model/config.go @@ -38,9 +38,10 @@ const ( DIRECT_MESSAGE_ANY = "any" DIRECT_MESSAGE_TEAM = "team" - PERMISSIONS_ALL = "all" - PERMISSIONS_TEAM_ADMIN = "team_admin" - PERMISSIONS_SYSTEM_ADMIN = "system_admin" + PERMISSIONS_ALL = "all" + PERMISSIONS_CHANNEL_ADMIN = "channel_admin" + PERMISSIONS_TEAM_ADMIN = "team_admin" + PERMISSIONS_SYSTEM_ADMIN = "system_admin" FAKE_SETTING = "********************************" @@ -80,6 +81,7 @@ type ServiceSettings struct { EnableSecurityFixAlert *bool EnableInsecureOutgoingConnections *bool EnableMultifactorAuthentication *bool + EnforceMultifactorAuthentication *bool AllowCorsFrom *string SessionLengthWebInDays *int SessionLengthMobileInDays *int @@ -98,6 +100,16 @@ type ClusterSettings struct { InterNodeUrls []string } +type MetricsSettings struct { + Enable *bool + BlockProfileRate *int + ListenAddress *string +} + +type AnalyticsSettings struct { + MaxUsersForStatistics *int +} + type SSOSettings struct { Enable bool Secret string @@ -219,8 +231,13 @@ type TeamSettings struct { RestrictTeamInvite *string RestrictPublicChannelManagement *string RestrictPrivateChannelManagement *string + RestrictPublicChannelCreation *string + RestrictPrivateChannelCreation *string + RestrictPublicChannelDeletion *string + RestrictPrivateChannelDeletion *string UserStatusAwayTimeout *int64 MaxChannelsPerTeam *int64 + MaxNotificationsPerChannel *int64 } type LdapSettings struct { @@ -243,6 +260,7 @@ type LdapSettings struct { UsernameAttribute *string NicknameAttribute *string IdAttribute *string + PositionAttribute *string // Syncronization SyncIntervalMinutes *int @@ -289,6 +307,7 @@ type SamlSettings struct { UsernameAttribute *string NicknameAttribute *string LocaleAttribute *string + PositionAttribute *string LoginButtonText *string } @@ -330,6 +349,8 @@ type Config struct { SamlSettings SamlSettings NativeAppSettings NativeAppSettings ClusterSettings ClusterSettings + MetricsSettings MetricsSettings + AnalyticsSettings AnalyticsSettings WebrtcSettings WebrtcSettings } @@ -376,23 +397,32 @@ func (o *Config) SetDefaults() { // Defaults to "s3.amazonaws.com" o.FileSettings.AmazonS3Endpoint = "s3.amazonaws.com" } + if o.FileSettings.AmazonS3Region == "" { // Defaults to "us-east-1" region. o.FileSettings.AmazonS3Region = "us-east-1" } + if o.FileSettings.AmazonS3SSL == nil { o.FileSettings.AmazonS3SSL = new(bool) *o.FileSettings.AmazonS3SSL = true // Secure by default. } + 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 = new(string) *o.FileSettings.PublicLinkSalt = NewRandomString(32) } + if o.FileSettings.InitialFont == "" { + // Defaults to "luximbi.ttf" + o.FileSettings.InitialFont = "luximbi.ttf" + } + if len(o.EmailSettings.InviteSalt) == 0 { o.EmailSettings.InviteSalt = NewRandomString(32) } @@ -426,6 +456,11 @@ func (o *Config) SetDefaults() { *o.ServiceSettings.EnableMultifactorAuthentication = false } + if o.ServiceSettings.EnforceMultifactorAuthentication == nil { + o.ServiceSettings.EnforceMultifactorAuthentication = new(bool) + *o.ServiceSettings.EnforceMultifactorAuthentication = false + } + if o.PasswordSettings.MinimumLength == nil { o.PasswordSettings.MinimumLength = new(int) *o.PasswordSettings.MinimumLength = PASSWORD_MINIMUM_LENGTH @@ -491,6 +526,30 @@ func (o *Config) SetDefaults() { *o.TeamSettings.RestrictPrivateChannelManagement = PERMISSIONS_ALL } + if o.TeamSettings.RestrictPublicChannelCreation == nil { + o.TeamSettings.RestrictPublicChannelCreation = new(string) + // If this setting does not exist, assume migration from <3.6, so use management setting as default. + *o.TeamSettings.RestrictPublicChannelCreation = *o.TeamSettings.RestrictPublicChannelManagement + } + + if o.TeamSettings.RestrictPrivateChannelCreation == nil { + o.TeamSettings.RestrictPrivateChannelCreation = new(string) + // If this setting does not exist, assume migration from <3.6, so use management setting as default. + *o.TeamSettings.RestrictPrivateChannelCreation = *o.TeamSettings.RestrictPrivateChannelManagement + } + + if o.TeamSettings.RestrictPublicChannelDeletion == nil { + o.TeamSettings.RestrictPublicChannelDeletion = new(string) + // If this setting does not exist, assume migration from <3.6, so use management setting as default. + *o.TeamSettings.RestrictPublicChannelDeletion = *o.TeamSettings.RestrictPublicChannelManagement + } + + if o.TeamSettings.RestrictPrivateChannelDeletion == nil { + o.TeamSettings.RestrictPrivateChannelDeletion = new(string) + // If this setting does not exist, assume migration from <3.6, so use management setting as default. + *o.TeamSettings.RestrictPrivateChannelDeletion = *o.TeamSettings.RestrictPrivateChannelManagement + } + if o.TeamSettings.UserStatusAwayTimeout == nil { o.TeamSettings.UserStatusAwayTimeout = new(int64) *o.TeamSettings.UserStatusAwayTimeout = 300 @@ -501,6 +560,11 @@ func (o *Config) SetDefaults() { *o.TeamSettings.MaxChannelsPerTeam = 2000 } + if o.TeamSettings.MaxNotificationsPerChannel == nil { + o.TeamSettings.MaxNotificationsPerChannel = new(int64) + *o.TeamSettings.MaxNotificationsPerChannel = 1000 + } + if o.EmailSettings.EnableSignInWithEmail == nil { o.EmailSettings.EnableSignInWithEmail = new(bool) @@ -671,6 +735,11 @@ func (o *Config) SetDefaults() { *o.LdapSettings.IdAttribute = "" } + if o.LdapSettings.PositionAttribute == nil { + o.LdapSettings.PositionAttribute = new(string) + *o.LdapSettings.PositionAttribute = "" + } + if o.LdapSettings.SyncIntervalMinutes == nil { o.LdapSettings.SyncIntervalMinutes = new(int) *o.LdapSettings.SyncIntervalMinutes = 60 @@ -772,6 +841,21 @@ func (o *Config) SetDefaults() { o.ClusterSettings.InterNodeUrls = []string{} } + if o.MetricsSettings.ListenAddress == nil { + o.MetricsSettings.ListenAddress = new(string) + *o.MetricsSettings.ListenAddress = ":8067" + } + + if o.MetricsSettings.Enable == nil { + o.MetricsSettings.Enable = new(bool) + *o.MetricsSettings.Enable = false + } + + if o.AnalyticsSettings.MaxUsersForStatistics == nil { + o.AnalyticsSettings.MaxUsersForStatistics = new(int) + *o.AnalyticsSettings.MaxUsersForStatistics = 2500 + } + if o.ComplianceSettings.Enable == nil { o.ComplianceSettings.Enable = new(bool) *o.ComplianceSettings.Enable = false @@ -882,6 +966,11 @@ func (o *Config) SetDefaults() { *o.SamlSettings.NicknameAttribute = "" } + if o.SamlSettings.PositionAttribute == nil { + o.SamlSettings.PositionAttribute = new(string) + *o.SamlSettings.PositionAttribute = "" + } + if o.SamlSettings.LocaleAttribute == nil { o.SamlSettings.LocaleAttribute = new(string) *o.SamlSettings.LocaleAttribute = "" @@ -952,6 +1041,11 @@ func (o *Config) SetDefaults() { *o.ServiceSettings.Forward80To443 = false } + if o.MetricsSettings.BlockProfileRate == nil { + o.MetricsSettings.BlockProfileRate = new(int) + *o.MetricsSettings.BlockProfileRate = 0 + } + o.defaultWebrtcSettings() } @@ -987,6 +1081,10 @@ func (o *Config) IsValid() *AppError { return NewLocAppError("Config.IsValid", "model.config.is_valid.max_channels.app_error", nil, "") } + if *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) { return NewLocAppError("Config.IsValid", "model.config.is_valid.restrict_direct_message.app_error", nil, "") } diff --git a/vendor/github.com/mattermost/platform/model/incoming_webhook.go b/vendor/github.com/mattermost/platform/model/incoming_webhook.go index c567edfd..72fa3e54 100644 --- a/vendor/github.com/mattermost/platform/model/incoming_webhook.go +++ b/vendor/github.com/mattermost/platform/model/incoming_webhook.go @@ -6,6 +6,7 @@ package model import ( "bytes" "encoding/json" + "fmt" "io" "regexp" "strings" @@ -233,7 +234,7 @@ func expandAnnouncements(i *IncomingWebhookRequest) { for _, field := range fields { f := field.(map[string]interface{}) if f["value"] != nil { - f["value"] = expandAnnouncement(f["value"].(string)) + f["value"] = expandAnnouncement(fmt.Sprintf("%v", f["value"])) } } } diff --git a/vendor/github.com/mattermost/platform/model/license.go b/vendor/github.com/mattermost/platform/model/license.go index 8d8d0068..7115aa1a 100644 --- a/vendor/github.com/mattermost/platform/model/license.go +++ b/vendor/github.com/mattermost/platform/model/license.go @@ -39,6 +39,7 @@ type Features struct { Office365OAuth *bool `json:"office365_oauth"` Compliance *bool `json:"compliance"` Cluster *bool `json:"cluster"` + Metrics *bool `json:"metrics"` CustomBrand *bool `json:"custom_brand"` MHPNS *bool `json:"mhpns"` SAML *bool `json:"saml"` @@ -55,6 +56,7 @@ func (f *Features) ToMap() map[string]interface{} { "office365": *f.Office365OAuth, "compliance": *f.Compliance, "cluster": *f.Cluster, + "metrics": *f.Metrics, "custom_brand": *f.CustomBrand, "mhpns": *f.MHPNS, "saml": *f.SAML, @@ -104,6 +106,11 @@ func (f *Features) SetDefaults() { *f.Cluster = *f.FutureFeatures } + if f.Metrics == nil { + f.Metrics = new(bool) + *f.Metrics = *f.FutureFeatures + } + if f.CustomBrand == nil { f.CustomBrand = new(bool) *f.CustomBrand = *f.FutureFeatures diff --git a/vendor/github.com/mattermost/platform/model/post.go b/vendor/github.com/mattermost/platform/model/post.go index da14b650..7097e031 100644 --- a/vendor/github.com/mattermost/platform/model/post.go +++ b/vendor/github.com/mattermost/platform/model/post.go @@ -17,8 +17,14 @@ const ( POST_JOIN_LEAVE = "system_join_leave" POST_ADD_REMOVE = "system_add_remove" POST_HEADER_CHANGE = "system_header_change" + POST_DISPLAYNAME_CHANGE = "system_displayname_change" POST_CHANNEL_DELETED = "system_channel_deleted" POST_EPHEMERAL = "system_ephemeral" + POST_FILEIDS_MAX_RUNES = 150 + POST_FILENAMES_MAX_RUNES = 4000 + POST_HASHTAGS_MAX_RUNES = 1000 + POST_MESSAGE_MAX_RUNES = 4000 + POST_PROPS_MAX_RUNES = 8000 ) type Post struct { @@ -38,6 +44,7 @@ type Post struct { Filenames StringArray `json:"filenames,omitempty"` // Deprecated, do not use this field any more FileIds StringArray `json:"file_ids,omitempty"` PendingPostId string `json:"pending_post_id" db:"-"` + HasReactions bool `json:"has_reactions,omitempty"` } func (o *Post) ToJson() string { @@ -102,28 +109,30 @@ func (o *Post) IsValid() *AppError { return NewLocAppError("Post.IsValid", "model.post.is_valid.original_id.app_error", nil, "") } - if utf8.RuneCountInString(o.Message) > 4000 { + if utf8.RuneCountInString(o.Message) > POST_MESSAGE_MAX_RUNES { return NewLocAppError("Post.IsValid", "model.post.is_valid.msg.app_error", nil, "id="+o.Id) } - if utf8.RuneCountInString(o.Hashtags) > 1000 { + if utf8.RuneCountInString(o.Hashtags) > POST_HASHTAGS_MAX_RUNES { return NewLocAppError("Post.IsValid", "model.post.is_valid.hashtags.app_error", nil, "id="+o.Id) } // should be removed once more message types are supported - if !(o.Type == POST_DEFAULT || o.Type == POST_JOIN_LEAVE || o.Type == POST_ADD_REMOVE || o.Type == POST_SLACK_ATTACHMENT || o.Type == POST_HEADER_CHANGE) { + if !(o.Type == POST_DEFAULT || o.Type == POST_JOIN_LEAVE || o.Type == POST_ADD_REMOVE || + o.Type == POST_SLACK_ATTACHMENT || o.Type == POST_HEADER_CHANGE || + o.Type == POST_DISPLAYNAME_CHANGE || o.Type == POST_CHANNEL_DELETED) { return NewLocAppError("Post.IsValid", "model.post.is_valid.type.app_error", nil, "id="+o.Type) } - if utf8.RuneCountInString(ArrayToJson(o.Filenames)) > 4000 { + if utf8.RuneCountInString(ArrayToJson(o.Filenames)) > POST_FILENAMES_MAX_RUNES { return NewLocAppError("Post.IsValid", "model.post.is_valid.filenames.app_error", nil, "id="+o.Id) } - if utf8.RuneCountInString(ArrayToJson(o.FileIds)) > 150 { + if utf8.RuneCountInString(ArrayToJson(o.FileIds)) > POST_FILEIDS_MAX_RUNES { return NewLocAppError("Post.IsValid", "model.post.is_valid.file_ids.app_error", nil, "id="+o.Id) } - if utf8.RuneCountInString(StringInterfaceToJson(o.Props)) > 8000 { + if utf8.RuneCountInString(StringInterfaceToJson(o.Props)) > POST_PROPS_MAX_RUNES { return NewLocAppError("Post.IsValid", "model.post.is_valid.props.app_error", nil, "id="+o.Id) } diff --git a/vendor/github.com/mattermost/platform/model/preference.go b/vendor/github.com/mattermost/platform/model/preference.go index cc35768c..94807d2c 100644 --- a/vendor/github.com/mattermost/platform/model/preference.go +++ b/vendor/github.com/mattermost/platform/model/preference.go @@ -33,6 +33,7 @@ const ( PREFERENCE_CATEGORY_LAST = "last" PREFERENCE_NAME_LAST_CHANNEL = "channel" + PREFERENCE_NAME_LAST_TEAM = "team" PREFERENCE_CATEGORY_NOTIFICATIONS = "notifications" PREFERENCE_NAME_EMAIL_INTERVAL = "email_interval" diff --git a/vendor/github.com/mattermost/platform/model/push_notification.go b/vendor/github.com/mattermost/platform/model/push_notification.go index d4c38029..3c010fb7 100644 --- a/vendor/github.com/mattermost/platform/model/push_notification.go +++ b/vendor/github.com/mattermost/platform/model/push_notification.go @@ -30,6 +30,7 @@ type PushNotification struct { Message string `json:"message"` Badge int `json:"badge"` ContentAvailable int `json:"cont_ava"` + TeamId string `json:"team_id"` ChannelId string `json:"channel_id"` ChannelName string `json:"channel_name"` Type string `json:"type"` diff --git a/vendor/github.com/mattermost/platform/model/reaction.go b/vendor/github.com/mattermost/platform/model/reaction.go new file mode 100644 index 00000000..afbdd1e8 --- /dev/null +++ b/vendor/github.com/mattermost/platform/model/reaction.go @@ -0,0 +1,78 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type Reaction struct { + UserId string `json:"user_id"` + PostId string `json:"post_id"` + EmojiName string `json:"emoji_name"` + CreateAt int64 `json:"create_at"` +} + +func (o *Reaction) ToJson() string { + if b, err := json.Marshal(o); err != nil { + return "" + } else { + return string(b) + } +} + +func ReactionFromJson(data io.Reader) *Reaction { + var o Reaction + + if err := json.NewDecoder(data).Decode(&o); err != nil { + return nil + } else { + return &o + } +} + +func ReactionsToJson(o []*Reaction) string { + if b, err := json.Marshal(o); err != nil { + return "" + } else { + return string(b) + } +} + +func ReactionsFromJson(data io.Reader) []*Reaction { + var o []*Reaction + + if err := json.NewDecoder(data).Decode(&o); err != nil { + return nil + } else { + return o + } +} + +func (o *Reaction) IsValid() *AppError { + if len(o.UserId) != 26 { + return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.user_id.app_error", nil, "user_id="+o.UserId) + } + + if len(o.PostId) != 26 { + return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.post_id.app_error", nil, "post_id="+o.PostId) + } + + if len(o.EmojiName) == 0 || len(o.EmojiName) > 64 { + return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.emoji_name.app_error", nil, "emoji_name="+o.EmojiName) + } + + if o.CreateAt == 0 { + return NewLocAppError("Reaction.IsValid", "model.reaction.is_valid.create_at.app_error", nil, "") + } + + return nil +} + +func (o *Reaction) PreSave() { + if o.CreateAt == 0 { + o.CreateAt = GetMillis() + } +} diff --git a/vendor/github.com/mattermost/platform/model/status.go b/vendor/github.com/mattermost/platform/model/status.go index 32486642..fec3a5f7 100644 --- a/vendor/github.com/mattermost/platform/model/status.go +++ b/vendor/github.com/mattermost/platform/model/status.go @@ -22,7 +22,7 @@ type Status struct { Status string `json:"status"` Manual bool `json:"manual"` LastActivityAt int64 `json:"last_activity_at"` - ActiveChannel string `json:"active_channel"` + ActiveChannel string `json:"active_channel" db:"-"` } func (o *Status) ToJson() string { @@ -44,3 +44,14 @@ func StatusFromJson(data io.Reader) *Status { return nil } } + +func StatusMapToInterfaceMap(statusMap map[string]*Status) map[string]interface{} { + interfaceMap := map[string]interface{}{} + for _, s := range statusMap { + // Omitted statues mean offline + if s.Status != STATUS_OFFLINE { + interfaceMap[s.UserId] = s.Status + } + } + return interfaceMap +} diff --git a/vendor/github.com/mattermost/platform/model/team.go b/vendor/github.com/mattermost/platform/model/team.go index d54a809f..3f05ce83 100644 --- a/vendor/github.com/mattermost/platform/model/team.go +++ b/vendor/github.com/mattermost/platform/model/team.go @@ -24,6 +24,7 @@ type Team struct { DeleteAt int64 `json:"delete_at"` DisplayName string `json:"display_name"` Name string `json:"name"` + Description string `json:"description"` Email string `json:"email"` Type string `json:"type"` CompanyName string `json:"company_name"` @@ -130,6 +131,10 @@ func (o *Team) IsValid() *AppError { return NewLocAppError("Team.IsValid", "model.team.is_valid.url.app_error", nil, "id="+o.Id) } + if len(o.Description) > 255 { + return NewLocAppError("Team.IsValid", "model.team.is_valid.description.app_error", nil, "id="+o.Id) + } + if IsReservedTeamName(o.Name) { return NewLocAppError("Team.IsValid", "model.team.is_valid.reserved.app_error", nil, "id="+o.Id) } diff --git a/vendor/github.com/mattermost/platform/model/team_member.go b/vendor/github.com/mattermost/platform/model/team_member.go index a040e916..36a567a4 100644 --- a/vendor/github.com/mattermost/platform/model/team_member.go +++ b/vendor/github.com/mattermost/platform/model/team_member.go @@ -16,6 +16,12 @@ type TeamMember struct { DeleteAt int64 `json:"delete_at"` } +type TeamUnread struct { + TeamId string `json:"team_id"` + MsgCount int64 `json:"msg_count"` + MentionCount int64 `json:"mention_count"` +} + func (o *TeamMember) ToJson() string { b, err := json.Marshal(o) if err != nil { @@ -55,6 +61,25 @@ func TeamMembersFromJson(data io.Reader) []*TeamMember { } } +func TeamsUnreadToJson(o []*TeamUnread) string { + if b, err := json.Marshal(o); err != nil { + return "[]" + } else { + return string(b) + } +} + +func TeamsUnreadFromJson(data io.Reader) []*TeamUnread { + decoder := json.NewDecoder(data) + var o []*TeamUnread + err := decoder.Decode(&o) + if err == nil { + return o + } else { + return nil + } +} + func (o *TeamMember) IsValid() *AppError { if len(o.TeamId) != 26 { diff --git a/vendor/github.com/mattermost/platform/model/team_signup.go b/vendor/github.com/mattermost/platform/model/team_signup.go deleted file mode 100644 index e3642044..00000000 --- a/vendor/github.com/mattermost/platform/model/team_signup.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package model - -import ( - "encoding/json" - "fmt" - "io" -) - -type TeamSignup struct { - Team Team `json:"team"` - User User `json:"user"` - Invites []string `json:"invites"` - Data string `json:"data"` - Hash string `json:"hash"` -} - -func TeamSignupFromJson(data io.Reader) *TeamSignup { - decoder := json.NewDecoder(data) - var o TeamSignup - err := decoder.Decode(&o) - if err == nil { - return &o - } else { - fmt.Println(err) - - return nil - } -} - -func (o *TeamSignup) ToJson() string { - b, err := json.Marshal(o) - if err != nil { - return "" - } else { - return string(b) - } -} diff --git a/vendor/github.com/mattermost/platform/model/user.go b/vendor/github.com/mattermost/platform/model/user.go index 330d26d8..76c3772c 100644 --- a/vendor/github.com/mattermost/platform/model/user.go +++ b/vendor/github.com/mattermost/platform/model/user.go @@ -37,6 +37,7 @@ type User struct { Nickname string `json:"nickname"` FirstName string `json:"first_name"` LastName string `json:"last_name"` + Position string `json:"position"` Roles string `json:"roles"` AllowMarketing bool `json:"allow_marketing,omitempty"` Props StringMap `json:"props,omitempty"` @@ -78,6 +79,10 @@ func (u *User) IsValid() *AppError { return NewLocAppError("User.IsValid", "model.user.is_valid.nickname.app_error", nil, "user_id="+u.Id) } + if utf8.RuneCountInString(u.Position) > 35 { + return NewLocAppError("User.IsValid", "model.user.is_valid.position.app_error", nil, "user_id="+u.Id) + } + if utf8.RuneCountInString(u.FirstName) > 64 { return NewLocAppError("User.IsValid", "model.user.is_valid.first_name.app_error", nil, "user_id="+u.Id) } diff --git a/vendor/github.com/mattermost/platform/model/autocomplete.go b/vendor/github.com/mattermost/platform/model/user_autocomplete.go similarity index 100% rename from vendor/github.com/mattermost/platform/model/autocomplete.go rename to vendor/github.com/mattermost/platform/model/user_autocomplete.go diff --git a/vendor/github.com/mattermost/platform/model/utils.go b/vendor/github.com/mattermost/platform/model/utils.go index 457b64c0..0ce243fe 100644 --- a/vendor/github.com/mattermost/platform/model/utils.go +++ b/vendor/github.com/mattermost/platform/model/utils.go @@ -304,7 +304,7 @@ func Etag(parts ...interface{}) string { return etag } -var validHashtag = regexp.MustCompile(`^(#[A-Za-zäöüÄÖÜß]+[A-Za-z0-9äöüÄÖÜß_\-]*[A-Za-z0-9äöüÄÖÜß])$`) +var validHashtag = regexp.MustCompile(`^(#\pL[\pL\d\-_.]*[\pL\d])$`) var puncStart = regexp.MustCompile(`^[^\pL\d\s#]+`) var hashtagStart = regexp.MustCompile(`^#{2,}`) var puncEnd = regexp.MustCompile(`[^\pL\d\s]+$`) diff --git a/vendor/github.com/mattermost/platform/model/version.go b/vendor/github.com/mattermost/platform/model/version.go index 9d9d8fc1..2a034dec 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.6.0", "3.5.0", "3.4.0", "3.3.0", diff --git a/vendor/github.com/mattermost/platform/model/websocket_message.go b/vendor/github.com/mattermost/platform/model/websocket_message.go index 5eb02642..5c956d57 100644 --- a/vendor/github.com/mattermost/platform/model/websocket_message.go +++ b/vendor/github.com/mattermost/platform/model/websocket_message.go @@ -18,6 +18,7 @@ const ( WEBSOCKET_EVENT_DIRECT_ADDED = "direct_added" WEBSOCKET_EVENT_NEW_USER = "new_user" WEBSOCKET_EVENT_LEAVE_TEAM = "leave_team" + WEBSOCKET_EVENT_UPDATE_TEAM = "update_team" WEBSOCKET_EVENT_USER_ADDED = "user_added" WEBSOCKET_EVENT_USER_UPDATED = "user_updated" WEBSOCKET_EVENT_USER_REMOVED = "user_removed" @@ -27,6 +28,8 @@ const ( WEBSOCKET_EVENT_HELLO = "hello" WEBSOCKET_EVENT_WEBRTC = "webrtc" WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge" + WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added" + WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed" ) type WebSocketMessage interface { @@ -34,6 +37,7 @@ type WebSocketMessage interface { IsValid() bool DoPreComputeJson() GetPreComputeJson() []byte + EventType() string } type WebsocketBroadcast struct { @@ -63,6 +67,10 @@ func (o *WebSocketEvent) IsValid() bool { return o.Event != "" } +func (o *WebSocketEvent) EventType() string { + return o.Event +} + func (o *WebSocketEvent) DoPreComputeJson() { b, err := json.Marshal(o) if err != nil { @@ -120,6 +128,10 @@ func (o *WebSocketResponse) IsValid() bool { return o.Status != "" } +func (o *WebSocketResponse) EventType() string { + return "" +} + func (o *WebSocketResponse) ToJson() string { b, err := json.Marshal(o) if err != nil { diff --git a/vendor/manifest b/vendor/manifest index b7ee7bda..18543d64 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -95,8 +95,8 @@ "importpath": "github.com/mattermost/platform/einterfaces", "repository": "https://github.com/mattermost/platform", "vcs": "git", - "revision": "b55ec6148caa93d54b660afe55408c643d217108", - "branch": "release-3.5", + "revision": "976296cd52533ff565407e55e872339cc312a0cf", + "branch": "release-3.6", "path": "/einterfaces", "notests": true }, @@ -104,8 +104,8 @@ "importpath": "github.com/mattermost/platform/model", "repository": "https://github.com/mattermost/platform", "vcs": "git", - "revision": "b55ec6148caa93d54b660afe55408c643d217108", - "branch": "release-3.5", + "revision": "976296cd52533ff565407e55e872339cc312a0cf", + "branch": "release-3.6", "path": "/model", "notests": true },