Sync with mattermost 3.2.0

This commit is contained in:
Wim 2016-07-22 23:14:13 +02:00
parent 28244ffd9a
commit 911c597377
15 changed files with 640 additions and 58 deletions

View File

@ -0,0 +1,22 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
import (
"github.com/mattermost/platform/model"
)
type EmojiInterface interface {
CanUserCreateEmoji(string, []*model.TeamMember) bool
}
var theEmojiInterface EmojiInterface
func RegisterEmojiInterface(newInterface EmojiInterface) {
theEmojiInterface = newInterface
}
func GetEmojiInterface() EmojiInterface {
return theEmojiInterface
}

View File

@ -0,0 +1,25 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
import (
"github.com/mattermost/platform/model"
)
type SamlInterface interface {
ConfigureSP() *model.AppError
BuildRequest(relayState string) (*model.SamlAuthRequest, *model.AppError)
DoLogin(encodedXML string, relayState map[string]string) (*model.User, *model.AppError)
GetMetadata() (string, *model.AppError)
}
var theSamlInterface SamlInterface
func RegisterSamlInterface(newInterface SamlInterface) {
theSamlInterface = newInterface
}
func GetSamlInterface() SamlInterface {
return theSamlInterface
}

View File

@ -7,7 +7,9 @@ import (
"bytes" "bytes"
"fmt" "fmt"
l4g "github.com/alecthomas/log4go" l4g "github.com/alecthomas/log4go"
"io"
"io/ioutil" "io/ioutil"
"mime/multipart"
"net/http" "net/http"
"net/url" "net/url"
"strconv" "strconv"
@ -106,6 +108,10 @@ func (c *Client) GetChannelNameRoute(channelName string) string {
return fmt.Sprintf("/teams/%v/channels/name/%v", c.GetTeamId(), channelName) return fmt.Sprintf("/teams/%v/channels/name/%v", c.GetTeamId(), channelName)
} }
func (c *Client) GetEmojiRoute() string {
return "/emoji"
}
func (c *Client) GetGeneralRoute() string { func (c *Client) GetGeneralRoute() string {
return "/general" return "/general"
} }
@ -185,6 +191,17 @@ func (c *Client) Must(result *Result, err *AppError) *Result {
return result return result
} }
// MustGeneric is a convenience function used for testing.
func (c *Client) MustGeneric(result interface{}, err *AppError) interface{} {
if err != nil {
l4g.Close()
time.Sleep(time.Second)
panic(err)
}
return result
}
// CheckStatusOK is a convenience function for checking the return of Web Service // CheckStatusOK is a convenience function for checking the return of Web Service
// call that return the a map of status=OK. // call that return the a map of status=OK.
func (c *Client) CheckStatusOK(r *http.Response) bool { func (c *Client) CheckStatusOK(r *http.Response) bool {
@ -328,10 +345,18 @@ func (c *Client) FindTeamByName(name string) (*Result, *AppError) {
} }
} }
func (c *Client) AddUserToTeam(userId string) (*Result, *AppError) { // Adds a user directly to the team without sending an invite.
// The teamId and userId are required. You must be a valid member of the team and/or
// have the correct role to add new users to the team. Returns a map of user_id=userId
// if successful, otherwise returns an AppError.
func (c *Client) AddUserToTeam(teamId string, userId string) (*Result, *AppError) {
if len(teamId) == 0 {
teamId = c.GetTeamId()
}
data := make(map[string]string) data := make(map[string]string)
data["user_id"] = userId data["user_id"] = userId
if r, err := c.DoApiPost(c.GetTeamRoute()+"/add_user_to_team", MapToJson(data)); err != nil { if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v", teamId)+"/add_user_to_team", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r) defer closeBody(r)
@ -354,6 +379,26 @@ func (c *Client) AddUserToTeamFromInvite(hash, dataToHash, inviteId string) (*Re
} }
} }
// Removes a user directly from the team.
// The teamId and userId are required. You must be a valid member of the team and/or
// have the correct role to remove a user from the team. Returns a map of user_id=userId
// if successful, otherwise returns an AppError.
func (c *Client) RemoveUserFromTeam(teamId string, userId string) (*Result, *AppError) {
if len(teamId) == 0 {
teamId = c.GetTeamId()
}
data := make(map[string]string)
data["user_id"] = userId
if r, err := c.DoApiPost(fmt.Sprintf("/teams/%v", teamId)+"/remove_user_from_team", MapToJson(data)); err != nil {
return nil, err
} else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil
}
}
func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) { func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetTeamRoute()+"/invite_members", invites.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/invite_members", invites.ToJson()); err != nil {
return nil, err return nil, err
@ -843,6 +888,20 @@ func (c *Client) GetSystemAnalytics(name string) (*Result, *AppError) {
} }
} }
// Initiate immediate synchronization of LDAP users.
// The synchronization will be performed asynchronously and this function will
// always return OK unless you don't have permissions.
// You must be the system administrator to use this function.
func (c *Client) LdapSyncNow() (*Result, *AppError) {
if r, err := c.DoApiPost("/admin/ldap_sync_now", ""); 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) CreateChannel(channel *Channel) (*Result, *AppError) { func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create", channel.ToJson()); err != nil { if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create", channel.ToJson()); err != nil {
return nil, err return nil, err
@ -949,6 +1008,7 @@ func (c *Client) JoinChannel(id string) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), nil}, nil r.Header.Get(HEADER_ETAG_SERVER), nil}, nil
} }
@ -958,6 +1018,7 @@ func (c *Client) JoinChannelByName(name string) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetChannelNameRoute(name)+"/join", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelNameRoute(name)+"/join", ""); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), nil}, nil r.Header.Get(HEADER_ETAG_SERVER), nil}, nil
} }
@ -967,6 +1028,7 @@ func (c *Client) LeaveChannel(id string) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/leave", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/leave", ""); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), nil}, nil r.Header.Get(HEADER_ETAG_SERVER), nil}, nil
} }
@ -976,6 +1038,7 @@ func (c *Client) DeleteChannel(id string) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/delete", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/delete", ""); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), nil}, nil r.Header.Get(HEADER_ETAG_SERVER), nil}, nil
} }
@ -987,6 +1050,7 @@ func (c *Client) AddChannelMember(id, user_id string) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/add", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/add", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), nil}, nil r.Header.Get(HEADER_ETAG_SERVER), nil}, nil
} }
@ -998,6 +1062,7 @@ func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/remove", MapToJson(data)); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/remove", MapToJson(data)); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), nil}, nil r.Header.Get(HEADER_ETAG_SERVER), nil}, nil
} }
@ -1007,6 +1072,7 @@ func (c *Client) UpdateLastViewedAt(channelId string) (*Result, *AppError) {
if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/update_last_viewed_at", ""); err != nil { if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/update_last_viewed_at", ""); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), nil}, nil r.Header.Get(HEADER_ETAG_SERVER), nil}, nil
} }
@ -1376,6 +1442,7 @@ func (c *Client) PostToWebhook(id, payload string) (*Result, *AppError) {
if r, err := c.DoPost("/hooks/"+id, payload, "application/x-www-form-urlencoded"); err != nil { if r, err := c.DoPost("/hooks/"+id, payload, "application/x-www-form-urlencoded"); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), nil}, nil r.Header.Get(HEADER_ETAG_SERVER), nil}, nil
} }
@ -1417,6 +1484,7 @@ func (c *Client) SetPreferences(preferences *Preferences) (*Result, *AppError) {
if r, err := c.DoApiPost("/preferences/save", preferences.ToJson()); err != nil { if r, err := c.DoApiPost("/preferences/save", preferences.ToJson()); err != nil {
return nil, err return nil, err
} else { } else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID), return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), preferences}, nil r.Header.Get(HEADER_ETAG_SERVER), preferences}, nil
} }
@ -1509,3 +1577,74 @@ func (c *Client) GetInitialLoad() (*Result, *AppError) {
r.Header.Get(HEADER_ETAG_SERVER), InitialLoadFromJson(r.Body)}, nil r.Header.Get(HEADER_ETAG_SERVER), InitialLoadFromJson(r.Body)}, nil
} }
} }
// ListEmoji returns a list of all user-created emoji for the server.
func (c *Client) ListEmoji() ([]*Emoji, *AppError) {
if r, err := c.DoApiGet(c.GetEmojiRoute()+"/list", "", ""); err != nil {
return nil, err
} else {
defer closeBody(r)
c.fillInExtraProperties(r)
return EmojiListFromJson(r.Body), nil
}
}
// CreateEmoji will save an emoji to the server if the current user has permission
// to do so. If successful, the provided emoji will be returned with its Id field
// filled in. Otherwise, an error will be returned.
func (c *Client) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoji, *AppError) {
c.clearExtraProperties()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
if part, err := writer.CreateFormFile("image", filename); err != nil {
return nil, NewLocAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error())
} else if _, err = io.Copy(part, bytes.NewBuffer(image)); err != nil {
return nil, NewLocAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error())
}
if err := writer.WriteField("emoji", emoji.ToJson()); err != nil {
return nil, NewLocAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error())
}
if err := writer.Close(); err != nil {
return nil, NewLocAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error())
}
rq, _ := http.NewRequest("POST", c.ApiUrl+c.GetEmojiRoute()+"/create", body)
rq.Header.Set("Content-Type", writer.FormDataContentType())
if len(c.AuthToken) > 0 {
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
}
if r, err := c.HttpClient.Do(rq); err != nil {
return nil, NewLocAppError("CreateEmoji", "model.client.connecting.app_error", nil, err.Error())
} else if r.StatusCode >= 300 {
return nil, AppErrorFromJson(r.Body)
} else {
defer closeBody(r)
c.fillInExtraProperties(r)
return EmojiFromJson(r.Body), nil
}
}
// DeleteEmoji will delete an emoji from the server if the current user has permission
// to do so. If successful, it will return status=ok. Otherwise, an error will be returned.
func (c *Client) DeleteEmoji(id string) (bool, *AppError) {
data := map[string]string{"id": id}
if r, err := c.DoApiPost(c.GetEmojiRoute()+"/delete", MapToJson(data)); err != nil {
return false, err
} else {
c.fillInExtraProperties(r)
return c.CheckStatusOK(r), nil
}
}
// GetCustomEmojiImageUrl returns the API route that can be used to get the image used by
// the given emoji.
func (c *Client) GetCustomEmojiImageUrl(id string) string {
return c.GetEmojiRoute() + "/" + id
}

View File

@ -6,7 +6,6 @@ package model
import ( import (
"encoding/json" "encoding/json"
"io" "io"
"strings"
) )
const ( const (
@ -20,6 +19,9 @@ const (
DATABASE_DRIVER_MYSQL = "mysql" DATABASE_DRIVER_MYSQL = "mysql"
DATABASE_DRIVER_POSTGRES = "postgres" DATABASE_DRIVER_POSTGRES = "postgres"
PASSWORD_MAXIMUM_LENGTH = 64
PASSWORD_MINIMUM_LENGTH = 5
SERVICE_GITLAB = "gitlab" SERVICE_GITLAB = "gitlab"
SERVICE_GOOGLE = "google" SERVICE_GOOGLE = "google"
@ -33,17 +35,16 @@ const (
DIRECT_MESSAGE_ANY = "any" DIRECT_MESSAGE_ANY = "any"
DIRECT_MESSAGE_TEAM = "team" DIRECT_MESSAGE_TEAM = "team"
FAKE_SETTING = "********************************" PERMISSIONS_ALL = "all"
) PERMISSIONS_TEAM_ADMIN = "team_admin"
PERMISSIONS_SYSTEM_ADMIN = "system_admin"
// should match the values in webapp/i18n/i18n.jsx FAKE_SETTING = "********************************"
var LOCALES = []string{
"en", RESTRICT_EMOJI_CREATION_ALL = "all"
"es", RESTRICT_EMOJI_CREATION_ADMIN = "admin"
"fr", RESTRICT_EMOJI_CREATION_SYSTEM_ADMIN = "system_admin"
"ja", )
"pt-BR",
}
type ServiceSettings struct { type ServiceSettings struct {
ListenAddress string ListenAddress string
@ -70,6 +71,8 @@ type ServiceSettings struct {
WebsocketSecurePort *int WebsocketSecurePort *int
WebsocketPort *int WebsocketPort *int
WebserverMode *string WebserverMode *string
EnableCustomEmoji *bool
RestrictCustomEmojiCreation *string
} }
type SSOSettings struct { type SSOSettings struct {
@ -93,12 +96,21 @@ type SqlSettings struct {
} }
type LogSettings struct { type LogSettings struct {
EnableConsole bool EnableConsole bool
ConsoleLevel string ConsoleLevel string
EnableFile bool EnableFile bool
FileLevel string FileLevel string
FileFormat string FileFormat string
FileLocation string FileLocation string
EnableWebhookDebugging bool
}
type PasswordSettings struct {
MinimumLength *int
Lowercase *bool
Number *bool
Uppercase *bool
Symbol *bool
} }
type FileSettings struct { type FileSettings struct {
@ -132,6 +144,7 @@ type EmailSettings struct {
RequireEmailVerification bool RequireEmailVerification bool
FeedbackName string FeedbackName string
FeedbackEmail string FeedbackEmail string
FeedbackOrganization *string
SMTPUsername string SMTPUsername string
SMTPPassword string SMTPPassword string
SMTPServer string SMTPServer string
@ -167,16 +180,19 @@ type SupportSettings struct {
} }
type TeamSettings struct { type TeamSettings struct {
SiteName string SiteName string
MaxUsersPerTeam int MaxUsersPerTeam int
EnableTeamCreation bool EnableTeamCreation bool
EnableUserCreation bool EnableUserCreation bool
EnableOpenServer *bool EnableOpenServer *bool
RestrictCreationToDomains string RestrictCreationToDomains string
RestrictTeamNames *bool RestrictTeamNames *bool
EnableCustomBrand *bool EnableCustomBrand *bool
CustomBrandText *string CustomBrandText *string
RestrictDirectMessage *string RestrictDirectMessage *string
RestrictTeamInvite *string
RestrictPublicChannelManagement *string
RestrictPrivateChannelManagement *string
} }
type LdapSettings struct { type LdapSettings struct {
@ -206,6 +222,7 @@ type LdapSettings struct {
// Advanced // Advanced
SkipCertificateVerification *bool SkipCertificateVerification *bool
QueryTimeout *int QueryTimeout *int
MaxPageSize *int
// Customization // Customization
LoginFieldName *string LoginFieldName *string
@ -223,11 +240,37 @@ type LocalizationSettings struct {
AvailableLocales *string AvailableLocales *string
} }
type SamlSettings struct {
// Basic
Enable *bool
Verify *bool
Encrypt *bool
IdpUrl *string
IdpDescriptorUrl *string
AssertionConsumerServiceURL *string
IdpCertificateFile *string
PublicCertificateFile *string
PrivateKeyFile *string
// User Mapping
FirstNameAttribute *string
LastNameAttribute *string
EmailAttribute *string
UsernameAttribute *string
NicknameAttribute *string
LocaleAttribute *string
LoginButtonText *string
}
type Config struct { type Config struct {
ServiceSettings ServiceSettings ServiceSettings ServiceSettings
TeamSettings TeamSettings TeamSettings TeamSettings
SqlSettings SqlSettings SqlSettings SqlSettings
LogSettings LogSettings LogSettings LogSettings
PasswordSettings PasswordSettings
FileSettings FileSettings FileSettings FileSettings
EmailSettings EmailSettings EmailSettings EmailSettings
RateLimitSettings RateLimitSettings RateLimitSettings RateLimitSettings
@ -238,6 +281,7 @@ type Config struct {
LdapSettings LdapSettings LdapSettings LdapSettings
ComplianceSettings ComplianceSettings ComplianceSettings ComplianceSettings
LocalizationSettings LocalizationSettings LocalizationSettings LocalizationSettings
SamlSettings SamlSettings
} }
func (o *Config) ToJson() string { func (o *Config) ToJson() string {
@ -324,6 +368,31 @@ func (o *Config) SetDefaults() {
*o.ServiceSettings.EnableMultifactorAuthentication = false *o.ServiceSettings.EnableMultifactorAuthentication = false
} }
if o.PasswordSettings.MinimumLength == nil {
o.PasswordSettings.MinimumLength = new(int)
*o.PasswordSettings.MinimumLength = PASSWORD_MINIMUM_LENGTH
}
if o.PasswordSettings.Lowercase == nil {
o.PasswordSettings.Lowercase = new(bool)
*o.PasswordSettings.Lowercase = false
}
if o.PasswordSettings.Number == nil {
o.PasswordSettings.Number = new(bool)
*o.PasswordSettings.Number = false
}
if o.PasswordSettings.Uppercase == nil {
o.PasswordSettings.Uppercase = new(bool)
*o.PasswordSettings.Uppercase = false
}
if o.PasswordSettings.Symbol == nil {
o.PasswordSettings.Symbol = new(bool)
*o.PasswordSettings.Symbol = false
}
if o.TeamSettings.RestrictTeamNames == nil { if o.TeamSettings.RestrictTeamNames == nil {
o.TeamSettings.RestrictTeamNames = new(bool) o.TeamSettings.RestrictTeamNames = new(bool)
*o.TeamSettings.RestrictTeamNames = true *o.TeamSettings.RestrictTeamNames = true
@ -349,6 +418,21 @@ func (o *Config) SetDefaults() {
*o.TeamSettings.RestrictDirectMessage = DIRECT_MESSAGE_ANY *o.TeamSettings.RestrictDirectMessage = DIRECT_MESSAGE_ANY
} }
if o.TeamSettings.RestrictTeamInvite == nil {
o.TeamSettings.RestrictTeamInvite = new(string)
*o.TeamSettings.RestrictTeamInvite = PERMISSIONS_ALL
}
if o.TeamSettings.RestrictPublicChannelManagement == nil {
o.TeamSettings.RestrictPublicChannelManagement = new(string)
*o.TeamSettings.RestrictPublicChannelManagement = PERMISSIONS_ALL
}
if o.TeamSettings.RestrictPrivateChannelManagement == nil {
o.TeamSettings.RestrictPrivateChannelManagement = new(string)
*o.TeamSettings.RestrictPrivateChannelManagement = PERMISSIONS_ALL
}
if o.EmailSettings.EnableSignInWithEmail == nil { if o.EmailSettings.EnableSignInWithEmail == nil {
o.EmailSettings.EnableSignInWithEmail = new(bool) o.EmailSettings.EnableSignInWithEmail = new(bool)
@ -379,6 +463,11 @@ func (o *Config) SetDefaults() {
*o.EmailSettings.PushNotificationContents = GENERIC_NOTIFICATION *o.EmailSettings.PushNotificationContents = GENERIC_NOTIFICATION
} }
if o.EmailSettings.FeedbackOrganization == nil {
o.EmailSettings.FeedbackOrganization = new(string)
*o.EmailSettings.FeedbackOrganization = ""
}
if !IsSafeLink(o.SupportSettings.TermsOfServiceLink) { if !IsSafeLink(o.SupportSettings.TermsOfServiceLink) {
o.SupportSettings.TermsOfServiceLink = nil o.SupportSettings.TermsOfServiceLink = nil
} }
@ -484,6 +573,11 @@ func (o *Config) SetDefaults() {
*o.LdapSettings.EmailAttribute = "" *o.LdapSettings.EmailAttribute = ""
} }
if o.LdapSettings.UsernameAttribute == nil {
o.LdapSettings.UsernameAttribute = new(string)
*o.LdapSettings.UsernameAttribute = ""
}
if o.LdapSettings.NicknameAttribute == nil { if o.LdapSettings.NicknameAttribute == nil {
o.LdapSettings.NicknameAttribute = new(string) o.LdapSettings.NicknameAttribute = new(string)
*o.LdapSettings.NicknameAttribute = "" *o.LdapSettings.NicknameAttribute = ""
@ -509,6 +603,11 @@ func (o *Config) SetDefaults() {
*o.LdapSettings.QueryTimeout = 60 *o.LdapSettings.QueryTimeout = 60
} }
if o.LdapSettings.MaxPageSize == nil {
o.LdapSettings.MaxPageSize = new(int)
*o.LdapSettings.MaxPageSize = 0
}
if o.LdapSettings.LoginFieldName == nil { if o.LdapSettings.LoginFieldName == nil {
o.LdapSettings.LoginFieldName = new(string) o.LdapSettings.LoginFieldName = new(string)
*o.LdapSettings.LoginFieldName = "" *o.LdapSettings.LoginFieldName = ""
@ -561,7 +660,19 @@ func (o *Config) SetDefaults() {
if o.ServiceSettings.WebserverMode == nil { if o.ServiceSettings.WebserverMode == nil {
o.ServiceSettings.WebserverMode = new(string) o.ServiceSettings.WebserverMode = new(string)
*o.ServiceSettings.WebserverMode = "regular" *o.ServiceSettings.WebserverMode = "gzip"
} else if *o.ServiceSettings.WebserverMode == "regular" {
*o.ServiceSettings.WebserverMode = "gzip"
}
if o.ServiceSettings.EnableCustomEmoji == nil {
o.ServiceSettings.EnableCustomEmoji = new(bool)
*o.ServiceSettings.EnableCustomEmoji = true
}
if o.ServiceSettings.RestrictCustomEmojiCreation == nil {
o.ServiceSettings.RestrictCustomEmojiCreation = new(string)
*o.ServiceSettings.RestrictCustomEmojiCreation = RESTRICT_EMOJI_CREATION_ALL
} }
if o.ComplianceSettings.Enable == nil { if o.ComplianceSettings.Enable == nil {
@ -591,7 +702,87 @@ func (o *Config) SetDefaults() {
if o.LocalizationSettings.AvailableLocales == nil { if o.LocalizationSettings.AvailableLocales == nil {
o.LocalizationSettings.AvailableLocales = new(string) o.LocalizationSettings.AvailableLocales = new(string)
*o.LocalizationSettings.AvailableLocales = strings.Join(LOCALES, ",") *o.LocalizationSettings.AvailableLocales = ""
}
if o.SamlSettings.Enable == nil {
o.SamlSettings.Enable = new(bool)
*o.SamlSettings.Enable = false
}
if o.SamlSettings.Verify == nil {
o.SamlSettings.Verify = new(bool)
*o.SamlSettings.Verify = false
}
if o.SamlSettings.Encrypt == nil {
o.SamlSettings.Encrypt = new(bool)
*o.SamlSettings.Encrypt = false
}
if o.SamlSettings.IdpUrl == nil {
o.SamlSettings.IdpUrl = new(string)
*o.SamlSettings.IdpUrl = ""
}
if o.SamlSettings.IdpDescriptorUrl == nil {
o.SamlSettings.IdpDescriptorUrl = new(string)
*o.SamlSettings.IdpDescriptorUrl = ""
}
if o.SamlSettings.IdpCertificateFile == nil {
o.SamlSettings.IdpCertificateFile = new(string)
*o.SamlSettings.IdpCertificateFile = ""
}
if o.SamlSettings.PublicCertificateFile == nil {
o.SamlSettings.PublicCertificateFile = new(string)
*o.SamlSettings.PublicCertificateFile = ""
}
if o.SamlSettings.PrivateKeyFile == nil {
o.SamlSettings.PrivateKeyFile = new(string)
*o.SamlSettings.PrivateKeyFile = ""
}
if o.SamlSettings.AssertionConsumerServiceURL == nil {
o.SamlSettings.AssertionConsumerServiceURL = new(string)
*o.SamlSettings.AssertionConsumerServiceURL = ""
}
if o.SamlSettings.LoginButtonText == nil || *o.SamlSettings.LoginButtonText == "" {
o.SamlSettings.LoginButtonText = new(string)
*o.SamlSettings.LoginButtonText = USER_AUTH_SERVICE_SAML_TEXT
}
if o.SamlSettings.FirstNameAttribute == nil {
o.SamlSettings.FirstNameAttribute = new(string)
*o.SamlSettings.FirstNameAttribute = ""
}
if o.SamlSettings.LastNameAttribute == nil {
o.SamlSettings.LastNameAttribute = new(string)
*o.SamlSettings.LastNameAttribute = ""
}
if o.SamlSettings.EmailAttribute == nil {
o.SamlSettings.EmailAttribute = new(string)
*o.SamlSettings.EmailAttribute = ""
}
if o.SamlSettings.UsernameAttribute == nil {
o.SamlSettings.UsernameAttribute = new(string)
*o.SamlSettings.UsernameAttribute = ""
}
if o.SamlSettings.NicknameAttribute == nil {
o.SamlSettings.NicknameAttribute = new(string)
*o.SamlSettings.NicknameAttribute = ""
}
if o.SamlSettings.LocaleAttribute == nil {
o.SamlSettings.LocaleAttribute = new(string)
*o.SamlSettings.LocaleAttribute = ""
} }
} }
@ -697,6 +888,78 @@ func (o *Config) IsValid() *AppError {
return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_sync_interval.app_error", nil, "") return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_sync_interval.app_error", nil, "")
} }
if *o.LdapSettings.MaxPageSize < 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.ldap_max_page_size.app_error", nil, "")
}
if *o.LdapSettings.Enable {
if *o.LdapSettings.LdapServer == "" ||
*o.LdapSettings.BaseDN == "" ||
*o.LdapSettings.BindUsername == "" ||
*o.LdapSettings.BindPassword == "" ||
*o.LdapSettings.FirstNameAttribute == "" ||
*o.LdapSettings.LastNameAttribute == "" ||
*o.LdapSettings.EmailAttribute == "" ||
*o.LdapSettings.UsernameAttribute == "" ||
*o.LdapSettings.IdAttribute == "" {
return NewLocAppError("Config.IsValid", "Required LDAP field missing", nil, "")
}
}
if *o.SamlSettings.Enable {
if len(*o.SamlSettings.IdpUrl) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_idp_url.app_error", nil, "")
}
if len(*o.SamlSettings.IdpDescriptorUrl) == 0 || !IsValidHttpUrl(*o.SamlSettings.IdpDescriptorUrl) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_idp_descriptor_url.app_error", nil, "")
}
if len(*o.SamlSettings.IdpCertificateFile) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_idp_cert.app_error", nil, "")
}
if len(*o.SamlSettings.EmailAttribute) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_email_attribute.app_error", nil, "")
}
if len(*o.SamlSettings.UsernameAttribute) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_username_attribute.app_error", nil, "")
}
if len(*o.SamlSettings.FirstNameAttribute) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_first_name_attribute.app_error", nil, "")
}
if len(*o.SamlSettings.LastNameAttribute) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_last_name_attribute.app_error", nil, "")
}
if *o.SamlSettings.Verify {
if len(*o.SamlSettings.AssertionConsumerServiceURL) == 0 || !IsValidHttpUrl(*o.SamlSettings.AssertionConsumerServiceURL) {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_assertion_consumer_service_url.app_error", nil, "")
}
}
if *o.SamlSettings.Encrypt {
if len(*o.SamlSettings.PrivateKeyFile) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_private_key.app_error", nil, "")
}
if len(*o.SamlSettings.PublicCertificateFile) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_public_cert.app_error", nil, "")
}
}
if len(*o.SamlSettings.EmailAttribute) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.saml_email_attribute.app_error", nil, "")
}
}
if *o.PasswordSettings.MinimumLength < PASSWORD_MINIMUM_LENGTH || *o.PasswordSettings.MinimumLength > PASSWORD_MAXIMUM_LENGTH {
return NewLocAppError("Config.IsValid", "model.config.is_valid.password_length.app_error", map[string]interface{}{"MinLength": PASSWORD_MINIMUM_LENGTH, "MaxLength": PASSWORD_MAXIMUM_LENGTH}, "")
}
return nil return nil
} }

95
vendor/github.com/mattermost/platform/model/emoji.go generated vendored Normal file
View File

@ -0,0 +1,95 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"io"
)
type Emoji struct {
Id string `json:"id"`
CreateAt int64 `json:"create_at"`
UpdateAt int64 `json:"update_at"`
DeleteAt int64 `json:"delete_at"`
CreatorId string `json:"creator_id"`
Name string `json:"name"`
}
func (emoji *Emoji) IsValid() *AppError {
if len(emoji.Id) != 26 {
return NewLocAppError("Emoji.IsValid", "model.emoji.id.app_error", nil, "")
}
if emoji.CreateAt == 0 {
return NewLocAppError("Emoji.IsValid", "model.emoji.create_at.app_error", nil, "id="+emoji.Id)
}
if emoji.UpdateAt == 0 {
return NewLocAppError("Emoji.IsValid", "model.emoji.update_at.app_error", nil, "id="+emoji.Id)
}
if len(emoji.CreatorId) != 26 {
return NewLocAppError("Emoji.IsValid", "model.emoji.user_id.app_error", nil, "")
}
if len(emoji.Name) == 0 || len(emoji.Name) > 64 {
return NewLocAppError("Emoji.IsValid", "model.emoji.name.app_error", nil, "")
}
return nil
}
func (emoji *Emoji) PreSave() {
if emoji.Id == "" {
emoji.Id = NewId()
}
emoji.CreateAt = GetMillis()
emoji.UpdateAt = emoji.CreateAt
}
func (emoji *Emoji) PreUpdate() {
emoji.UpdateAt = GetMillis()
}
func (emoji *Emoji) ToJson() string {
b, err := json.Marshal(emoji)
if err != nil {
return ""
} else {
return string(b)
}
}
func EmojiFromJson(data io.Reader) *Emoji {
decoder := json.NewDecoder(data)
var emoji Emoji
err := decoder.Decode(&emoji)
if err == nil {
return &emoji
} else {
return nil
}
}
func EmojiListToJson(emojiList []*Emoji) string {
b, err := json.Marshal(emojiList)
if err != nil {
return ""
} else {
return string(b)
}
}
func EmojiListFromJson(data io.Reader) []*Emoji {
decoder := json.NewDecoder(data)
var emojiList []*Emoji
err := decoder.Decode(&emojiList)
if err == nil {
return emojiList
} else {
return nil
}
}

View File

@ -28,8 +28,11 @@ func removeTaskByName(name string) {
delete(tasks, name) delete(tasks, name)
} }
func getTaskByName(name string) *ScheduledTask { func GetTaskByName(name string) *ScheduledTask {
return tasks[name] if task, ok := tasks[name]; ok {
return task
}
return nil
} }
func GetAllTasks() *map[string]*ScheduledTask { func GetAllTasks() *map[string]*ScheduledTask {

View File

@ -5,4 +5,5 @@ package model
const ( const (
USER_AUTH_SERVICE_LDAP = "ldap" USER_AUTH_SERVICE_LDAP = "ldap"
LDAP_SYNC_TASK_NAME = "LDAP Syncronization"
) )

View File

@ -32,14 +32,16 @@ type Customer struct {
} }
type Features struct { type Features struct {
Users *int `json:"users"` Users *int `json:"users"`
LDAP *bool `json:"ldap"` LDAP *bool `json:"ldap"`
MFA *bool `json:"mfa"` MFA *bool `json:"mfa"`
GoogleSSO *bool `json:"google_sso"` GoogleSSO *bool `json:"google_sso"`
Compliance *bool `json:"compliance"` Compliance *bool `json:"compliance"`
CustomBrand *bool `json:"custom_brand"` CustomBrand *bool `json:"custom_brand"`
MHPNS *bool `json:"mhpns"` MHPNS *bool `json:"mhpns"`
FutureFeatures *bool `json:"future_features"` SAML *bool `json:"saml"`
PasswordRequirements *bool `json:"password_requirements"`
FutureFeatures *bool `json:"future_features"`
} }
func (f *Features) SetDefaults() { func (f *Features) SetDefaults() {
@ -82,6 +84,16 @@ func (f *Features) SetDefaults() {
f.MHPNS = new(bool) f.MHPNS = new(bool)
*f.MHPNS = *f.FutureFeatures *f.MHPNS = *f.FutureFeatures
} }
if f.SAML == nil {
f.SAML = new(bool)
*f.SAML = *f.FutureFeatures
}
if f.PasswordRequirements == nil {
f.PasswordRequirements = new(bool)
*f.PasswordRequirements = *f.FutureFeatures
}
} }
func (l *License) IsExpired() bool { func (l *License) IsExpired() bool {

View File

@ -17,6 +17,7 @@ const (
ACTION_CHANNEL_VIEWED = "channel_viewed" ACTION_CHANNEL_VIEWED = "channel_viewed"
ACTION_DIRECT_ADDED = "direct_added" ACTION_DIRECT_ADDED = "direct_added"
ACTION_NEW_USER = "new_user" ACTION_NEW_USER = "new_user"
ACTION_LEAVE_TEAM = "leave_team"
ACTION_USER_ADDED = "user_added" ACTION_USER_ADDED = "user_added"
ACTION_USER_REMOVED = "user_removed" ACTION_USER_REMOVED = "user_removed"
ACTION_PREFERENCE_CHANGED = "preference_changed" ACTION_PREFERENCE_CHANGED = "preference_changed"

18
vendor/github.com/mattermost/platform/model/saml.go generated vendored Normal file
View File

@ -0,0 +1,18 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
const (
USER_AUTH_SERVICE_SAML = "saml"
USER_AUTH_SERVICE_SAML_TEXT = "With SAML"
SAML_IDP_CERTIFICATE = 1
SAML_PRIVATE_KEY = 2
SAML_PUBLIC_CERT = 3
)
type SamlAuthRequest struct {
Base64AuthRequest string
URL string
RelayState string
}

View File

@ -14,9 +14,10 @@ const (
) )
type TeamMember struct { type TeamMember struct {
TeamId string `json:"team_id"` TeamId string `json:"team_id"`
UserId string `json:"user_id"` UserId string `json:"user_id"`
Roles string `json:"roles"` Roles string `json:"roles"`
DeleteAt int64 `json:"delete_at"`
} }
func (o *TeamMember) ToJson() string { func (o *TeamMember) ToJson() string {

View File

@ -27,7 +27,6 @@ const (
DEFAULT_LOCALE = "en" DEFAULT_LOCALE = "en"
USER_AUTH_SERVICE_EMAIL = "email" USER_AUTH_SERVICE_EMAIL = "email"
USER_AUTH_SERVICE_USERNAME = "username" USER_AUTH_SERVICE_USERNAME = "username"
MIN_PASSWORD_LENGTH = 5
) )
type User struct { type User struct {
@ -95,10 +94,6 @@ func (u *User) IsValid() *AppError {
return NewLocAppError("User.IsValid", "model.user.is_valid.last_name.app_error", nil, "user_id="+u.Id) return NewLocAppError("User.IsValid", "model.user.is_valid.last_name.app_error", nil, "user_id="+u.Id)
} }
if len(u.Password) > 128 {
return NewLocAppError("User.IsValid", "model.user.is_valid.pwd.app_error", nil, "user_id="+u.Id)
}
if u.AuthData != nil && len(*u.AuthData) > 128 { if u.AuthData != nil && len(*u.AuthData) > 128 {
return NewLocAppError("User.IsValid", "model.user.is_valid.auth_data.app_error", nil, "user_id="+u.Id) return NewLocAppError("User.IsValid", "model.user.is_valid.auth_data.app_error", nil, "user_id="+u.Id)
} }
@ -208,7 +203,6 @@ func (u *User) SetDefaultNotifications() {
u.NotifyProps["desktop"] = USER_NOTIFY_ALL u.NotifyProps["desktop"] = USER_NOTIFY_ALL
u.NotifyProps["desktop_sound"] = "true" u.NotifyProps["desktop_sound"] = "true"
u.NotifyProps["mention_keys"] = u.Username + ",@" + u.Username u.NotifyProps["mention_keys"] = u.Username + ",@" + u.Username
u.NotifyProps["all"] = "true"
u.NotifyProps["channel"] = "true" u.NotifyProps["channel"] = "true"
if u.FirstName == "" { if u.FirstName == "" {
@ -244,8 +238,8 @@ func (u *User) ToJson() string {
} }
// Generate a valid strong etag so the browser can cache the results // Generate a valid strong etag so the browser can cache the results
func (u *User) Etag() string { func (u *User) Etag(showFullName, showEmail bool) string {
return Etag(u.Id, u.UpdateAt) return Etag(u.Id, u.UpdateAt, showFullName, showEmail)
} }
func (u *User) IsOffline() bool { func (u *User) IsOffline() bool {
@ -363,13 +357,13 @@ func isValidRole(role string) bool {
return false return false
} }
// Make sure you acually want to use this function. In context.go there are functions to check permssions // Make sure you acually want to use this function. In context.go there are functions to check permissions
// This function should not be used to check permissions. // This function should not be used to check permissions.
func (u *User) IsInRole(inRole string) bool { func (u *User) IsInRole(inRole string) bool {
return IsInRole(u.Roles, inRole) return IsInRole(u.Roles, inRole)
} }
// Make sure you acually want to use this function. In context.go there are functions to check permssions // Make sure you acually want to use this function. In context.go there are functions to check permissions
// This function should not be used to check permissions. // This function should not be used to check permissions.
func IsInRole(userRoles string, inRole string) bool { func IsInRole(userRoles string, inRole string) bool {
roles := strings.Split(userRoles, " ") roles := strings.Split(userRoles, " ")

View File

@ -20,6 +20,13 @@ import (
"github.com/pborman/uuid" "github.com/pborman/uuid"
) )
const (
LOWERCASE_LETTERS = "abcdefghijklmnopqrstuvwxyz"
UPPERCASE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
NUMBERS = "0123456789"
SYMBOLS = " !\"\\#$%&'()*+,-./:;<=>?@[]^_`|~"
)
type StringInterface map[string]interface{} type StringInterface map[string]interface{}
type StringMap map[string]string type StringMap map[string]string
type StringArray []string type StringArray []string

View File

@ -13,6 +13,7 @@ import (
// It should be maitained in chronological order with most current // It should be maitained in chronological order with most current
// release at the front of the list. // release at the front of the list.
var versions = []string{ var versions = []string{
"3.2.0",
"3.1.0", "3.1.0",
"3.0.0", "3.0.0",
"2.2.0", "2.2.0",

8
vendor/manifest vendored
View File

@ -63,8 +63,8 @@
"importpath": "github.com/mattermost/platform/einterfaces", "importpath": "github.com/mattermost/platform/einterfaces",
"repository": "https://github.com/mattermost/platform", "repository": "https://github.com/mattermost/platform",
"vcs": "git", "vcs": "git",
"revision": "974238231b9cdbd39a825ec8e9299fbb0b51f6b8", "revision": "ab52700aaa76a5623de23cd0156f5dbd9a24e264",
"branch": "release-3.1", "branch": "release-3.2",
"path": "/einterfaces", "path": "/einterfaces",
"notests": true "notests": true
}, },
@ -72,8 +72,8 @@
"importpath": "github.com/mattermost/platform/model", "importpath": "github.com/mattermost/platform/model",
"repository": "https://github.com/mattermost/platform", "repository": "https://github.com/mattermost/platform",
"vcs": "git", "vcs": "git",
"revision": "974238231b9cdbd39a825ec8e9299fbb0b51f6b8", "revision": "ab52700aaa76a5623de23cd0156f5dbd9a24e264",
"branch": "release-3.1", "branch": "release-3.2",
"path": "/model", "path": "/model",
"notests": true "notests": true
}, },