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
# 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.
@echo Testing TE race conditions
@@ -398,7 +401,7 @@ stop-client: ## Stops the webapp.
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.

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

@@ -574,7 +574,9 @@ func CheckEtag(t *testing.T, data interface{}, resp *model.Response) {
func CheckNoError(t *testing.T, resp *model.Response) {
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) {
@@ -637,8 +639,8 @@ func CheckInternalErrorStatus(t *testing.T, resp *model.Response) {
func CheckErrorMessage(t *testing.T, resp *model.Response, errorId string) {
t.Helper()
require.NotNil(t, resp.Error)
require.Equal(t, resp.Error.Id, errorId, "incorrect error message")
require.NotNilf(t, resp.Error, "should have errored with message: %s", errorId)
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) {

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

@@ -27,6 +27,7 @@ func (api *API) InitChannel() {
api.BaseRoutes.ChannelsForTeam.Handle("/deleted", api.ApiSessionRequired(getDeletedChannelsForTeam)).Methods("GET")
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_archived", api.ApiSessionRequired(searchArchivedChannelsForTeam)).Methods("POST")
api.BaseRoutes.ChannelsForTeam.Handle("/autocomplete", api.ApiSessionRequired(autocompleteChannelsForTeam)).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")
@@ -681,12 +682,7 @@ func getDeletedChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Reques
return
}
if !c.App.SessionHasPermissionToTeam(c.App.Session, c.Params.TeamId, model.PERMISSION_MANAGE_TEAM) {
c.SetPermissionError(model.PERMISSION_MANAGE_TEAM)
return
}
channels, err := c.App.GetDeletedChannels(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage)
channels, err := c.App.GetDeletedChannels(c.Params.TeamId, c.Params.Page*c.Params.PerPage, c.Params.PerPage, c.App.Session.UserId)
if err != nil {
c.Err = err
return
@@ -860,6 +856,42 @@ func searchChannelsForTeam(c *Context, w http.ResponseWriter, r *http.Request) {
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) {
props := model.ChannelSearchFromJson(r.Body)
if props == nil {

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

@@ -678,9 +678,6 @@ func TestGetDeletedChannelsForTeam(t *testing.T) {
Client := th.Client
team := th.BasicTeam
_, resp := Client.GetDeletedChannelsForTeam(team.Id, 0, 100, "")
CheckForbiddenStatus(t, resp)
th.LoginTeamAdmin()
channels, resp := Client.GetDeletedChannelsForTeam(team.Id, 0, 100, "")
@@ -706,6 +703,31 @@ func TestGetDeletedChannelsForTeam(t *testing.T) {
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, "")
CheckNoError(t, resp)
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) {
th := Setup().InitBasic()
defer th.TearDown()

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

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

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

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

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

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

@@ -1260,8 +1260,8 @@ func (a *App) GetAllChannelsCount(opts model.ChannelSearchOpts) (int64, *model.A
return a.Srv.Store.Channel().GetAllChannelsCount(storeOpts)
}
func (a *App) GetDeletedChannels(teamId string, offset int, limit int) (*model.ChannelList, *model.AppError) {
return a.Srv.Store.Channel().GetDeleted(teamId, offset, limit)
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, userId)
}
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)
}
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) {
includeDeleted := *a.Config().TeamSettings.ExperimentalViewArchivedChannels

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

@@ -7,6 +7,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/model"
)
@@ -42,6 +43,15 @@ func TestInviteProvider(t *testing.T) {
userAndInvalidPrivate := "@" + basicUser3.Username + " ~" + privateChannel2.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 {
desc string
expected string
@@ -97,6 +107,11 @@ func TestInviteProvider(t *testing.T) {
expected: "api.command_invite.user_not_in_team.app_error",
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",
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
}
// 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
// for the listener that can later be used to remove it.
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
// 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
func (a *App) ensurePostActionCookieSecret() error {
if a.Srv.postActionCookieSecret != nil {

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

@@ -7,7 +7,6 @@ import (
"bytes"
"fmt"
"io"
"net/mail"
"net/url"
"path"
"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 {
license := a.License()
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() {
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 {
team, err := a.GetTeamByName(teamName)
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
}

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

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

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

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

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

@@ -8,7 +8,6 @@ import (
"encoding/json"
"image"
"image/color"
"math/rand"
"strings"
"testing"
"time"
@@ -74,8 +73,7 @@ func TestCreateOAuthUser(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
r := rand.New(rand.NewSource(time.Now().UnixNano()))
glUser := oauthgitlab.GitLabUser{Id: int64(r.Intn(1000)) + 1, Username: "o" + model.NewId(), Email: model.NewId() + "@simulator.amazonses.com", Name: "Joram Wilander"}
glUser := oauthgitlab.GitLabUser{Id: 42, Username: "o" + model.NewId(), Email: model.NewId() + "@simulator.amazonses.com", Name: "Joram Wilander"}
json := glUser.ToJson()
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 gitlabUserObj oauthgitlab.GitLabUser
user, gitlabUserObj = createGitlabUser(t, th.App, username, email)
user2, _ = createGitlabUser(t, th.App, username2, email2)
user, gitlabUserObj = createGitlabUser(t, th.App, 1, username, email)
user2, _ = createGitlabUser(t, th.App, 2, username2, email2)
t.Run("UpdateUsername", 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
}
func createGitlabUser(t *testing.T, a *App, username string, email string) (*model.User, oauthgitlab.GitLabUser) {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
gitlabUserObj := oauthgitlab.GitLabUser{Id: int64(r.Intn(1000)) + 1, Username: username, Login: "user1", Email: email, Name: "Test User"}
func createGitlabUser(t *testing.T, a *App, id int64, username string, email string) (*model.User, oauthgitlab.GitLabUser) {
gitlabUserObj := oauthgitlab.GitLabUser{Id: id, Username: username, Login: "user1", Email: email, Name: "Test User"}
gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
var user *model.User

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

@@ -21,7 +21,7 @@ services:
POSTGRES_PASSWORD: mostest
POSTGRES_DB: mattermost_test
minio:
image: "minio/minio:RELEASE.2019-08-14T20-37-41Z"
image: "minio/minio:RELEASE.2019-10-11T00-38-09Z"
command: "server /data"
networks:
- 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.")
}
api := api4.Init(server, server.AppOptions, server.Router)
wsapi.Init(server.FakeApp(), server.WebSocketRouter)
web.New(server, server.AppOptions, server.Router)
serverErr := server.Start()
if serverErr != nil {
mlog.Critical(serverErr.Error())
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 *server.Config().ServiceSettings.EnableTesting {
manualtesting.Init(api)

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

@@ -50,7 +50,7 @@ require (
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mattn/go-sqlite3 v1.11.0
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/muesli/smartcrop v0.3.0 // 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.1.19 h1:0ymbfaLG1/utH2+BydNiF+dx1jSEmdr/nylOtkGHZZg=
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.38/go.mod h1:qD0lajrGW49lKZLtXKtCB4X/qkMf0a5tBvN2PaZg7Gg=
github.com/minio/minio-go/v6 v6.0.40 h1:MlSCSXvItiu2jINMxYdhUU99KR4446Db+0iAU1IKaZ0=
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/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=

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

@@ -764,7 +764,7 @@
},
{
"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",
@@ -1864,7 +1864,7 @@
},
{
"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",

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

@@ -2235,6 +2235,16 @@ func (c *Client4) SearchChannels(teamId string, search *ChannelSearch) ([]*Chann
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.
func (c *Client4) SearchAllChannels(search *ChannelSearch) (*ChannelListWithTeamData, *Response) {
r, err := c.DoApiPost(c.GetChannelsRoute()+"/search", search.ToJson())

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

@@ -24,109 +24,182 @@ func TestFileInfoIsValid(t *testing.T) {
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 = ""
require.NotNil(t, info.IsValid(), "empty Id isn't valid")
t.Run("Empty ID is not valid", func(t *testing.T) {
info.Id = ""
assert.NotNil(t, info.IsValid(), "empty Id isn't valid")
info.Id = NewId()
})
info.Id = NewId()
info.CreateAt = 0
require.NotNil(t, info.IsValid(), "empty CreateAt isn't valid")
t.Run("CreateAt 0 is not valid", func(t *testing.T) {
info.CreateAt = 0
assert.NotNil(t, info.IsValid(), "empty CreateAt isn't valid")
info.CreateAt = 1234
})
info.CreateAt = 1234
info.UpdateAt = 0
require.NotNil(t, info.IsValid(), "empty UpdateAt isn't valid")
t.Run("UpdateAt 0 is not valid", func(t *testing.T) {
info.UpdateAt = 0
assert.NotNil(t, info.IsValid(), "empty UpdateAt isn't valid")
info.UpdateAt = 1234
})
info.UpdateAt = 1234
info.PostId = NewId()
require.Nil(t, info.IsValid())
t.Run("New Post ID is valid", func(t *testing.T) {
info.PostId = NewId()
assert.Nil(t, info.IsValid())
})
info.Path = ""
require.NotNil(t, info.IsValid(), "empty Path isn't valid")
info.Path = "fake/path.png"
require.Nil(t, info.IsValid())
t.Run("Empty path is not valid", func(t *testing.T) {
info.Path = ""
assert.NotNil(t, info.IsValid(), "empty Path isn't valid")
info.Path = "fake/path.png"
})
}
func TestFileInfoIsImage(t *testing.T) {
info := &FileInfo{MimeType: "image/png"}
assert.True(t, info.IsImage(), "file is an image")
info := &FileInfo{}
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"
assert.False(t, info.IsImage(), "file is not an image")
t.Run("MimeType set to text/plain is not considered an image", func(t *testing.T) {
info.MimeType = "text/plain"
assert.False(t, info.IsImage(), "Text file should not be considered as an image")
})
}
func TestGetInfoForFile(t *testing.T) {
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")
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
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")
require.Nilf(t, err, "Failed to load testgif.gif")
info, err = GetInfoForBytes("testgif.gif", animatedGifFile)
require.Nil(t, err)
assert.Equalf(t, info.Name, "testgif.gif", "Got incorrect filename: %v", info.Name)
assert.Equalf(t, info.Extension, "gif", "Got incorrect extension: %v", info.Extension)
assert.EqualValuesf(t, info.Size, 38689, "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, 118, "Got incorrect width: %v", info.Width)
assert.Equalf(t, info.Height, 118, "Got incorrect height: %v", info.Height)
assert.Falsef(t, info.HasPreviewImage, "Got incorrect has preview image: %v", info.HasPreviewImage)
var ttc = []struct {
testName string
filename string
file []byte
usePrefixForMime bool
expectedExtension string
expectedSize int
expectedMime string
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)
require.Nil(t, err)
assert.Equalf(t, info.Name, "filewithoutextension", "Got incorrect filename: %v", info.Name)
assert.Equalf(t, info.Extension, "", "Got incorrect extension: %v", info.Extension)
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)
for _, tc := range ttc {
t.Run(tc.testName, func(t *testing.T) {
info, errApp := GetInfoForBytes(tc.filename, tc.file)
require.Nil(t, errApp)
// Always make the extension lower case to make it easier to use in other places
info, err = GetInfoForBytes("file.TXT", fakeFile)
require.Nil(t, err)
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.Equalf(t, tc.filename, info.Name, "Got incorrect filename: %v", info.Name)
assert.Equalf(t, tc.expectedExtension, info.Extension, "Got incorrect extension: %v", info.Extension)
assert.EqualValuesf(t, tc.expectedSize, info.Size, "Got incorrect size: %v", info.Size)
assert.Equalf(t, tc.expectedWidth, info.Width, "Got incorrect width: %v", info.Width)
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
info, err = GetInfoForBytes("file.tif", fakeFile)
require.Nil(t, err)
assert.Equalf(t, info.Name, "file.tif", "Got incorrect filename: %v", info.Name)
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)
if tc.usePrefixForMime {
assert.Truef(t, strings.HasPrefix(info.MimeType, tc.expectedMime), "Got incorrect mime type: %v", info.MimeType)
} else {
assert.Equalf(t, tc.expectedMime, info.MimeType, "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
func (u *User) SanitizeInput() {
u.AuthData = NewString("")
u.AuthService = ""
func (u *User) SanitizeInput(isAdmin bool) {
if !isAdmin {
u.AuthData = NewString("")
u.AuthService = ""
}
u.LastPasswordUpdate = 0
u.LastPictureUpdate = 0
u.FailedAttempts = 0

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

@@ -9,6 +9,9 @@ import (
"github.com/pkg/errors"
)
// Helpers provide a common patterns plugins use.
//
// Plugins obtain access to the Helpers by embedding MattermostPlugin.
type Helpers interface {
// 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.
@@ -55,6 +58,7 @@ type Helpers interface {
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 {
API API
}

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

@@ -4,12 +4,14 @@
package plugin
import (
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/model"
"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")
if err != nil {
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
// retrieval from another EnsureBot. Just try the basic retrieve existing again.
defer func() {
if retBotId == "" || retErr != nil {
if retBotID == "" || retErr != nil {
var err error
var botIdBytes []byte
var botIDBytes []byte
err = utils.ProgressiveRetry(func() error {
botIdBytes, err = p.API.KVGet(BOT_USER_KEY)
botIDBytes, err = p.API.KVGet(BOT_USER_KEY)
if err != nil {
return err
}
return nil
})
if err == nil && botIdBytes != nil {
retBotId = string(botIdBytes)
if err == nil && botIDBytes != nil {
retBotID = string(botIDBytes)
retErr = nil
}
}
}()
botIdBytes, kvGetErr := p.API.KVGet(BOT_USER_KEY)
botIDBytes, kvGetErr := p.API.KVGet(BOT_USER_KEY)
if kvGetErr != nil {
return "", errors.Wrap(kvGetErr, "failed to get bot")
}
// If the bot has already been created, there is nothing to do.
if botIdBytes != nil {
botId := string(botIdBytes)
return botId, nil
if botIDBytes != nil {
botID := string(botIDBytes)
return botID, nil
}
// 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"
)
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.
//
type smtpClient interface {
@@ -204,15 +216,29 @@ func TestConnection(config *model.Config) {
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}
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
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 {
return nil
}
@@ -235,34 +261,34 @@ func SendMailUsingConfigAdvanced(mimeTo, smtpTo string, from, replyTo mail.Addre
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 {
mlog.Debug("sending mail", mlog.String("to", smtpTo), mlog.String("subject", subject))
func SendMail(c smtpClient, mail mailData, fileBackend filesstore.FileBackend, date time.Time) *model.AppError {
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 {
mlog.Warn("Unable to convert html body to text", mlog.Err(err))
txtBody = ""
}
headers := map[string][]string{
"From": {from.String()},
"To": {mimeTo},
"Subject": {encodeRFC2047Word(subject)},
"From": {mail.from.String()},
"To": {mail.mimeTo},
"Subject": {encodeRFC2047Word(mail.subject)},
"Content-Transfer-Encoding": {"8bit"},
"Auto-Submitted": {"auto-generated"},
"Precedence": {"bulk"},
}
if len(replyTo.Address) > 0 {
headers["Reply-To"] = []string{replyTo.String()}
if len(mail.replyTo.Address) > 0 {
headers["Reply-To"] = []string{mail.replyTo.String()}
}
for k, v := range mimeHeaders {
for k, v := range mail.mimeHeaders {
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.AddAlternative("text/html", htmlMessage)
for name, reader := range embeddedFiles {
for name, reader := range mail.embeddedFiles {
m.EmbedReader(name, reader)
}
for _, fileInfo := range attachments {
for _, fileInfo := range mail.attachments {
bytes, err := fileBackend.ReadFile(fileInfo.Path)
if err != nil {
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)
}
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)
}

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

@@ -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) {
utils.T = utils.GetUserTranslations("en")
@@ -136,15 +180,8 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
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
DeleteMailBox(smtpTo)
DeleteMailBox("test2@example.com")
fileBackend, err := filesstore.NewFileBackend(&cfg.FileSettings, true)
assert.Nil(t, err)
@@ -178,31 +215,43 @@ func TestSendMailUsingConfigAdvanced(t *testing.T) {
headers := make(map[string]string)
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)
//Check if the email was send to the right email address
var resultsMailbox JSONMessageHeaderInbucket
err = RetryInbucket(5, func() error {
var mailErr error
resultsMailbox, mailErr = GetMailBox(smtpTo)
resultsMailbox, mailErr = GetMailBox(mail.smtpTo)
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.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.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
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
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
assert.Equal(t, "TestValue", resultsEmail.Header["Testheader"][0])
@@ -330,7 +379,8 @@ func TestSendMail(t *testing.T) {
for testName, tc := range testCases {
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)
if len(tc.contains) > 0 {
require.Contains(t, string(mocm.data), tc.contains)

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

@@ -1036,7 +1036,7 @@ func (s SqlChannelStore) GetPublicChannelsForTeam(teamId string, offset int, lim
PublicChannels pc ON (pc.Id = Channels.Id)
WHERE
pc.TeamId = :TeamId
AND pc.DeleteAt = 0
AND pc.DeleteAt = 0
ORDER BY pc.DisplayName
LIMIT :Limit
OFFSET :Offset
@@ -1242,10 +1242,24 @@ func (s SqlChannelStore) GetDeletedByName(teamId string, name string) (*model.Ch
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{}
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 {
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) {
deleteFilter := "AND c.DeleteAt = 0"
if includeDeleted {

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

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

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

@@ -70,10 +70,10 @@ const (
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
// 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)
if err != nil {
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
// os.Exit instead of returning an error.
UpgradeDatabaseToVersion31(sqlStore)
UpgradeDatabaseToVersion32(sqlStore)
UpgradeDatabaseToVersion33(sqlStore)
UpgradeDatabaseToVersion34(sqlStore)
UpgradeDatabaseToVersion35(sqlStore)
UpgradeDatabaseToVersion36(sqlStore)
UpgradeDatabaseToVersion37(sqlStore)
UpgradeDatabaseToVersion38(sqlStore)
UpgradeDatabaseToVersion39(sqlStore)
UpgradeDatabaseToVersion310(sqlStore)
UpgradeDatabaseToVersion40(sqlStore)
UpgradeDatabaseToVersion41(sqlStore)
UpgradeDatabaseToVersion42(sqlStore)
UpgradeDatabaseToVersion43(sqlStore)
UpgradeDatabaseToVersion44(sqlStore)
UpgradeDatabaseToVersion45(sqlStore)
UpgradeDatabaseToVersion46(sqlStore)
UpgradeDatabaseToVersion47(sqlStore)
UpgradeDatabaseToVersion471(sqlStore)
UpgradeDatabaseToVersion472(sqlStore)
UpgradeDatabaseToVersion48(sqlStore)
UpgradeDatabaseToVersion481(sqlStore)
UpgradeDatabaseToVersion49(sqlStore)
UpgradeDatabaseToVersion410(sqlStore)
UpgradeDatabaseToVersion50(sqlStore)
UpgradeDatabaseToVersion51(sqlStore)
UpgradeDatabaseToVersion52(sqlStore)
UpgradeDatabaseToVersion53(sqlStore)
UpgradeDatabaseToVersion54(sqlStore)
UpgradeDatabaseToVersion55(sqlStore)
UpgradeDatabaseToVersion56(sqlStore)
UpgradeDatabaseToVersion57(sqlStore)
UpgradeDatabaseToVersion58(sqlStore)
UpgradeDatabaseToVersion59(sqlStore)
UpgradeDatabaseToVersion510(sqlStore)
UpgradeDatabaseToVersion511(sqlStore)
UpgradeDatabaseToVersion512(sqlStore)
UpgradeDatabaseToVersion513(sqlStore)
UpgradeDatabaseToVersion514(sqlStore)
UpgradeDatabaseToVersion515(sqlStore)
UpgradeDatabaseToVersion516(sqlStore)
upgradeDatabaseToVersion31(sqlStore)
upgradeDatabaseToVersion32(sqlStore)
upgradeDatabaseToVersion33(sqlStore)
upgradeDatabaseToVersion34(sqlStore)
upgradeDatabaseToVersion35(sqlStore)
upgradeDatabaseToVersion36(sqlStore)
upgradeDatabaseToVersion37(sqlStore)
upgradeDatabaseToVersion38(sqlStore)
upgradeDatabaseToVersion39(sqlStore)
upgradeDatabaseToVersion310(sqlStore)
upgradeDatabaseToVersion40(sqlStore)
upgradeDatabaseToVersion41(sqlStore)
upgradeDatabaseToVersion42(sqlStore)
upgradeDatabaseToVersion43(sqlStore)
upgradeDatabaseToVersion44(sqlStore)
upgradeDatabaseToVersion45(sqlStore)
upgradeDatabaseToVersion46(sqlStore)
upgradeDatabaseToVersion47(sqlStore)
upgradeDatabaseToVersion471(sqlStore)
upgradeDatabaseToVersion472(sqlStore)
upgradeDatabaseToVersion48(sqlStore)
upgradeDatabaseToVersion481(sqlStore)
upgradeDatabaseToVersion49(sqlStore)
upgradeDatabaseToVersion410(sqlStore)
upgradeDatabaseToVersion50(sqlStore)
upgradeDatabaseToVersion51(sqlStore)
upgradeDatabaseToVersion52(sqlStore)
upgradeDatabaseToVersion53(sqlStore)
upgradeDatabaseToVersion54(sqlStore)
upgradeDatabaseToVersion55(sqlStore)
upgradeDatabaseToVersion56(sqlStore)
upgradeDatabaseToVersion57(sqlStore)
upgradeDatabaseToVersion58(sqlStore)
upgradeDatabaseToVersion59(sqlStore)
upgradeDatabaseToVersion510(sqlStore)
upgradeDatabaseToVersion511(sqlStore)
upgradeDatabaseToVersion512(sqlStore)
upgradeDatabaseToVersion513(sqlStore)
upgradeDatabaseToVersion514(sqlStore)
upgradeDatabaseToVersion515(sqlStore)
upgradeDatabaseToVersion516(sqlStore)
return nil
}
@@ -187,14 +187,14 @@ func shouldPerformUpgrade(sqlStore SqlStore, currentSchemaVersion string, expect
return false
}
func UpgradeDatabaseToVersion31(sqlStore SqlStore) {
func upgradeDatabaseToVersion31(sqlStore SqlStore) {
if shouldPerformUpgrade(sqlStore, VERSION_3_0_0, VERSION_3_1_0) {
sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "ContentType", "varchar(128)", "varchar(128)", "")
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) {
sqlStore.CreateColumnIfNotExists("TeamMembers", "DeleteAt", "bigint(20)", "bigint", "0")
@@ -208,7 +208,7 @@ func themeMigrationFailed(err error) {
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 sqlStore.DoesColumnExist("Users", "ThemeProps") {
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) {
sqlStore.CreateColumnIfNotExists("Status", "Manual", "BOOLEAN", "BOOLEAN", "0")
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) {
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'")
@@ -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) {
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) {
// Add EditAt column to Posts
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) {
// Add the IsPinned column to posts.
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) {
sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE)
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) {
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) {
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) {
// Increase maximum length of the Users table Roles column.
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) {
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) {
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) {
// Add the IsActive column to UserAccessToken.
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) {
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) {
sqlStore.CreateColumnIfNotExists("IncomingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
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) {
sqlStore.AlterColumnTypeIfExists("Users", "Position", "varchar(128)", "varchar(128)")
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
// ChannelMemberHistory table. So for those cases we need to do an upgrade between
// 4.7.0 and 4.7.1
func UpgradeDatabaseToVersion471(sqlStore SqlStore) {
func upgradeDatabaseToVersion471(sqlStore SqlStore) {
// If any new instances started with 4.7, they would have the bad Email column on the
// ChannelMemberHistory table. So for those cases we need to do an upgrade between
// 4.7.0 and 4.7.1
if shouldPerformUpgrade(sqlStore, VERSION_4_7_0, VERSION_4_7_1) {
sqlStore.RemoveColumnIfExists("ChannelMemberHistory", "Email")
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) {
sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
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) {
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) {
sqlStore.RemoveIndexIfExists("idx_channels_displayname", "Channels")
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
// 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()`.
@@ -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) {
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
// 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()`.
@@ -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) {
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) {
sqlStore.CreateColumnIfNotExists("OutgoingWebhooks", "Username", "varchar(64)", "varchar(64)", "")
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) {
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) {
sqlStore.AlterColumnTypeIfExists("OutgoingWebhooks", "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) {
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) {
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) {
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) {
// 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
// bring the upgraded (from v5.0) and fresh install schemas back in sync.
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) {
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) {
sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "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) {
// Enforce all teams have an InviteID set
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) {
sqlStore.CreateColumnIfNotExistsNoDefault("TeamMembers", "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) {
// 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'")
@@ -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) {
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) {
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 sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
sqlStore.GetMaster().Exec("ALTER TABLE Tokens ALTER COLUMN Extra TYPE varchar(2048)")

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

@@ -15,41 +15,41 @@ func TestStoreUpgrade(t *testing.T) {
sqlStore := ss.(SqlStore)
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")
})
t.Run("upgrade from invalid version", func(t *testing.T) {
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.Equal(t, "invalid", sqlStore.GetCurrentSchemaVersion())
})
t.Run("upgrade from unsupported version", func(t *testing.T) {
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.Equal(t, "2.0.0", sqlStore.GetCurrentSchemaVersion())
})
t.Run("upgrade from earliest supported version", func(t *testing.T) {
saveSchemaVersion(sqlStore, VERSION_3_0_0)
err := UpgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
err := upgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
require.NoError(t, err)
require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion())
})
t.Run("upgrade from no existing version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "")
err := UpgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
err := upgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
require.NoError(t, err)
require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion())
})
t.Run("upgrade schema running earlier minor version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "5.1.0")
err := UpgradeDatabase(sqlStore, "5.8.0")
err := upgradeDatabase(sqlStore, "5.8.0")
require.NoError(t, err)
// Assert CURRENT_SCHEMA_VERSION, not 5.8.0, since the migrations will move
// 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) {
saveSchemaVersion(sqlStore, "5.29.0")
err := UpgradeDatabase(sqlStore, "5.8.0")
err := upgradeDatabase(sqlStore, "5.8.0")
require.NoError(t, err)
require.Equal(t, "5.29.0", sqlStore.GetCurrentSchemaVersion())
})
t.Run("upgrade schema running earlier major version", func(t *testing.T) {
saveSchemaVersion(sqlStore, "4.1.0")
err := UpgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
err := upgradeDatabase(sqlStore, CURRENT_SCHEMA_VERSION)
require.NoError(t, err)
require.Equal(t, CURRENT_SCHEMA_VERSION, sqlStore.GetCurrentSchemaVersion())
})
t.Run("upgrade schema running later major version", func(t *testing.T) {
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.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)
GetByNameIncludeDeleted(team_id string, name string, allowFromCache bool) (*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)
GetAllChannels(page, perPage int, opts ChannelSearchOpts) (*model.ChannelListWithTeamData, *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)
SearchAllChannels(term string, opts ChannelSearchOpts) (*model.ChannelListWithTeamData, *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)
SearchMore(userId string, teamId string, 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.Type = model.CHANNEL_OPEN
userId := model.NewId()
_, err := ss.Channel().Save(&o1, -1)
require.Nil(t, err)
err = ss.Channel().Delete(o1.Id, model.GetMillis())
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.Len(t, *list, 1, "wrong list")
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)
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.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())
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.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.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.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
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)
var r0 *model.ChannelList
@@ -1539,6 +1539,31 @@ func (_m *ChannelStore) SearchInTeam(teamId string, term string, includeDeleted
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
func (_m *ChannelStore) SearchMore(userId string, teamId string, term string) (*model.ChannelList, *model.AppError) {
ret := _m.Called(userId, teamId, term)

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

@@ -904,10 +904,10 @@ func (s *TimerLayerChannelStore) GetChannelsByScheme(schemeId string, offset int
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()
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)
if s.Root.Metrics != nil {

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

@@ -292,7 +292,7 @@
{{template "unsupported_browser-system_browser" .Props.SystemBrowser}}
{{end}}
<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>

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

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

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

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

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

@@ -1,6 +1,6 @@
/*
* 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");
* 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")
}
// maxkeys should default to 1000 or less.
if maxkeys == 0 || maxkeys > 1000 {
maxkeys = 1000
}
// 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
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")
}
for _, obj := range listBucketResult.Contents {
obj.Key, err = url.QueryUnescape(obj.Key)
for i, obj := range listBucketResult.Contents {
listBucketResult.Contents[i].Key, err = url.QueryUnescape(obj.Key)
if err != nil {
return listBucketResult, err
}
}
for _, obj := range listBucketResult.CommonPrefixes {
obj.Prefix, err = url.QueryUnescape(obj.Prefix)
for i, obj := range listBucketResult.CommonPrefixes {
listBucketResult.CommonPrefixes[i].Prefix, err = url.QueryUnescape(obj.Prefix)
if err != nil {
return listBucketResult, err
}
@@ -401,12 +399,10 @@ func (c Client) listObjectsQuery(bucketName, objectPrefix, objectMarker, delimit
urlValues.Set("marker", objectMarker)
}
// maxkeys should default to 1000 or less.
if maxkeys == 0 || maxkeys > 1000 {
maxkeys = 1000
}
// 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
urlValues.Set("encoding-type", "url")
@@ -433,15 +429,15 @@ func (c Client) listObjectsQuery(bucketName, objectPrefix, objectMarker, delimit
return listBucketResult, err
}
for _, obj := range listBucketResult.Contents {
obj.Key, err = url.QueryUnescape(obj.Key)
for i, obj := range listBucketResult.Contents {
listBucketResult.Contents[i].Key, err = url.QueryUnescape(obj.Key)
if err != nil {
return listBucketResult, err
}
}
for _, obj := range listBucketResult.CommonPrefixes {
obj.Prefix, err = url.QueryUnescape(obj.Prefix)
for i, obj := range listBucketResult.CommonPrefixes {
listBucketResult.CommonPrefixes[i].Prefix, err = url.QueryUnescape(obj.Prefix)
if err != nil {
return listBucketResult, err
}
@@ -642,15 +638,15 @@ func (c Client) listMultipartUploadsQuery(bucketName, keyMarker, uploadIDMarker,
return listMultipartUploadsResult, err
}
for _, obj := range listMultipartUploadsResult.Uploads {
obj.Key, err = url.QueryUnescape(obj.Key)
for i, obj := range listMultipartUploadsResult.Uploads {
listMultipartUploadsResult.Uploads[i].Key, err = url.QueryUnescape(obj.Key)
if err != nil {
return listMultipartUploadsResult, err
}
}
for _, obj := range listMultipartUploadsResult.CommonPrefixes {
obj.Prefix, err = url.QueryUnescape(obj.Prefix)
for i, obj := range listMultipartUploadsResult.CommonPrefixes {
listMultipartUploadsResult.CommonPrefixes[i].Prefix, err = url.QueryUnescape(obj.Prefix)
if err != nil {
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() {
var notificationInfo NotificationInfo
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)
continue
}
@@ -211,7 +216,11 @@ func (c Client) ListenBucketNotification(bucketName, prefix, suffix string, even
return
}
}
if err = bio.Err(); err != nil {
notificationInfoCh <- NotificationInfo{
Err: err,
}
}
// Close current connection before looping further.
closeResponse(resp)
}

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

@@ -104,7 +104,7 @@ type Options struct {
// Global constants.
const (
libraryName = "minio-go"
libraryVersion = "v6.0.38"
libraryVersion = "v6.0.40"
)
// 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/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
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/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
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/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
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/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
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=
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=

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

@@ -132,7 +132,7 @@ github.com/mattn/go-sqlite3
github.com/matttproud/golang_protobuf_extensions/pbutil
# github.com/miekg/dns v1.1.19
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/pkg/credentials
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) {
if !CheckClientCompatability(r.UserAgent()) {
renderUnsuppportedBrowser(c.App, w, r)
renderUnsupportedBrowser(c.App, w, r)
return
}

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

@@ -44,7 +44,7 @@ type SystemBrowser struct {
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")
page := utils.NewHTMLTemplate(app.HTMLTemplates(), "unsupported_browser")