Sync with mattermost 3.6.0
This commit is contained in:
parent
9987ac3f13
commit
93114b7682
|
@ -11,13 +11,17 @@ type ClusterInterface interface {
|
||||||
StartInterNodeCommunication()
|
StartInterNodeCommunication()
|
||||||
StopInterNodeCommunication()
|
StopInterNodeCommunication()
|
||||||
GetClusterInfos() []*model.ClusterInfo
|
GetClusterInfos() []*model.ClusterInfo
|
||||||
|
GetClusterStats() ([]*model.ClusterStats, *model.AppError)
|
||||||
RemoveAllSessionsForUserId(userId string)
|
RemoveAllSessionsForUserId(userId string)
|
||||||
InvalidateCacheForUser(userId string)
|
InvalidateCacheForUser(userId string)
|
||||||
|
InvalidateCacheForChannel(channelId string)
|
||||||
|
InvalidateCacheForChannelPosts(channelId string)
|
||||||
Publish(event *model.WebSocketEvent)
|
Publish(event *model.WebSocketEvent)
|
||||||
UpdateStatus(status *model.Status)
|
UpdateStatus(status *model.Status)
|
||||||
GetLogs() ([]string, *model.AppError)
|
GetLogs() ([]string, *model.AppError)
|
||||||
GetClusterId() string
|
GetClusterId() string
|
||||||
ConfigChanged(previousConfig *model.Config, newConfig *model.Config, sendToOtherServer bool) *model.AppError
|
ConfigChanged(previousConfig *model.Config, newConfig *model.Config, sendToOtherServer bool) *model.AppError
|
||||||
|
InvalidateAllCaches() *model.AppError
|
||||||
}
|
}
|
||||||
|
|
||||||
var theClusterInterface ClusterInterface
|
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"
|
CHANNEL_MARK_UNREAD_MENTION = "mention"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ChannelUnread struct {
|
||||||
|
TeamId string
|
||||||
|
TotalMsgCount int64
|
||||||
|
MsgCount int64
|
||||||
|
MentionCount int64
|
||||||
|
NotifyProps StringMap
|
||||||
|
}
|
||||||
|
|
||||||
type ChannelMember struct {
|
type ChannelMember struct {
|
||||||
ChannelId string `json:"channel_id"`
|
ChannelId string `json:"channel_id"`
|
||||||
UserId string `json:"user_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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
l4g "github.com/alecthomas/log4go"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
|
@ -15,6 +14,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
l4g "github.com/alecthomas/log4go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -48,6 +49,13 @@ type Result struct {
|
||||||
Data interface{}
|
Data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResponseMetadata struct {
|
||||||
|
StatusCode int
|
||||||
|
Error *AppError
|
||||||
|
RequestId string
|
||||||
|
Etag string
|
||||||
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Url string // The location of the server like "http://localhost:8065"
|
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"
|
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
|
// 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
|
// 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.
|
// the Team struct with the Id, CreateAt and other server-decided fields populated.
|
||||||
func (c *Client) CreateTeam(team *Team) (*Result, *AppError) {
|
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.
|
// GetMe returns the current user.
|
||||||
func (c *Client) GetMe(etag string) (*Result, *AppError) {
|
func (c *Client) GetMe(etag string) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiGet("/users/me", "", etag); err != nil {
|
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.
|
// LoginById authenticates a user by user id and password.
|
||||||
func (c *Client) LoginById(id string, password string) (*Result, *AppError) {
|
func (c *Client) LoginById(id string, password string) (*Result, *AppError) {
|
||||||
m := make(map[string]string)
|
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) {
|
func (c *Client) Command(channelId string, command string) (*Result, *AppError) {
|
||||||
m := make(map[string]string)
|
args := &CommandArgs{ChannelId: channelId, Command: command}
|
||||||
m["command"] = command
|
if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/execute", args.ToJson()); err != nil {
|
||||||
m["channelId"] = channelId
|
|
||||||
m["suggest"] = strconv.FormatBool(suggest)
|
|
||||||
if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/execute", MapToJson(m)); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
defer closeBody(r)
|
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) {
|
func (c *Client) RegenCommandToken(data map[string]string) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/regen_token", MapToJson(data)); err != nil {
|
if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/regen_token", MapToJson(data)); err != nil {
|
||||||
return nil, err
|
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) {
|
func (c *Client) SaveConfig(config *Config) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiPost("/admin/save_config", config.ToJson()); err != nil {
|
if r, err := c.DoApiPost("/admin/save_config", config.ToJson()); err != nil {
|
||||||
return nil, err
|
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) {
|
func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/more", "", etag); err != nil {
|
if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/more", "", etag); err != nil {
|
||||||
return nil, err
|
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) {
|
func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/counts", "", etag); err != nil {
|
if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/counts", "", etag); err != nil {
|
||||||
return nil, err
|
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) {
|
func (c *Client) JoinChannel(id string) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil {
|
if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1240,6 +1324,7 @@ func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) {
|
||||||
// UpdateLastViewedAt will mark a channel as read.
|
// UpdateLastViewedAt will mark a channel as read.
|
||||||
// The channelId indicates the channel to mark as read. If active is true, push notifications
|
// 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.
|
// 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) {
|
func (c *Client) UpdateLastViewedAt(channelId string, active bool) (*Result, *AppError) {
|
||||||
data := make(map[string]interface{})
|
data := make(map[string]interface{})
|
||||||
data["active"] = active
|
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) {
|
func (c *Client) GetChannelStats(id string, etag string) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/stats", "", etag); err != nil {
|
if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/stats", "", etag); err != nil {
|
||||||
return nil, err
|
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) {
|
func (c *Client) CreatePost(post *Post) (*Result, *AppError) {
|
||||||
if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/create", post.ToJson()); err != nil {
|
if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/create", post.ToJson()); err != nil {
|
||||||
return nil, err
|
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) {
|
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 {
|
if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/delete", postId), ""); err != nil {
|
||||||
return nil, err
|
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.
|
// SetActiveChannel sets the the channel id the user is currently viewing.
|
||||||
// The channelId key is required but the value can be blank. Returns standard
|
// The channelId key is required but the value can be blank. Returns standard
|
||||||
// response.
|
// response.
|
||||||
|
// SCHEDULED FOR DEPRECATION IN 3.8 - use ViewChannel instead
|
||||||
func (c *Client) SetActiveChannel(channelId string) (*Result, *AppError) {
|
func (c *Client) SetActiveChannel(channelId string) (*Result, *AppError) {
|
||||||
data := map[string]string{}
|
data := map[string]string{}
|
||||||
data["channel_id"] = channelId
|
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.
|
// GetTeamMember will return a team member object based on the team id and user id provided.
|
||||||
// Must be authenticated.
|
// Must be authenticated.
|
||||||
func (c *Client) GetTeamMember(teamId string, userId string) (*Result, *AppError) {
|
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
|
// GetTeamMembersByIds will return team member objects as an array based on the
|
||||||
// team id and a list of user ids provided. Must be authenticated.
|
// team id and a list of user ids provided. Must be authenticated.
|
||||||
func (c *Client) GetTeamMembersByIds(teamId string, userIds []string) (*Result, *AppError) {
|
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 {
|
if r, err := c.DoApiPost(c.GetEmojiRoute()+"/delete", MapToJson(data)); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
} else {
|
} else {
|
||||||
|
defer closeBody(r)
|
||||||
c.fillInExtraProperties(r)
|
c.fillInExtraProperties(r)
|
||||||
return c.CheckStatusOK(r), nil
|
return c.CheckStatusOK(r), nil
|
||||||
}
|
}
|
||||||
|
@ -2060,6 +2233,7 @@ func (c *Client) UploadCertificateFile(data []byte, contentType string) *AppErro
|
||||||
return AppErrorFromJson(rp.Body)
|
return AppErrorFromJson(rp.Body)
|
||||||
} else {
|
} else {
|
||||||
defer closeBody(rp)
|
defer closeBody(rp)
|
||||||
|
c.fillInExtraProperties(rp)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2071,6 +2245,7 @@ func (c *Client) RemoveCertificateFile(filename string) *AppError {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
defer closeBody(r)
|
defer closeBody(r)
|
||||||
|
c.fillInExtraProperties(r)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2082,6 +2257,7 @@ func (c *Client) SamlCertificateStatus(filename string) (map[string]interface{},
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
defer closeBody(r)
|
defer closeBody(r)
|
||||||
|
c.fillInExtraProperties(r)
|
||||||
return StringInterfaceFromJson(r.Body), nil
|
return StringInterfaceFromJson(r.Body), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2110,3 +2286,36 @@ func (c *Client) GetFileInfosForPost(channelId string, postId string, etag strin
|
||||||
return FileInfosFromJson(r.Body), nil
|
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 {
|
type CommandResponse struct {
|
||||||
ResponseType string `json:"response_type"`
|
ResponseType string `json:"response_type"`
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
IconURL string `json:"icon_url"`
|
||||||
GotoLocation string `json:"goto_location"`
|
GotoLocation string `json:"goto_location"`
|
||||||
Attachments interface{} `json:"attachments"`
|
Attachments interface{} `json:"attachments"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,10 @@ const (
|
||||||
DIRECT_MESSAGE_ANY = "any"
|
DIRECT_MESSAGE_ANY = "any"
|
||||||
DIRECT_MESSAGE_TEAM = "team"
|
DIRECT_MESSAGE_TEAM = "team"
|
||||||
|
|
||||||
PERMISSIONS_ALL = "all"
|
PERMISSIONS_ALL = "all"
|
||||||
PERMISSIONS_TEAM_ADMIN = "team_admin"
|
PERMISSIONS_CHANNEL_ADMIN = "channel_admin"
|
||||||
PERMISSIONS_SYSTEM_ADMIN = "system_admin"
|
PERMISSIONS_TEAM_ADMIN = "team_admin"
|
||||||
|
PERMISSIONS_SYSTEM_ADMIN = "system_admin"
|
||||||
|
|
||||||
FAKE_SETTING = "********************************"
|
FAKE_SETTING = "********************************"
|
||||||
|
|
||||||
|
@ -80,6 +81,7 @@ type ServiceSettings struct {
|
||||||
EnableSecurityFixAlert *bool
|
EnableSecurityFixAlert *bool
|
||||||
EnableInsecureOutgoingConnections *bool
|
EnableInsecureOutgoingConnections *bool
|
||||||
EnableMultifactorAuthentication *bool
|
EnableMultifactorAuthentication *bool
|
||||||
|
EnforceMultifactorAuthentication *bool
|
||||||
AllowCorsFrom *string
|
AllowCorsFrom *string
|
||||||
SessionLengthWebInDays *int
|
SessionLengthWebInDays *int
|
||||||
SessionLengthMobileInDays *int
|
SessionLengthMobileInDays *int
|
||||||
|
@ -98,6 +100,16 @@ type ClusterSettings struct {
|
||||||
InterNodeUrls []string
|
InterNodeUrls []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MetricsSettings struct {
|
||||||
|
Enable *bool
|
||||||
|
BlockProfileRate *int
|
||||||
|
ListenAddress *string
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnalyticsSettings struct {
|
||||||
|
MaxUsersForStatistics *int
|
||||||
|
}
|
||||||
|
|
||||||
type SSOSettings struct {
|
type SSOSettings struct {
|
||||||
Enable bool
|
Enable bool
|
||||||
Secret string
|
Secret string
|
||||||
|
@ -219,8 +231,13 @@ type TeamSettings struct {
|
||||||
RestrictTeamInvite *string
|
RestrictTeamInvite *string
|
||||||
RestrictPublicChannelManagement *string
|
RestrictPublicChannelManagement *string
|
||||||
RestrictPrivateChannelManagement *string
|
RestrictPrivateChannelManagement *string
|
||||||
|
RestrictPublicChannelCreation *string
|
||||||
|
RestrictPrivateChannelCreation *string
|
||||||
|
RestrictPublicChannelDeletion *string
|
||||||
|
RestrictPrivateChannelDeletion *string
|
||||||
UserStatusAwayTimeout *int64
|
UserStatusAwayTimeout *int64
|
||||||
MaxChannelsPerTeam *int64
|
MaxChannelsPerTeam *int64
|
||||||
|
MaxNotificationsPerChannel *int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type LdapSettings struct {
|
type LdapSettings struct {
|
||||||
|
@ -243,6 +260,7 @@ type LdapSettings struct {
|
||||||
UsernameAttribute *string
|
UsernameAttribute *string
|
||||||
NicknameAttribute *string
|
NicknameAttribute *string
|
||||||
IdAttribute *string
|
IdAttribute *string
|
||||||
|
PositionAttribute *string
|
||||||
|
|
||||||
// Syncronization
|
// Syncronization
|
||||||
SyncIntervalMinutes *int
|
SyncIntervalMinutes *int
|
||||||
|
@ -289,6 +307,7 @@ type SamlSettings struct {
|
||||||
UsernameAttribute *string
|
UsernameAttribute *string
|
||||||
NicknameAttribute *string
|
NicknameAttribute *string
|
||||||
LocaleAttribute *string
|
LocaleAttribute *string
|
||||||
|
PositionAttribute *string
|
||||||
|
|
||||||
LoginButtonText *string
|
LoginButtonText *string
|
||||||
}
|
}
|
||||||
|
@ -330,6 +349,8 @@ type Config struct {
|
||||||
SamlSettings SamlSettings
|
SamlSettings SamlSettings
|
||||||
NativeAppSettings NativeAppSettings
|
NativeAppSettings NativeAppSettings
|
||||||
ClusterSettings ClusterSettings
|
ClusterSettings ClusterSettings
|
||||||
|
MetricsSettings MetricsSettings
|
||||||
|
AnalyticsSettings AnalyticsSettings
|
||||||
WebrtcSettings WebrtcSettings
|
WebrtcSettings WebrtcSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,23 +397,32 @@ func (o *Config) SetDefaults() {
|
||||||
// Defaults to "s3.amazonaws.com"
|
// Defaults to "s3.amazonaws.com"
|
||||||
o.FileSettings.AmazonS3Endpoint = "s3.amazonaws.com"
|
o.FileSettings.AmazonS3Endpoint = "s3.amazonaws.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.FileSettings.AmazonS3Region == "" {
|
if o.FileSettings.AmazonS3Region == "" {
|
||||||
// Defaults to "us-east-1" region.
|
// Defaults to "us-east-1" region.
|
||||||
o.FileSettings.AmazonS3Region = "us-east-1"
|
o.FileSettings.AmazonS3Region = "us-east-1"
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.FileSettings.AmazonS3SSL == nil {
|
if o.FileSettings.AmazonS3SSL == nil {
|
||||||
o.FileSettings.AmazonS3SSL = new(bool)
|
o.FileSettings.AmazonS3SSL = new(bool)
|
||||||
*o.FileSettings.AmazonS3SSL = true // Secure by default.
|
*o.FileSettings.AmazonS3SSL = true // Secure by default.
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.FileSettings.MaxFileSize == nil {
|
if o.FileSettings.MaxFileSize == nil {
|
||||||
o.FileSettings.MaxFileSize = new(int64)
|
o.FileSettings.MaxFileSize = new(int64)
|
||||||
*o.FileSettings.MaxFileSize = 52428800 // 50 MB
|
*o.FileSettings.MaxFileSize = 52428800 // 50 MB
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*o.FileSettings.PublicLinkSalt) == 0 {
|
if len(*o.FileSettings.PublicLinkSalt) == 0 {
|
||||||
o.FileSettings.PublicLinkSalt = new(string)
|
o.FileSettings.PublicLinkSalt = new(string)
|
||||||
*o.FileSettings.PublicLinkSalt = NewRandomString(32)
|
*o.FileSettings.PublicLinkSalt = NewRandomString(32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.FileSettings.InitialFont == "" {
|
||||||
|
// Defaults to "luximbi.ttf"
|
||||||
|
o.FileSettings.InitialFont = "luximbi.ttf"
|
||||||
|
}
|
||||||
|
|
||||||
if len(o.EmailSettings.InviteSalt) == 0 {
|
if len(o.EmailSettings.InviteSalt) == 0 {
|
||||||
o.EmailSettings.InviteSalt = NewRandomString(32)
|
o.EmailSettings.InviteSalt = NewRandomString(32)
|
||||||
}
|
}
|
||||||
|
@ -426,6 +456,11 @@ func (o *Config) SetDefaults() {
|
||||||
*o.ServiceSettings.EnableMultifactorAuthentication = false
|
*o.ServiceSettings.EnableMultifactorAuthentication = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.ServiceSettings.EnforceMultifactorAuthentication == nil {
|
||||||
|
o.ServiceSettings.EnforceMultifactorAuthentication = new(bool)
|
||||||
|
*o.ServiceSettings.EnforceMultifactorAuthentication = false
|
||||||
|
}
|
||||||
|
|
||||||
if o.PasswordSettings.MinimumLength == nil {
|
if o.PasswordSettings.MinimumLength == nil {
|
||||||
o.PasswordSettings.MinimumLength = new(int)
|
o.PasswordSettings.MinimumLength = new(int)
|
||||||
*o.PasswordSettings.MinimumLength = PASSWORD_MINIMUM_LENGTH
|
*o.PasswordSettings.MinimumLength = PASSWORD_MINIMUM_LENGTH
|
||||||
|
@ -491,6 +526,30 @@ func (o *Config) SetDefaults() {
|
||||||
*o.TeamSettings.RestrictPrivateChannelManagement = PERMISSIONS_ALL
|
*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 {
|
if o.TeamSettings.UserStatusAwayTimeout == nil {
|
||||||
o.TeamSettings.UserStatusAwayTimeout = new(int64)
|
o.TeamSettings.UserStatusAwayTimeout = new(int64)
|
||||||
*o.TeamSettings.UserStatusAwayTimeout = 300
|
*o.TeamSettings.UserStatusAwayTimeout = 300
|
||||||
|
@ -501,6 +560,11 @@ func (o *Config) SetDefaults() {
|
||||||
*o.TeamSettings.MaxChannelsPerTeam = 2000
|
*o.TeamSettings.MaxChannelsPerTeam = 2000
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.TeamSettings.MaxNotificationsPerChannel == nil {
|
||||||
|
o.TeamSettings.MaxNotificationsPerChannel = new(int64)
|
||||||
|
*o.TeamSettings.MaxNotificationsPerChannel = 1000
|
||||||
|
}
|
||||||
|
|
||||||
if o.EmailSettings.EnableSignInWithEmail == nil {
|
if o.EmailSettings.EnableSignInWithEmail == nil {
|
||||||
o.EmailSettings.EnableSignInWithEmail = new(bool)
|
o.EmailSettings.EnableSignInWithEmail = new(bool)
|
||||||
|
|
||||||
|
@ -671,6 +735,11 @@ func (o *Config) SetDefaults() {
|
||||||
*o.LdapSettings.IdAttribute = ""
|
*o.LdapSettings.IdAttribute = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.LdapSettings.PositionAttribute == nil {
|
||||||
|
o.LdapSettings.PositionAttribute = new(string)
|
||||||
|
*o.LdapSettings.PositionAttribute = ""
|
||||||
|
}
|
||||||
|
|
||||||
if o.LdapSettings.SyncIntervalMinutes == nil {
|
if o.LdapSettings.SyncIntervalMinutes == nil {
|
||||||
o.LdapSettings.SyncIntervalMinutes = new(int)
|
o.LdapSettings.SyncIntervalMinutes = new(int)
|
||||||
*o.LdapSettings.SyncIntervalMinutes = 60
|
*o.LdapSettings.SyncIntervalMinutes = 60
|
||||||
|
@ -772,6 +841,21 @@ func (o *Config) SetDefaults() {
|
||||||
o.ClusterSettings.InterNodeUrls = []string{}
|
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 {
|
if o.ComplianceSettings.Enable == nil {
|
||||||
o.ComplianceSettings.Enable = new(bool)
|
o.ComplianceSettings.Enable = new(bool)
|
||||||
*o.ComplianceSettings.Enable = false
|
*o.ComplianceSettings.Enable = false
|
||||||
|
@ -882,6 +966,11 @@ func (o *Config) SetDefaults() {
|
||||||
*o.SamlSettings.NicknameAttribute = ""
|
*o.SamlSettings.NicknameAttribute = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.SamlSettings.PositionAttribute == nil {
|
||||||
|
o.SamlSettings.PositionAttribute = new(string)
|
||||||
|
*o.SamlSettings.PositionAttribute = ""
|
||||||
|
}
|
||||||
|
|
||||||
if o.SamlSettings.LocaleAttribute == nil {
|
if o.SamlSettings.LocaleAttribute == nil {
|
||||||
o.SamlSettings.LocaleAttribute = new(string)
|
o.SamlSettings.LocaleAttribute = new(string)
|
||||||
*o.SamlSettings.LocaleAttribute = ""
|
*o.SamlSettings.LocaleAttribute = ""
|
||||||
|
@ -952,6 +1041,11 @@ func (o *Config) SetDefaults() {
|
||||||
*o.ServiceSettings.Forward80To443 = false
|
*o.ServiceSettings.Forward80To443 = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.MetricsSettings.BlockProfileRate == nil {
|
||||||
|
o.MetricsSettings.BlockProfileRate = new(int)
|
||||||
|
*o.MetricsSettings.BlockProfileRate = 0
|
||||||
|
}
|
||||||
|
|
||||||
o.defaultWebrtcSettings()
|
o.defaultWebrtcSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,6 +1081,10 @@ func (o *Config) IsValid() *AppError {
|
||||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_channels.app_error", nil, "")
|
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) {
|
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, "")
|
return NewLocAppError("Config.IsValid", "model.config.is_valid.restrict_direct_message.app_error", nil, "")
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ package model
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -233,7 +234,7 @@ func expandAnnouncements(i *IncomingWebhookRequest) {
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
f := field.(map[string]interface{})
|
f := field.(map[string]interface{})
|
||||||
if f["value"] != nil {
|
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"`
|
Office365OAuth *bool `json:"office365_oauth"`
|
||||||
Compliance *bool `json:"compliance"`
|
Compliance *bool `json:"compliance"`
|
||||||
Cluster *bool `json:"cluster"`
|
Cluster *bool `json:"cluster"`
|
||||||
|
Metrics *bool `json:"metrics"`
|
||||||
CustomBrand *bool `json:"custom_brand"`
|
CustomBrand *bool `json:"custom_brand"`
|
||||||
MHPNS *bool `json:"mhpns"`
|
MHPNS *bool `json:"mhpns"`
|
||||||
SAML *bool `json:"saml"`
|
SAML *bool `json:"saml"`
|
||||||
|
@ -55,6 +56,7 @@ func (f *Features) ToMap() map[string]interface{} {
|
||||||
"office365": *f.Office365OAuth,
|
"office365": *f.Office365OAuth,
|
||||||
"compliance": *f.Compliance,
|
"compliance": *f.Compliance,
|
||||||
"cluster": *f.Cluster,
|
"cluster": *f.Cluster,
|
||||||
|
"metrics": *f.Metrics,
|
||||||
"custom_brand": *f.CustomBrand,
|
"custom_brand": *f.CustomBrand,
|
||||||
"mhpns": *f.MHPNS,
|
"mhpns": *f.MHPNS,
|
||||||
"saml": *f.SAML,
|
"saml": *f.SAML,
|
||||||
|
@ -104,6 +106,11 @@ func (f *Features) SetDefaults() {
|
||||||
*f.Cluster = *f.FutureFeatures
|
*f.Cluster = *f.FutureFeatures
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.Metrics == nil {
|
||||||
|
f.Metrics = new(bool)
|
||||||
|
*f.Metrics = *f.FutureFeatures
|
||||||
|
}
|
||||||
|
|
||||||
if f.CustomBrand == nil {
|
if f.CustomBrand == nil {
|
||||||
f.CustomBrand = new(bool)
|
f.CustomBrand = new(bool)
|
||||||
*f.CustomBrand = *f.FutureFeatures
|
*f.CustomBrand = *f.FutureFeatures
|
||||||
|
|
|
@ -17,8 +17,14 @@ const (
|
||||||
POST_JOIN_LEAVE = "system_join_leave"
|
POST_JOIN_LEAVE = "system_join_leave"
|
||||||
POST_ADD_REMOVE = "system_add_remove"
|
POST_ADD_REMOVE = "system_add_remove"
|
||||||
POST_HEADER_CHANGE = "system_header_change"
|
POST_HEADER_CHANGE = "system_header_change"
|
||||||
|
POST_DISPLAYNAME_CHANGE = "system_displayname_change"
|
||||||
POST_CHANNEL_DELETED = "system_channel_deleted"
|
POST_CHANNEL_DELETED = "system_channel_deleted"
|
||||||
POST_EPHEMERAL = "system_ephemeral"
|
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 {
|
type Post struct {
|
||||||
|
@ -38,6 +44,7 @@ type Post struct {
|
||||||
Filenames StringArray `json:"filenames,omitempty"` // Deprecated, do not use this field any more
|
Filenames StringArray `json:"filenames,omitempty"` // Deprecated, do not use this field any more
|
||||||
FileIds StringArray `json:"file_ids,omitempty"`
|
FileIds StringArray `json:"file_ids,omitempty"`
|
||||||
PendingPostId string `json:"pending_post_id" db:"-"`
|
PendingPostId string `json:"pending_post_id" db:"-"`
|
||||||
|
HasReactions bool `json:"has_reactions,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Post) ToJson() string {
|
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, "")
|
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)
|
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)
|
return NewLocAppError("Post.IsValid", "model.post.is_valid.hashtags.app_error", nil, "id="+o.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// should be removed once more message types are supported
|
// 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)
|
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)
|
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)
|
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)
|
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_CATEGORY_LAST = "last"
|
||||||
PREFERENCE_NAME_LAST_CHANNEL = "channel"
|
PREFERENCE_NAME_LAST_CHANNEL = "channel"
|
||||||
|
PREFERENCE_NAME_LAST_TEAM = "team"
|
||||||
|
|
||||||
PREFERENCE_CATEGORY_NOTIFICATIONS = "notifications"
|
PREFERENCE_CATEGORY_NOTIFICATIONS = "notifications"
|
||||||
PREFERENCE_NAME_EMAIL_INTERVAL = "email_interval"
|
PREFERENCE_NAME_EMAIL_INTERVAL = "email_interval"
|
||||||
|
|
|
@ -30,6 +30,7 @@ type PushNotification struct {
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Badge int `json:"badge"`
|
Badge int `json:"badge"`
|
||||||
ContentAvailable int `json:"cont_ava"`
|
ContentAvailable int `json:"cont_ava"`
|
||||||
|
TeamId string `json:"team_id"`
|
||||||
ChannelId string `json:"channel_id"`
|
ChannelId string `json:"channel_id"`
|
||||||
ChannelName string `json:"channel_name"`
|
ChannelName string `json:"channel_name"`
|
||||||
Type string `json:"type"`
|
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"`
|
Status string `json:"status"`
|
||||||
Manual bool `json:"manual"`
|
Manual bool `json:"manual"`
|
||||||
LastActivityAt int64 `json:"last_activity_at"`
|
LastActivityAt int64 `json:"last_activity_at"`
|
||||||
ActiveChannel string `json:"active_channel"`
|
ActiveChannel string `json:"active_channel" db:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Status) ToJson() string {
|
func (o *Status) ToJson() string {
|
||||||
|
@ -44,3 +44,14 @@ func StatusFromJson(data io.Reader) *Status {
|
||||||
return nil
|
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"`
|
DeleteAt int64 `json:"delete_at"`
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
CompanyName string `json:"company_name"`
|
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)
|
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) {
|
if IsReservedTeamName(o.Name) {
|
||||||
return NewLocAppError("Team.IsValid", "model.team.is_valid.reserved.app_error", nil, "id="+o.Id)
|
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"`
|
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 {
|
func (o *TeamMember) ToJson() string {
|
||||||
b, err := json.Marshal(o)
|
b, err := json.Marshal(o)
|
||||||
if err != nil {
|
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 {
|
func (o *TeamMember) IsValid() *AppError {
|
||||||
|
|
||||||
if len(o.TeamId) != 26 {
|
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"`
|
Nickname string `json:"nickname"`
|
||||||
FirstName string `json:"first_name"`
|
FirstName string `json:"first_name"`
|
||||||
LastName string `json:"last_name"`
|
LastName string `json:"last_name"`
|
||||||
|
Position string `json:"position"`
|
||||||
Roles string `json:"roles"`
|
Roles string `json:"roles"`
|
||||||
AllowMarketing bool `json:"allow_marketing,omitempty"`
|
AllowMarketing bool `json:"allow_marketing,omitempty"`
|
||||||
Props StringMap `json:"props,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)
|
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 {
|
if utf8.RuneCountInString(u.FirstName) > 64 {
|
||||||
return NewLocAppError("User.IsValid", "model.user.is_valid.first_name.app_error", nil, "user_id="+u.Id)
|
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
|
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 puncStart = regexp.MustCompile(`^[^\pL\d\s#]+`)
|
||||||
var hashtagStart = regexp.MustCompile(`^#{2,}`)
|
var hashtagStart = regexp.MustCompile(`^#{2,}`)
|
||||||
var puncEnd = regexp.MustCompile(`[^\pL\d\s]+$`)
|
var puncEnd = regexp.MustCompile(`[^\pL\d\s]+$`)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
// It should be maitained in chronological order with most current
|
// It should be maitained in chronological order with most current
|
||||||
// release at the front of the list.
|
// release at the front of the list.
|
||||||
var versions = []string{
|
var versions = []string{
|
||||||
|
"3.6.0",
|
||||||
"3.5.0",
|
"3.5.0",
|
||||||
"3.4.0",
|
"3.4.0",
|
||||||
"3.3.0",
|
"3.3.0",
|
||||||
|
|
|
@ -18,6 +18,7 @@ const (
|
||||||
WEBSOCKET_EVENT_DIRECT_ADDED = "direct_added"
|
WEBSOCKET_EVENT_DIRECT_ADDED = "direct_added"
|
||||||
WEBSOCKET_EVENT_NEW_USER = "new_user"
|
WEBSOCKET_EVENT_NEW_USER = "new_user"
|
||||||
WEBSOCKET_EVENT_LEAVE_TEAM = "leave_team"
|
WEBSOCKET_EVENT_LEAVE_TEAM = "leave_team"
|
||||||
|
WEBSOCKET_EVENT_UPDATE_TEAM = "update_team"
|
||||||
WEBSOCKET_EVENT_USER_ADDED = "user_added"
|
WEBSOCKET_EVENT_USER_ADDED = "user_added"
|
||||||
WEBSOCKET_EVENT_USER_UPDATED = "user_updated"
|
WEBSOCKET_EVENT_USER_UPDATED = "user_updated"
|
||||||
WEBSOCKET_EVENT_USER_REMOVED = "user_removed"
|
WEBSOCKET_EVENT_USER_REMOVED = "user_removed"
|
||||||
|
@ -27,6 +28,8 @@ const (
|
||||||
WEBSOCKET_EVENT_HELLO = "hello"
|
WEBSOCKET_EVENT_HELLO = "hello"
|
||||||
WEBSOCKET_EVENT_WEBRTC = "webrtc"
|
WEBSOCKET_EVENT_WEBRTC = "webrtc"
|
||||||
WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge"
|
WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge"
|
||||||
|
WEBSOCKET_EVENT_REACTION_ADDED = "reaction_added"
|
||||||
|
WEBSOCKET_EVENT_REACTION_REMOVED = "reaction_removed"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebSocketMessage interface {
|
type WebSocketMessage interface {
|
||||||
|
@ -34,6 +37,7 @@ type WebSocketMessage interface {
|
||||||
IsValid() bool
|
IsValid() bool
|
||||||
DoPreComputeJson()
|
DoPreComputeJson()
|
||||||
GetPreComputeJson() []byte
|
GetPreComputeJson() []byte
|
||||||
|
EventType() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsocketBroadcast struct {
|
type WebsocketBroadcast struct {
|
||||||
|
@ -63,6 +67,10 @@ func (o *WebSocketEvent) IsValid() bool {
|
||||||
return o.Event != ""
|
return o.Event != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *WebSocketEvent) EventType() string {
|
||||||
|
return o.Event
|
||||||
|
}
|
||||||
|
|
||||||
func (o *WebSocketEvent) DoPreComputeJson() {
|
func (o *WebSocketEvent) DoPreComputeJson() {
|
||||||
b, err := json.Marshal(o)
|
b, err := json.Marshal(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -120,6 +128,10 @@ func (o *WebSocketResponse) IsValid() bool {
|
||||||
return o.Status != ""
|
return o.Status != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *WebSocketResponse) EventType() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (o *WebSocketResponse) ToJson() string {
|
func (o *WebSocketResponse) ToJson() string {
|
||||||
b, err := json.Marshal(o)
|
b, err := json.Marshal(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -95,8 +95,8 @@
|
||||||
"importpath": "github.com/mattermost/platform/einterfaces",
|
"importpath": "github.com/mattermost/platform/einterfaces",
|
||||||
"repository": "https://github.com/mattermost/platform",
|
"repository": "https://github.com/mattermost/platform",
|
||||||
"vcs": "git",
|
"vcs": "git",
|
||||||
"revision": "b55ec6148caa93d54b660afe55408c643d217108",
|
"revision": "976296cd52533ff565407e55e872339cc312a0cf",
|
||||||
"branch": "release-3.5",
|
"branch": "release-3.6",
|
||||||
"path": "/einterfaces",
|
"path": "/einterfaces",
|
||||||
"notests": true
|
"notests": true
|
||||||
},
|
},
|
||||||
|
@ -104,8 +104,8 @@
|
||||||
"importpath": "github.com/mattermost/platform/model",
|
"importpath": "github.com/mattermost/platform/model",
|
||||||
"repository": "https://github.com/mattermost/platform",
|
"repository": "https://github.com/mattermost/platform",
|
||||||
"vcs": "git",
|
"vcs": "git",
|
||||||
"revision": "b55ec6148caa93d54b660afe55408c643d217108",
|
"revision": "976296cd52533ff565407e55e872339cc312a0cf",
|
||||||
"branch": "release-3.5",
|
"branch": "release-3.6",
|
||||||
"path": "/model",
|
"path": "/model",
|
||||||
"notests": true
|
"notests": true
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue