Merge branch 'master' into mark-as-unread

Этот коммит содержится в:
Harrison Healey
2019-11-12 14:20:50 -05:00
родитель 6e6174a9ee 0c8b580458
Коммит df7cbcb440
45 изменённых файлов: 1002 добавлений и 792 удалений

Просмотреть файл

@@ -230,7 +230,10 @@ check-prereqs: ## Checks prerequisite software status.
./scripts/prereq-check.sh ./scripts/prereq-check.sh
# TODO: remove govet and gofmt checks once golangci-lint is being enforced. # TODO: remove govet and gofmt checks once golangci-lint is being enforced.
check-style: govet gofmt check-licenses ## Runs govet and gofmt against all packages. check-style: govet gofmt check-licenses check-plugin-golint ## Runs govet and gofmt against all packages and also ensures plugin package golint compliant
check-plugin-golint: # Checks if golint returns any uncompliant code for any file that starts with plugin/helpers
@! golint ./plugin/ | grep plugin/helpers
test-te-race: ## Checks for race conditions in the team edition. test-te-race: ## Checks for race conditions in the team edition.
@echo Testing TE race conditions @echo Testing TE race conditions
@@ -398,7 +401,7 @@ stop-client: ## Stops the webapp.
cd $(BUILD_WEBAPP_DIR) && $(MAKE) stop cd $(BUILD_WEBAPP_DIR) && $(MAKE) stop
stop: stop-server stop-client ## Stops server and client. stop: stop-server stop-client stop-docker ## Stops server, client and the docker compose.
restart: restart-server restart-client ## Restarts the server and webapp. restart: restart-server restart-client ## Restarts the server and webapp.

Просмотреть файл

@@ -574,7 +574,9 @@ func CheckEtag(t *testing.T, data interface{}, resp *model.Response) {
func CheckNoError(t *testing.T, resp *model.Response) { func CheckNoError(t *testing.T, resp *model.Response) {
t.Helper() t.Helper()
require.Nil(t, resp.Error) if resp.Error != nil {
require.FailNow(t, "Expected no error, got %q", resp.Error.Error())
}
} }
func checkHTTPStatus(t *testing.T, resp *model.Response, expectedStatus int, expectError bool) { func checkHTTPStatus(t *testing.T, resp *model.Response, expectedStatus int, expectError bool) {
@@ -637,8 +639,8 @@ func CheckInternalErrorStatus(t *testing.T, resp *model.Response) {
func CheckErrorMessage(t *testing.T, resp *model.Response, errorId string) { func CheckErrorMessage(t *testing.T, resp *model.Response, errorId string) {
t.Helper() t.Helper()
require.NotNil(t, resp.Error) require.NotNilf(t, resp.Error, "should have errored with message: %s", errorId)
require.Equal(t, resp.Error.Id, errorId, "incorrect error message") require.Equalf(t, resp.Error.Id, errorId, "incorrect error message, actual: %s, expected: %s", resp.Error.Id, errorId)
} }
func CheckStartsWith(t *testing.T, value, prefix, message string) { func CheckStartsWith(t *testing.T, value, prefix, message string) {

Просмотреть файл

@@ -27,6 +27,7 @@ func (api *API) InitChannel() {
api.BaseRoutes.ChannelsForTeam.Handle("/deleted", api.ApiSessionRequired(getDeletedChannelsForTeam)).Methods("GET") api.BaseRoutes.ChannelsForTeam.Handle("/deleted", api.ApiSessionRequired(getDeletedChannelsForTeam)).Methods("GET")
api.BaseRoutes.ChannelsForTeam.Handle("/ids", api.ApiSessionRequired(getPublicChannelsByIdsForTeam)).Methods("POST") api.BaseRoutes.ChannelsForTeam.Handle("/ids", api.ApiSessionRequired(getPublicChannelsByIdsForTeam)).Methods("POST")
api.BaseRoutes.ChannelsForTeam.Handle("/search", api.ApiSessionRequired(searchChannelsForTeam)).Methods("POST") api.BaseRoutes.ChannelsForTeam.Handle("/search", api.ApiSessionRequired(searchChannelsForTeam)).Methods("POST")
api.BaseRoutes.ChannelsForTeam.Handle("/search_archived", api.ApiSessionRequired(searchArchivedChannelsForTeam)).Methods("POST")
api.BaseRoutes.ChannelsForTeam.Handle("/autocomplete", api.ApiSessionRequired(autocompleteChannelsForTeam)).Methods("GET") api.BaseRoutes.ChannelsForTeam.Handle("/autocomplete", api.ApiSessionRequired(autocompleteChannelsForTeam)).Methods("GET")
api.BaseRoutes.ChannelsForTeam.Handle("/search_autocomplete", api.ApiSessionRequired(autocompleteChannelsForTeamForSearch)).Methods("GET") api.BaseRoutes.ChannelsForTeam.Handle("/search_autocomplete", api.ApiSessionRequired(autocompleteChannelsForTeamForSearch)).Methods("GET")
api.BaseRoutes.User.Handle("/teams/{team_id:[A-Za-z0-9]+}/channels", api.ApiSessionRequired(getChannelsForTeamForUser)).Methods("GET") api.BaseRoutes.User.Handle("/teams/{team_id:[A-Za-z0-9]+}/channels", api.ApiSessionRequired(getChannelsForTeamForUser)).Methods("GET")
@@ -681,12 +682,7 @@ func getDeletedChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Reques
return return
} }
if !c.App.SessionHasPermissionToTeam(c.App.Session, c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) { channels, err := c.App.GetDeletedChannels(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage, c.App.Session.UserId)
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
return
}
channels, err := c.App.GetDeletedChannels(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage)
if err != nil { if err != nil {
c.Err = err c.Err = err
return return
@@ -860,6 +856,42 @@ func searchChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(channels.ToJson())) w.Write([]byte(channels.ToJson()))
} }
func searchArchivedChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequireTeamId()
if c.Err != nil {
return
}
props := model.ChannelSearchFromJson(r.Body)
if props == nil {
c.SetInvalidParam("channel_search")
return
}
var channels *model.ChannelList
var err *model.AppError
if c.App.SessionHasPermissionToTeam(c.App.Session, c.Params.TeamId, model.PERMISSION_LIST_TEAM_CHANNELS) {
channels, err = c.App.SearchArchivedChannels(c.Params.TeamId, props.Term, c.App.Session.UserId)
} else {
// If the user is not a team member, return a 404
if _, err = c.App.GetTeamMember(c.Params.TeamId, c.App.Session.UserId); err != nil {
c.Err = err
return
}
channels, err = c.App.SearchArchivedChannels(c.Params.TeamId, props.Term, c.App.Session.UserId)
}
if err != nil {
c.Err = err
return
}
// Don't fill in channels props, since unused by client and potentially expensive.
w.Write([]byte(channels.ToJson()))
}
func searchAllChannels(c *Context, w http.ResponseWriter, r *http.Request) { func searchAllChannels(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.ChannelSearchFromJson(r.Body) props := model.ChannelSearchFromJson(r.Body)
if props == nil { if props == nil {

Просмотреть файл

@@ -678,9 +678,6 @@ func TestGetDeletedChannelsForTeam(t *testing.T) {
Client := th.Client Client := th.Client
team := th.BasicTeam team := th.BasicTeam
_, resp := Client.GetDeletedChannelsForTeam(team.Id, 0, 100, "")
CheckForbiddenStatus(t, resp)
th.LoginTeamAdmin() th.LoginTeamAdmin()
channels, resp := Client.GetDeletedChannelsForTeam(team.Id, 0, 100, "") channels, resp := Client.GetDeletedChannelsForTeam(team.Id, 0, 100, "")
@@ -706,6 +703,31 @@ func TestGetDeletedChannelsForTeam(t *testing.T) {
t.Fatal("should be 2 deleted channels") t.Fatal("should be 2 deleted channels")
} }
th.LoginBasic()
privateChannel1 := th.CreatePrivateChannel()
Client.DeleteChannel(privateChannel1.Id)
channels, resp = Client.GetDeletedChannelsForTeam(team.Id, 0, 100, "")
CheckNoError(t, resp)
if len(channels) != numInitialChannelsForTeam+3 {
t.Fatal("should be 3 deleted channels")
}
// Login as different user and create private channel
th.LoginBasic2()
privateChannel2 := th.CreatePrivateChannel()
Client.DeleteChannel(privateChannel2.Id)
// Log back in as first user
th.LoginBasic()
channels, resp = Client.GetDeletedChannelsForTeam(team.Id, 0, 100, "")
CheckNoError(t, resp)
if len(channels) != numInitialChannelsForTeam+3 {
t.Fatal("should still be 3 deleted channels", len(channels), numInitialChannelsForTeam+3)
}
channels, resp = Client.GetDeletedChannelsForTeam(team.Id, 0, 1, "") channels, resp = Client.GetDeletedChannelsForTeam(team.Id, 0, 1, "")
CheckNoError(t, resp) CheckNoError(t, resp)
if len(channels) != 1 { if len(channels) != 1 {
@@ -1060,6 +1082,100 @@ func TestSearchChannels(t *testing.T) {
}) })
} }
func TestSearchArchivedChannels(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()
Client := th.Client
search := &model.ChannelSearch{Term: th.BasicChannel.Name}
Client.DeleteChannel(th.BasicChannel.Id)
channels, resp := Client.SearchArchivedChannels(th.BasicTeam.Id, search)
CheckNoError(t, resp)
found := false
for _, c := range channels {
if c.Type != model.CHANNEL_OPEN {
t.Fatal("should only return public channels")
}
if c.Id == th.BasicChannel.Id {
found = true
}
}
if !found {
t.Fatal("didn't find channel")
}
search.Term = th.BasicPrivateChannel.Name
Client.DeleteChannel(th.BasicPrivateChannel.Id)
channels, resp = Client.SearchArchivedChannels(th.BasicTeam.Id, search)
CheckNoError(t, resp)
found = false
for _, c := range channels {
if c.Id == th.BasicPrivateChannel.Id {
found = true
}
}
if !found {
t.Fatal("couldn't find private channel")
}
search.Term = ""
_, resp = Client.SearchArchivedChannels(th.BasicTeam.Id, search)
CheckNoError(t, resp)
search.Term = th.BasicDeletedChannel.Name
_, resp = Client.SearchArchivedChannels(model.NewId(), search)
CheckNotFoundStatus(t, resp)
_, resp = Client.SearchArchivedChannels("junk", search)
CheckBadRequestStatus(t, resp)
_, resp = th.SystemAdminClient.SearchArchivedChannels(th.BasicTeam.Id, search)
CheckNoError(t, resp)
// Check the appropriate permissions are enforced.
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
// Remove list channels permission from the user
th.RemovePermissionFromRole(model.PERMISSION_LIST_TEAM_CHANNELS.Id, model.TEAM_USER_ROLE_ID)
t.Run("Search for a BasicDeletedChannel, which the user is a member of", func(t *testing.T) {
search.Term = th.BasicDeletedChannel.Name
channelList, resp := Client.SearchArchivedChannels(th.BasicTeam.Id, search)
CheckNoError(t, resp)
channelNames := []string{}
for _, c := range channelList {
channelNames = append(channelNames, c.Name)
}
require.Contains(t, channelNames, th.BasicDeletedChannel.Name)
})
t.Run("Remove the user from BasicDeletedChannel and search again, should still return", func(t *testing.T) {
th.App.RemoveUserFromChannel(th.BasicUser.Id, th.BasicUser.Id, th.BasicDeletedChannel)
search.Term = th.BasicDeletedChannel.Name
channelList, resp := Client.SearchArchivedChannels(th.BasicTeam.Id, search)
CheckNoError(t, resp)
channelNames := []string{}
for _, c := range channelList {
channelNames = append(channelNames, c.Name)
}
require.Contains(t, channelNames, th.BasicDeletedChannel.Name)
})
}
func TestSearchAllChannels(t *testing.T) { func TestSearchAllChannels(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic()
defer th.TearDown() defer th.TearDown()

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@@ -86,7 +86,7 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
user.SanitizeInput() user.SanitizeInput(c.IsSystemAdmin())
tokenId := r.URL.Query().Get("t") tokenId := r.URL.Query().Get("t")
inviteId := r.URL.Query().Get("iid") inviteId := r.URL.Query().Get("iid")

Просмотреть файл

@@ -110,10 +110,15 @@ func TestCreateUserInputFilter(t *testing.T) {
_, resp := th.SystemAdminClient.CreateUser(user) _, resp := th.SystemAdminClient.CreateUser(user)
CheckBadRequestStatus(t, resp) CheckBadRequestStatus(t, resp)
}) })
t.Run("ValidAuthServiceFilter", func(t *testing.T) {
t.Run("AuthServiceFilter", func(t *testing.T) { user := &model.User{Email: "foobar+testdomainrestriction@mattermost.org", Username: GenerateTestUsername(), AuthService: "ldap", AuthData: model.NewString("999099")}
user := &model.User{Email: "foobar+testdomainrestriction@mattermost.org", Password: "Password1", Username: GenerateTestUsername(), AuthService: "ldap"}
_, resp := th.SystemAdminClient.CreateUser(user) _, resp := th.SystemAdminClient.CreateUser(user)
CheckNoError(t, resp)
})
t.Run("InvalidAuthServiceFilter", func(t *testing.T) {
user := &model.User{Email: "foobar+testdomainrestriction@mattermost.org", Password: "Password1", Username: GenerateTestUsername(), AuthService: "ldap"}
_, resp := th.Client.CreateUser(user)
CheckBadRequestStatus(t, resp) CheckBadRequestStatus(t, resp)
}) })
}) })

Просмотреть файл

@@ -1260,8 +1260,8 @@ func (a *App) GetAllChannelsCount(opts model.ChannelSearchOpts) (int64, *model.A
return a.Srv.Store.Channel().GetAllChannelsCount(storeOpts) return a.Srv.Store.Channel().GetAllChannelsCount(storeOpts)
} }
func (a *App) GetDeletedChannels(teamId string, offset int, limit int) (*model.ChannelList, *model.AppError) { func (a *App) GetDeletedChannels(teamId string, offset int, limit int, userId string) (*model.ChannelList, *model.AppError) {
return a.Srv.Store.Channel().GetDeleted(teamId, offset, limit) return a.Srv.Store.Channel().GetDeleted(teamId, offset, limit, userId)
} }
func (a *App) GetChannelsUserNotIn(teamId string, userId string, offset int, limit int) (*model.ChannelList, *model.AppError) { func (a *App) GetChannelsUserNotIn(teamId string, userId string, offset int, limit int) (*model.ChannelList, *model.AppError) {
@@ -1894,6 +1894,12 @@ func (a *App) SearchChannels(teamId string, term string) (*model.ChannelList, *m
return a.Srv.Store.Channel().SearchInTeam(teamId, term, includeDeleted) return a.Srv.Store.Channel().SearchInTeam(teamId, term, includeDeleted)
} }
func (a *App) SearchArchivedChannels(teamId string, term string, userId string) (*model.ChannelList, *model.AppError) {
term = strings.TrimSpace(term)
return a.Srv.Store.Channel().SearchArchivedInTeam(teamId, term, userId)
}
func (a *App) SearchChannelsForUser(userId, teamId, term string) (*model.ChannelList, *model.AppError) { func (a *App) SearchChannelsForUser(userId, teamId, term string) (*model.ChannelList, *model.AppError) {
includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels

Просмотреть файл

@@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
) )
@@ -42,6 +43,15 @@ func TestInviteProvider(t *testing.T) {
userAndInvalidPrivate := "@" + basicUser3.Username + " ~" + privateChannel2.Name userAndInvalidPrivate := "@" + basicUser3.Username + " ~" + privateChannel2.Name
deactivatedUserPublicChannel := "@" + deactivatedUser.Username + " ~" + channel.Name deactivatedUserPublicChannel := "@" + deactivatedUser.Username + " ~" + channel.Name
groupChannel := th.createChannel(th.BasicTeam, model.CHANNEL_PRIVATE)
var err *model.AppError
_, err = th.App.AddChannelMember(th.BasicUser.Id, groupChannel, "", "")
require.Nil(t, err)
groupChannel.GroupConstrained = model.NewBool(true)
groupChannel, _ = th.App.UpdateChannel(groupChannel)
groupChannelNonUser := "@" + th.BasicUser2.Username + " ~" + groupChannel.Name
tests := []struct { tests := []struct {
desc string desc string
expected string expected string
@@ -97,6 +107,11 @@ func TestInviteProvider(t *testing.T) {
expected: "api.command_invite.user_not_in_team.app_error", expected: "api.command_invite.user_not_in_team.app_error",
msg: basicUser4.Username, msg: basicUser4.Username,
}, },
{
desc: "try to add a user not part of the group to a group channel",
expected: "api.command_invite.group_constrained_user_denied",
msg: groupChannelNonUser,
},
{ {
desc: "try to add a user to a private channel with no permission", desc: "try to add a user to a private channel with no permission",
expected: "api.command_invite.private_channel.app_error", expected: "api.command_invite.private_channel.app_error",
@@ -116,3 +131,59 @@ func TestInviteProvider(t *testing.T) {
}) })
} }
} }
func TestInviteGroup(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
th.BasicTeam.GroupConstrained = model.NewBool(true)
var err *model.AppError
_, _ = th.App.AddTeamMember(th.BasicTeam.Id, th.BasicUser.Id)
_, err = th.App.AddTeamMember(th.BasicTeam.Id, th.BasicUser2.Id)
require.Nil(t, err)
th.BasicTeam, _ = th.App.UpdateTeam(th.BasicTeam)
privateChannel := th.createChannel(th.BasicTeam, model.CHANNEL_PRIVATE)
groupChannelUser1 := "@" + th.BasicUser.Username + " ~" + privateChannel.Name
groupChannelUser2 := "@" + th.BasicUser2.Username + " ~" + privateChannel.Name
basicUser3 := th.CreateUser()
groupChannelUser3 := "@" + basicUser3.Username + " ~" + privateChannel.Name
InviteP := InviteProvider{}
args := &model.CommandArgs{
T: func(s string, args ...interface{}) string { return s },
ChannelId: th.BasicChannel.Id,
TeamId: th.BasicTeam.Id,
Session: model.Session{UserId: th.BasicUser.Id, TeamMembers: []*model.TeamMember{{TeamId: th.BasicTeam.Id, Roles: model.TEAM_USER_ROLE_ID}}},
}
tests := []struct {
desc string
expected string
msg string
}{
{
desc: "try to add an existing user part of the group to a group channel",
expected: "api.command_invite.user_already_in_channel.app_error",
msg: groupChannelUser1,
},
{
desc: "try to add a user part of the group to a group channel",
expected: "api.command_invite.success",
msg: groupChannelUser2,
},
{
desc: "try to add a user NOT part of the group to a group channel",
expected: "api.command_invite.user_not_in_team.app_error",
msg: groupChannelUser3,
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
actual := InviteP.DoCommand(th.App, args, test.msg).Text
assert.Equal(t, test.expected, actual)
})
}
}

Просмотреть файл

@@ -83,7 +83,7 @@ func (a *App) LimitedClientConfig() map[string]string {
return a.Srv.limitedClientConfig return a.Srv.limitedClientConfig
} }
// Registers a function with a given to be called when the config is reloaded and may have changed. The function // Registers a function with a given listener to be called when the config is reloaded and may have changed. The function
// will be called with two arguments: the old config and the new config. AddConfigListener returns a unique ID // will be called with two arguments: the old config and the new config. AddConfigListener returns a unique ID
// for the listener that can later be used to remove it. // for the listener that can later be used to remove it.
func (s *Server) AddConfigListener(listener func(*model.Config, *model.Config)) string { func (s *Server) AddConfigListener(listener func(*model.Config, *model.Config)) string {
@@ -104,7 +104,7 @@ func (a *App) RemoveConfigListener(id string) {
} }
// ensurePostActionCookieSecret ensures that the key for encrypting PostActionCookie exists // ensurePostActionCookieSecret ensures that the key for encrypting PostActionCookie exists
// and future calls to PostAcrionCookieSecret will always return a valid key, same on all // and future calls to PostActionCookieSecret will always return a valid key, same on all
// servers in the cluster // servers in the cluster
func (a *App) ensurePostActionCookieSecret() error { func (a *App) ensurePostActionCookieSecret() error {
if a.Srv.postActionCookieSecret != nil { if a.Srv.postActionCookieSecret != nil {

Просмотреть файл

@@ -7,7 +7,6 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"net/mail"
"net/url" "net/url"
"path" "path"
"strings" "strings"
@@ -525,8 +524,6 @@ func (a *App) SendMail(to, subject, htmlBody string) *model.AppError {
func (a *App) SendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader) *model.AppError { func (a *App) SendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader) *model.AppError {
license := a.License() license := a.License()
config := a.Config() config := a.Config()
fromMail := mail.Address{Name: *config.EmailSettings.FeedbackName, Address: *config.EmailSettings.FeedbackEmail}
replyTo := mail.Address{Name: *config.EmailSettings.FeedbackName, Address: *config.EmailSettings.ReplyToAddress}
return mailservice.SendMailUsingConfigAdvanced(to, to, fromMail, replyTo, subject, htmlBody, nil, embeddedFiles, nil, config, license != nil && *license.Features.Compliance) return mailservice.SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, embeddedFiles, config, license != nil && *license.Features.Compliance)
} }

Просмотреть файл

@@ -100,7 +100,7 @@ func (a *App) sendNotificationEmail(notification *postNotification, user *model.
a.Srv.Go(func() { a.Srv.Go(func() {
if err := a.SendNotificationMail(user.Email, html.UnescapeString(subjectText), bodyText); err != nil { if err := a.SendNotificationMail(user.Email, html.UnescapeString(subjectText), bodyText); err != nil {
mlog.Error("Error while sending the email", mlog.String("email", user.Email), mlog.Err(err)) mlog.Error("Error while sending the email", mlog.String("user_email", user.Email), mlog.Err(err))
} }
}) })
@@ -285,7 +285,7 @@ func getFormattedPostTime(user *model.User, post *model.Post, useMilitaryTime bo
func (a *App) generateHyperlinkForChannels(postMessage, teamName, teamURL string) string { func (a *App) generateHyperlinkForChannels(postMessage, teamName, teamURL string) string {
team, err := a.GetTeamByName(teamName) team, err := a.GetTeamByName(teamName)
if err != nil { if err != nil {
mlog.Error("Encountered error while looking up team by name", mlog.String("Team Name", teamName), mlog.Err(err)) mlog.Error("Encountered error while looking up team by name", mlog.String("team_name", teamName), mlog.Err(err))
return postMessage return postMessage
} }

Просмотреть файл

@@ -186,7 +186,7 @@ func NewServer(options ...Option) (*Server, error) {
return nil, errors.Wrapf(err, "unable to load Mattermost translation files") return nil, errors.Wrapf(err, "unable to load Mattermost translation files")
} }
err := s.RunOldAppInitalization() err := s.RunOldAppInitialization()
if err != nil { if err != nil {
return nil, err return nil, err
} }

Просмотреть файл

@@ -18,11 +18,11 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// This is a bridge between the old and new initalization for the context refactor. // This is a bridge between the old and new initialization for the context refactor.
// It calls app layer initalization code that then turns around and acts on the server. // It calls app layer initialization code that then turns around and acts on the server.
// Don't add anything new here, new initilization should be done in the server and // Don't add anything new here, new initialization should be done in the server and
// performed in the NewServer function. // performed in the NewServer function.
func (s *Server) RunOldAppInitalization() error { func (s *Server) RunOldAppInitialization() error {
s.FakeApp().CreatePushNotificationsHub() s.FakeApp().CreatePushNotificationsHub()
s.FakeApp().StartPushNotificationsHubWorkers() s.FakeApp().StartPushNotificationsHubWorkers()

Просмотреть файл

@@ -8,7 +8,6 @@ import (
"encoding/json" "encoding/json"
"image" "image"
"image/color" "image/color"
"math/rand"
"strings" "strings"
"testing" "testing"
"time" "time"
@@ -74,8 +73,7 @@ func TestCreateOAuthUser(t *testing.T) {
th := Setup(t).InitBasic() th := Setup(t).InitBasic()
defer th.TearDown() defer th.TearDown()
r := rand.New(rand.NewSource(time.Now().UnixNano())) glUser := oauthgitlab.GitLabUser{Id: 42, Username: "o" + model.NewId(), Email: model.NewId() + "@simulator.amazonses.com", Name: "Joram Wilander"}
glUser := oauthgitlab.GitLabUser{Id: int64(r.Intn(1000)) + 1, Username: "o" + model.NewId(), Email: model.NewId() + "@simulator.amazonses.com", Name: "Joram Wilander"}
json := glUser.ToJson() json := glUser.ToJson()
user, err := th.App.CreateOAuthUser(model.USER_AUTH_SERVICE_GITLAB, strings.NewReader(json), th.BasicTeam.Id) user, err := th.App.CreateOAuthUser(model.USER_AUTH_SERVICE_GITLAB, strings.NewReader(json), th.BasicTeam.Id)
@@ -253,8 +251,8 @@ func TestUpdateOAuthUserAttrs(t *testing.T) {
var user, user2 *model.User var user, user2 *model.User
var gitlabUserObj oauthgitlab.GitLabUser var gitlabUserObj oauthgitlab.GitLabUser
user, gitlabUserObj = createGitlabUser(t, th.App, username, email) user, gitlabUserObj = createGitlabUser(t, th.App, 1, username, email)
user2, _ = createGitlabUser(t, th.App, username2, email2) user2, _ = createGitlabUser(t, th.App, 2, username2, email2)
t.Run("UpdateUsername", func(t *testing.T) { t.Run("UpdateUsername", func(t *testing.T) {
t.Run("NoExistingUserWithSameUsername", func(t *testing.T) { t.Run("NoExistingUserWithSameUsername", func(t *testing.T) {
@@ -443,9 +441,8 @@ func getGitlabUserPayload(gitlabUser oauthgitlab.GitLabUser, t *testing.T) []byt
return payload return payload
} }
func createGitlabUser(t *testing.T, a *App, username string, email string) (*model.User, oauthgitlab.GitLabUser) { func createGitlabUser(t *testing.T, a *App, id int64, username string, email string) (*model.User, oauthgitlab.GitLabUser) {
r := rand.New(rand.NewSource(time.Now().UnixNano())) gitlabUserObj := oauthgitlab.GitLabUser{Id: id, Username: username, Login: "user1", Email: email, Name: "Test User"}
gitlabUserObj := oauthgitlab.GitLabUser{Id: int64(r.Intn(1000)) + 1, Username: username, Login: "user1", Email: email, Name: "Test User"}
gitlabUser := getGitlabUserPayload(gitlabUserObj, t) gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
var user *model.User var user *model.User

Просмотреть файл

@@ -21,7 +21,7 @@ services:
POSTGRES_PASSWORD: mostest POSTGRES_PASSWORD: mostest
POSTGRES_DB: mattermost_test POSTGRES_DB: mattermost_test
minio: minio:
image: "minio/minio:RELEASE.2019-08-14T20-37-41Z" image: "minio/minio:RELEASE.2019-10-11T00-38-09Z"
command: "server /data" command: "server /data"
networks: networks:
- mm-test - mm-test

Просмотреть файл

@@ -72,16 +72,16 @@ func runServer(configStore config.Store, disableConfigWatch bool, usedPlatform b
mlog.Error("The platform binary has been deprecated, please switch to using the mattermost binary.") mlog.Error("The platform binary has been deprecated, please switch to using the mattermost binary.")
} }
api := api4.Init(server, server.AppOptions, server.Router)
wsapi.Init(server.FakeApp(), server.WebSocketRouter)
web.New(server, server.AppOptions, server.Router)
serverErr := server.Start() serverErr := server.Start()
if serverErr != nil { if serverErr != nil {
mlog.Critical(serverErr.Error()) mlog.Critical(serverErr.Error())
return serverErr return serverErr
} }
api := api4.Init(server, server.AppOptions, server.Router)
wsapi.Init(server.FakeApp(), server.WebSocketRouter)
web.New(server, server.AppOptions, server.Router)
// If we allow testing then listen for manual testing URL hits // If we allow testing then listen for manual testing URL hits
if *server.Config().ServiceSettings.EnableTesting { if *server.Config().ServiceSettings.EnableTesting {
manualtesting.Init(api) manualtesting.Init(api)

2
go.mod
Просмотреть файл

@@ -50,7 +50,7 @@ require (
github.com/mattn/go-runewidth v0.0.4 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mattn/go-sqlite3 v1.11.0 github.com/mattn/go-sqlite3 v1.11.0
github.com/miekg/dns v1.1.19 // indirect github.com/miekg/dns v1.1.19 // indirect
github.com/minio/minio-go/v6 v6.0.38 github.com/minio/minio-go/v6 v6.0.40
github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect
github.com/muesli/smartcrop v0.3.0 // indirect github.com/muesli/smartcrop v0.3.0 // indirect
github.com/olekukonko/tablewriter v0.0.1 // indirect github.com/olekukonko/tablewriter v0.0.1 // indirect

4
go.sum
Просмотреть файл

@@ -263,8 +263,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.19 h1:0ymbfaLG1/utH2+BydNiF+dx1jSEmdr/nylOtkGHZZg= github.com/miekg/dns v1.1.19 h1:0ymbfaLG1/utH2+BydNiF+dx1jSEmdr/nylOtkGHZZg=
github.com/miekg/dns v1.1.19/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.19/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/minio/minio-go/v6 v6.0.38 h1:zd3yagckaBVAMJT+HsbpURx9ndqYQp/N/udc1UVS72E= github.com/minio/minio-go/v6 v6.0.40 h1:MlSCSXvItiu2jINMxYdhUU99KR4446Db+0iAU1IKaZ0=
github.com/minio/minio-go/v6 v6.0.38/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg= github.com/minio/minio-go/v6 v6.0.40/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=

Просмотреть файл

@@ -764,7 +764,7 @@
}, },
{ {
"id": "api.command_invite.group_constrained_user_denied", "id": "api.command_invite.group_constrained_user_denied",
"translation": "User cannot be added to this channel because it is constrained to group members only." "translation": "This channel is managed by groups. This user is not part of a group that is synched to this channel."
}, },
{ {
"id": "api.command_invite.hint", "id": "api.command_invite.hint",
@@ -1864,7 +1864,7 @@
}, },
{ {
"id": "api.team.add_members.user_denied", "id": "api.team.add_members.user_denied",
"translation": "Team membership denied to the following users because of group constraints: {{ .UserIDs }}" "translation": "This team is managed by groups. This user is not part of a group that is synched to this team."
}, },
{ {
"id": "api.team.add_user_to_team.added", "id": "api.team.add_user_to_team.added",

Просмотреть файл

@@ -2235,6 +2235,16 @@ func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Chann
return ChannelSliceFromJson(r.Body), BuildResponse(r) return ChannelSliceFromJson(r.Body), BuildResponse(r)
} }
// SearchArchivedChannels returns the archived channels on a team matching the provided search term.
func (c *Client4) SearchArchivedChannels(teamId string, search *ChannelSearch) ([]*Channel, *Response) {
r, err := c.DoApiPost(c.GetChannelsForTeamRoute(teamId)+"/search_archived", search.ToJson())
if err != nil {
return nil, BuildErrorResponse(r, err)
}
defer closeBody(r)
return ChannelSliceFromJson(r.Body), BuildResponse(r)
}
// SearchAllChannels search in all the channels. Must be a system administrator. // SearchAllChannels search in all the channels. Must be a system administrator.
func (c *Client4) SearchAllChannels(search *ChannelSearch) (*ChannelListWithTeamData, *Response) { func (c *Client4) SearchAllChannels(search *ChannelSearch) (*ChannelListWithTeamData, *Response) {
r, err := c.DoApiPost(c.GetChannelsRoute()+"/search", search.ToJson()) r, err := c.DoApiPost(c.GetChannelsRoute()+"/search", search.ToJson())

Просмотреть файл

@@ -24,109 +24,182 @@ func TestFileInfoIsValid(t *testing.T) {
Path: "fake/path.png", Path: "fake/path.png",
} }
require.Nil(t, info.IsValid()) t.Run("Valid File Info", func(t *testing.T) {
assert.Nil(t, info.IsValid())
})
info.Id = "" t.Run("Empty ID is not valid", func(t *testing.T) {
require.NotNil(t, info.IsValid(), "empty Id isn't valid") info.Id = ""
assert.NotNil(t, info.IsValid(), "empty Id isn't valid")
info.Id = NewId()
})
info.Id = NewId() t.Run("CreateAt 0 is not valid", func(t *testing.T) {
info.CreateAt = 0 info.CreateAt = 0
require.NotNil(t, info.IsValid(), "empty CreateAt isn't valid") assert.NotNil(t, info.IsValid(), "empty CreateAt isn't valid")
info.CreateAt = 1234
})
info.CreateAt = 1234 t.Run("UpdateAt 0 is not valid", func(t *testing.T) {
info.UpdateAt = 0 info.UpdateAt = 0
require.NotNil(t, info.IsValid(), "empty UpdateAt isn't valid") assert.NotNil(t, info.IsValid(), "empty UpdateAt isn't valid")
info.UpdateAt = 1234
})
info.UpdateAt = 1234 t.Run("New Post ID is valid", func(t *testing.T) {
info.PostId = NewId() info.PostId = NewId()
require.Nil(t, info.IsValid()) assert.Nil(t, info.IsValid())
})
info.Path = "" t.Run("Empty path is not valid", func(t *testing.T) {
require.NotNil(t, info.IsValid(), "empty Path isn't valid") info.Path = ""
assert.NotNil(t, info.IsValid(), "empty Path isn't valid")
info.Path = "fake/path.png" info.Path = "fake/path.png"
require.Nil(t, info.IsValid()) })
} }
func TestFileInfoIsImage(t *testing.T) { func TestFileInfoIsImage(t *testing.T) {
info := &FileInfo{MimeType: "image/png"} info := &FileInfo{}
assert.True(t, info.IsImage(), "file is an image") t.Run("MimeType set to image/png is considered an image", func(t *testing.T) {
info.MimeType = "image/png"
assert.True(t, info.IsImage(), "PNG file should be considered as an image")
})
info.MimeType = "text/plain" t.Run("MimeType set to text/plain is not considered an image", func(t *testing.T) {
assert.False(t, info.IsImage(), "file is not an image") info.MimeType = "text/plain"
assert.False(t, info.IsImage(), "Text file should not be considered as an image")
})
} }
func TestGetInfoForFile(t *testing.T) { func TestGetInfoForFile(t *testing.T) {
fakeFile := make([]byte, 1000) fakeFile := make([]byte, 1000)
info, errApp := GetInfoForBytes("file.txt", fakeFile)
require.Nil(t, errApp)
assert.Equalf(t, info.Name, "file.txt", "Got incorrect filename: %v", info.Name)
assert.Equalf(t, info.Extension, "txt", "Got incorrect extension: %v", info.Extension)
assert.EqualValuesf(t, info.Size, 1000, "Got incorrect size: %v", info.Size)
assert.Truef(t, strings.HasPrefix(info.MimeType, "text/plain"), "Got incorrect mime type: %v", info.MimeType)
assert.Equalf(t, info.Width, 0, "Got incorrect width: %v", info.Width)
assert.Equalf(t, info.Height, 0, "Got incorrect height: %v", info.Height)
assert.Falsef(t, info.HasPreviewImage, "Got incorrect has preview image: %v", info.HasPreviewImage)
pngFile, err := ioutil.ReadFile("../tests/test.png") pngFile, err := ioutil.ReadFile("../tests/test.png")
require.Nilf(t, err, "Failed to load test.png") require.Nilf(t, err, "Failed to load test.png")
info, err = GetInfoForBytes("test.png", pngFile)
require.Nil(t, err)
assert.Equalf(t, info.Name, "test.png", "Got incorrect filename: %v", info.Name)
assert.Equalf(t, info.Extension, "png", "Got incorrect extension: %v", info.Extension)
assert.EqualValues(t, info.Size, 279591, "Got incorrect size: %v", info.Size)
assert.Equalf(t, info.MimeType, "image/png", "Got incorrect mime type: %v", info.MimeType)
assert.Equalf(t, info.Width, 408, "Got incorrect width: %v", info.Width)
assert.Equalf(t, info.Height, 336, "Got incorrect height: %v", info.Height)
assert.Truef(t, info.HasPreviewImage, "Got incorrect has preview image: %v", info.HasPreviewImage)
// base 64 encoded version of handtinywhite.gif from http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever // base 64 encoded version of handtinywhite.gif from http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever
gifFile, _ := base64.StdEncoding.DecodeString("R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=") gifFile, _ := base64.StdEncoding.DecodeString("R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=")
info, err = GetInfoForBytes("handtinywhite.gif", gifFile)
require.Nil(t, err)
assert.Equalf(t, info.Name, "handtinywhite.gif", "Got incorrect filename: %v", info.Name)
assert.Equalf(t, info.Extension, "gif", "Got incorrect extension: %v", info.Extension)
assert.EqualValuesf(t, info.Size, 35, "Got incorrect size: %v", info.Size)
assert.Equalf(t, info.MimeType, "image/gif", "Got incorrect mime type: %v", info.MimeType)
assert.Equalf(t, info.Width, 1, "Got incorrect width: %v", info.Width)
assert.Equalf(t, info.Height, 1, "Got incorrect height: %v", info.Height)
assert.Truef(t, info.HasPreviewImage, "Got incorrect has preview image: %v", info.HasPreviewImage)
animatedGifFile, err := ioutil.ReadFile("../tests/testgif.gif") animatedGifFile, err := ioutil.ReadFile("../tests/testgif.gif")
require.Nilf(t, err, "Failed to load testgif.gif") require.Nilf(t, err, "Failed to load testgif.gif")
info, err = GetInfoForBytes("testgif.gif", animatedGifFile) var ttc = []struct {
require.Nil(t, err) testName string
assert.Equalf(t, info.Name, "testgif.gif", "Got incorrect filename: %v", info.Name) filename string
assert.Equalf(t, info.Extension, "gif", "Got incorrect extension: %v", info.Extension) file []byte
assert.EqualValuesf(t, info.Size, 38689, "Got incorrect size: %v", info.Size) usePrefixForMime bool
assert.Equalf(t, info.MimeType, "image/gif", "Got incorrect mime type: %v", info.MimeType) expectedExtension string
assert.Equalf(t, info.Width, 118, "Got incorrect width: %v", info.Width) expectedSize int
assert.Equalf(t, info.Height, 118, "Got incorrect height: %v", info.Height) expectedMime string
assert.Falsef(t, info.HasPreviewImage, "Got incorrect has preview image: %v", info.HasPreviewImage) expectedWidth int
expectedHeight int
expectedHasPreviewImage bool
}{
{
testName: "Text File",
filename: "file.txt",
file: fakeFile,
usePrefixForMime: true,
expectedExtension: "txt",
expectedSize: 1000,
expectedMime: "text/plain",
expectedWidth: 0,
expectedHeight: 0,
expectedHasPreviewImage: false,
},
{
testName: "PNG file",
filename: "test.png",
file: pngFile,
usePrefixForMime: false,
expectedExtension: "png",
expectedSize: 279591,
expectedMime: "image/png",
expectedWidth: 408,
expectedHeight: 336,
expectedHasPreviewImage: true,
},
{
testName: "Static Gif File",
filename: "handtinywhite.gif",
file: gifFile,
usePrefixForMime: false,
expectedExtension: "gif",
expectedSize: 35,
expectedMime: "image/gif",
expectedWidth: 1,
expectedHeight: 1,
expectedHasPreviewImage: true,
},
{
testName: "Animated Gif File",
filename: "testgif.gif",
file: animatedGifFile,
usePrefixForMime: false,
expectedExtension: "gif",
expectedSize: 38689,
expectedMime: "image/gif",
expectedWidth: 118,
expectedHeight: 118,
expectedHasPreviewImage: false,
},
{
testName: "No extension File",
filename: "filewithoutextension",
file: fakeFile,
usePrefixForMime: false,
expectedExtension: "",
expectedSize: 1000,
expectedMime: "",
expectedWidth: 0,
expectedHeight: 0,
expectedHasPreviewImage: false,
},
{
// Always make the extension lower case to make it easier to use in other places
testName: "Uppercase extension File",
filename: "file.TXT",
file: fakeFile,
usePrefixForMime: true,
expectedExtension: "txt",
expectedSize: 1000,
expectedMime: "text/plain",
expectedWidth: 0,
expectedHeight: 0,
expectedHasPreviewImage: false,
},
{
// Don't error out for image formats we don't support
testName: "Not supported File",
filename: "file.tif",
file: fakeFile,
usePrefixForMime: false,
expectedExtension: "tif",
expectedSize: 1000,
expectedMime: "image/tiff",
expectedWidth: 0,
expectedHeight: 0,
expectedHasPreviewImage: false,
},
}
info, err = GetInfoForBytes("filewithoutextension", fakeFile) for _, tc := range ttc {
require.Nil(t, err) t.Run(tc.testName, func(t *testing.T) {
assert.Equalf(t, info.Name, "filewithoutextension", "Got incorrect filename: %v", info.Name) info, errApp := GetInfoForBytes(tc.filename, tc.file)
assert.Equalf(t, info.Extension, "", "Got incorrect extension: %v", info.Extension) require.Nil(t, errApp)
assert.EqualValuesf(t, info.Size, 1000, "Got incorrect size: %v", info.Size)
assert.Equalf(t, info.MimeType, "", "Got incorrect mime type: %v", info.MimeType)
assert.Equalf(t, info.Width, 0, "Got incorrect width: %v", info.Width)
assert.Equalf(t, info.Height, 0, "Got incorrect height: %v", info.Height)
assert.Falsef(t, info.HasPreviewImage, "Got incorrect has preview image: %v", info.HasPreviewImage)
// Always make the extension lower case to make it easier to use in other places assert.Equalf(t, tc.filename, info.Name, "Got incorrect filename: %v", info.Name)
info, err = GetInfoForBytes("file.TXT", fakeFile) assert.Equalf(t, tc.expectedExtension, info.Extension, "Got incorrect extension: %v", info.Extension)
require.Nil(t, err) assert.EqualValuesf(t, tc.expectedSize, info.Size, "Got incorrect size: %v", info.Size)
assert.Equalf(t, info.Name, "file.TXT", "Got incorrect filename: %v", info.Name) assert.Equalf(t, tc.expectedWidth, info.Width, "Got incorrect width: %v", info.Width)
assert.Equalf(t, info.Extension, "txt", "Got incorrect extension: %v", info.Extension) assert.Equalf(t, tc.expectedHeight, info.Height, "Got incorrect height: %v", info.Height)
assert.Equalf(t, tc.expectedHasPreviewImage, info.HasPreviewImage, "Got incorrect has preview image: %v", info.HasPreviewImage)
// Don't error out for image formats we don't support if tc.usePrefixForMime {
info, err = GetInfoForBytes("file.tif", fakeFile) assert.Truef(t, strings.HasPrefix(info.MimeType, tc.expectedMime), "Got incorrect mime type: %v", info.MimeType)
require.Nil(t, err) } else {
assert.Equalf(t, info.Name, "file.tif", "Got incorrect filename: %v", info.Name) assert.Equalf(t, tc.expectedMime, info.MimeType, "Got incorrect mime type: %v", info.MimeType)
assert.Equalf(t, info.Extension, "tif", "Got incorrect extension: %v", info.Extension) }
assert.True(t, info.MimeType == "image/x-tiff" || info.MimeType == "image/tiff", "Got incorrect mime type: %v", info.MimeType) })
}
} }

Просмотреть файл

@@ -512,9 +512,11 @@ func (u *User) Sanitize(options map[string]bool) {
} }
// Remove any input data from the user object that is not user controlled // Remove any input data from the user object that is not user controlled
func (u *User) SanitizeInput() { func (u *User) SanitizeInput(isAdmin bool) {
u.AuthData = NewString("") if !isAdmin {
u.AuthService = "" u.AuthData = NewString("")
u.AuthService = ""
}
u.LastPasswordUpdate = 0 u.LastPasswordUpdate = 0
u.LastPictureUpdate = 0 u.LastPictureUpdate = 0
u.FailedAttempts = 0 u.FailedAttempts = 0

Просмотреть файл

@@ -9,6 +9,9 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Helpers provide a common patterns plugins use.
//
// Plugins obtain access to the Helpers by embedding MattermostPlugin.
type Helpers interface { type Helpers interface {
// EnsureBot either returns an existing bot user matching the given bot, or creates a bot user from the given bot. // EnsureBot either returns an existing bot user matching the given bot, or creates a bot user from the given bot.
// Returns the id of the resulting bot. // Returns the id of the resulting bot.
@@ -55,6 +58,7 @@ type Helpers interface {
KVSetWithExpiryJSON(key string, value interface{}, expireInSeconds int64) error KVSetWithExpiryJSON(key string, value interface{}, expireInSeconds int64) error
} }
// HelpersImpl implements the helpers interface with an API that retrieves data on behalf of the plugin.
type HelpersImpl struct { type HelpersImpl struct {
API API API API
} }

Просмотреть файл

@@ -4,12 +4,14 @@
package plugin package plugin
import ( import (
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils" "github.com/mattermost/mattermost-server/utils"
"github.com/pkg/errors"
) )
func (p *HelpersImpl) EnsureBot(bot *model.Bot) (retBotId string, retErr error) { // EnsureBot implements Helpers.EnsureBot
func (p *HelpersImpl) EnsureBot(bot *model.Bot) (retBotID string, retErr error) {
err := p.ensureServerVersion("5.10.0") err := p.ensureServerVersion("5.10.0")
if err != nil { if err != nil {
return "", errors.Wrap(err, "failed to ensure bot") return "", errors.Wrap(err, "failed to ensure bot")
@@ -23,34 +25,34 @@ func (p *HelpersImpl) EnsureBot(bot *model.Bot) (retBotId string, retErr error)
// If we fail for any reason, this could be a race between creation of bot and // If we fail for any reason, this could be a race between creation of bot and
// retrieval from another EnsureBot. Just try the basic retrieve existing again. // retrieval from another EnsureBot. Just try the basic retrieve existing again.
defer func() { defer func() {
if retBotId == "" || retErr != nil { if retBotID == "" || retErr != nil {
var err error var err error
var botIdBytes []byte var botIDBytes []byte
err = utils.ProgressiveRetry(func() error { err = utils.ProgressiveRetry(func() error {
botIdBytes, err = p.API.KVGet(BOT_USER_KEY) botIDBytes, err = p.API.KVGet(BOT_USER_KEY)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
}) })
if err == nil && botIdBytes != nil { if err == nil && botIDBytes != nil {
retBotId = string(botIdBytes) retBotID = string(botIDBytes)
retErr = nil retErr = nil
} }
} }
}() }()
botIdBytes, kvGetErr := p.API.KVGet(BOT_USER_KEY) botIDBytes, kvGetErr := p.API.KVGet(BOT_USER_KEY)
if kvGetErr != nil { if kvGetErr != nil {
return "", errors.Wrap(kvGetErr, "failed to get bot") return "", errors.Wrap(kvGetErr, "failed to get bot")
} }
// If the bot has already been created, there is nothing to do. // If the bot has already been created, there is nothing to do.
if botIdBytes != nil { if botIDBytes != nil {
botId := string(botIdBytes) botID := string(botIDBytes)
return botId, nil return botID, nil
} }
// Check for an existing bot user with that username. If one exists, then use that. // Check for an existing bot user with that username. If one exists, then use that.

Просмотреть файл

@@ -24,6 +24,18 @@ import (
"github.com/mattermost/mattermost-server/utils" "github.com/mattermost/mattermost-server/utils"
) )
type mailData struct {
mimeTo string
smtpTo string
from mail.Address
replyTo mail.Address
subject string
htmlBody string
attachments []*model.FileInfo
embeddedFiles map[string]io.Reader
mimeHeaders map[string]string
}
// smtpClient is implemented by an smtp.Client. See https://golang.org/pkg/net/smtp/#Client. // smtpClient is implemented by an smtp.Client. See https://golang.org/pkg/net/smtp/#Client.
// //
type smtpClient interface { type smtpClient interface {
@@ -204,15 +216,29 @@ func TestConnection(config *model.Config) {
defer c.Close() defer c.Close()
} }
func SendMailUsingConfig(to, subject, htmlBody string, config *model.Config, enableComplianceFeatures bool) *model.AppError { func SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, config *model.Config, enableComplianceFeatures bool) *model.AppError {
fromMail := mail.Address{Name: *config.EmailSettings.FeedbackName, Address: *config.EmailSettings.FeedbackEmail} fromMail := mail.Address{Name: *config.EmailSettings.FeedbackName, Address: *config.EmailSettings.FeedbackEmail}
replyTo := mail.Address{Name: *config.EmailSettings.FeedbackName, Address: *config.EmailSettings.ReplyToAddress} replyTo := mail.Address{Name: *config.EmailSettings.FeedbackName, Address: *config.EmailSettings.ReplyToAddress}
return SendMailUsingConfigAdvanced(to, to, fromMail, replyTo, subject, htmlBody, nil, nil, nil, config, enableComplianceFeatures) mail := mailData{
mimeTo: to,
smtpTo: to,
from: fromMail,
replyTo: replyTo,
subject: subject,
htmlBody: htmlBody,
embeddedFiles: embeddedFiles,
}
return sendMailUsingConfigAdvanced(mail, config, enableComplianceFeatures)
}
func SendMailUsingConfig(to, subject, htmlBody string, config *model.Config, enableComplianceFeatures bool) *model.AppError {
return SendMailWithEmbeddedFilesUsingConfig(to, subject, htmlBody, nil, config, enableComplianceFeatures)
} }
// allows for sending an email with attachments and differing MIME/SMTP recipients // allows for sending an email with attachments and differing MIME/SMTP recipients
func SendMailUsingConfigAdvanced(mimeTo, smtpTo string, from, replyTo mail.Address, subject, htmlBody string, attachments []*model.FileInfo, embeddedFiles map[string]io.Reader, mimeHeaders map[string]string, config *model.Config, enableComplianceFeatures bool) *model.AppError { func sendMailUsingConfigAdvanced(mail mailData, config *model.Config, enableComplianceFeatures bool) *model.AppError {
if len(*config.EmailSettings.SMTPServer) == 0 { if len(*config.EmailSettings.SMTPServer) == 0 {
return nil return nil
} }
@@ -235,34 +261,34 @@ func SendMailUsingConfigAdvanced(mimeTo, smtpTo string, from, replyTo mail.Addre
return err return err
} }
return SendMail(c, mimeTo, smtpTo, from, replyTo, subject, htmlBody, attachments, embeddedFiles, mimeHeaders, fileBackend, time.Now()) return SendMail(c, mail, fileBackend, time.Now())
} }
func SendMail(c smtpClient, mimeTo, smtpTo string, from, replyTo mail.Address, subject, htmlBody string, attachments []*model.FileInfo, embeddedFiles map[string]io.Reader, mimeHeaders map[string]string, fileBackend filesstore.FileBackend, date time.Time) *model.AppError { func SendMail(c smtpClient, mail mailData, fileBackend filesstore.FileBackend, date time.Time) *model.AppError {
mlog.Debug("sending mail", mlog.String("to", smtpTo), mlog.String("subject", subject)) mlog.Debug("sending mail", mlog.String("to", mail.smtpTo), mlog.String("subject", mail.subject))
htmlMessage := "\r\n<html><body>" + htmlBody + "</body></html>" htmlMessage := "\r\n<html><body>" + mail.htmlBody + "</body></html>"
txtBody, err := html2text.FromString(htmlBody) txtBody, err := html2text.FromString(mail.htmlBody)
if err != nil { if err != nil {
mlog.Warn("Unable to convert html body to text", mlog.Err(err)) mlog.Warn("Unable to convert html body to text", mlog.Err(err))
txtBody = "" txtBody = ""
} }
headers := map[string][]string{ headers := map[string][]string{
"From": {from.String()}, "From": {mail.from.String()},
"To": {mimeTo}, "To": {mail.mimeTo},
"Subject": {encodeRFC2047Word(subject)}, "Subject": {encodeRFC2047Word(mail.subject)},
"Content-Transfer-Encoding": {"8bit"}, "Content-Transfer-Encoding": {"8bit"},
"Auto-Submitted": {"auto-generated"}, "Auto-Submitted": {"auto-generated"},
"Precedence": {"bulk"}, "Precedence": {"bulk"},
} }
if len(replyTo.Address) > 0 { if len(mail.replyTo.Address) > 0 {
headers["Reply-To"] = []string{replyTo.String()} headers["Reply-To"] = []string{mail.replyTo.String()}
} }
for k, v := range mimeHeaders { for k, v := range mail.mimeHeaders {
headers[k] = []string{encodeRFC2047Word(v)} headers[k] = []string{encodeRFC2047Word(v)}
} }
@@ -272,11 +298,11 @@ func SendMail(c smtpClient, mimeTo, smtpTo string, from, replyTo mail.Address, s
m.SetBody("text/plain", txtBody) m.SetBody("text/plain", txtBody)
m.AddAlternative("text/html", htmlMessage) m.AddAlternative("text/html", htmlMessage)
for name, reader := range embeddedFiles { for name, reader := range mail.embeddedFiles {
m.EmbedReader(name, reader) m.EmbedReader(name, reader)
} }
for _, fileInfo := range attachments { for _, fileInfo := range mail.attachments {
bytes, err := fileBackend.ReadFile(fileInfo.Path) bytes, err := fileBackend.ReadFile(fileInfo.Path)
if err != nil { if err != nil {
return err return err
@@ -290,11 +316,11 @@ func SendMail(c smtpClient, mimeTo, smtpTo string, from, replyTo mail.Address, s
})) }))
} }
if err = c.Mail(from.Address); err != nil { if err = c.Mail(mail.from.Address); err != nil {
return model.NewAppError("SendMail", "utils.mail.send_mail.from_address.app_error", nil, err.Error(), http.StatusInternalServerError) return model.NewAppError("SendMail", "utils.mail.send_mail.from_address.app_error", nil, err.Error(), http.StatusInternalServerError)
} }
if err = c.Rcpt(smtpTo); err != nil { if err = c.Rcpt(mail.smtpTo); err != nil {
return model.NewAppError("SendMail", "utils.mail.send_mail.to_address.app_error", nil, err.Error(), http.StatusInternalServerError) return model.NewAppError("SendMail", "utils.mail.send_mail.to_address.app_error", nil, err.Error(), http.StatusInternalServerError)
} }

Просмотреть файл

@@ -128,6 +128,50 @@ func TestSendMailUsingConfig(t *testing.T) {
} }
} }
func TestSendMailWithEmbeddedFilesUsingConfig(t *testing.T) {
utils.T = utils.GetUserTranslations("en")
fs, err := config.NewFileStore("config.json", false)
require.Nil(t, err)
cfg := fs.Get()
var emailTo = "test@example.com"
var emailSubject = "Testing this email"
var emailBody = "This is a test from autobot"
//Delete all the messages before check the sample email
DeleteMailBox(emailTo)
embeddedFiles := map[string]io.Reader{
"test1.png": bytes.NewReader([]byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")),
"test2.png": bytes.NewReader([]byte("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")),
}
err2 := SendMailWithEmbeddedFilesUsingConfig(emailTo, emailSubject, emailBody, embeddedFiles, cfg, true)
require.Nil(t, err2, "Should connect to the SMTP Server")
//Check if the email was send to the right email address
var resultsMailbox JSONMessageHeaderInbucket
err3 := RetryInbucket(5, func() error {
var err error
resultsMailbox, err = GetMailBox(emailTo)
return err
})
if err3 != nil {
t.Log(err3)
t.Log("No email was received, maybe due load on the server. Skipping this verification")
} else {
if len(resultsMailbox) > 0 {
require.Contains(t, resultsMailbox[0].To[0], emailTo, "Wrong To: recipient")
resultsEmail, err := GetMessageFromMailbox(emailTo, resultsMailbox[0].ID)
require.Nil(t, err, "Could not get message from mailbox")
require.Contains(t, emailBody, resultsEmail.Body.Text, "Wrong received message %s", resultsEmail.Body.Text)
// Usign the message size because the inbucket API doesn't return embedded attachments through the API
require.Greater(t, resultsEmail.Size, 1500, "the file size should be more because the embedded attachemtns")
}
}
}
func TestSendMailUsingConfigAdvanced(t *testing.T) { func TestSendMailUsingConfigAdvanced(t *testing.T) {
utils.T = utils.GetUserTranslations("en") utils.T = utils.GetUserTranslations("en")
@@ -136,15 +180,8 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
cfg := fs.Get() cfg := fs.Get()
var mimeTo = "test@example.com"
var smtpTo = "test2@example.com"
var from = mail.Address{Name: "Nobody", Address: "nobody@mattermost.com"}
var replyTo = mail.Address{Name: "ReplyTo", Address: "reply_to@mattermost.com"}
var emailSubject = "Testing this email"
var emailBody = "This is a test from autobot"
//Delete all the messages before check the sample email //Delete all the messages before check the sample email
DeleteMailBox(smtpTo) DeleteMailBox("test2@example.com")
fileBackend, err := filesstore.NewFileBackend(&cfg.FileSettings, true) fileBackend, err := filesstore.NewFileBackend(&cfg.FileSettings, true)
assert.Nil(t, err) assert.Nil(t, err)
@@ -178,31 +215,43 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
headers := make(map[string]string) headers := make(map[string]string)
headers["TestHeader"] = "TestValue" headers["TestHeader"] = "TestValue"
err = SendMailUsingConfigAdvanced(mimeTo, smtpTo, from, replyTo, emailSubject, emailBody, attachments, embeddedFiles, headers, cfg, true) mail := mailData{
mimeTo: "test@example.com",
smtpTo: "test2@example.com",
from: mail.Address{Name: "Nobody", Address: "nobody@mattermost.com"},
replyTo: mail.Address{Name: "ReplyTo", Address: "reply_to@mattermost.com"},
subject: "Testing this email",
htmlBody: "This is a test from autobot",
attachments: attachments,
embeddedFiles: embeddedFiles,
mimeHeaders: headers,
}
err = sendMailUsingConfigAdvanced(mail, cfg, true)
require.Nil(t, err, "Should connect to the STMP Server: %v", err) require.Nil(t, err, "Should connect to the STMP Server: %v", err)
//Check if the email was send to the right email address //Check if the email was send to the right email address
var resultsMailbox JSONMessageHeaderInbucket var resultsMailbox JSONMessageHeaderInbucket
err = RetryInbucket(5, func() error { err = RetryInbucket(5, func() error {
var mailErr error var mailErr error
resultsMailbox, mailErr = GetMailBox(smtpTo) resultsMailbox, mailErr = GetMailBox(mail.smtpTo)
return mailErr return mailErr
}) })
require.Nil(t, err, "No emails found for address %s. error: %v", smtpTo, err) require.Nil(t, err, "No emails found for address %s. error: %v", mail.smtpTo, err)
require.NotEqual(t, len(resultsMailbox), 0) require.NotEqual(t, len(resultsMailbox), 0)
require.Contains(t, resultsMailbox[0].To[0], mimeTo, "Wrong To recipient") require.Contains(t, resultsMailbox[0].To[0], mail.mimeTo, "Wrong To recipient")
resultsEmail, err := GetMessageFromMailbox(smtpTo, resultsMailbox[0].ID) resultsEmail, err := GetMessageFromMailbox(mail.smtpTo, resultsMailbox[0].ID)
require.Nil(t, err) require.Nil(t, err)
require.Contains(t, emailBody, resultsEmail.Body.Text, "Wrong received message") require.Contains(t, mail.htmlBody, resultsEmail.Body.Text, "Wrong received message")
// verify that the To header of the email message is set to the MIME recipient, even though we got it out of the SMTP recipient's email inbox // verify that the To header of the email message is set to the MIME recipient, even though we got it out of the SMTP recipient's email inbox
assert.Equal(t, mimeTo, resultsEmail.Header["To"][0]) assert.Equal(t, mail.mimeTo, resultsEmail.Header["To"][0])
// verify that the MIME from address is correct - unfortunately, we can't verify the SMTP from address // verify that the MIME from address is correct - unfortunately, we can't verify the SMTP from address
assert.Equal(t, from.String(), resultsEmail.Header["From"][0]) assert.Equal(t, mail.from.String(), resultsEmail.Header["From"][0])
// check that the custom mime headers came through - header case seems to get mutated // check that the custom mime headers came through - header case seems to get mutated
assert.Equal(t, "TestValue", resultsEmail.Header["Testheader"][0]) assert.Equal(t, "TestValue", resultsEmail.Header["Testheader"][0])
@@ -330,7 +379,8 @@ func TestSendMail(t *testing.T) {
for testName, tc := range testCases { for testName, tc := range testCases {
t.Run(testName, func(t *testing.T) { t.Run(testName, func(t *testing.T) {
appErr = SendMail(mocm, "", "", mail.Address{}, tc.replyTo, "", "", nil, nil, nil, mockBackend, time.Now()) mail := mailData{"", "", mail.Address{}, tc.replyTo, "", "", nil, nil, nil}
appErr = SendMail(mocm, mail, mockBackend, time.Now())
require.Nil(t, appErr) require.Nil(t, appErr)
if len(tc.contains) > 0 { if len(tc.contains) > 0 {
require.Contains(t, string(mocm.data), tc.contains) require.Contains(t, string(mocm.data), tc.contains)

Просмотреть файл

@@ -1242,10 +1242,24 @@ func (s SqlChannelStore) GetDeletedByName(teamId string, name string) (*model.Ch
return &channel, nil return &channel, nil
} }
func (s SqlChannelStore) GetDeleted(teamId string, offset int, limit int) (*model.ChannelList, *model.AppError) { func (s SqlChannelStore) GetDeleted(teamId string, offset int, limit int, userId string) (*model.ChannelList, *model.AppError) {
channels := &model.ChannelList{} channels := &model.ChannelList{}
if _, err := s.GetReplica().Select(channels, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND DeleteAt != 0 ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset}); err != nil { query := `
SELECT * FROM Channels
WHERE (TeamId = :TeamId OR TeamId = '')
AND DeleteAt != 0
AND Type != 'P'
UNION
SELECT * FROM Channels
WHERE (TeamId = :TeamId OR TeamId = '')
AND DeleteAt != 0
AND Type = 'P'
AND Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId)
ORDER BY DisplayName LIMIT :Limit OFFSET :Offset
`
if _, err := s.GetReplica().Select(channels, query, map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset, "UserId": userId}); err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return nil, model.NewAppError("SqlChannelStore.GetDeleted", "store.sql_channel.get_deleted.missing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusNotFound) return nil, model.NewAppError("SqlChannelStore.GetDeleted", "store.sql_channel.get_deleted.missing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusNotFound)
} }
@@ -2245,6 +2259,57 @@ func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted
}) })
} }
func (s SqlChannelStore) SearchArchivedInTeam(teamId string, term string, userId string) (*model.ChannelList, *model.AppError) {
publicChannels, publicErr := s.performSearch(`
SELECT
Channels.*
FROM
Channels
JOIN
Channels c ON (c.Id = Channels.Id)
WHERE
c.TeamId = :TeamId
SEARCH_CLAUSE
AND c.DeleteAt != 0
AND c.Type != 'P'
ORDER BY c.DisplayName
LIMIT 100
`, term, map[string]interface{}{
"TeamId": teamId,
"UserId": userId,
})
privateChannels, privateErr := s.performSearch(`
SELECT
Channels.*
FROM
Channels
JOIN
Channels c ON (c.Id = Channels.Id)
WHERE
c.TeamId = :TeamId
SEARCH_CLAUSE
AND c.DeleteAt != 0
AND c.Type = 'P'
AND c.Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId)
ORDER BY c.DisplayName
LIMIT 100
`, term, map[string]interface{}{
"TeamId": teamId,
"UserId": userId,
})
output := *publicChannels
output = append(output, *privateChannels...)
outputErr := publicErr
if privateErr != nil {
outputErr = privateErr
}
return &output, outputErr
}
func (s SqlChannelStore) SearchForUserInTeam(userId string, teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) { func (s SqlChannelStore) SearchForUserInTeam(userId string, teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) {
deleteFilter := "AND c.DeleteAt = 0" deleteFilter := "AND c.DeleteAt = 0"
if includeDeleted { if includeDeleted {

Просмотреть файл

@@ -162,7 +162,7 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter
os.Exit(EXIT_CREATE_TABLE) os.Exit(EXIT_CREATE_TABLE)
} }
err = UpgradeDatabase(supplier, model.CurrentVersion) err = upgradeDatabase(supplier, model.CurrentVersion)
if err != nil { if err != nil {
mlog.Critical("Failed to upgrade database.", mlog.Err(err)) mlog.Critical("Failed to upgrade database.", mlog.Err(err))
time.Sleep(time.Second) time.Sleep(time.Second)

Просмотреть файл

@@ -70,10 +70,10 @@ const (
EXIT_TEAM_INVITEID_MIGRATION_FAILED = 1006 EXIT_TEAM_INVITEID_MIGRATION_FAILED = 1006
) )
// UpgradeDatabase attempts to migrate the schema to the latest supported version. // upgradeDatabase attempts to migrate the schema to the latest supported version.
// The value of model.CurrentVersion is accepted as a parameter for unit testing, but it is not // The value of model.CurrentVersion is accepted as a parameter for unit testing, but it is not
// used to stop migrations at that version. // used to stop migrations at that version.
func UpgradeDatabase(sqlStore SqlStore, currentModelVersionString string) error { func upgradeDatabase(sqlStore SqlStore, currentModelVersionString string) error {
currentModelVersion, err := semver.Parse(currentModelVersionString) currentModelVersion, err := semver.Parse(currentModelVersionString)
if err != nil { if err != nil {
return errors.Wrapf(err, "failed to parse current model version %s", currentModelVersionString) return errors.Wrapf(err, "failed to parse current model version %s", currentModelVersionString)
@@ -122,47 +122,47 @@ func UpgradeDatabase(sqlStore SqlStore, currentModelVersionString string) error
// Otherwise, apply any necessary migrations. Note that these methods currently invoke // Otherwise, apply any necessary migrations. Note that these methods currently invoke
// os.Exit instead of returning an error. // os.Exit instead of returning an error.
UpgradeDatabaseToVersion31(sqlStore) upgradeDatabaseToVersion31(sqlStore)
UpgradeDatabaseToVersion32(sqlStore) upgradeDatabaseToVersion32(sqlStore)
UpgradeDatabaseToVersion33(sqlStore) upgradeDatabaseToVersion33(sqlStore)
UpgradeDatabaseToVersion34(sqlStore) upgradeDatabaseToVersion34(sqlStore)
UpgradeDatabaseToVersion35(sqlStore) upgradeDatabaseToVersion35(sqlStore)
UpgradeDatabaseToVersion36(sqlStore) upgradeDatabaseToVersion36(sqlStore)
UpgradeDatabaseToVersion37(sqlStore) upgradeDatabaseToVersion37(sqlStore)
UpgradeDatabaseToVersion38(sqlStore) upgradeDatabaseToVersion38(sqlStore)
UpgradeDatabaseToVersion39(sqlStore) upgradeDatabaseToVersion39(sqlStore)
UpgradeDatabaseToVersion310(sqlStore) upgradeDatabaseToVersion310(sqlStore)
UpgradeDatabaseToVersion40(sqlStore) upgradeDatabaseToVersion40(sqlStore)
UpgradeDatabaseToVersion41(sqlStore) upgradeDatabaseToVersion41(sqlStore)
UpgradeDatabaseToVersion42(sqlStore) upgradeDatabaseToVersion42(sqlStore)
UpgradeDatabaseToVersion43(sqlStore) upgradeDatabaseToVersion43(sqlStore)
UpgradeDatabaseToVersion44(sqlStore) upgradeDatabaseToVersion44(sqlStore)
UpgradeDatabaseToVersion45(sqlStore) upgradeDatabaseToVersion45(sqlStore)
UpgradeDatabaseToVersion46(sqlStore) upgradeDatabaseToVersion46(sqlStore)
UpgradeDatabaseToVersion47(sqlStore) upgradeDatabaseToVersion47(sqlStore)
UpgradeDatabaseToVersion471(sqlStore) upgradeDatabaseToVersion471(sqlStore)
UpgradeDatabaseToVersion472(sqlStore) upgradeDatabaseToVersion472(sqlStore)
UpgradeDatabaseToVersion48(sqlStore) upgradeDatabaseToVersion48(sqlStore)
UpgradeDatabaseToVersion481(sqlStore) upgradeDatabaseToVersion481(sqlStore)
UpgradeDatabaseToVersion49(sqlStore) upgradeDatabaseToVersion49(sqlStore)
UpgradeDatabaseToVersion410(sqlStore) upgradeDatabaseToVersion410(sqlStore)
UpgradeDatabaseToVersion50(sqlStore) upgradeDatabaseToVersion50(sqlStore)
UpgradeDatabaseToVersion51(sqlStore) upgradeDatabaseToVersion51(sqlStore)
UpgradeDatabaseToVersion52(sqlStore) upgradeDatabaseToVersion52(sqlStore)
UpgradeDatabaseToVersion53(sqlStore) upgradeDatabaseToVersion53(sqlStore)
UpgradeDatabaseToVersion54(sqlStore) upgradeDatabaseToVersion54(sqlStore)
UpgradeDatabaseToVersion55(sqlStore) upgradeDatabaseToVersion55(sqlStore)
UpgradeDatabaseToVersion56(sqlStore) upgradeDatabaseToVersion56(sqlStore)
UpgradeDatabaseToVersion57(sqlStore) upgradeDatabaseToVersion57(sqlStore)
UpgradeDatabaseToVersion58(sqlStore) upgradeDatabaseToVersion58(sqlStore)
UpgradeDatabaseToVersion59(sqlStore) upgradeDatabaseToVersion59(sqlStore)
UpgradeDatabaseToVersion510(sqlStore) upgradeDatabaseToVersion510(sqlStore)
UpgradeDatabaseToVersion511(sqlStore) upgradeDatabaseToVersion511(sqlStore)
UpgradeDatabaseToVersion512(sqlStore) upgradeDatabaseToVersion512(sqlStore)
UpgradeDatabaseToVersion513(sqlStore) upgradeDatabaseToVersion513(sqlStore)
UpgradeDatabaseToVersion514(sqlStore) upgradeDatabaseToVersion514(sqlStore)
UpgradeDatabaseToVersion515(sqlStore) upgradeDatabaseToVersion515(sqlStore)
UpgradeDatabaseToVersion516(sqlStore) upgradeDatabaseToVersion516(sqlStore)
return nil return nil
} }
@@ -187,14 +187,14 @@ func shouldPerformUpgrade(sqlStore SqlStore, currentSchemaVersion string, expect
return false return false
} }
func UpgradeDatabaseToVersion31(sqlStore SqlStore) { func upgradeDatabaseToVersion31(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_0_0, VERSION_3_1_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_0_0, VERSION_3_1_0) {
sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "") sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "")
saveSchemaVersion(sqlStore, VERSION_3_1_0) saveSchemaVersion(sqlStore, VERSION_3_1_0)
} }
} }
func UpgradeDatabaseToVersion32(sqlStore SqlStore) { func upgradeDatabaseToVersion32(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_1_0, VERSION_3_2_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_1_0, VERSION_3_2_0) {
sqlStore.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0") sqlStore.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0")
@@ -208,7 +208,7 @@ func themeMigrationFailed(err error) {
os.Exit(EXIT_THEME_MIGRATION) os.Exit(EXIT_THEME_MIGRATION)
} }
func UpgradeDatabaseToVersion33(sqlStore SqlStore) { func upgradeDatabaseToVersion33(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_2_0, VERSION_3_3_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_2_0, VERSION_3_3_0) {
if sqlStore.DoesColumnExist("Users", "ThemeProps") { if sqlStore.DoesColumnExist("Users", "ThemeProps") {
params := map[string]interface{}{ params := map[string]interface{}{
@@ -291,7 +291,7 @@ func UpgradeDatabaseToVersion33(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion34(sqlStore SqlStore) { func upgradeDatabaseToVersion34(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_3_0, VERSION_3_4_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_3_0, VERSION_3_4_0) {
sqlStore.CreateColumnIfNotExists("Status", "Manual", "BOOLEAN", "BOOLEAN", "0") sqlStore.CreateColumnIfNotExists("Status", "Manual", "BOOLEAN", "BOOLEAN", "0")
sqlStore.CreateColumnIfNotExists("Status", "ActiveChannel", "varchar(26)", "varchar(26)", "") sqlStore.CreateColumnIfNotExists("Status", "ActiveChannel", "varchar(26)", "varchar(26)", "")
@@ -300,7 +300,7 @@ func UpgradeDatabaseToVersion34(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion35(sqlStore SqlStore) { func upgradeDatabaseToVersion35(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_4_0, VERSION_3_5_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_4_0, VERSION_3_5_0) {
sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user' WHERE Roles = ''") sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user' WHERE Roles = ''")
sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user system_admin' WHERE Roles = 'system_admin'") sqlStore.GetMaster().Exec("UPDATE Users SET Roles = 'system_user system_admin' WHERE Roles = 'system_admin'")
@@ -323,7 +323,7 @@ func UpgradeDatabaseToVersion35(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion36(sqlStore SqlStore) { func upgradeDatabaseToVersion36(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_5_0, VERSION_3_6_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_5_0, VERSION_3_6_0) {
sqlStore.CreateColumnIfNotExists("Posts", "HasReactions", "tinyint", "boolean", "0") sqlStore.CreateColumnIfNotExists("Posts", "HasReactions", "tinyint", "boolean", "0")
@@ -340,7 +340,7 @@ func UpgradeDatabaseToVersion36(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion37(sqlStore SqlStore) { func upgradeDatabaseToVersion37(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_6_0, VERSION_3_7_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_6_0, VERSION_3_7_0) {
// Add EditAt column to Posts // Add EditAt column to Posts
sqlStore.CreateColumnIfNotExists("Posts", "EditAt", " bigint", " bigint", "0") sqlStore.CreateColumnIfNotExists("Posts", "EditAt", " bigint", " bigint", "0")
@@ -349,7 +349,7 @@ func UpgradeDatabaseToVersion37(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion38(sqlStore SqlStore) { func upgradeDatabaseToVersion38(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_7_0, VERSION_3_8_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_7_0, VERSION_3_8_0) {
// Add the IsPinned column to posts. // Add the IsPinned column to posts.
sqlStore.CreateColumnIfNotExists("Posts", "IsPinned", "boolean", "boolean", "0") sqlStore.CreateColumnIfNotExists("Posts", "IsPinned", "boolean", "boolean", "0")
@@ -358,7 +358,7 @@ func UpgradeDatabaseToVersion38(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion39(sqlStore SqlStore) { func upgradeDatabaseToVersion39(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_8_0, VERSION_3_9_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_8_0, VERSION_3_9_0) {
sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE) sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE)
sqlStore.RemoveTableIfExists("PasswordRecovery") sqlStore.RemoveTableIfExists("PasswordRecovery")
@@ -367,19 +367,19 @@ func UpgradeDatabaseToVersion39(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion310(sqlStore SqlStore) { func upgradeDatabaseToVersion310(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_9_0, VERSION_3_10_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_9_0, VERSION_3_10_0) {
saveSchemaVersion(sqlStore, VERSION_3_10_0) saveSchemaVersion(sqlStore, VERSION_3_10_0)
} }
} }
func UpgradeDatabaseToVersion40(sqlStore SqlStore) { func upgradeDatabaseToVersion40(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_10_0, VERSION_4_0_0) { if shouldPerformUpgrade(sqlStore, VERSION_3_10_0, VERSION_4_0_0) {
saveSchemaVersion(sqlStore, VERSION_4_0_0) saveSchemaVersion(sqlStore, VERSION_4_0_0)
} }
} }
func UpgradeDatabaseToVersion41(sqlStore SqlStore) { func upgradeDatabaseToVersion41(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_0_0, VERSION_4_1_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_0_0, VERSION_4_1_0) {
// Increase maximum length of the Users table Roles column. // Increase maximum length of the Users table Roles column.
if sqlStore.GetMaxLengthOfColumnIfExists("Users", "Roles") != "256" { if sqlStore.GetMaxLengthOfColumnIfExists("Users", "Roles") != "256" {
@@ -392,19 +392,19 @@ func UpgradeDatabaseToVersion41(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion42(sqlStore SqlStore) { func upgradeDatabaseToVersion42(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_1_0, VERSION_4_2_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_1_0, VERSION_4_2_0) {
saveSchemaVersion(sqlStore, VERSION_4_2_0) saveSchemaVersion(sqlStore, VERSION_4_2_0)
} }
} }
func UpgradeDatabaseToVersion43(sqlStore SqlStore) { func upgradeDatabaseToVersion43(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_2_0, VERSION_4_3_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_2_0, VERSION_4_3_0) {
saveSchemaVersion(sqlStore, VERSION_4_3_0) saveSchemaVersion(sqlStore, VERSION_4_3_0)
} }
} }
func UpgradeDatabaseToVersion44(sqlStore SqlStore) { func upgradeDatabaseToVersion44(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_3_0, VERSION_4_4_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_3_0, VERSION_4_4_0) {
// Add the IsActive column to UserAccessToken. // Add the IsActive column to UserAccessToken.
sqlStore.CreateColumnIfNotExists("UserAccessTokens", "IsActive", "boolean", "boolean", "1") sqlStore.CreateColumnIfNotExists("UserAccessTokens", "IsActive", "boolean", "boolean", "1")
@@ -413,13 +413,13 @@ func UpgradeDatabaseToVersion44(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion45(sqlStore SqlStore) { func upgradeDatabaseToVersion45(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_4_0, VERSION_4_5_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_4_0, VERSION_4_5_0) {
saveSchemaVersion(sqlStore, VERSION_4_5_0) saveSchemaVersion(sqlStore, VERSION_4_5_0)
} }
} }
func UpgradeDatabaseToVersion46(sqlStore SqlStore) { func upgradeDatabaseToVersion46(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_5_0, VERSION_4_6_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_5_0, VERSION_4_6_0) {
sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "Username", "varchar(64)", "varchar(64)", "") sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "") sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "")
@@ -427,7 +427,7 @@ func UpgradeDatabaseToVersion46(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion47(sqlStore SqlStore) { func upgradeDatabaseToVersion47(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_6_0, VERSION_4_7_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_6_0, VERSION_4_7_0) {
sqlStore.AlterColumnTypeIfExists("Users", "Position", "varchar(128)", "varchar(128)") sqlStore.AlterColumnTypeIfExists("Users", "Position", "varchar(128)", "varchar(128)")
sqlStore.AlterColumnTypeIfExists("OAuthAuthData", "State", "varchar(1024)", "varchar(1024)") sqlStore.AlterColumnTypeIfExists("OAuthAuthData", "State", "varchar(1024)", "varchar(1024)")
@@ -437,37 +437,37 @@ func UpgradeDatabaseToVersion47(sqlStore SqlStore) {
} }
} }
// If any new instances started with 4.7, they would have the bad Email column on the func upgradeDatabaseToVersion471(sqlStore SqlStore) {
// ChannelMemberHistory table. So for those cases we need to do an upgrade between // If any new instances started with 4.7, they would have the bad Email column on the
// 4.7.0 and 4.7.1 // ChannelMemberHistory table. So for those cases we need to do an upgrade between
func UpgradeDatabaseToVersion471(sqlStore SqlStore) { // 4.7.0 and 4.7.1
if shouldPerformUpgrade(sqlStore, VERSION_4_7_0, VERSION_4_7_1) { if shouldPerformUpgrade(sqlStore, VERSION_4_7_0, VERSION_4_7_1) {
sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email") sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email")
saveSchemaVersion(sqlStore, VERSION_4_7_1) saveSchemaVersion(sqlStore, VERSION_4_7_1)
} }
} }
func UpgradeDatabaseToVersion472(sqlStore SqlStore) { func upgradeDatabaseToVersion472(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_7_1, VERSION_4_7_2) { if shouldPerformUpgrade(sqlStore, VERSION_4_7_1, VERSION_4_7_2) {
sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels") sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
saveSchemaVersion(sqlStore, VERSION_4_7_2) saveSchemaVersion(sqlStore, VERSION_4_7_2)
} }
} }
func UpgradeDatabaseToVersion48(sqlStore SqlStore) { func upgradeDatabaseToVersion48(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_7_2, VERSION_4_8_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_7_2, VERSION_4_8_0) {
saveSchemaVersion(sqlStore, VERSION_4_8_0) saveSchemaVersion(sqlStore, VERSION_4_8_0)
} }
} }
func UpgradeDatabaseToVersion481(sqlStore SqlStore) { func upgradeDatabaseToVersion481(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_8_0, VERSION_4_8_1) { if shouldPerformUpgrade(sqlStore, VERSION_4_8_0, VERSION_4_8_1) {
sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels") sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
saveSchemaVersion(sqlStore, VERSION_4_8_1) saveSchemaVersion(sqlStore, VERSION_4_8_1)
} }
} }
func UpgradeDatabaseToVersion49(sqlStore SqlStore) { func upgradeDatabaseToVersion49(sqlStore SqlStore) {
// This version of Mattermost includes an App-Layer migration which migrates from hard-coded roles configured by // This version of Mattermost includes an App-Layer migration which migrates from hard-coded roles configured by
// a number of parameters in `config.json` to a `Roles` table in the database. The migration code can be seen // a number of parameters in `config.json` to a `Roles` table in the database. The migration code can be seen
// in the file `app/app.go` in the function `DoAdvancedPermissionsMigration()`. // in the file `app/app.go` in the function `DoAdvancedPermissionsMigration()`.
@@ -485,7 +485,7 @@ func UpgradeDatabaseToVersion49(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion410(sqlStore SqlStore) { func upgradeDatabaseToVersion410(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_4_9_0, VERSION_4_10_0) { if shouldPerformUpgrade(sqlStore, VERSION_4_9_0, VERSION_4_10_0) {
sqlStore.RemoveIndexIfExists("Name_2", "Channels") sqlStore.RemoveIndexIfExists("Name_2", "Channels")
@@ -497,7 +497,7 @@ func UpgradeDatabaseToVersion410(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion50(sqlStore SqlStore) { func upgradeDatabaseToVersion50(sqlStore SqlStore) {
// This version of Mattermost includes an App-Layer migration which migrates from hard-coded emojis configured // This version of Mattermost includes an App-Layer migration which migrates from hard-coded emojis configured
// in `config.json` to a `Permission` in the database. The migration code can be seen // in `config.json` to a `Permission` in the database. The migration code can be seen
// in the file `app/app.go` in the function `DoEmojisPermissionsMigration()`. // in the file `app/app.go` in the function `DoEmojisPermissionsMigration()`.
@@ -536,13 +536,13 @@ func UpgradeDatabaseToVersion50(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion51(sqlStore SqlStore) { func upgradeDatabaseToVersion51(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_0_0, VERSION_5_1_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_0_0, VERSION_5_1_0) {
saveSchemaVersion(sqlStore, VERSION_5_1_0) saveSchemaVersion(sqlStore, VERSION_5_1_0)
} }
} }
func UpgradeDatabaseToVersion52(sqlStore SqlStore) { func upgradeDatabaseToVersion52(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_1_0, VERSION_5_2_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_1_0, VERSION_5_2_0) {
sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "Username", "varchar(64)", "varchar(64)", "") sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "") sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "IconURL", "varchar(1024)", "varchar(1024)", "")
@@ -550,13 +550,13 @@ func UpgradeDatabaseToVersion52(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion53(sqlStore SqlStore) { func upgradeDatabaseToVersion53(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_2_0, VERSION_5_3_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_2_0, VERSION_5_3_0) {
saveSchemaVersion(sqlStore, VERSION_5_3_0) saveSchemaVersion(sqlStore, VERSION_5_3_0)
} }
} }
func UpgradeDatabaseToVersion54(sqlStore SqlStore) { func upgradeDatabaseToVersion54(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_3_0, VERSION_5_4_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_3_0, VERSION_5_4_0) {
sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "Description", "varchar(500)", "varchar(500)") sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "Description", "varchar(500)", "varchar(500)")
sqlStore.AlterColumnTypeIfExists("IncomingWebhooks", "Description", "varchar(500)", "varchar(500)") sqlStore.AlterColumnTypeIfExists("IncomingWebhooks", "Description", "varchar(500)", "varchar(500)")
@@ -569,13 +569,13 @@ func UpgradeDatabaseToVersion54(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion55(sqlStore SqlStore) { func upgradeDatabaseToVersion55(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_4_0, VERSION_5_5_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_4_0, VERSION_5_5_0) {
saveSchemaVersion(sqlStore, VERSION_5_5_0) saveSchemaVersion(sqlStore, VERSION_5_5_0)
} }
} }
func UpgradeDatabaseToVersion56(sqlStore SqlStore) { func upgradeDatabaseToVersion56(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_5_0, VERSION_5_6_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_5_0, VERSION_5_6_0) {
sqlStore.CreateColumnIfNotExists("PluginKeyValueStore", "ExpireAt", "bigint(20)", "bigint", "0") sqlStore.CreateColumnIfNotExists("PluginKeyValueStore", "ExpireAt", "bigint(20)", "bigint", "0")
@@ -595,15 +595,15 @@ func UpgradeDatabaseToVersion56(sqlStore SqlStore) {
} }
func UpgradeDatabaseToVersion57(sqlStore SqlStore) { func upgradeDatabaseToVersion57(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_6_0, VERSION_5_7_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_6_0, VERSION_5_7_0) {
saveSchemaVersion(sqlStore, VERSION_5_7_0) saveSchemaVersion(sqlStore, VERSION_5_7_0)
} }
} }
func UpgradeDatabaseToVersion58(sqlStore SqlStore) { func upgradeDatabaseToVersion58(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_7_0, VERSION_5_8_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_7_0, VERSION_5_8_0) {
// idx_channels_txt was removed in `UpgradeDatabaseToVersion50`, but merged as part of // idx_channels_txt was removed in `upgradeDatabaseToVersion50`, but merged as part of
// v5.1, so the migration wouldn't apply to anyone upgrading from v5.0. Remove it again to // v5.1, so the migration wouldn't apply to anyone upgrading from v5.0. Remove it again to
// bring the upgraded (from v5.0) and fresh install schemas back in sync. // bring the upgraded (from v5.0) and fresh install schemas back in sync.
sqlStore.RemoveIndexIfExists("idx_channels_txt", "Channels") sqlStore.RemoveIndexIfExists("idx_channels_txt", "Channels")
@@ -621,13 +621,13 @@ func UpgradeDatabaseToVersion58(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion59(sqlStore SqlStore) { func upgradeDatabaseToVersion59(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_8_0, VERSION_5_9_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_8_0, VERSION_5_9_0) {
saveSchemaVersion(sqlStore, VERSION_5_9_0) saveSchemaVersion(sqlStore, VERSION_5_9_0)
} }
} }
func UpgradeDatabaseToVersion510(sqlStore SqlStore) { func upgradeDatabaseToVersion510(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_9_0, VERSION_5_10_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_9_0, VERSION_5_10_0) {
sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(4)", "boolean") sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(4)", "boolean")
sqlStore.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(4)", "boolean") sqlStore.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(4)", "boolean")
@@ -639,7 +639,7 @@ func UpgradeDatabaseToVersion510(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion511(sqlStore SqlStore) { func upgradeDatabaseToVersion511(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_10_0, VERSION_5_11_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_10_0, VERSION_5_11_0) {
// Enforce all teams have an InviteID set // Enforce all teams have an InviteID set
var teams []*model.Team var teams []*model.Team
@@ -658,7 +658,7 @@ func UpgradeDatabaseToVersion511(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion512(sqlStore SqlStore) { func upgradeDatabaseToVersion512(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_11_0, VERSION_5_12_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_11_0, VERSION_5_12_0) {
sqlStore.CreateColumnIfNotExistsNoDefault("TeamMembers", "SchemeGuest", "boolean", "boolean") sqlStore.CreateColumnIfNotExistsNoDefault("TeamMembers", "SchemeGuest", "boolean", "boolean")
sqlStore.CreateColumnIfNotExistsNoDefault("ChannelMembers", "SchemeGuest", "boolean", "boolean") sqlStore.CreateColumnIfNotExistsNoDefault("ChannelMembers", "SchemeGuest", "boolean", "boolean")
@@ -674,7 +674,7 @@ func UpgradeDatabaseToVersion512(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion513(sqlStore SqlStore) { func upgradeDatabaseToVersion513(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_12_0, VERSION_5_13_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_12_0, VERSION_5_13_0) {
// The previous jobs ran once per minute, cluttering the Jobs table with somewhat useless entries. Clean that up. // The previous jobs ran once per minute, cluttering the Jobs table with somewhat useless entries. Clean that up.
sqlStore.GetMaster().Exec("DELETE FROM Jobs WHERE Type = 'plugins'") sqlStore.GetMaster().Exec("DELETE FROM Jobs WHERE Type = 'plugins'")
@@ -683,19 +683,19 @@ func UpgradeDatabaseToVersion513(sqlStore SqlStore) {
} }
} }
func UpgradeDatabaseToVersion514(sqlStore SqlStore) { func upgradeDatabaseToVersion514(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_13_0, VERSION_5_14_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_13_0, VERSION_5_14_0) {
saveSchemaVersion(sqlStore, VERSION_5_14_0) saveSchemaVersion(sqlStore, VERSION_5_14_0)
} }
} }
func UpgradeDatabaseToVersion515(sqlStore SqlStore) { func upgradeDatabaseToVersion515(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_14_0, VERSION_5_15_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_14_0, VERSION_5_15_0) {
saveSchemaVersion(sqlStore, VERSION_5_15_0) saveSchemaVersion(sqlStore, VERSION_5_15_0)
} }
} }
func UpgradeDatabaseToVersion516(sqlStore SqlStore) { func upgradeDatabaseToVersion516(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_5_15_0, VERSION_5_16_0) { if shouldPerformUpgrade(sqlStore, VERSION_5_15_0, VERSION_5_16_0) {
if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES { if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
sqlStore.GetMaster().Exec("ALTER TABLE Tokens ALTER COLUMN Extra TYPE varchar(2048)") sqlStore.GetMaster().Exec("ALTER TABLE Tokens ALTER COLUMN Extra TYPE varchar(2048)")

Просмотреть файл

@@ -15,41 +15,41 @@ func TestStoreUpgrade(t *testing.T) {
sqlStore := ss.(SqlStore) sqlStore := ss.(SqlStore)
t.Run("invalid currentModelVersion", func(t *testing.T) { t.Run("invalid currentModelVersion", func(t *testing.T) {
err := UpgradeDatabase(sqlStore, "notaversion") err := upgradeDatabase(sqlStore, "notaversion")
require.EqualError(t, err, "failed to parse current model version notaversion: No Major.Minor.Patch elements found") require.EqualError(t, err, "failed to parse current model version notaversion: No Major.Minor.Patch elements found")
}) })
t.Run("upgrade from invalid version", func(t *testing.T) { t.Run("upgrade from invalid version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "invalid") saveSchemaVersion(sqlStore, "invalid")
err := UpgradeDatabase(sqlStore, "5.8.0") err := upgradeDatabase(sqlStore, "5.8.0")
require.EqualError(t, err, "failed to parse database schema version invalid: No Major.Minor.Patch elements found") require.EqualError(t, err, "failed to parse database schema version invalid: No Major.Minor.Patch elements found")
require.Equal(t, "invalid", sqlStore.GetCurrentSchemaVersion()) require.Equal(t, "invalid", sqlStore.GetCurrentSchemaVersion())
}) })
t.Run("upgrade from unsupported version", func(t *testing.T) { t.Run("upgrade from unsupported version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "2.0.0") saveSchemaVersion(sqlStore, "2.0.0")
err := UpgradeDatabase(sqlStore, "5.8.0") err := upgradeDatabase(sqlStore, "5.8.0")
require.EqualError(t, err, "Database schema version 2.0.0 is no longer supported. This Mattermost server supports automatic upgrades from schema version 3.0.0 through schema version 5.8.0. Please manually upgrade to at least version 3.0.0 before continuing.") require.EqualError(t, err, "Database schema version 2.0.0 is no longer supported. This Mattermost server supports automatic upgrades from schema version 3.0.0 through schema version 5.8.0. Please manually upgrade to at least version 3.0.0 before continuing.")
require.Equal(t, "2.0.0", sqlStore.GetCurrentSchemaVersion()) require.Equal(t, "2.0.0", sqlStore.GetCurrentSchemaVersion())
}) })
t.Run("upgrade from earliest supported version", func(t *testing.T) { t.Run("upgrade from earliest supported version", func(t *testing.T) {
saveSchemaVersion(sqlStore, VERSION_3_0_0) saveSchemaVersion(sqlStore, VERSION_3_0_0)
err := UpgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION) err := upgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion()) require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion())
}) })
t.Run("upgrade from no existing version", func(t *testing.T) { t.Run("upgrade from no existing version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "") saveSchemaVersion(sqlStore, "")
err := UpgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION) err := upgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion()) require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion())
}) })
t.Run("upgrade schema running earlier minor version", func(t *testing.T) { t.Run("upgrade schema running earlier minor version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "5.1.0") saveSchemaVersion(sqlStore, "5.1.0")
err := UpgradeDatabase(sqlStore, "5.8.0") err := upgradeDatabase(sqlStore, "5.8.0")
require.NoError(t, err) require.NoError(t, err)
// Assert CURRENT_SCHEMA_VERSION, not 5.8.0, since the migrations will move // Assert CURRENT_SCHEMA_VERSION, not 5.8.0, since the migrations will move
// past 5.8.0 regardless of the input parameter. // past 5.8.0 regardless of the input parameter.
@@ -58,21 +58,21 @@ func TestStoreUpgrade(t *testing.T) {
t.Run("upgrade schema running later minor version", func(t *testing.T) { t.Run("upgrade schema running later minor version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "5.29.0") saveSchemaVersion(sqlStore, "5.29.0")
err := UpgradeDatabase(sqlStore, "5.8.0") err := upgradeDatabase(sqlStore, "5.8.0")
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "5.29.0", sqlStore.GetCurrentSchemaVersion()) require.Equal(t, "5.29.0", sqlStore.GetCurrentSchemaVersion())
}) })
t.Run("upgrade schema running earlier major version", func(t *testing.T) { t.Run("upgrade schema running earlier major version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "4.1.0") saveSchemaVersion(sqlStore, "4.1.0")
err := UpgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION) err := upgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion()) require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion())
}) })
t.Run("upgrade schema running later major version", func(t *testing.T) { t.Run("upgrade schema running later major version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "6.0.0") saveSchemaVersion(sqlStore, "6.0.0")
err := UpgradeDatabase(sqlStore, "5.8.0") err := upgradeDatabase(sqlStore, "5.8.0")
require.EqualError(t, err, "Database schema version 6.0.0 is not supported. This Mattermost server supports only >=5.8.0, <6.0.0. Please upgrade to at least version 6.0.0 before continuing.") require.EqualError(t, err, "Database schema version 6.0.0 is not supported. This Mattermost server supports only >=5.8.0, <6.0.0. Please upgrade to at least version 6.0.0 before continuing.")
require.Equal(t, "6.0.0", sqlStore.GetCurrentSchemaVersion()) require.Equal(t, "6.0.0", sqlStore.GetCurrentSchemaVersion())
}) })

Просмотреть файл

@@ -129,7 +129,7 @@ type ChannelStore interface {
GetByNames(team_id string, names []string, allowFromCache bool) ([]*model.Channel, *model.AppError) GetByNames(team_id string, names []string, allowFromCache bool) ([]*model.Channel, *model.AppError)
GetByNameIncludeDeleted(team_id string, name string, allowFromCache bool) (*model.Channel, *model.AppError) GetByNameIncludeDeleted(team_id string, name string, allowFromCache bool) (*model.Channel, *model.AppError)
GetDeletedByName(team_id string, name string) (*model.Channel, *model.AppError) GetDeletedByName(team_id string, name string) (*model.Channel, *model.AppError)
GetDeleted(team_id string, offset int, limit int) (*model.ChannelList, *model.AppError) GetDeleted(team_id string, offset int, limit int, userId string) (*model.ChannelList, *model.AppError)
GetChannels(teamId string, userId string, includeDeleted bool) (*model.ChannelList, *model.AppError) GetChannels(teamId string, userId string, includeDeleted bool) (*model.ChannelList, *model.AppError)
GetAllChannels(page, perPage int, opts ChannelSearchOpts) (*model.ChannelListWithTeamData, *model.AppError) GetAllChannels(page, perPage int, opts ChannelSearchOpts) (*model.ChannelListWithTeamData, *model.AppError)
GetAllChannelsCount(opts ChannelSearchOpts) (int64, *model.AppError) GetAllChannelsCount(opts ChannelSearchOpts) (int64, *model.AppError)
@@ -175,6 +175,7 @@ type ChannelStore interface {
AutocompleteInTeamForSearch(teamId string, userId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) AutocompleteInTeamForSearch(teamId string, userId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError)
SearchAllChannels(term string, opts ChannelSearchOpts) (*model.ChannelListWithTeamData, *model.AppError) SearchAllChannels(term string, opts ChannelSearchOpts) (*model.ChannelListWithTeamData, *model.AppError)
SearchInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) SearchInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError)
SearchArchivedInTeam(teamId string, term string, userId string) (*model.ChannelList, *model.AppError)
SearchForUserInTeam(userId string, teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError) SearchForUserInTeam(userId string, teamId string, term string, includeDeleted bool) (*model.ChannelList, *model.AppError)
SearchMore(userId string, teamId string, term string) (*model.ChannelList, *model.AppError) SearchMore(userId string, teamId string, term string) (*model.ChannelList, *model.AppError)
SearchGroupChannels(userId, term string) (*model.ChannelList, *model.AppError) SearchGroupChannels(userId, term string) (*model.ChannelList, *model.AppError)

Просмотреть файл

@@ -687,13 +687,15 @@ func testChannelStoreGetDeleted(t *testing.T, ss store.Store) {
o1.Name = "zz" + model.NewId() + "b" o1.Name = "zz" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN o1.Type = model.CHANNEL_OPEN
userId := model.NewId()
_, err := ss.Channel().Save(&o1, -1) _, err := ss.Channel().Save(&o1, -1)
require.Nil(t, err) require.Nil(t, err)
err = ss.Channel().Delete(o1.Id, model.GetMillis()) err = ss.Channel().Delete(o1.Id, model.GetMillis())
require.Nil(t, err, "channel should have been deleted") require.Nil(t, err, "channel should have been deleted")
list, err := ss.Channel().GetDeleted(o1.TeamId, 0, 100) list, err := ss.Channel().GetDeleted(o1.TeamId, 0, 100, userId)
require.Nil(t, err, err) require.Nil(t, err, err)
require.Len(t, *list, 1, "wrong list") require.Len(t, *list, 1, "wrong list")
require.Equal(t, o1.Name, (*list)[0].Name, "missing channel") require.Equal(t, o1.Name, (*list)[0].Name, "missing channel")
@@ -706,7 +708,7 @@ func testChannelStoreGetDeleted(t *testing.T, ss store.Store) {
_, err = ss.Channel().Save(&o2, -1) _, err = ss.Channel().Save(&o2, -1)
require.Nil(t, err) require.Nil(t, err)
list, err = ss.Channel().GetDeleted(o1.TeamId, 0, 100) list, err = ss.Channel().GetDeleted(o1.TeamId, 0, 100, userId)
require.Nil(t, err, err) require.Nil(t, err, err)
require.Len(t, *list, 1, "wrong list") require.Len(t, *list, 1, "wrong list")
@@ -722,15 +724,15 @@ func testChannelStoreGetDeleted(t *testing.T, ss store.Store) {
err = ss.Channel().Delete(o3.Id, model.GetMillis()) err = ss.Channel().Delete(o3.Id, model.GetMillis())
require.Nil(t, err, "channel should have been deleted") require.Nil(t, err, "channel should have been deleted")
list, err = ss.Channel().GetDeleted(o1.TeamId, 0, 100) list, err = ss.Channel().GetDeleted(o1.TeamId, 0, 100, userId)
require.Nil(t, err, err) require.Nil(t, err, err)
require.Len(t, *list, 2, "wrong list length") require.Len(t, *list, 2, "wrong list length")
list, err = ss.Channel().GetDeleted(o1.TeamId, 0, 1) list, err = ss.Channel().GetDeleted(o1.TeamId, 0, 1, userId)
require.Nil(t, err, err) require.Nil(t, err, err)
require.Len(t, *list, 1, "wrong list length") require.Len(t, *list, 1, "wrong list length")
list, err = ss.Channel().GetDeleted(o1.TeamId, 1, 1) list, err = ss.Channel().GetDeleted(o1.TeamId, 1, 1, userId)
require.Nil(t, err, err) require.Nil(t, err, err)
require.Len(t, *list, 1, "wrong list length") require.Len(t, *list, 1, "wrong list length")

Просмотреть файл

@@ -647,7 +647,7 @@ func (_m *ChannelStore) GetChannelsByScheme(schemeId string, offset int, limit i
} }
// GetDeleted provides a mock function with given fields: team_id, offset, limit // GetDeleted provides a mock function with given fields: team_id, offset, limit
func (_m *ChannelStore) GetDeleted(team_id string, offset int, limit int) (*model.ChannelList, *model.AppError) { func (_m *ChannelStore) GetDeleted(team_id string, offset int, limit int, userId string) (*model.ChannelList, *model.AppError) {
ret := _m.Called(team_id, offset, limit) ret := _m.Called(team_id, offset, limit)
var r0 *model.ChannelList var r0 *model.ChannelList
@@ -1539,6 +1539,31 @@ func (_m *ChannelStore) SearchInTeam(teamId string, term string, includeDeleted
return r0, r1 return r0, r1
} }
// SearchArchivedInTeam provides a mock function with given fields: teamId, term, userId
func (_m *ChannelStore) SearchArchivedInTeam(teamId string, term string, userId string) (*model.ChannelList, *model.AppError) {
ret := _m.Called(teamId, term, userId)
var r0 *model.ChannelList
if rf, ok := ret.Get(0).(func(string, string, string) *model.ChannelList); ok {
r0 = rf(teamId, term, userId)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*model.ChannelList)
}
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(string, string, string) *model.AppError); ok {
r1 = rf(teamId, term, userId)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
}
return r0, r1
}
// SearchMore provides a mock function with given fields: userId, teamId, term // SearchMore provides a mock function with given fields: userId, teamId, term
func (_m *ChannelStore) SearchMore(userId string, teamId string, term string) (*model.ChannelList, *model.AppError) { func (_m *ChannelStore) SearchMore(userId string, teamId string, term string) (*model.ChannelList, *model.AppError) {
ret := _m.Called(userId, teamId, term) ret := _m.Called(userId, teamId, term)

Просмотреть файл

@@ -904,10 +904,10 @@ func (s *TimerLayerChannelStore) GetChannelsByScheme(schemeId string, offset int
return resultVar0, resultVar1 return resultVar0, resultVar1
} }
func (s *TimerLayerChannelStore) GetDeleted(team_id string, offset int, limit int) (*model.ChannelList, *model.AppError) { func (s *TimerLayerChannelStore) GetDeleted(team_id string, offset int, limit int, userId string) (*model.ChannelList, *model.AppError) {
start := timemodule.Now() start := timemodule.Now()
resultVar0, resultVar1 := s.ChannelStore.GetDeleted(team_id, offset, limit) resultVar0, resultVar1 := s.ChannelStore.GetDeleted(team_id, offset, limit, userId)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second) elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil { if s.Root.Metrics != nil {

Просмотреть файл

@@ -292,7 +292,7 @@
{{template "unsupported_browser-system_browser" .Props.SystemBrowser}} {{template "unsupported_browser-system_browser" .Props.SystemBrowser}}
{{end}} {{end}}
<div class='learn-more-about-sup'> <div class='learn-more-about-sup'>
<a href='https://docs.mattermost.com/install/requirements.html#pc-web' target='_blank'>{{.Props.LearnMoreString}}</a> <a href='https://docs.mattermost.com/install/requirements.html#pc-web' target='_blank' rel='noopener noreferrer'>{{.Props.LearnMoreString}}</a>
</div> </div>
</div> </div>
</div> </div>

Просмотреть файл

@@ -14,26 +14,20 @@ import (
func TestValidateLicense(t *testing.T) { func TestValidateLicense(t *testing.T) {
b1 := []byte("junk") b1 := []byte("junk")
if ok, _ := ValidateLicense(b1); ok { ok, _ := ValidateLicense(b1)
t.Fatal("should have failed - bad license") require.False(t, ok, "should have failed - bad license")
}
b2 := []byte("junkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunk") b2 := []byte("junkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunkjunk")
if ok, _ := ValidateLicense(b2); ok { ok, _ = ValidateLicense(b2)
t.Fatal("should have failed - bad license") require.False(t, ok, "should have failed - bad license")
}
} }
func TestGetLicenseFileLocation(t *testing.T) { func TestGetLicenseFileLocation(t *testing.T) {
fileName := GetLicenseFileLocation("") fileName := GetLicenseFileLocation("")
if len(fileName) == 0 { require.NotEmpty(t, fileName, "invalid default file name")
t.Fatal("invalid default file name")
}
fileName = GetLicenseFileLocation("mattermost.mattermost-license") fileName = GetLicenseFileLocation("mattermost.mattermost-license")
if fileName != "mattermost.mattermost-license" { require.Equal(t, fileName, "mattermost.mattermost-license", "invalid file name")
t.Fatal("invalid file name")
}
} }
func TestGetLicenseFileFromDisk(t *testing.T) { func TestGetLicenseFileFromDisk(t *testing.T) {

Просмотреть файл

@@ -5,6 +5,8 @@ package utils
import ( import (
"testing" "testing"
"github.com/stretchr/testify/require"
) )
func TestUrlEncode(t *testing.T) { func TestUrlEncode(t *testing.T) {
@@ -12,24 +14,15 @@ func TestUrlEncode(t *testing.T) {
toEncode := "testing 1 2 3" toEncode := "testing 1 2 3"
encoded := UrlEncode(toEncode) encoded := UrlEncode(toEncode)
if encoded != "testing%201%202%203" { require.Equal(t, encoded, "testing%201%202%203")
t.Log(encoded)
t.Fatal("should be equal")
}
toEncode = "testing123" toEncode = "testing123"
encoded = UrlEncode(toEncode) encoded = UrlEncode(toEncode)
if encoded != "testing123" { require.Equal(t, encoded, "testing123")
t.Log(encoded)
t.Fatal("should be equal")
}
toEncode = "testing$#~123" toEncode = "testing$#~123"
encoded = UrlEncode(toEncode) encoded = UrlEncode(toEncode)
if encoded != "testing%24%23~123" { require.Equal(t, encoded, "testing%24%23~123")
t.Log(encoded)
t.Fatal("should be equal")
}
} }

42
vendor/github.com/minio/minio-go/v6/api-list.go сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,6 @@
/* /*
* MinIO Go Library for Amazon S3 Compatible Cloud Storage * MinIO Go Library for Amazon S3 Compatible Cloud Storage
* Copyright 2015-2017 MinIO, Inc. * Copyright 2015-2019 MinIO, Inc.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -208,12 +208,10 @@ func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken s
urlValues.Set("fetch-owner", "true") urlValues.Set("fetch-owner", "true")
} }
// maxkeys should default to 1000 or less.
if maxkeys == 0 || maxkeys > 1000 {
maxkeys = 1000
}
// Set max keys. // Set max keys.
urlValues.Set("max-keys", fmt.Sprintf("%d", maxkeys)) if maxkeys > 0 {
urlValues.Set("max-keys", fmt.Sprintf("%d", maxkeys))
}
// Set start-after // Set start-after
if startAfter != "" { if startAfter != "" {
@@ -248,15 +246,15 @@ func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken s
return listBucketResult, errors.New("Truncated response should have continuation token set") return listBucketResult, errors.New("Truncated response should have continuation token set")
} }
for _, obj := range listBucketResult.Contents { for i, obj := range listBucketResult.Contents {
obj.Key, err = url.QueryUnescape(obj.Key) listBucketResult.Contents[i].Key, err = url.QueryUnescape(obj.Key)
if err != nil { if err != nil {
return listBucketResult, err return listBucketResult, err
} }
} }
for _, obj := range listBucketResult.CommonPrefixes { for i, obj := range listBucketResult.CommonPrefixes {
obj.Prefix, err = url.QueryUnescape(obj.Prefix) listBucketResult.CommonPrefixes[i].Prefix, err = url.QueryUnescape(obj.Prefix)
if err != nil { if err != nil {
return listBucketResult, err return listBucketResult, err
} }
@@ -401,12 +399,10 @@ func (c Client) listObjectsQuery(bucketName, objectPrefix, objectMarker, delimit
urlValues.Set("marker", objectMarker) urlValues.Set("marker", objectMarker)
} }
// maxkeys should default to 1000 or less.
if maxkeys == 0 || maxkeys > 1000 {
maxkeys = 1000
}
// Set max keys. // Set max keys.
urlValues.Set("max-keys", fmt.Sprintf("%d", maxkeys)) if maxkeys > 0 {
urlValues.Set("max-keys", fmt.Sprintf("%d", maxkeys))
}
// Always set encoding-type // Always set encoding-type
urlValues.Set("encoding-type", "url") urlValues.Set("encoding-type", "url")
@@ -433,15 +429,15 @@ func (c Client) listObjectsQuery(bucketName, objectPrefix, objectMarker, delimit
return listBucketResult, err return listBucketResult, err
} }
for _, obj := range listBucketResult.Contents { for i, obj := range listBucketResult.Contents {
obj.Key, err = url.QueryUnescape(obj.Key) listBucketResult.Contents[i].Key, err = url.QueryUnescape(obj.Key)
if err != nil { if err != nil {
return listBucketResult, err return listBucketResult, err
} }
} }
for _, obj := range listBucketResult.CommonPrefixes { for i, obj := range listBucketResult.CommonPrefixes {
obj.Prefix, err = url.QueryUnescape(obj.Prefix) listBucketResult.CommonPrefixes[i].Prefix, err = url.QueryUnescape(obj.Prefix)
if err != nil { if err != nil {
return listBucketResult, err return listBucketResult, err
} }
@@ -642,15 +638,15 @@ func (c Client) listMultipartUploadsQuery(bucketName, keyMarker, uploadIDMarker,
return listMultipartUploadsResult, err return listMultipartUploadsResult, err
} }
for _, obj := range listMultipartUploadsResult.Uploads { for i, obj := range listMultipartUploadsResult.Uploads {
obj.Key, err = url.QueryUnescape(obj.Key) listMultipartUploadsResult.Uploads[i].Key, err = url.QueryUnescape(obj.Key)
if err != nil { if err != nil {
return listMultipartUploadsResult, err return listMultipartUploadsResult, err
} }
} }
for _, obj := range listMultipartUploadsResult.CommonPrefixes { for i, obj := range listMultipartUploadsResult.CommonPrefixes {
obj.Prefix, err = url.QueryUnescape(obj.Prefix) listMultipartUploadsResult.CommonPrefixes[i].Prefix, err = url.QueryUnescape(obj.Prefix)
if err != nil { if err != nil {
return listMultipartUploadsResult, err return listMultipartUploadsResult, err
} }

11
vendor/github.com/minio/minio-go/v6/api-notification.go сгенерированный поставляемый
Просмотреть файл

@@ -200,6 +200,11 @@ func (c Client) ListenBucketNotification(bucketName, prefix, suffix string, even
for bio.Scan() { for bio.Scan() {
var notificationInfo NotificationInfo var notificationInfo NotificationInfo
if err = json.Unmarshal(bio.Bytes(), &notificationInfo); err != nil { if err = json.Unmarshal(bio.Bytes(), &notificationInfo); err != nil {
// Unexpected error during json unmarshal, send
// the error to caller for actionable as needed.
notificationInfoCh <- NotificationInfo{
Err: err,
}
closeResponse(resp) closeResponse(resp)
continue continue
} }
@@ -211,7 +216,11 @@ func (c Client) ListenBucketNotification(bucketName, prefix, suffix string, even
return return
} }
} }
if err = bio.Err(); err != nil {
notificationInfoCh <- NotificationInfo{
Err: err,
}
}
// Close current connection before looping further. // Close current connection before looping further.
closeResponse(resp) closeResponse(resp)
} }

2
vendor/github.com/minio/minio-go/v6/api.go сгенерированный поставляемый
Просмотреть файл

@@ -104,7 +104,7 @@ type Options struct {
// Global constants. // Global constants.
const ( const (
libraryName = "minio-go" libraryName = "minio-go"
libraryVersion = "v6.0.38" libraryVersion = "v6.0.40"
) )
// User Agent should always following the below style. // User Agent should always following the below style.

3
vendor/github.com/minio/minio-go/v6/go.sum сгенерированный поставляемый
Просмотреть файл

@@ -1,3 +1,4 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -10,6 +11,7 @@ github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKU
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -18,6 +20,7 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo=

2
vendor/modules.txt поставляемый
Просмотреть файл

@@ -132,7 +132,7 @@ github.com/mattn/go-sqlite3
github.com/matttproud/golang_protobuf_extensions/pbutil github.com/matttproud/golang_protobuf_extensions/pbutil
# github.com/miekg/dns v1.1.19 # github.com/miekg/dns v1.1.19
github.com/miekg/dns github.com/miekg/dns
# github.com/minio/minio-go/v6 v6.0.38 # github.com/minio/minio-go/v6 v6.0.40
github.com/minio/minio-go/v6 github.com/minio/minio-go/v6
github.com/minio/minio-go/v6/pkg/credentials github.com/minio/minio-go/v6/pkg/credentials
github.com/minio/minio-go/v6/pkg/encrypt github.com/minio/minio-go/v6/pkg/encrypt

Просмотреть файл

@@ -60,7 +60,7 @@ func (w *Web) InitStatic() {
func root(c *Context, w http.ResponseWriter, r *http.Request) { func root(c *Context, w http.ResponseWriter, r *http.Request) {
if !CheckClientCompatability(r.UserAgent()) { if !CheckClientCompatability(r.UserAgent()) {
renderUnsuppportedBrowser(c.App, w, r) renderUnsupportedBrowser(c.App, w, r)
return return
} }

Просмотреть файл

@@ -44,7 +44,7 @@ type SystemBrowser struct {
MakeDefaultString string MakeDefaultString string
} }
func renderUnsuppportedBrowser(app *app.App, w http.ResponseWriter, r *http.Request) { func renderUnsupportedBrowser(app *app.App, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "no-store") w.Header().Set("Cache-Control", "no-store")
page := utils.NewHTMLTemplate(app.HTMLTemplates(), "unsupported_browser") page := utils.NewHTMLTemplate(app.HTMLTemplates(), "unsupported_browser")