Sync with mattermost 3.6.0
This commit is contained in:
parent
9987ac3f13
commit
93114b7682
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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"`
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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"`
|
||||
}
|
||||
|
|
|
@ -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, "")
|
||||
}
|
||||
|
|
|
@ -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"]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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]+$`)
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue