Sync with mattermost 3.5.0
This commit is contained in:
parent
08ebee6b4f
commit
1d5cd1d7c4
|
@ -153,7 +153,7 @@ func (b *Bmattermost) handleMatterClient(mchan chan *MMMessage) {
|
|||
for message := range b.mc.MessageChan {
|
||||
// do not post our own messages back to irc
|
||||
// only listen to message from our team
|
||||
if message.Raw.Event == "posted" && b.mc.User.Username != message.Username && message.Raw.TeamId == b.TeamId {
|
||||
if message.Raw.Event == "posted" && b.mc.User.Username != message.Username && message.Raw.Data["team_id"].(string) == b.TeamId {
|
||||
flog.Debugf("Receiving from matterclient %#v", message)
|
||||
m := &MMMessage{}
|
||||
m.Username = message.Username
|
||||
|
|
|
@ -264,7 +264,7 @@ func (m *MMClient) parseActionPost(rmsg *Message) {
|
|||
}
|
||||
rmsg.Username = m.GetUser(data.UserId).Username
|
||||
rmsg.Channel = m.GetChannelName(data.ChannelId)
|
||||
rmsg.Team = m.GetTeamName(rmsg.Raw.TeamId)
|
||||
rmsg.Team = m.GetTeamName(rmsg.Raw.Data["team_id"].(string))
|
||||
// direct message
|
||||
if rmsg.Raw.Data["channel_type"] == "D" {
|
||||
rmsg.Channel = m.GetUser(data.UserId).Username
|
||||
|
@ -275,7 +275,7 @@ func (m *MMClient) parseActionPost(rmsg *Message) {
|
|||
}
|
||||
|
||||
func (m *MMClient) UpdateUsers() error {
|
||||
mmusers, err := m.Client.GetProfilesForDirectMessageList(m.Team.Id)
|
||||
mmusers, err := m.Client.GetProfiles(0, 1000, "")
|
||||
if err != nil {
|
||||
return errors.New(err.DetailedError)
|
||||
}
|
||||
|
@ -305,7 +305,7 @@ func (m *MMClient) GetChannelName(channelId string) string {
|
|||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for _, t := range m.OtherTeams {
|
||||
for _, channel := range append(t.Channels.Channels, t.MoreChannels.Channels...) {
|
||||
for _, channel := range append(*t.Channels, *t.MoreChannels...) {
|
||||
if channel.Id == channelId {
|
||||
return channel.Name
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ func (m *MMClient) GetChannelId(name string, teamId string) string {
|
|||
}
|
||||
for _, t := range m.OtherTeams {
|
||||
if t.Id == teamId {
|
||||
for _, channel := range append(t.Channels.Channels, t.MoreChannels.Channels...) {
|
||||
for _, channel := range append(*t.Channels, *t.MoreChannels...) {
|
||||
if channel.Name == name {
|
||||
return channel.Id
|
||||
}
|
||||
|
@ -336,7 +336,7 @@ func (m *MMClient) GetChannelHeader(channelId string) string {
|
|||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for _, t := range m.OtherTeams {
|
||||
for _, channel := range append(t.Channels.Channels, t.MoreChannels.Channels...) {
|
||||
for _, channel := range append(*t.Channels, *t.MoreChannels...) {
|
||||
if channel.Id == channelId {
|
||||
return channel.Header
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ func (m *MMClient) PostMessage(channelId string, text string) {
|
|||
func (m *MMClient) JoinChannel(channelId string) error {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for _, c := range m.Team.Channels.Channels {
|
||||
for _, c := range *m.Team.Channels {
|
||||
if c.Id == channelId {
|
||||
m.log.Debug("Not joining ", channelId, " already joined.")
|
||||
return nil
|
||||
|
@ -397,7 +397,7 @@ func (m *MMClient) GetPublicLink(filename string) string {
|
|||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return res.Data.(string)
|
||||
return res
|
||||
}
|
||||
|
||||
func (m *MMClient) GetPublicLinks(filenames []string) []string {
|
||||
|
@ -407,7 +407,7 @@ func (m *MMClient) GetPublicLinks(filenames []string) []string {
|
|||
if err != nil {
|
||||
continue
|
||||
}
|
||||
output = append(output, res.Data.(string))
|
||||
output = append(output, res)
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
@ -432,15 +432,17 @@ func (m *MMClient) UpdateLastViewed(channelId string) {
|
|||
}
|
||||
|
||||
func (m *MMClient) UsernamesInChannel(channelId string) []string {
|
||||
ceiRes, err := m.Client.GetChannelExtraInfo(channelId, 5000, "")
|
||||
res, err := m.Client.GetMyChannelMembers()
|
||||
if err != nil {
|
||||
m.log.Errorf("UsernamesInChannel(%s) failed: %s", channelId, err)
|
||||
return []string{}
|
||||
}
|
||||
extra := ceiRes.Data.(*model.ChannelExtra)
|
||||
members := res.Data.(*model.ChannelMembers)
|
||||
result := []string{}
|
||||
for _, member := range extra.Members {
|
||||
result = append(result, member.Username)
|
||||
for _, channel := range *members {
|
||||
if channel.ChannelId == channelId {
|
||||
result = append(result, m.GetUser(channel.UserId).Username)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -500,10 +502,10 @@ func (m *MMClient) GetChannels() []*model.Channel {
|
|||
defer m.RUnlock()
|
||||
var channels []*model.Channel
|
||||
// our primary team channels first
|
||||
channels = append(channels, m.Team.Channels.Channels...)
|
||||
channels = append(channels, *m.Team.Channels...)
|
||||
for _, t := range m.OtherTeams {
|
||||
if t.Id != m.Team.Id {
|
||||
channels = append(channels, t.Channels.Channels...)
|
||||
channels = append(channels, *t.Channels...)
|
||||
}
|
||||
}
|
||||
return channels
|
||||
|
@ -515,7 +517,7 @@ func (m *MMClient) GetMoreChannels() []*model.Channel {
|
|||
defer m.RUnlock()
|
||||
var channels []*model.Channel
|
||||
for _, t := range m.OtherTeams {
|
||||
channels = append(channels, t.MoreChannels.Channels...)
|
||||
channels = append(channels, *t.MoreChannels...)
|
||||
}
|
||||
return channels
|
||||
}
|
||||
|
@ -526,8 +528,8 @@ func (m *MMClient) GetTeamFromChannel(channelId string) string {
|
|||
defer m.RUnlock()
|
||||
var channels []*model.Channel
|
||||
for _, t := range m.OtherTeams {
|
||||
channels = append(channels, t.Channels.Channels...)
|
||||
channels = append(channels, t.MoreChannels.Channels...)
|
||||
channels = append(channels, *t.Channels...)
|
||||
channels = append(channels, *t.MoreChannels...)
|
||||
for _, c := range channels {
|
||||
if c.Id == channelId {
|
||||
return t.Id
|
||||
|
@ -540,11 +542,13 @@ func (m *MMClient) GetTeamFromChannel(channelId string) string {
|
|||
func (m *MMClient) GetLastViewedAt(channelId string) int64 {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
/*
|
||||
for _, t := range m.OtherTeams {
|
||||
if _, ok := t.Channels.Members[channelId]; ok {
|
||||
return t.Channels.Members[channelId].LastViewedAt
|
||||
}
|
||||
}
|
||||
*/
|
||||
return 0
|
||||
}
|
||||
|
||||
|
@ -619,7 +623,7 @@ func (m *MMClient) initUser() error {
|
|||
//m.log.Debug("initUser(): loading all team data")
|
||||
for _, v := range initData.Teams {
|
||||
m.Client.SetTeamId(v.Id)
|
||||
mmusers, _ := m.Client.GetProfiles(v.Id, "")
|
||||
mmusers, _ := m.Client.GetProfiles(0, 1000, "")
|
||||
t := &Team{Team: v, Users: mmusers.Data.(map[string]*model.User), Id: v.Id}
|
||||
mmchannels, _ := m.Client.GetChannels("")
|
||||
t.Channels = mmchannels.Data.(*model.ChannelList)
|
||||
|
|
|
@ -13,7 +13,6 @@ type ClusterInterface interface {
|
|||
GetClusterInfos() []*model.ClusterInfo
|
||||
RemoveAllSessionsForUserId(userId string)
|
||||
InvalidateCacheForUser(userId string)
|
||||
InvalidateCacheForChannel(channelId string)
|
||||
Publish(event *model.WebSocketEvent)
|
||||
UpdateStatus(status *model.Status)
|
||||
GetLogs() ([]string, *model.AppError)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
type MfaInterface interface {
|
||||
GenerateQrCode(user *model.User) ([]byte, *model.AppError)
|
||||
GenerateSecret(user *model.User) (string, []byte, *model.AppError)
|
||||
Activate(user *model.User, token string) *model.AppError
|
||||
Deactivate(userId string) *model.AppError
|
||||
ValidateToken(secret, token string) (bool, *model.AppError)
|
||||
|
|
|
@ -0,0 +1,372 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
type Permission struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type Role struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Permissions []string `json:"permissions"`
|
||||
}
|
||||
|
||||
var PERMISSION_INVITE_USER *Permission
|
||||
var PERMISSION_ADD_USER_TO_TEAM *Permission
|
||||
var PERMISSION_USE_SLASH_COMMANDS *Permission
|
||||
var PERMISSION_MANAGE_SLASH_COMMANDS *Permission
|
||||
var PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS *Permission
|
||||
var PERMISSION_CREATE_PUBLIC_CHANNEL *Permission
|
||||
var PERMISSION_CREATE_PRIVATE_CHANNEL *Permission
|
||||
var PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS *Permission
|
||||
var PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS *Permission
|
||||
var PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE *Permission
|
||||
var PERMISSION_MANAGE_ROLES *Permission
|
||||
var PERMISSION_CREATE_DIRECT_CHANNEL *Permission
|
||||
var PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES *Permission
|
||||
var PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES *Permission
|
||||
var PERMISSION_LIST_TEAM_CHANNELS *Permission
|
||||
var PERMISSION_JOIN_PUBLIC_CHANNELS *Permission
|
||||
var PERMISSION_DELETE_PUBLIC_CHANNEL *Permission
|
||||
var PERMISSION_DELETE_PRIVATE_CHANNEL *Permission
|
||||
var PERMISSION_EDIT_OTHER_USERS *Permission
|
||||
var PERMISSION_READ_CHANNEL *Permission
|
||||
var PERMISSION_PERMANENT_DELETE_USER *Permission
|
||||
var PERMISSION_UPLOAD_FILE *Permission
|
||||
var PERMISSION_GET_PUBLIC_LINK *Permission
|
||||
var PERMISSION_MANAGE_WEBHOOKS *Permission
|
||||
var PERMISSION_MANAGE_OTHERS_WEBHOOKS *Permission
|
||||
var PERMISSION_MANAGE_OAUTH *Permission
|
||||
var PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH *Permission
|
||||
var PERMISSION_CREATE_POST *Permission
|
||||
var PERMISSION_EDIT_POST *Permission
|
||||
var PERMISSION_EDIT_OTHERS_POSTS *Permission
|
||||
var PERMISSION_REMOVE_USER_FROM_TEAM *Permission
|
||||
var PERMISSION_MANAGE_TEAM *Permission
|
||||
var PERMISSION_IMPORT_TEAM *Permission
|
||||
|
||||
// General permission that encompases all system admin functions
|
||||
// in the future this could be broken up to allow access to some
|
||||
// admin functions but not others
|
||||
var PERMISSION_MANAGE_SYSTEM *Permission
|
||||
|
||||
var ROLE_SYSTEM_USER *Role
|
||||
var ROLE_SYSTEM_ADMIN *Role
|
||||
|
||||
var ROLE_TEAM_USER *Role
|
||||
var ROLE_TEAM_ADMIN *Role
|
||||
|
||||
var ROLE_CHANNEL_USER *Role
|
||||
var ROLE_CHANNEL_ADMIN *Role
|
||||
var ROLE_CHANNEL_GUEST *Role
|
||||
|
||||
var BuiltInRoles map[string]*Role
|
||||
|
||||
func InitalizePermissions() {
|
||||
PERMISSION_INVITE_USER = &Permission{
|
||||
"invite_user",
|
||||
"authentication.permissions.team_invite_user.name",
|
||||
"authentication.permissions.team_invite_user.description",
|
||||
}
|
||||
PERMISSION_ADD_USER_TO_TEAM = &Permission{
|
||||
"add_user_to_team",
|
||||
"authentication.permissions.add_user_to_team.name",
|
||||
"authentication.permissions.add_user_to_team.description",
|
||||
}
|
||||
PERMISSION_USE_SLASH_COMMANDS = &Permission{
|
||||
"use_slash_commands",
|
||||
"authentication.permissions.team_use_slash_commands.name",
|
||||
"authentication.permissions.team_use_slash_commands.description",
|
||||
}
|
||||
PERMISSION_MANAGE_SLASH_COMMANDS = &Permission{
|
||||
"manage_slash_commands",
|
||||
"authentication.permissions.manage_slash_commands.name",
|
||||
"authentication.permissions.manage_slash_commands.description",
|
||||
}
|
||||
PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS = &Permission{
|
||||
"manage_others_slash_commands",
|
||||
"authentication.permissions.manage_others_slash_commands.name",
|
||||
"authentication.permissions.manage_others_slash_commands.description",
|
||||
}
|
||||
PERMISSION_CREATE_PUBLIC_CHANNEL = &Permission{
|
||||
"create_public_channel",
|
||||
"authentication.permissions.create_public_channel.name",
|
||||
"authentication.permissions.create_public_channel.description",
|
||||
}
|
||||
PERMISSION_CREATE_PRIVATE_CHANNEL = &Permission{
|
||||
"create_private_channel",
|
||||
"authentication.permissions.create_private_channel.name",
|
||||
"authentication.permissions.create_private_channel.description",
|
||||
}
|
||||
PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS = &Permission{
|
||||
"manage_public_channel_members",
|
||||
"authentication.permissions.manage_public_channel_members.name",
|
||||
"authentication.permissions.manage_public_channel_members.description",
|
||||
}
|
||||
PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS = &Permission{
|
||||
"manage_private_channel_members",
|
||||
"authentication.permissions.manage_private_channel_members.name",
|
||||
"authentication.permissions.manage_private_channel_members.description",
|
||||
}
|
||||
PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE = &Permission{
|
||||
"assign_system_admin_role",
|
||||
"authentication.permissions.assign_system_admin_role.name",
|
||||
"authentication.permissions.assign_system_admin_role.description",
|
||||
}
|
||||
PERMISSION_MANAGE_ROLES = &Permission{
|
||||
"manage_roles",
|
||||
"authentication.permissions.manage_roles.name",
|
||||
"authentication.permissions.manage_roles.description",
|
||||
}
|
||||
PERMISSION_MANAGE_SYSTEM = &Permission{
|
||||
"manage_system",
|
||||
"authentication.permissions.manage_system.name",
|
||||
"authentication.permissions.manage_system.description",
|
||||
}
|
||||
PERMISSION_CREATE_DIRECT_CHANNEL = &Permission{
|
||||
"create_direct_channel",
|
||||
"authentication.permissions.create_direct_channel.name",
|
||||
"authentication.permissions.create_direct_channel.description",
|
||||
}
|
||||
PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES = &Permission{
|
||||
"manage__publicchannel_properties",
|
||||
"authentication.permissions.manage_public_channel_properties.name",
|
||||
"authentication.permissions.manage_public_channel_properties.description",
|
||||
}
|
||||
PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES = &Permission{
|
||||
"manage_private_channel_properties",
|
||||
"authentication.permissions.manage_private_channel_properties.name",
|
||||
"authentication.permissions.manage_private_channel_properties.description",
|
||||
}
|
||||
PERMISSION_LIST_TEAM_CHANNELS = &Permission{
|
||||
"list_team_channels",
|
||||
"authentication.permissions.list_team_channels.name",
|
||||
"authentication.permissions.list_team_channels.description",
|
||||
}
|
||||
PERMISSION_JOIN_PUBLIC_CHANNELS = &Permission{
|
||||
"join_public_channels",
|
||||
"authentication.permissions.join_public_channels.name",
|
||||
"authentication.permissions.join_public_channels.description",
|
||||
}
|
||||
PERMISSION_DELETE_PUBLIC_CHANNEL = &Permission{
|
||||
"delete_public_channel",
|
||||
"authentication.permissions.delete_public_channel.name",
|
||||
"authentication.permissions.delete_public_channel.description",
|
||||
}
|
||||
PERMISSION_DELETE_PRIVATE_CHANNEL = &Permission{
|
||||
"delete_private_channel",
|
||||
"authentication.permissions.delete_private_channel.name",
|
||||
"authentication.permissions.delete_private_channel.description",
|
||||
}
|
||||
PERMISSION_EDIT_OTHER_USERS = &Permission{
|
||||
"edit_other_users",
|
||||
"authentication.permissions.edit_other_users.name",
|
||||
"authentication.permissions.edit_other_users.description",
|
||||
}
|
||||
PERMISSION_READ_CHANNEL = &Permission{
|
||||
"read_channel",
|
||||
"authentication.permissions.read_channel.name",
|
||||
"authentication.permissions.read_channel.description",
|
||||
}
|
||||
PERMISSION_PERMANENT_DELETE_USER = &Permission{
|
||||
"permanent_delete_user",
|
||||
"authentication.permissions.permanent_delete_user.name",
|
||||
"authentication.permissions.permanent_delete_user.description",
|
||||
}
|
||||
PERMISSION_UPLOAD_FILE = &Permission{
|
||||
"upload_file",
|
||||
"authentication.permissions.upload_file.name",
|
||||
"authentication.permissions.upload_file.description",
|
||||
}
|
||||
PERMISSION_GET_PUBLIC_LINK = &Permission{
|
||||
"get_public_link",
|
||||
"authentication.permissions.get_public_link.name",
|
||||
"authentication.permissions.get_public_link.description",
|
||||
}
|
||||
PERMISSION_MANAGE_WEBHOOKS = &Permission{
|
||||
"manage_webhooks",
|
||||
"authentication.permissions.manage_webhooks.name",
|
||||
"authentication.permissions.manage_webhooks.description",
|
||||
}
|
||||
PERMISSION_MANAGE_OTHERS_WEBHOOKS = &Permission{
|
||||
"manage_others_webhooks",
|
||||
"authentication.permissions.manage_others_webhooks.name",
|
||||
"authentication.permissions.manage_others_webhooks.description",
|
||||
}
|
||||
PERMISSION_MANAGE_OAUTH = &Permission{
|
||||
"manage_oauth",
|
||||
"authentication.permissions.manage_oauth.name",
|
||||
"authentication.permissions.manage_oauth.description",
|
||||
}
|
||||
PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH = &Permission{
|
||||
"manage_sytem_wide_oauth",
|
||||
"authentication.permissions.manage_sytem_wide_oauth.name",
|
||||
"authentication.permissions.manage_sytem_wide_oauth.description",
|
||||
}
|
||||
PERMISSION_CREATE_POST = &Permission{
|
||||
"create_post",
|
||||
"authentication.permissions.create_post.name",
|
||||
"authentication.permissions.create_post.description",
|
||||
}
|
||||
PERMISSION_EDIT_POST = &Permission{
|
||||
"edit_post",
|
||||
"authentication.permissions.edit_post.name",
|
||||
"authentication.permissions.edit_post.description",
|
||||
}
|
||||
PERMISSION_EDIT_OTHERS_POSTS = &Permission{
|
||||
"edit_others_posts",
|
||||
"authentication.permissions.edit_others_posts.name",
|
||||
"authentication.permissions.edit_others_posts.description",
|
||||
}
|
||||
PERMISSION_REMOVE_USER_FROM_TEAM = &Permission{
|
||||
"remove_user_from_team",
|
||||
"authentication.permissions.remove_user_from_team.name",
|
||||
"authentication.permissions.remove_user_from_team.description",
|
||||
}
|
||||
PERMISSION_MANAGE_TEAM = &Permission{
|
||||
"manage_team",
|
||||
"authentication.permissions.manage_team.name",
|
||||
"authentication.permissions.manage_team.description",
|
||||
}
|
||||
PERMISSION_IMPORT_TEAM = &Permission{
|
||||
"import_team",
|
||||
"authentication.permissions.import_team.name",
|
||||
"authentication.permissions.import_team.description",
|
||||
}
|
||||
}
|
||||
|
||||
func InitalizeRoles() {
|
||||
InitalizePermissions()
|
||||
BuiltInRoles = make(map[string]*Role)
|
||||
|
||||
ROLE_CHANNEL_USER = &Role{
|
||||
"channel_user",
|
||||
"authentication.roles.channel_user.name",
|
||||
"authentication.roles.channel_user.description",
|
||||
[]string{
|
||||
PERMISSION_READ_CHANNEL.Id,
|
||||
PERMISSION_MANAGE_PUBLIC_CHANNEL_MEMBERS.Id,
|
||||
PERMISSION_MANAGE_PRIVATE_CHANNEL_MEMBERS.Id,
|
||||
PERMISSION_UPLOAD_FILE.Id,
|
||||
PERMISSION_GET_PUBLIC_LINK.Id,
|
||||
PERMISSION_CREATE_POST.Id,
|
||||
PERMISSION_EDIT_POST.Id,
|
||||
PERMISSION_USE_SLASH_COMMANDS.Id,
|
||||
},
|
||||
}
|
||||
BuiltInRoles[ROLE_CHANNEL_USER.Id] = ROLE_CHANNEL_USER
|
||||
ROLE_CHANNEL_ADMIN = &Role{
|
||||
"channel_admin",
|
||||
"authentication.roles.channel_admin.name",
|
||||
"authentication.roles.channel_admin.description",
|
||||
[]string{},
|
||||
}
|
||||
BuiltInRoles[ROLE_CHANNEL_ADMIN.Id] = ROLE_CHANNEL_ADMIN
|
||||
ROLE_CHANNEL_GUEST = &Role{
|
||||
"guest",
|
||||
"authentication.roles.global_guest.name",
|
||||
"authentication.roles.global_guest.description",
|
||||
[]string{},
|
||||
}
|
||||
BuiltInRoles[ROLE_CHANNEL_GUEST.Id] = ROLE_CHANNEL_GUEST
|
||||
|
||||
ROLE_TEAM_USER = &Role{
|
||||
"team_user",
|
||||
"authentication.roles.team_user.name",
|
||||
"authentication.roles.team_user.description",
|
||||
[]string{
|
||||
PERMISSION_LIST_TEAM_CHANNELS.Id,
|
||||
PERMISSION_JOIN_PUBLIC_CHANNELS.Id,
|
||||
},
|
||||
}
|
||||
BuiltInRoles[ROLE_TEAM_USER.Id] = ROLE_TEAM_USER
|
||||
ROLE_TEAM_ADMIN = &Role{
|
||||
"team_admin",
|
||||
"authentication.roles.team_admin.name",
|
||||
"authentication.roles.team_admin.description",
|
||||
[]string{
|
||||
PERMISSION_EDIT_OTHERS_POSTS.Id,
|
||||
PERMISSION_ADD_USER_TO_TEAM.Id,
|
||||
PERMISSION_REMOVE_USER_FROM_TEAM.Id,
|
||||
PERMISSION_MANAGE_TEAM.Id,
|
||||
PERMISSION_IMPORT_TEAM.Id,
|
||||
PERMISSION_MANAGE_ROLES.Id,
|
||||
PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
|
||||
PERMISSION_MANAGE_SLASH_COMMANDS.Id,
|
||||
PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS.Id,
|
||||
PERMISSION_MANAGE_WEBHOOKS.Id,
|
||||
},
|
||||
}
|
||||
BuiltInRoles[ROLE_TEAM_ADMIN.Id] = ROLE_TEAM_ADMIN
|
||||
|
||||
ROLE_SYSTEM_USER = &Role{
|
||||
"system_user",
|
||||
"authentication.roles.global_user.name",
|
||||
"authentication.roles.global_user.description",
|
||||
[]string{
|
||||
PERMISSION_CREATE_DIRECT_CHANNEL.Id,
|
||||
PERMISSION_PERMANENT_DELETE_USER.Id,
|
||||
PERMISSION_MANAGE_OAUTH.Id,
|
||||
},
|
||||
}
|
||||
BuiltInRoles[ROLE_SYSTEM_USER.Id] = ROLE_SYSTEM_USER
|
||||
ROLE_SYSTEM_ADMIN = &Role{
|
||||
"system_admin",
|
||||
"authentication.roles.global_admin.name",
|
||||
"authentication.roles.global_admin.description",
|
||||
// System admins can do anything channel and team admins can do
|
||||
// plus everything members of teams and channels can do to all teams
|
||||
// and channels on the system
|
||||
append(
|
||||
append(
|
||||
append(
|
||||
append(
|
||||
[]string{
|
||||
PERMISSION_ASSIGN_SYSTEM_ADMIN_ROLE.Id,
|
||||
PERMISSION_MANAGE_SYSTEM.Id,
|
||||
PERMISSION_MANAGE_PUBLIC_CHANNEL_PROPERTIES.Id,
|
||||
PERMISSION_DELETE_PUBLIC_CHANNEL.Id,
|
||||
PERMISSION_CREATE_PUBLIC_CHANNEL.Id,
|
||||
PERMISSION_MANAGE_PRIVATE_CHANNEL_PROPERTIES.Id,
|
||||
PERMISSION_DELETE_PRIVATE_CHANNEL.Id,
|
||||
PERMISSION_CREATE_PRIVATE_CHANNEL.Id,
|
||||
PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH.Id,
|
||||
PERMISSION_MANAGE_OTHERS_WEBHOOKS.Id,
|
||||
PERMISSION_EDIT_OTHER_USERS.Id,
|
||||
PERMISSION_MANAGE_OAUTH.Id,
|
||||
PERMISSION_INVITE_USER.Id,
|
||||
},
|
||||
ROLE_TEAM_USER.Permissions...,
|
||||
),
|
||||
ROLE_CHANNEL_USER.Permissions...,
|
||||
),
|
||||
ROLE_TEAM_ADMIN.Permissions...,
|
||||
),
|
||||
ROLE_CHANNEL_ADMIN.Permissions...,
|
||||
),
|
||||
}
|
||||
BuiltInRoles[ROLE_SYSTEM_ADMIN.Id] = ROLE_SYSTEM_ADMIN
|
||||
|
||||
}
|
||||
|
||||
func RoleIdsToString(roles []string) string {
|
||||
output := ""
|
||||
for _, role := range roles {
|
||||
output += role + ", "
|
||||
}
|
||||
|
||||
if output == "" {
|
||||
return "[<NO ROLES>]"
|
||||
}
|
||||
|
||||
return output[:len(output)-1]
|
||||
}
|
||||
|
||||
func init() {
|
||||
InitalizeRoles()
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type UserAutocompleteInChannel struct {
|
||||
InChannel []*User `json:"in_channel"`
|
||||
OutOfChannel []*User `json:"out_of_channel"`
|
||||
}
|
||||
|
||||
type UserAutocompleteInTeam struct {
|
||||
InTeam []*User `json:"in_team"`
|
||||
}
|
||||
|
||||
func (o *UserAutocompleteInChannel) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func UserAutocompleteInChannelFromJson(data io.Reader) *UserAutocompleteInChannel {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o UserAutocompleteInChannel
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o *UserAutocompleteInTeam) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func UserAutocompleteInTeamFromJson(data io.Reader) *UserAutocompleteInTeam {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o UserAutocompleteInTeam
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -14,6 +14,10 @@ const (
|
|||
CHANNEL_PRIVATE = "P"
|
||||
CHANNEL_DIRECT = "D"
|
||||
DEFAULT_CHANNEL = "town-square"
|
||||
CHANNEL_DISPLAY_NAME_MAX_RUNES = 64
|
||||
CHANNEL_NAME_MAX_LENGTH = 64
|
||||
CHANNEL_HEADER_MAX_RUNES = 1024
|
||||
CHANNEL_PURPOSE_MAX_RUNES = 250
|
||||
)
|
||||
|
||||
type Channel struct {
|
||||
|
@ -57,8 +61,8 @@ func (o *Channel) Etag() string {
|
|||
return Etag(o.Id, o.UpdateAt)
|
||||
}
|
||||
|
||||
func (o *Channel) ExtraEtag(memberLimit int) string {
|
||||
return Etag(o.Id, o.ExtraUpdateAt, memberLimit)
|
||||
func (o *Channel) StatsEtag() string {
|
||||
return Etag(o.Id, o.ExtraUpdateAt)
|
||||
}
|
||||
|
||||
func (o *Channel) IsValid() *AppError {
|
||||
|
@ -75,11 +79,11 @@ func (o *Channel) IsValid() *AppError {
|
|||
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.update_at.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(o.DisplayName) > 64 {
|
||||
if utf8.RuneCountInString(o.DisplayName) > CHANNEL_DISPLAY_NAME_MAX_RUNES {
|
||||
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.display_name.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if len(o.Name) > 64 {
|
||||
if len(o.Name) > CHANNEL_NAME_MAX_LENGTH {
|
||||
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.name.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
|
@ -91,11 +95,11 @@ func (o *Channel) IsValid() *AppError {
|
|||
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.type.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(o.Header) > 1024 {
|
||||
if utf8.RuneCountInString(o.Header) > CHANNEL_HEADER_MAX_RUNES {
|
||||
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.header.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(o.Purpose) > 128 {
|
||||
if utf8.RuneCountInString(o.Purpose) > CHANNEL_PURPOSE_MAX_RUNES {
|
||||
return NewLocAppError("Channel.IsValid", "model.channel.is_valid.purpose.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ExtraMember struct {
|
||||
Id string `json:"id"`
|
||||
Nickname string `json:"nickname"`
|
||||
Email string `json:"email"`
|
||||
Roles string `json:"roles"`
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
func (o *ExtraMember) Sanitize(options map[string]bool) {
|
||||
if len(options) == 0 || !options["email"] {
|
||||
o.Email = ""
|
||||
}
|
||||
}
|
||||
|
||||
type ChannelExtra struct {
|
||||
Id string `json:"id"`
|
||||
Members []ExtraMember `json:"members"`
|
||||
MemberCount int64 `json:"member_count"`
|
||||
}
|
||||
|
||||
func (o *ChannelExtra) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func ChannelExtraFromJson(data io.Reader) *ChannelExtra {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o ChannelExtra
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -8,15 +8,11 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
type ChannelList struct {
|
||||
Channels []*Channel `json:"channels"`
|
||||
Members map[string]*ChannelMember `json:"members"`
|
||||
}
|
||||
type ChannelList []*Channel
|
||||
|
||||
func (o *ChannelList) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
if b, err := json.Marshal(o); err != nil {
|
||||
return "[]"
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
|
@ -28,7 +24,7 @@ func (o *ChannelList) Etag() string {
|
|||
var t int64 = 0
|
||||
var delta int64 = 0
|
||||
|
||||
for _, v := range o.Channels {
|
||||
for _, v := range *o {
|
||||
if v.LastPostAt > t {
|
||||
t = v.LastPostAt
|
||||
id = v.Id
|
||||
|
@ -39,30 +35,9 @@ func (o *ChannelList) Etag() string {
|
|||
id = v.Id
|
||||
}
|
||||
|
||||
member := o.Members[v.Id]
|
||||
|
||||
if member != nil {
|
||||
max := v.LastPostAt
|
||||
if v.UpdateAt > max {
|
||||
max = v.UpdateAt
|
||||
}
|
||||
|
||||
delta += max - member.LastViewedAt
|
||||
|
||||
if member.LastViewedAt > t {
|
||||
t = member.LastViewedAt
|
||||
id = v.Id
|
||||
}
|
||||
|
||||
if member.LastUpdateAt > t {
|
||||
t = member.LastUpdateAt
|
||||
id = v.Id
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Etag(id, t, delta, len(o.Channels))
|
||||
return Etag(id, t, delta, len(*o))
|
||||
}
|
||||
|
||||
func ChannelListFromJson(data io.Reader) *ChannelList {
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
CHANNEL_ROLE_ADMIN = "admin"
|
||||
CHANNEL_NOTIFY_DEFAULT = "default"
|
||||
CHANNEL_NOTIFY_ALL = "all"
|
||||
CHANNEL_NOTIFY_MENTION = "mention"
|
||||
|
@ -30,6 +29,27 @@ type ChannelMember struct {
|
|||
LastUpdateAt int64 `json:"last_update_at"`
|
||||
}
|
||||
|
||||
type ChannelMembers []ChannelMember
|
||||
|
||||
func (o *ChannelMembers) ToJson() string {
|
||||
if b, err := json.Marshal(o); err != nil {
|
||||
return "[]"
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func ChannelMembersFromJson(data io.Reader) *ChannelMembers {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o ChannelMembers
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o *ChannelMember) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
|
@ -60,12 +80,6 @@ func (o *ChannelMember) IsValid() *AppError {
|
|||
return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.user_id.app_error", nil, "")
|
||||
}
|
||||
|
||||
for _, role := range strings.Split(o.Roles, " ") {
|
||||
if !(role == "" || role == CHANNEL_ROLE_ADMIN) {
|
||||
return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.role.app_error", nil, "role="+role)
|
||||
}
|
||||
}
|
||||
|
||||
notifyLevel := o.NotifyProps["desktop"]
|
||||
if len(notifyLevel) > 20 || !IsChannelNotifyLevelValid(notifyLevel) {
|
||||
return NewLocAppError("ChannelMember.IsValid", "model.channel_member.is_valid.notify_level.app_error",
|
||||
|
@ -89,6 +103,10 @@ func (o *ChannelMember) PreUpdate() {
|
|||
o.LastUpdateAt = GetMillis()
|
||||
}
|
||||
|
||||
func (o *ChannelMember) GetRoles() []string {
|
||||
return strings.Fields(o.Roles)
|
||||
}
|
||||
|
||||
func IsChannelNotifyLevelValid(notifyLevel string) bool {
|
||||
return notifyLevel == CHANNEL_NOTIFY_DEFAULT ||
|
||||
notifyLevel == CHANNEL_NOTIFY_ALL ||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type ChannelStats struct {
|
||||
ChannelId string `json:"channel_id"`
|
||||
MemberCount int64 `json:"member_count"`
|
||||
}
|
||||
|
||||
func (o *ChannelStats) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func ChannelStatsFromJson(data io.Reader) *ChannelStats {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o ChannelStats
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -108,6 +108,10 @@ func (c *Client) GetChannelRoute(channelId string) string {
|
|||
return fmt.Sprintf("/teams/%v/channels/%v", c.GetTeamId(), channelId)
|
||||
}
|
||||
|
||||
func (c *Client) GetUserRequiredRoute(userId string) string {
|
||||
return fmt.Sprintf("/users/%v", userId)
|
||||
}
|
||||
|
||||
func (c *Client) GetChannelNameRoute(channelName string) string {
|
||||
return fmt.Sprintf("/teams/%v/channels/name/%v", c.GetTeamId(), channelName)
|
||||
}
|
||||
|
@ -120,9 +124,14 @@ func (c *Client) GetGeneralRoute() string {
|
|||
return "/general"
|
||||
}
|
||||
|
||||
func (c *Client) GetFileRoute(fileId string) string {
|
||||
return fmt.Sprintf("/files/%v", fileId)
|
||||
}
|
||||
|
||||
func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppError) {
|
||||
rq, _ := http.NewRequest("POST", c.Url+url, strings.NewReader(data))
|
||||
rq.Header.Set("Content-Type", contentType)
|
||||
rq.Close = true
|
||||
|
||||
if rp, err := c.HttpClient.Do(rq); err != nil {
|
||||
return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error())
|
||||
|
@ -136,6 +145,7 @@ func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppErro
|
|||
|
||||
func (c *Client) DoApiPost(url string, data string) (*http.Response, *AppError) {
|
||||
rq, _ := http.NewRequest("POST", c.ApiUrl+url, strings.NewReader(data))
|
||||
rq.Close = true
|
||||
|
||||
if len(c.AuthToken) > 0 {
|
||||
rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
|
||||
|
@ -153,6 +163,7 @@ func (c *Client) DoApiPost(url string, data string) (*http.Response, *AppError)
|
|||
|
||||
func (c *Client) DoApiGet(url string, data string, etag string) (*http.Response, *AppError) {
|
||||
rq, _ := http.NewRequest("GET", c.ApiUrl+url, strings.NewReader(data))
|
||||
rq.Close = true
|
||||
|
||||
if len(etag) > 0 {
|
||||
rq.Header.Set(HEADER_ETAG_CLIENT, etag)
|
||||
|
@ -500,10 +511,9 @@ func (c *Client) GetMe(etag string) (*Result, *AppError) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetProfilesForDirectMessageList returns a map of users for a team that can be direct
|
||||
// messaged, using user id as the key. Must be authenticated.
|
||||
func (c *Client) GetProfilesForDirectMessageList(teamId string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet("/users/profiles_for_dm_list/"+teamId, "", ""); err != nil {
|
||||
// GetProfiles returns a map of users using user id as the key. Must be authenticated.
|
||||
func (c *Client) GetProfiles(offset int, limit int, etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(fmt.Sprintf("/users/%v/%v", offset, limit), "", etag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
|
@ -512,10 +522,10 @@ func (c *Client) GetProfilesForDirectMessageList(teamId string) (*Result, *AppEr
|
|||
}
|
||||
}
|
||||
|
||||
// GetProfiles returns a map of users for a team using user id as the key. Must
|
||||
// GetProfilesInTeam returns a map of users for a team using user id as the key. Must
|
||||
// be authenticated.
|
||||
func (c *Client) GetProfiles(teamId string, etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet("/users/profiles/"+teamId, "", etag); err != nil {
|
||||
func (c *Client) GetProfilesInTeam(teamId string, offset int, limit int, etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(fmt.Sprintf("/teams/%v/users/%v/%v", teamId, offset, limit), "", etag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
|
@ -524,10 +534,10 @@ func (c *Client) GetProfiles(teamId string, etag string) (*Result, *AppError) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetDirectProfiles gets a map of users that are currently shown in the sidebar,
|
||||
// using user id as the key. Must be authenticated.
|
||||
func (c *Client) GetDirectProfiles(etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet("/users/direct_profiles", "", etag); err != nil {
|
||||
// GetProfilesInChannel returns a map of users for a channel using user id as the key. Must
|
||||
// be authenticated.
|
||||
func (c *Client) GetProfilesInChannel(channelId string, offset int, limit int, etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(fmt.Sprintf(c.GetChannelRoute(channelId)+"/users/%v/%v", offset, limit), "", etag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
|
@ -536,6 +546,70 @@ func (c *Client) GetDirectProfiles(etag string) (*Result, *AppError) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetProfilesNotInChannel returns a map of users not in a channel but on the team using user id as the key. Must
|
||||
// be authenticated.
|
||||
func (c *Client) GetProfilesNotInChannel(channelId string, offset int, limit int, etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(fmt.Sprintf(c.GetChannelRoute(channelId)+"/users/not_in_channel/%v/%v", offset, limit), "", etag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetProfilesByIds returns a map of users based on the user ids provided. Must
|
||||
// be authenticated.
|
||||
func (c *Client) GetProfilesByIds(userIds []string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiPost("/users/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), UserMapFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// SearchUsers returns a list of users that have a username matching or similar to the search term. Must
|
||||
// be authenticated.
|
||||
func (c *Client) SearchUsers(params UserSearch) (*Result, *AppError) {
|
||||
if r, err := c.DoApiPost("/users/search", params.ToJson()); 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
|
||||
}
|
||||
}
|
||||
|
||||
// AutocompleteUsersInChannel returns two lists for autocompletion of users in a channel. The first list "in_channel",
|
||||
// specifies users in the channel. The second list "out_of_channel" specifies users outside of the
|
||||
// channel. Term, the string to search against, is required, channel id is also required. Must be authenticated.
|
||||
func (c *Client) AutocompleteUsersInChannel(term string, channelId string) (*Result, *AppError) {
|
||||
url := fmt.Sprintf("%s/users/autocomplete?term=%s", c.GetChannelRoute(channelId), 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), UserAutocompleteInChannelFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// AutocompleteUsersInTeam returns a list for autocompletion of users in a team. The list "in_team" specifies
|
||||
// the users in the team that match the provided term, matching against username, full name and
|
||||
// nickname. Must be authenticated.
|
||||
func (c *Client) AutocompleteUsersInTeam(term string) (*Result, *AppError) {
|
||||
url := fmt.Sprintf("%s/users/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), UserAutocompleteInTeamFromJson(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)
|
||||
|
@ -622,15 +696,16 @@ func (c *Client) CheckMfa(loginId string) (*Result, *AppError) {
|
|||
}
|
||||
}
|
||||
|
||||
// GenerateMfaQrCode returns a QR code imagem containing the secret, to be scanned
|
||||
// by a multi-factor authentication mobile application. Must be authenticated.
|
||||
func (c *Client) GenerateMfaQrCode() (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet("/users/generate_mfa_qr", "", ""); err != nil {
|
||||
// GenerateMfaSecret returns a QR code image containing the secret, to be scanned
|
||||
// by a multi-factor authentication mobile application. It also returns the secret
|
||||
// for manual entry. Must be authenticated.
|
||||
func (c *Client) GenerateMfaSecret() (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet("/users/generate_mfa_secret", "", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), r.Body}, nil
|
||||
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -934,6 +1009,7 @@ func (c *Client) SaveComplianceReport(job *Compliance) (*Result, *AppError) {
|
|||
func (c *Client) DownloadComplianceReport(id string) (*Result, *AppError) {
|
||||
var rq *http.Request
|
||||
rq, _ = http.NewRequest("GET", c.ApiUrl+"/admin/download_compliance_report/"+id, nil)
|
||||
rq.Close = true
|
||||
|
||||
if len(c.AuthToken) > 0 {
|
||||
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
|
||||
|
@ -1047,13 +1123,13 @@ func (c *Client) UpdateNotifyProps(data map[string]string) (*Result, *AppError)
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetChannels(etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/", "", etag); err != nil {
|
||||
func (c *Client) GetMyChannelMembers() (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/members", "", ""); 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
|
||||
r.Header.Get(HEADER_ETAG_SERVER), ChannelMembersFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1087,6 +1163,16 @@ func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetChannels(etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/", "", etag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), ChannelListFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) JoinChannel(id string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil {
|
||||
return nil, err
|
||||
|
@ -1166,13 +1252,23 @@ func (c *Client) UpdateLastViewedAt(channelId string, active bool) (*Result, *Ap
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetChannelExtraInfo(id string, memberLimit int, etag string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/extra_info/"+strconv.FormatInt(int64(memberLimit), 10), "", etag); err != nil {
|
||||
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
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), ChannelExtraFromJson(r.Body)}, nil
|
||||
r.Header.Get(HEADER_ETAG_SERVER), ChannelStatsFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetChannelMember(channelId string, userId string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+"/members/"+userId, "", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), ChannelMemberFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1285,13 +1381,39 @@ func (c *Client) UploadProfileFile(data []byte, contentType string) (*Result, *A
|
|||
return c.uploadFile(c.ApiUrl+"/users/newimage", data, contentType)
|
||||
}
|
||||
|
||||
func (c *Client) UploadPostAttachment(data []byte, contentType string) (*Result, *AppError) {
|
||||
return c.uploadFile(c.ApiUrl+c.GetTeamRoute()+"/files/upload", data, contentType)
|
||||
func (c *Client) UploadPostAttachment(data []byte, channelId string, filename string) (*FileUploadResponse, *AppError) {
|
||||
c.clearExtraProperties()
|
||||
|
||||
body := &bytes.Buffer{}
|
||||
writer := multipart.NewWriter(body)
|
||||
|
||||
if part, err := writer.CreateFormFile("files", filename); err != nil {
|
||||
return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error())
|
||||
} else if _, err = io.Copy(part, bytes.NewBuffer(data)); err != nil {
|
||||
return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.file.app_error", nil, err.Error())
|
||||
}
|
||||
|
||||
if part, err := writer.CreateFormField("channel_id"); err != nil {
|
||||
return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error())
|
||||
} else if _, err = io.Copy(part, strings.NewReader(channelId)); err != nil {
|
||||
return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.channel_id.app_error", nil, err.Error())
|
||||
}
|
||||
|
||||
if err := writer.Close(); err != nil {
|
||||
return nil, NewLocAppError("UploadPostAttachment", "model.client.upload_post_attachment.writer.app_error", nil, err.Error())
|
||||
}
|
||||
|
||||
if result, err := c.uploadFile(c.ApiUrl+c.GetTeamRoute()+"/files/upload", body.Bytes(), writer.FormDataContentType()); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return result.Data.(*FileUploadResponse), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) uploadFile(url string, data []byte, contentType string) (*Result, *AppError) {
|
||||
rq, _ := http.NewRequest("POST", url, bytes.NewReader(data))
|
||||
rq.Header.Set("Content-Type", contentType)
|
||||
rq.Close = true
|
||||
|
||||
if len(c.AuthToken) > 0 {
|
||||
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
|
||||
|
@ -1308,55 +1430,51 @@ func (c *Client) uploadFile(url string, data []byte, contentType string) (*Resul
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetFile(url string, isFullUrl bool) (*Result, *AppError) {
|
||||
var rq *http.Request
|
||||
if isFullUrl {
|
||||
rq, _ = http.NewRequest("GET", url, nil)
|
||||
func (c *Client) GetFile(fileId string) (io.ReadCloser, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get", "", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
rq, _ = http.NewRequest("GET", c.ApiUrl+c.GetTeamRoute()+"/files/get"+url, nil)
|
||||
}
|
||||
|
||||
if len(c.AuthToken) > 0 {
|
||||
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
|
||||
}
|
||||
|
||||
if rp, err := c.HttpClient.Do(rq); err != nil {
|
||||
return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error())
|
||||
} else if rp.StatusCode >= 300 {
|
||||
return nil, AppErrorFromJson(rp.Body)
|
||||
} else {
|
||||
defer closeBody(rp)
|
||||
return &Result{rp.Header.Get(HEADER_REQUEST_ID),
|
||||
rp.Header.Get(HEADER_ETAG_SERVER), rp.Body}, nil
|
||||
c.fillInExtraProperties(r)
|
||||
return r.Body, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetFileInfo(url string) (*Result, *AppError) {
|
||||
var rq *http.Request
|
||||
rq, _ = http.NewRequest("GET", c.ApiUrl+c.GetTeamRoute()+"/files/get_info"+url, nil)
|
||||
|
||||
if len(c.AuthToken) > 0 {
|
||||
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
|
||||
}
|
||||
|
||||
if rp, err := c.HttpClient.Do(rq); err != nil {
|
||||
return nil, NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error())
|
||||
} else if rp.StatusCode >= 300 {
|
||||
return nil, AppErrorFromJson(rp.Body)
|
||||
func (c *Client) GetFileThumbnail(fileId string) (io.ReadCloser, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get_thumbnail", "", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(rp)
|
||||
return &Result{rp.Header.Get(HEADER_REQUEST_ID),
|
||||
rp.Header.Get(HEADER_ETAG_SERVER), FileInfoFromJson(rp.Body)}, nil
|
||||
c.fillInExtraProperties(r)
|
||||
return r.Body, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetPublicLink(filename string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiPost(c.GetTeamRoute()+"/files/get_public_link", MapToJson(map[string]string{"filename": filename})); err != nil {
|
||||
func (c *Client) GetFilePreview(fileId string) (io.ReadCloser, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get_preview", "", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), StringFromJson(r.Body)}, nil
|
||||
c.fillInExtraProperties(r)
|
||||
return r.Body, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetFileInfo(fileId string) (*FileInfo, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get_info", "", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
c.fillInExtraProperties(r)
|
||||
return FileInfoFromJson(r.Body), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetPublicLink(fileId string) (string, *AppError) {
|
||||
if r, err := c.DoApiGet(c.GetFileRoute(fileId)+"/get_public_link", "", ""); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
c.fillInExtraProperties(r)
|
||||
return StringFromJson(r.Body), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1370,8 +1488,25 @@ func (c *Client) UpdateUser(user *User) (*Result, *AppError) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Client) UpdateUserRoles(data map[string]string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiPost("/users/update_roles", MapToJson(data)); err != nil {
|
||||
func (c *Client) UpdateUserRoles(userId string, roles string) (*Result, *AppError) {
|
||||
data := make(map[string]string)
|
||||
data["new_roles"] = roles
|
||||
|
||||
if r, err := c.DoApiPost(c.GetUserRequiredRoute(userId)+"/update_roles", MapToJson(data)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) UpdateTeamRoles(userId string, roles string) (*Result, *AppError) {
|
||||
data := make(map[string]string)
|
||||
data["new_roles"] = roles
|
||||
data["user_id"] = userId
|
||||
|
||||
if r, err := c.DoApiPost(c.GetTeamRoute()+"/update_member_roles", MapToJson(data)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
|
@ -1479,6 +1614,18 @@ func (c *Client) GetStatuses() (*Result, *AppError) {
|
|||
}
|
||||
}
|
||||
|
||||
// GetStatusesByIds returns a map of string statuses using user id as the key,
|
||||
// based on the provided user ids
|
||||
func (c *Client) GetStatusesByIds(userIds []string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiPost("/users/status/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), MapFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
@ -1504,8 +1651,46 @@ func (c *Client) GetMyTeam(etag string) (*Result, *AppError) {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Client) GetTeamMembers(teamId string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet("/teams/members/"+teamId, "", ""); err != nil {
|
||||
// GetTeamMembers will return a page of team member objects as an array paged based on the
|
||||
// team id, offset and limit provided. Must be authenticated.
|
||||
func (c *Client) GetTeamMembers(teamId string, offset int, limit int) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(fmt.Sprintf("/teams/%v/members/%v/%v", teamId, 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), TeamMembersFromJson(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) {
|
||||
if r, err := c.DoApiGet(fmt.Sprintf("/teams/%v/members/%v", teamId, userId), "", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return &Result{r.Header.Get(HEADER_REQUEST_ID),
|
||||
r.Header.Get(HEADER_ETAG_SERVER), TeamMemberFromJson(r.Body)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 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) GetTeamStats(teamId string) (*Result, *AppError) {
|
||||
if r, err := c.DoApiGet(fmt.Sprintf("/teams/%v/stats", teamId), "", ""); 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) {
|
||||
if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v/members/ids", teamId), ArrayToJson(userIds)); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
|
@ -1820,6 +2005,7 @@ func (c *Client) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoj
|
|||
|
||||
rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetEmojiRoute()+"/create", body)
|
||||
rq.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
rq.Close = true
|
||||
|
||||
if len(c.AuthToken) > 0 {
|
||||
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
|
||||
|
@ -1862,6 +2048,7 @@ func (c *Client) UploadCertificateFile(data []byte, contentType string) *AppErro
|
|||
url := c.ApiUrl + "/admin/add_certificate"
|
||||
rq, _ := http.NewRequest("POST", url, bytes.NewReader(data))
|
||||
rq.Header.Set("Content-Type", contentType)
|
||||
rq.Close = true
|
||||
|
||||
if len(c.AuthToken) > 0 {
|
||||
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
|
||||
|
@ -1898,3 +2085,28 @@ func (c *Client) SamlCertificateStatus(filename string) (map[string]interface{},
|
|||
return StringInterfaceFromJson(r.Body), nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetWebrtcToken if Successful returns a map with a valid token, stun server and turn server with credentials to use with
|
||||
// the Mattermost WebRTC service, otherwise returns an AppError. Must be authenticated user.
|
||||
func (c *Client) GetWebrtcToken() (map[string]string, *AppError) {
|
||||
if r, err := c.DoApiPost("/webrtc/token", ""); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
return MapFromJson(r.Body), nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetFileInfosForPost returns a list of FileInfo objects for a given post id, if successful.
|
||||
// Otherwise, it returns an error.
|
||||
func (c *Client) GetFileInfosForPost(channelId string, postId string, etag string) ([]*FileInfo, *AppError) {
|
||||
c.clearExtraProperties()
|
||||
|
||||
if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/get_file_infos", postId), "", etag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
defer closeBody(r)
|
||||
c.fillInExtraProperties(r)
|
||||
return FileInfosFromJson(r.Body), nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ type CompliancePost struct {
|
|||
PostType string
|
||||
PostProps string
|
||||
PostHashtags string
|
||||
PostFilenames string
|
||||
PostFileIds string
|
||||
}
|
||||
|
||||
func CompliancePostHeader() []string {
|
||||
|
@ -60,7 +60,7 @@ func CompliancePostHeader() []string {
|
|||
"PostType",
|
||||
"PostProps",
|
||||
"PostHashtags",
|
||||
"PostFilenames",
|
||||
"PostFileIds",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +99,6 @@ func (me *CompliancePost) Row() []string {
|
|||
me.PostType,
|
||||
me.PostProps,
|
||||
me.PostHashtags,
|
||||
me.PostFilenames,
|
||||
me.PostFileIds,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,14 @@ const (
|
|||
type ServiceSettings struct {
|
||||
SiteURL *string
|
||||
ListenAddress string
|
||||
ConnectionSecurity *string
|
||||
TLSCertFile *string
|
||||
TLSKeyFile *string
|
||||
UseLetsEncrypt *bool
|
||||
LetsEncryptCertificateCacheFile *string
|
||||
Forward80To443 *bool
|
||||
ReadTimeout *int
|
||||
WriteTimeout *int
|
||||
MaximumLoginAttempts int
|
||||
SegmentDeveloperKey string
|
||||
GoogleDeveloperKey string
|
||||
|
@ -147,9 +155,7 @@ type FileSettings struct {
|
|||
AmazonS3Bucket string
|
||||
AmazonS3Region string
|
||||
AmazonS3Endpoint string
|
||||
AmazonS3BucketEndpoint string
|
||||
AmazonS3LocationConstraint *bool
|
||||
AmazonS3LowercaseBucket *bool
|
||||
AmazonS3SSL *bool
|
||||
}
|
||||
|
||||
type EmailSettings struct {
|
||||
|
@ -177,8 +183,9 @@ type EmailSettings struct {
|
|||
}
|
||||
|
||||
type RateLimitSettings struct {
|
||||
EnableRateLimiter bool
|
||||
Enable *bool
|
||||
PerSec int
|
||||
MaxBurst *int
|
||||
MemoryStoreSize int
|
||||
VaryByRemoteAddr bool
|
||||
VaryByHeader string
|
||||
|
@ -205,7 +212,6 @@ type TeamSettings struct {
|
|||
EnableUserCreation bool
|
||||
EnableOpenServer *bool
|
||||
RestrictCreationToDomains string
|
||||
RestrictTeamNames *bool
|
||||
EnableCustomBrand *bool
|
||||
CustomBrandText *string
|
||||
CustomDescriptionText *string
|
||||
|
@ -214,6 +220,7 @@ type TeamSettings struct {
|
|||
RestrictPublicChannelManagement *string
|
||||
RestrictPrivateChannelManagement *string
|
||||
UserStatusAwayTimeout *int64
|
||||
MaxChannelsPerTeam *int64
|
||||
}
|
||||
|
||||
type LdapSettings struct {
|
||||
|
@ -292,6 +299,17 @@ type NativeAppSettings struct {
|
|||
IosAppDownloadLink *string
|
||||
}
|
||||
|
||||
type WebrtcSettings struct {
|
||||
Enable *bool
|
||||
GatewayWebsocketUrl *string
|
||||
GatewayAdminUrl *string
|
||||
GatewayAdminSecret *string
|
||||
StunURI *string
|
||||
TurnURI *string
|
||||
TurnUsername *string
|
||||
TurnSharedKey *string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
ServiceSettings ServiceSettings
|
||||
TeamSettings TeamSettings
|
||||
|
@ -312,6 +330,7 @@ type Config struct {
|
|||
SamlSettings SamlSettings
|
||||
NativeAppSettings NativeAppSettings
|
||||
ClusterSettings ClusterSettings
|
||||
WebrtcSettings WebrtcSettings
|
||||
}
|
||||
|
||||
func (o *Config) ToJson() string {
|
||||
|
@ -353,26 +372,27 @@ func (o *Config) SetDefaults() {
|
|||
o.SqlSettings.AtRestEncryptKey = NewRandomString(32)
|
||||
}
|
||||
|
||||
if o.FileSettings.AmazonS3Endpoint == "" {
|
||||
// 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.AmazonS3LocationConstraint == nil {
|
||||
o.FileSettings.AmazonS3LocationConstraint = new(bool)
|
||||
*o.FileSettings.AmazonS3LocationConstraint = false
|
||||
}
|
||||
|
||||
if o.FileSettings.AmazonS3LowercaseBucket == nil {
|
||||
o.FileSettings.AmazonS3LowercaseBucket = new(bool)
|
||||
*o.FileSettings.AmazonS3LowercaseBucket = false
|
||||
}
|
||||
|
||||
if len(o.EmailSettings.InviteSalt) == 0 {
|
||||
o.EmailSettings.InviteSalt = NewRandomString(32)
|
||||
}
|
||||
|
@ -431,11 +451,6 @@ func (o *Config) SetDefaults() {
|
|||
*o.PasswordSettings.Symbol = false
|
||||
}
|
||||
|
||||
if o.TeamSettings.RestrictTeamNames == nil {
|
||||
o.TeamSettings.RestrictTeamNames = new(bool)
|
||||
*o.TeamSettings.RestrictTeamNames = true
|
||||
}
|
||||
|
||||
if o.TeamSettings.EnableCustomBrand == nil {
|
||||
o.TeamSettings.EnableCustomBrand = new(bool)
|
||||
*o.TeamSettings.EnableCustomBrand = false
|
||||
|
@ -481,6 +496,11 @@ func (o *Config) SetDefaults() {
|
|||
*o.TeamSettings.UserStatusAwayTimeout = 300
|
||||
}
|
||||
|
||||
if o.TeamSettings.MaxChannelsPerTeam == nil {
|
||||
o.TeamSettings.MaxChannelsPerTeam = new(int64)
|
||||
*o.TeamSettings.MaxChannelsPerTeam = 2000
|
||||
}
|
||||
|
||||
if o.EmailSettings.EnableSignInWithEmail == nil {
|
||||
o.EmailSettings.EnableSignInWithEmail = new(bool)
|
||||
|
||||
|
@ -881,6 +901,58 @@ func (o *Config) SetDefaults() {
|
|||
o.NativeAppSettings.IosAppDownloadLink = new(string)
|
||||
*o.NativeAppSettings.IosAppDownloadLink = "https://about.mattermost.com/mattermost-ios-app/"
|
||||
}
|
||||
|
||||
if o.RateLimitSettings.Enable == nil {
|
||||
o.RateLimitSettings.Enable = new(bool)
|
||||
*o.RateLimitSettings.Enable = false
|
||||
}
|
||||
|
||||
if o.RateLimitSettings.MaxBurst == nil {
|
||||
o.RateLimitSettings.MaxBurst = new(int)
|
||||
*o.RateLimitSettings.MaxBurst = 100
|
||||
}
|
||||
|
||||
if o.ServiceSettings.ConnectionSecurity == nil {
|
||||
o.ServiceSettings.ConnectionSecurity = new(string)
|
||||
*o.ServiceSettings.ConnectionSecurity = ""
|
||||
}
|
||||
|
||||
if o.ServiceSettings.TLSKeyFile == nil {
|
||||
o.ServiceSettings.TLSKeyFile = new(string)
|
||||
*o.ServiceSettings.TLSKeyFile = ""
|
||||
}
|
||||
|
||||
if o.ServiceSettings.TLSCertFile == nil {
|
||||
o.ServiceSettings.TLSCertFile = new(string)
|
||||
*o.ServiceSettings.TLSCertFile = ""
|
||||
}
|
||||
|
||||
if o.ServiceSettings.UseLetsEncrypt == nil {
|
||||
o.ServiceSettings.UseLetsEncrypt = new(bool)
|
||||
*o.ServiceSettings.UseLetsEncrypt = false
|
||||
}
|
||||
|
||||
if o.ServiceSettings.LetsEncryptCertificateCacheFile == nil {
|
||||
o.ServiceSettings.LetsEncryptCertificateCacheFile = new(string)
|
||||
*o.ServiceSettings.LetsEncryptCertificateCacheFile = "./config/letsencrypt.cache"
|
||||
}
|
||||
|
||||
if o.ServiceSettings.ReadTimeout == nil {
|
||||
o.ServiceSettings.ReadTimeout = new(int)
|
||||
*o.ServiceSettings.ReadTimeout = 300
|
||||
}
|
||||
|
||||
if o.ServiceSettings.WriteTimeout == nil {
|
||||
o.ServiceSettings.WriteTimeout = new(int)
|
||||
*o.ServiceSettings.WriteTimeout = 300
|
||||
}
|
||||
|
||||
if o.ServiceSettings.Forward80To443 == nil {
|
||||
o.ServiceSettings.Forward80To443 = new(bool)
|
||||
*o.ServiceSettings.Forward80To443 = false
|
||||
}
|
||||
|
||||
o.defaultWebrtcSettings()
|
||||
}
|
||||
|
||||
func (o *Config) IsValid() *AppError {
|
||||
|
@ -911,6 +983,10 @@ func (o *Config) IsValid() *AppError {
|
|||
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_users.app_error", nil, "")
|
||||
}
|
||||
|
||||
if *o.TeamSettings.MaxChannelsPerTeam <= 0 {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_channels.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, "")
|
||||
}
|
||||
|
@ -1083,6 +1159,26 @@ func (o *Config) IsValid() *AppError {
|
|||
return NewLocAppError("Config.IsValid", "model.config.is_valid.sitename_length.app_error", map[string]interface{}{"MaxLength": SITENAME_MAX_LENGTH}, "")
|
||||
}
|
||||
|
||||
if *o.RateLimitSettings.MaxBurst <= 0 {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.max_burst.app_error", nil, "")
|
||||
}
|
||||
|
||||
if err := o.isValidWebrtcSettings(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !(*o.ServiceSettings.ConnectionSecurity == CONN_SECURITY_NONE || *o.ServiceSettings.ConnectionSecurity == CONN_SECURITY_TLS) {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.webserver_security.app_error", nil, "")
|
||||
}
|
||||
|
||||
if *o.ServiceSettings.ReadTimeout <= 0 {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.read_timeout.app_error", nil, "")
|
||||
}
|
||||
|
||||
if *o.ServiceSettings.WriteTimeout <= 0 {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.write_timeout.app_error", nil, "")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1121,3 +1217,71 @@ func (o *Config) Sanitize() {
|
|||
o.SqlSettings.DataSourceReplicas[i] = FAKE_SETTING
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Config) defaultWebrtcSettings() {
|
||||
if o.WebrtcSettings.Enable == nil {
|
||||
o.WebrtcSettings.Enable = new(bool)
|
||||
*o.WebrtcSettings.Enable = false
|
||||
}
|
||||
|
||||
if o.WebrtcSettings.GatewayWebsocketUrl == nil {
|
||||
o.WebrtcSettings.GatewayWebsocketUrl = new(string)
|
||||
*o.WebrtcSettings.GatewayWebsocketUrl = ""
|
||||
}
|
||||
|
||||
if o.WebrtcSettings.GatewayAdminUrl == nil {
|
||||
o.WebrtcSettings.GatewayAdminUrl = new(string)
|
||||
*o.WebrtcSettings.GatewayAdminUrl = ""
|
||||
}
|
||||
|
||||
if o.WebrtcSettings.GatewayAdminSecret == nil {
|
||||
o.WebrtcSettings.GatewayAdminSecret = new(string)
|
||||
*o.WebrtcSettings.GatewayAdminSecret = ""
|
||||
}
|
||||
|
||||
if o.WebrtcSettings.StunURI == nil {
|
||||
o.WebrtcSettings.StunURI = new(string)
|
||||
*o.WebrtcSettings.StunURI = ""
|
||||
}
|
||||
|
||||
if o.WebrtcSettings.TurnURI == nil {
|
||||
o.WebrtcSettings.TurnURI = new(string)
|
||||
*o.WebrtcSettings.TurnURI = ""
|
||||
}
|
||||
|
||||
if o.WebrtcSettings.TurnUsername == nil {
|
||||
o.WebrtcSettings.TurnUsername = new(string)
|
||||
*o.WebrtcSettings.TurnUsername = ""
|
||||
}
|
||||
|
||||
if o.WebrtcSettings.TurnSharedKey == nil {
|
||||
o.WebrtcSettings.TurnSharedKey = new(string)
|
||||
*o.WebrtcSettings.TurnSharedKey = ""
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Config) isValidWebrtcSettings() *AppError {
|
||||
if *o.WebrtcSettings.Enable {
|
||||
if len(*o.WebrtcSettings.GatewayWebsocketUrl) == 0 || !IsValidWebsocketUrl(*o.WebrtcSettings.GatewayWebsocketUrl) {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_ws_url.app_error", nil, "")
|
||||
} else if len(*o.WebrtcSettings.GatewayAdminUrl) == 0 || !IsValidHttpUrl(*o.WebrtcSettings.GatewayAdminUrl) {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_admin_url.app_error", nil, "")
|
||||
} else if len(*o.WebrtcSettings.GatewayAdminSecret) == 0 {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_gateway_admin_secret.app_error", nil, "")
|
||||
} else if len(*o.WebrtcSettings.StunURI) != 0 && !IsValidTurnOrStunServer(*o.WebrtcSettings.StunURI) {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_stun_uri.app_error", nil, "")
|
||||
} else if len(*o.WebrtcSettings.TurnURI) != 0 {
|
||||
if !IsValidTurnOrStunServer(*o.WebrtcSettings.TurnURI) {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_uri.app_error", nil, "")
|
||||
}
|
||||
if len(*o.WebrtcSettings.TurnUsername) == 0 {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_username.app_error", nil, "")
|
||||
} else if len(*o.WebrtcSettings.TurnSharedKey) == 0 {
|
||||
return NewLocAppError("Config.IsValid", "model.config.is_valid.webrtc_turn_shared_key.app_error", nil, "")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ var (
|
|||
)
|
||||
|
||||
type FileUploadResponse struct {
|
||||
Filenames []string `json:"filenames"`
|
||||
FileInfos []*FileInfo `json:"file_infos"`
|
||||
ClientIds []string `json:"client_ids"`
|
||||
}
|
||||
|
||||
|
|
|
@ -6,54 +6,31 @@ package model
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"image"
|
||||
"image/gif"
|
||||
"io"
|
||||
"mime"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FileInfo struct {
|
||||
Filename string `json:"filename"`
|
||||
Size int `json:"size"`
|
||||
Id string `json:"id"`
|
||||
CreatorId string `json:"user_id"`
|
||||
PostId string `json:"post_id,omitempty"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
DeleteAt int64 `json:"delete_at"`
|
||||
Path string `json:"-"` // not sent back to the client
|
||||
ThumbnailPath string `json:"-"` // not sent back to the client
|
||||
PreviewPath string `json:"-"` // not sent back to the client
|
||||
Name string `json:"name"`
|
||||
Extension string `json:"extension"`
|
||||
Size int64 `json:"size"`
|
||||
MimeType string `json:"mime_type"`
|
||||
HasPreviewImage bool `json:"has_preview_image"`
|
||||
}
|
||||
|
||||
func GetInfoForBytes(filename string, data []byte) (*FileInfo, *AppError) {
|
||||
size := len(data)
|
||||
|
||||
var mimeType string
|
||||
extension := filepath.Ext(filename)
|
||||
isImage := IsFileExtImage(extension)
|
||||
if isImage {
|
||||
mimeType = GetImageMimeType(extension)
|
||||
} else {
|
||||
mimeType = mime.TypeByExtension(extension)
|
||||
}
|
||||
|
||||
if extension != "" && extension[0] == '.' {
|
||||
// the client expects a file extension without the leading period
|
||||
extension = extension[1:]
|
||||
}
|
||||
|
||||
hasPreviewImage := isImage
|
||||
if mimeType == "image/gif" {
|
||||
// just show the gif itself instead of a preview image for animated gifs
|
||||
if gifImage, err := gif.DecodeAll(bytes.NewReader(data)); err != nil {
|
||||
return nil, NewLocAppError("GetInfoForBytes", "model.file_info.get.gif.app_error", nil, "filename="+filename)
|
||||
} else {
|
||||
hasPreviewImage = len(gifImage.Image) == 1
|
||||
}
|
||||
}
|
||||
|
||||
return &FileInfo{
|
||||
Filename: filename,
|
||||
Size: size,
|
||||
Extension: extension,
|
||||
MimeType: mimeType,
|
||||
HasPreviewImage: hasPreviewImage,
|
||||
}, nil
|
||||
Width int `json:"width,omitempty"`
|
||||
Height int `json:"height,omitempty"`
|
||||
HasPreviewImage bool `json:"has_preview_image,omitempty"`
|
||||
}
|
||||
|
||||
func (info *FileInfo) ToJson() string {
|
||||
|
@ -75,3 +52,123 @@ func FileInfoFromJson(data io.Reader) *FileInfo {
|
|||
return &info
|
||||
}
|
||||
}
|
||||
|
||||
func FileInfosToJson(infos []*FileInfo) string {
|
||||
b, err := json.Marshal(infos)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func FileInfosFromJson(data io.Reader) []*FileInfo {
|
||||
decoder := json.NewDecoder(data)
|
||||
|
||||
var infos []*FileInfo
|
||||
if err := decoder.Decode(&infos); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
return infos
|
||||
}
|
||||
}
|
||||
|
||||
func (o *FileInfo) PreSave() {
|
||||
if o.Id == "" {
|
||||
o.Id = NewId()
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
o.CreateAt = GetMillis()
|
||||
o.UpdateAt = o.CreateAt
|
||||
}
|
||||
}
|
||||
|
||||
func (o *FileInfo) IsValid() *AppError {
|
||||
if len(o.Id) != 26 {
|
||||
return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.id.app_error", nil, "")
|
||||
}
|
||||
|
||||
if len(o.CreatorId) != 26 {
|
||||
return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.user_id.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if len(o.PostId) != 0 && len(o.PostId) != 26 {
|
||||
return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.post_id.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if o.CreateAt == 0 {
|
||||
return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.create_at.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if o.UpdateAt == 0 {
|
||||
return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.update_at.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if o.Path == "" {
|
||||
return NewLocAppError("FileInfo.IsValid", "model.file_info.is_valid.path.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *FileInfo) IsImage() bool {
|
||||
return strings.HasPrefix(o.MimeType, "image")
|
||||
}
|
||||
|
||||
func GetInfoForBytes(name string, data []byte) (*FileInfo, *AppError) {
|
||||
info := &FileInfo{
|
||||
Name: name,
|
||||
Size: int64(len(data)),
|
||||
}
|
||||
var err *AppError
|
||||
|
||||
extension := strings.ToLower(filepath.Ext(name))
|
||||
info.MimeType = mime.TypeByExtension(extension)
|
||||
|
||||
if extension != "" && extension[0] == '.' {
|
||||
// The client expects a file extension without the leading period
|
||||
info.Extension = extension[1:]
|
||||
} else {
|
||||
info.Extension = extension
|
||||
}
|
||||
|
||||
if info.IsImage() {
|
||||
// Only set the width and height if it's actually an image that we can understand
|
||||
if config, _, err := image.DecodeConfig(bytes.NewReader(data)); err == nil {
|
||||
info.Width = config.Width
|
||||
info.Height = config.Height
|
||||
|
||||
if info.MimeType == "image/gif" {
|
||||
// Just show the gif itself instead of a preview image for animated gifs
|
||||
if gifConfig, err := gif.DecodeAll(bytes.NewReader(data)); err != nil {
|
||||
// Still return the rest of the info even though it doesn't appear to be an actual gif
|
||||
info.HasPreviewImage = true
|
||||
err = NewLocAppError("GetInfoForBytes", "model.file_info.get.gif.app_error", nil, "name="+name)
|
||||
} else {
|
||||
info.HasPreviewImage = len(gifConfig.Image) == 1
|
||||
}
|
||||
} else {
|
||||
info.HasPreviewImage = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return info, err
|
||||
}
|
||||
|
||||
func GetEtagForFileInfos(infos []*FileInfo) string {
|
||||
if len(infos) == 0 {
|
||||
return Etag()
|
||||
}
|
||||
|
||||
var maxUpdateAt int64
|
||||
|
||||
for _, info := range infos {
|
||||
if info.UpdateAt > maxUpdateAt {
|
||||
maxUpdateAt = info.UpdateAt
|
||||
}
|
||||
}
|
||||
|
||||
return Etag(infos[0].PostId, maxUpdateAt)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ type InitialLoad struct {
|
|||
User *User `json:"user"`
|
||||
TeamMembers []*TeamMember `json:"team_members"`
|
||||
Teams []*Team `json:"teams"`
|
||||
DirectProfiles map[string]*User `json:"direct_profiles"`
|
||||
Preferences Preferences `json:"preferences"`
|
||||
ClientCfg map[string]string `json:"client_cfg"`
|
||||
LicenseCfg map[string]string `json:"license_cfg"`
|
||||
|
|
|
@ -43,6 +43,7 @@ type Features struct {
|
|||
MHPNS *bool `json:"mhpns"`
|
||||
SAML *bool `json:"saml"`
|
||||
PasswordRequirements *bool `json:"password_requirements"`
|
||||
// after we enabled more features for webrtc we'll need to control them with this
|
||||
FutureFeatures *bool `json:"future_features"`
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,8 @@ type Post struct {
|
|||
Type string `json:"type"`
|
||||
Props StringInterface `json:"props"`
|
||||
Hashtags string `json:"hashtags"`
|
||||
Filenames StringArray `json:"filenames"`
|
||||
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:"-"`
|
||||
}
|
||||
|
||||
|
@ -118,6 +119,10 @@ func (o *Post) IsValid() *AppError {
|
|||
return NewLocAppError("Post.IsValid", "model.post.is_valid.filenames.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(ArrayToJson(o.FileIds)) > 150 {
|
||||
return NewLocAppError("Post.IsValid", "model.post.is_valid.file_ids.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if utf8.RuneCountInString(StringInterfaceToJson(o.Props)) > 8000 {
|
||||
return NewLocAppError("Post.IsValid", "model.post.is_valid.props.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
@ -145,15 +150,16 @@ func (o *Post) PreSave() {
|
|||
if o.Filenames == nil {
|
||||
o.Filenames = []string{}
|
||||
}
|
||||
|
||||
if o.FileIds == nil {
|
||||
o.FileIds = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Post) MakeNonNil() {
|
||||
if o.Props == nil {
|
||||
o.Props = make(map[string]interface{})
|
||||
}
|
||||
if o.Filenames == nil {
|
||||
o.Filenames = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Post) AddProp(key string, value interface{}) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
const (
|
||||
SESSION_COOKIE_TOKEN = "MMAUTHTOKEN"
|
||||
SESSION_CACHE_SIZE = 10000
|
||||
SESSION_CACHE_SIZE = 25000
|
||||
SESSION_PROP_PLATFORM = "platform"
|
||||
SESSION_PROP_OS = "os"
|
||||
SESSION_PROP_BROWSER = "browser"
|
||||
|
@ -115,6 +115,10 @@ func (me *Session) IsMobileApp() bool {
|
|||
(strings.HasPrefix(me.DeviceId, PUSH_NOTIFY_APPLE+":") || strings.HasPrefix(me.DeviceId, PUSH_NOTIFY_ANDROID+":"))
|
||||
}
|
||||
|
||||
func (me *Session) GetUserRoles() []string {
|
||||
return strings.Fields(me.Roles)
|
||||
}
|
||||
|
||||
func SessionsToJson(o []*Session) string {
|
||||
if b, err := json.Marshal(o); err != nil {
|
||||
return "[]"
|
||||
|
|
|
@ -12,8 +12,9 @@ const (
|
|||
STATUS_OFFLINE = "offline"
|
||||
STATUS_AWAY = "away"
|
||||
STATUS_ONLINE = "online"
|
||||
STATUS_CACHE_SIZE = 10000
|
||||
STATUS_CACHE_SIZE = 25000
|
||||
STATUS_CHANNEL_TIMEOUT = 20000 // 20 seconds
|
||||
STATUS_MIN_UPDATE_TIME = 120000 // 2 minutes
|
||||
)
|
||||
|
||||
type Status struct {
|
||||
|
|
|
@ -100,7 +100,7 @@ func (o *Team) Etag() string {
|
|||
return Etag(o.Id, o.UpdateAt)
|
||||
}
|
||||
|
||||
func (o *Team) IsValid(restrictTeamNames bool) *AppError {
|
||||
func (o *Team) IsValid() *AppError {
|
||||
|
||||
if len(o.Id) != 26 {
|
||||
return NewLocAppError("Team.IsValid", "model.team.is_valid.id.app_error", nil, "")
|
||||
|
@ -130,7 +130,7 @@ func (o *Team) IsValid(restrictTeamNames bool) *AppError {
|
|||
return NewLocAppError("Team.IsValid", "model.team.is_valid.url.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
if restrictTeamNames && IsReservedTeamName(o.Name) {
|
||||
if IsReservedTeamName(o.Name) {
|
||||
return NewLocAppError("Team.IsValid", "model.team.is_valid.reserved.app_error", nil, "id="+o.Id)
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ func IsValidTeamName(s string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if len(s) <= 3 {
|
||||
if len(s) <= 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,6 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
ROLE_TEAM_ADMIN = "admin"
|
||||
)
|
||||
|
||||
type TeamMember struct {
|
||||
TeamId string `json:"team_id"`
|
||||
UserId string `json:"user_id"`
|
||||
|
@ -59,48 +55,6 @@ func TeamMembersFromJson(data io.Reader) []*TeamMember {
|
|||
}
|
||||
}
|
||||
|
||||
func IsValidTeamRoles(teamRoles string) bool {
|
||||
|
||||
roles := strings.Split(teamRoles, " ")
|
||||
|
||||
for _, r := range roles {
|
||||
if !isValidTeamRole(r) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func isValidTeamRole(role string) bool {
|
||||
if role == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
if role == ROLE_TEAM_ADMIN {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func IsInTeamRole(teamRoles string, inRole string) bool {
|
||||
roles := strings.Split(teamRoles, " ")
|
||||
|
||||
for _, r := range roles {
|
||||
if r == inRole {
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *TeamMember) IsTeamAdmin() bool {
|
||||
return IsInTeamRole(o.Roles, ROLE_TEAM_ADMIN)
|
||||
}
|
||||
|
||||
func (o *TeamMember) IsValid() *AppError {
|
||||
|
||||
if len(o.TeamId) != 26 {
|
||||
|
@ -111,11 +65,12 @@ func (o *TeamMember) IsValid() *AppError {
|
|||
return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.user_id.app_error", nil, "")
|
||||
}
|
||||
|
||||
for _, role := range strings.Split(o.Roles, " ") {
|
||||
if !(role == "" || role == ROLE_TEAM_ADMIN) {
|
||||
return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.role.app_error", nil, "role="+role)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *TeamMember) PreUpdate() {
|
||||
}
|
||||
|
||||
func (o *TeamMember) GetRoles() []string {
|
||||
return strings.Fields(o.Roles)
|
||||
}
|
||||
|
|
|
@ -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 TeamStats struct {
|
||||
TeamId string `json:"team_id"`
|
||||
TotalMemberCount int64 `json:"total_member_count"`
|
||||
ActiveMemberCount int64 `json:"active_member_count"`
|
||||
}
|
||||
|
||||
func (o *TeamStats) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func TeamStatsFromJson(data io.Reader) *TeamStats {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o TeamStats
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
ROLE_SYSTEM_ADMIN = "system_admin"
|
||||
USER_NOTIFY_ALL = "all"
|
||||
USER_NOTIFY_MENTION = "mention"
|
||||
USER_NOTIFY_NONE = "none"
|
||||
|
@ -233,14 +232,15 @@ func (u *User) Sanitize(options map[string]bool) {
|
|||
if len(options) != 0 && !options["passwordupdate"] {
|
||||
u.LastPasswordUpdate = 0
|
||||
}
|
||||
if len(options) != 0 && !options["authservice"] {
|
||||
u.AuthService = ""
|
||||
}
|
||||
}
|
||||
|
||||
func (u *User) ClearNonProfileFields() {
|
||||
u.Password = ""
|
||||
u.AuthData = new(string)
|
||||
*u.AuthData = ""
|
||||
u.AuthService = ""
|
||||
u.MfaActive = false
|
||||
u.MfaSecret = ""
|
||||
u.EmailVerified = false
|
||||
u.AllowMarketing = false
|
||||
|
@ -319,9 +319,17 @@ func (u *User) GetDisplayNameForPreference(nameFormat string) string {
|
|||
return displayName
|
||||
}
|
||||
|
||||
func (u *User) GetRoles() []string {
|
||||
return strings.Fields(u.Roles)
|
||||
}
|
||||
|
||||
func (u *User) GetRawRoles() string {
|
||||
return u.Roles
|
||||
}
|
||||
|
||||
func IsValidUserRoles(userRoles string) bool {
|
||||
|
||||
roles := strings.Split(userRoles, " ")
|
||||
roles := strings.Fields(userRoles)
|
||||
|
||||
for _, r := range roles {
|
||||
if !isValidRole(r) {
|
||||
|
@ -329,19 +337,17 @@ func IsValidUserRoles(userRoles string) bool {
|
|||
}
|
||||
}
|
||||
|
||||
// Exclude just the system_admin role explicitly to prevent mistakes
|
||||
if len(roles) == 1 && roles[0] == "system_admin" {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func isValidRole(role string) bool {
|
||||
if role == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
if role == ROLE_SYSTEM_ADMIN {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
func isValidRole(roleId string) bool {
|
||||
_, ok := BuiltInRoles[roleId]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Make sure you acually want to use this function. In context.go there are functions to check permissions
|
||||
|
@ -411,6 +417,26 @@ func UserMapFromJson(data io.Reader) map[string]*User {
|
|||
}
|
||||
}
|
||||
|
||||
func UserListToJson(u []*User) string {
|
||||
b, err := json.Marshal(u)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
func UserListFromJson(data io.Reader) []*User {
|
||||
decoder := json.NewDecoder(data)
|
||||
var users []*User
|
||||
err := decoder.Decode(&users)
|
||||
if err == nil {
|
||||
return users
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// HashPassword generates a hash using the bcrypt.GenerateFromPassword
|
||||
func HashPassword(password string) string {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type UserSearch struct {
|
||||
Term string `json:"term"`
|
||||
TeamId string `json:"team_id"`
|
||||
InChannelId string `json:"in_channel_id"`
|
||||
NotInChannelId string `json:"not_in_channel_id"`
|
||||
AllowInactive bool `json:"allow_inactive"`
|
||||
}
|
||||
|
||||
// ToJson convert a User to a json string
|
||||
func (u *UserSearch) ToJson() string {
|
||||
b, err := json.Marshal(u)
|
||||
if err != nil {
|
||||
return ""
|
||||
} else {
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
// UserSearchFromJson will decode the input and return a User
|
||||
func UserSearchFromJson(data io.Reader) *UserSearch {
|
||||
decoder := json.NewDecoder(data)
|
||||
var us UserSearch
|
||||
err := decoder.Decode(&us)
|
||||
if err == nil {
|
||||
return &us
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"regexp"
|
||||
|
@ -74,13 +75,21 @@ func (er *AppError) ToJson() string {
|
|||
|
||||
// AppErrorFromJson will decode the input and return an AppError
|
||||
func AppErrorFromJson(data io.Reader) *AppError {
|
||||
decoder := json.NewDecoder(data)
|
||||
str := ""
|
||||
bytes, rerr := ioutil.ReadAll(data)
|
||||
if rerr != nil {
|
||||
str = rerr.Error()
|
||||
} else {
|
||||
str = string(bytes)
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(strings.NewReader(str))
|
||||
var er AppError
|
||||
err := decoder.Decode(&er)
|
||||
if err == nil {
|
||||
return &er
|
||||
} else {
|
||||
return NewLocAppError("AppErrorFromJson", "model.utils.decode_json.app_error", nil, err.Error())
|
||||
return NewLocAppError("AppErrorFromJson", "model.utils.decode_json.app_error", nil, "body: "+str)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,6 +175,23 @@ func ArrayFromJson(data io.Reader) []string {
|
|||
}
|
||||
}
|
||||
|
||||
func ArrayFromInterface(data interface{}) []string {
|
||||
stringArray := []string{}
|
||||
|
||||
dataArray, ok := data.([]interface{})
|
||||
if !ok {
|
||||
return stringArray
|
||||
}
|
||||
|
||||
for _, v := range dataArray {
|
||||
if str, ok := v.(string); ok {
|
||||
stringArray = append(stringArray, str)
|
||||
}
|
||||
}
|
||||
|
||||
return stringArray
|
||||
}
|
||||
|
||||
func StringInterfaceToJson(objmap map[string]interface{}) string {
|
||||
if b, err := json.Marshal(objmap); err != nil {
|
||||
return ""
|
||||
|
@ -227,58 +253,15 @@ func IsValidEmail(email string) bool {
|
|||
}
|
||||
|
||||
var reservedName = []string{
|
||||
"www",
|
||||
"web",
|
||||
"signup",
|
||||
"login",
|
||||
"admin",
|
||||
"support",
|
||||
"notify",
|
||||
"test",
|
||||
"demo",
|
||||
"mail",
|
||||
"team",
|
||||
"channel",
|
||||
"internal",
|
||||
"localhost",
|
||||
"dockerhost",
|
||||
"stag",
|
||||
"post",
|
||||
"cluster",
|
||||
"api",
|
||||
"oauth",
|
||||
}
|
||||
|
||||
var wwwStart = regexp.MustCompile(`^www`)
|
||||
var betaStart = regexp.MustCompile(`^beta`)
|
||||
var ciStart = regexp.MustCompile(`^ci`)
|
||||
|
||||
func GetSubDomain(s string) (string, string) {
|
||||
s = strings.Replace(s, "http://", "", 1)
|
||||
s = strings.Replace(s, "https://", "", 1)
|
||||
|
||||
match := wwwStart.MatchString(s)
|
||||
if match {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
match = betaStart.MatchString(s)
|
||||
if match {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
match = ciStart.MatchString(s)
|
||||
if match {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
parts := strings.Split(s, ".")
|
||||
|
||||
if len(parts) != 3 {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
||||
func IsValidChannelIdentifier(s string) bool {
|
||||
|
||||
if !IsValidAlphaNum(s, true) {
|
||||
|
@ -413,6 +396,18 @@ func IsValidHttpsUrl(rawUrl string) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func IsValidTurnOrStunServer(rawUri string) bool {
|
||||
if strings.Index(rawUri, "turn:") != 0 && strings.Index(rawUri, "stun:") != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if _, err := url.ParseRequestURI(rawUri); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func IsSafeLink(link *string) bool {
|
||||
if link != nil {
|
||||
if IsValidHttpUrl(*link) {
|
||||
|
@ -426,3 +421,15 @@ func IsSafeLink(link *string) bool {
|
|||
|
||||
return true
|
||||
}
|
||||
|
||||
func IsValidWebsocketUrl(rawUrl string) bool {
|
||||
if strings.Index(rawUrl, "ws://") != 0 && strings.Index(rawUrl, "wss://") != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if _, err := url.ParseRequestURI(rawUrl); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -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.5.0",
|
||||
"3.4.0",
|
||||
"3.3.0",
|
||||
"3.2.0",
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
type GatewayResponse struct {
|
||||
Status string `json:"janus"`
|
||||
}
|
||||
|
||||
func GatewayResponseFromJson(data io.Reader) *GatewayResponse {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o GatewayResponse
|
||||
err := decoder.Decode(&o)
|
||||
if err == nil {
|
||||
return &o
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ package model
|
|||
import (
|
||||
"encoding/json"
|
||||
"github.com/gorilla/websocket"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type WebSocketClient struct {
|
||||
|
@ -17,19 +16,18 @@ type WebSocketClient struct {
|
|||
Sequence int64 // The ever-incrementing sequence attached to each WebSocket action
|
||||
EventChannel chan *WebSocketEvent
|
||||
ResponseChannel chan *WebSocketResponse
|
||||
ListenError *AppError
|
||||
}
|
||||
|
||||
// NewWebSocketClient constructs a new WebSocket client with convienence
|
||||
// methods for talking to the server.
|
||||
func NewWebSocketClient(url, authToken string) (*WebSocketClient, *AppError) {
|
||||
header := http.Header{}
|
||||
header.Set(HEADER_AUTH, "BEARER "+authToken)
|
||||
conn, _, err := websocket.DefaultDialer.Dial(url+API_URL_SUFFIX+"/users/websocket", header)
|
||||
conn, _, err := websocket.DefaultDialer.Dial(url+API_URL_SUFFIX+"/users/websocket", nil)
|
||||
if err != nil {
|
||||
return nil, NewLocAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error())
|
||||
}
|
||||
|
||||
return &WebSocketClient{
|
||||
client := &WebSocketClient{
|
||||
url,
|
||||
url + API_URL_SUFFIX,
|
||||
conn,
|
||||
|
@ -37,19 +35,26 @@ func NewWebSocketClient(url, authToken string) (*WebSocketClient, *AppError) {
|
|||
1,
|
||||
make(chan *WebSocketEvent, 100),
|
||||
make(chan *WebSocketResponse, 100),
|
||||
}, nil
|
||||
nil,
|
||||
}
|
||||
|
||||
client.SendMessage(WEBSOCKET_AUTHENTICATION_CHALLENGE, map[string]interface{}{"token": authToken})
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (wsc *WebSocketClient) Connect() *AppError {
|
||||
header := http.Header{}
|
||||
header.Set(HEADER_AUTH, "BEARER "+wsc.AuthToken)
|
||||
|
||||
var err error
|
||||
wsc.Conn, _, err = websocket.DefaultDialer.Dial(wsc.ApiUrl+"/users/websocket", header)
|
||||
wsc.Conn, _, err = websocket.DefaultDialer.Dial(wsc.ApiUrl+"/users/websocket", nil)
|
||||
if err != nil {
|
||||
return NewLocAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error())
|
||||
}
|
||||
|
||||
wsc.EventChannel = make(chan *WebSocketEvent, 100)
|
||||
wsc.ResponseChannel = make(chan *WebSocketResponse, 100)
|
||||
|
||||
wsc.SendMessage(WEBSOCKET_AUTHENTICATION_CHALLENGE, map[string]interface{}{"token": wsc.AuthToken})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -59,10 +64,20 @@ func (wsc *WebSocketClient) Close() {
|
|||
|
||||
func (wsc *WebSocketClient) Listen() {
|
||||
go func() {
|
||||
defer func() {
|
||||
wsc.Conn.Close()
|
||||
close(wsc.EventChannel)
|
||||
close(wsc.ResponseChannel)
|
||||
}()
|
||||
|
||||
for {
|
||||
var rawMsg json.RawMessage
|
||||
var err error
|
||||
if _, rawMsg, err = wsc.Conn.ReadMessage(); err != nil {
|
||||
if !websocket.IsCloseError(err, websocket.CloseNormalClosure, websocket.CloseNoStatusReceived) {
|
||||
wsc.ListenError = NewLocAppError("NewWebSocketClient", "model.websocket_client.connect_fail.app_error", nil, err.Error())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -77,6 +92,7 @@ func (wsc *WebSocketClient) Listen() {
|
|||
wsc.ResponseChannel <- &response
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -107,3 +123,12 @@ func (wsc *WebSocketClient) UserTyping(channelId, parentId string) {
|
|||
func (wsc *WebSocketClient) GetStatuses() {
|
||||
wsc.SendMessage("get_statuses", nil)
|
||||
}
|
||||
|
||||
// GetStatusesByIds will fetch certain user statuses based on ids and return
|
||||
// a map of string statuses using user id as the key
|
||||
func (wsc *WebSocketClient) GetStatusesByIds(userIds []string) {
|
||||
data := map[string]interface{}{
|
||||
"user_ids": userIds,
|
||||
}
|
||||
wsc.SendMessage("get_statuses_by_ids", data)
|
||||
}
|
||||
|
|
|
@ -25,33 +25,57 @@ const (
|
|||
WEBSOCKET_EVENT_EPHEMERAL_MESSAGE = "ephemeral_message"
|
||||
WEBSOCKET_EVENT_STATUS_CHANGE = "status_change"
|
||||
WEBSOCKET_EVENT_HELLO = "hello"
|
||||
WEBSOCKET_EVENT_WEBRTC = "webrtc"
|
||||
WEBSOCKET_AUTHENTICATION_CHALLENGE = "authentication_challenge"
|
||||
)
|
||||
|
||||
type WebSocketMessage interface {
|
||||
ToJson() string
|
||||
IsValid() bool
|
||||
DoPreComputeJson()
|
||||
GetPreComputeJson() []byte
|
||||
}
|
||||
|
||||
type WebsocketBroadcast struct {
|
||||
OmitUsers map[string]bool `json:"omit_users"` // broadcast is omitted for users listed here
|
||||
UserId string `json:"user_id"` // broadcast only occurs for this user
|
||||
ChannelId string `json:"channel_id"` // broadcast only occurs for users in this channel
|
||||
TeamId string `json:"team_id"` // broadcast only occurs for users in this team
|
||||
}
|
||||
|
||||
type WebSocketEvent struct {
|
||||
TeamId string `json:"team_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
UserId string `json:"user_id"`
|
||||
Event string `json:"event"`
|
||||
Data map[string]interface{} `json:"data"`
|
||||
Broadcast *WebsocketBroadcast `json:"broadcast"`
|
||||
PreComputeJson []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *WebSocketEvent) Add(key string, value interface{}) {
|
||||
m.Data[key] = value
|
||||
}
|
||||
|
||||
func NewWebSocketEvent(teamId string, channelId string, userId string, event string) *WebSocketEvent {
|
||||
return &WebSocketEvent{TeamId: teamId, ChannelId: channelId, UserId: userId, Event: event, Data: make(map[string]interface{})}
|
||||
func NewWebSocketEvent(event, teamId, channelId, userId string, omitUsers map[string]bool) *WebSocketEvent {
|
||||
return &WebSocketEvent{Event: event, Data: make(map[string]interface{}),
|
||||
Broadcast: &WebsocketBroadcast{TeamId: teamId, ChannelId: channelId, UserId: userId, OmitUsers: omitUsers}}
|
||||
}
|
||||
|
||||
func (o *WebSocketEvent) IsValid() bool {
|
||||
return o.Event != ""
|
||||
}
|
||||
|
||||
func (o *WebSocketEvent) DoPreComputeJson() {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
o.PreComputeJson = []byte("")
|
||||
} else {
|
||||
o.PreComputeJson = b
|
||||
}
|
||||
}
|
||||
|
||||
func (o *WebSocketEvent) GetPreComputeJson() []byte {
|
||||
return o.PreComputeJson
|
||||
}
|
||||
|
||||
func (o *WebSocketEvent) ToJson() string {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
|
@ -77,6 +101,7 @@ type WebSocketResponse struct {
|
|||
SeqReply int64 `json:"seq_reply,omitempty"`
|
||||
Data map[string]interface{} `json:"data,omitempty"`
|
||||
Error *AppError `json:"error,omitempty"`
|
||||
PreComputeJson []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *WebSocketResponse) Add(key string, value interface{}) {
|
||||
|
@ -104,6 +129,19 @@ func (o *WebSocketResponse) ToJson() string {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *WebSocketResponse) DoPreComputeJson() {
|
||||
b, err := json.Marshal(o)
|
||||
if err != nil {
|
||||
o.PreComputeJson = []byte("")
|
||||
} else {
|
||||
o.PreComputeJson = b
|
||||
}
|
||||
}
|
||||
|
||||
func (o *WebSocketResponse) GetPreComputeJson() []byte {
|
||||
return o.PreComputeJson
|
||||
}
|
||||
|
||||
func WebSocketResponseFromJson(data io.Reader) *WebSocketResponse {
|
||||
decoder := json.NewDecoder(data)
|
||||
var o WebSocketResponse
|
||||
|
|
|
@ -87,8 +87,8 @@
|
|||
"importpath": "github.com/mattermost/platform/einterfaces",
|
||||
"repository": "https://github.com/mattermost/platform",
|
||||
"vcs": "git",
|
||||
"revision": "57f25fa59c71821cc38fd220b133aa6a40815e12",
|
||||
"branch": "release-3.4",
|
||||
"revision": "b55ec6148caa93d54b660afe55408c643d217108",
|
||||
"branch": "release-3.5",
|
||||
"path": "/einterfaces",
|
||||
"notests": true
|
||||
},
|
||||
|
@ -96,8 +96,8 @@
|
|||
"importpath": "github.com/mattermost/platform/model",
|
||||
"repository": "https://github.com/mattermost/platform",
|
||||
"vcs": "git",
|
||||
"revision": "57f25fa59c71821cc38fd220b133aa6a40815e12",
|
||||
"branch": "release-3.4",
|
||||
"revision": "b55ec6148caa93d54b660afe55408c643d217108",
|
||||
"branch": "release-3.5",
|
||||
"path": "/model",
|
||||
"notests": true
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue