Merge branch 'release-4.7' into XYZ-110

Этот коммит содержится в:
Jonathan Fritz
2018-02-13 08:39:56 -05:00
родитель 7b2861de3a 8b79f5d49c
Коммит 18fa32567b
87 изменённых файлов: 1229 добавлений и 1407 удалений

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

@@ -237,8 +237,7 @@ func (a *App) TestEmail(userId string, cfg *model.Config) *model.AppError {
return err
} else {
T := utils.GetUserTranslations(user.Locale)
license := a.License()
if err := utils.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), cfg, license != nil && *license.Features.Compliance); err != nil {
if err := utils.SendMailUsingConfig(user.Email, T("api.admin.test_email.subject"), T("api.admin.test_email.body"), cfg); err != nil {
return err
}
}

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

@@ -4,7 +4,6 @@
package app
import (
"crypto/ecdsa"
"html/template"
"net"
"net/http"
@@ -59,20 +58,15 @@ type App struct {
configFile string
configListeners map[string]func(*model.Config, *model.Config)
licenseValue atomic.Value
clientLicenseValue atomic.Value
licenseListeners map[string]func()
newStore func() store.Store
htmlTemplateWatcher *utils.HTMLTemplateWatcher
sessionCache *utils.Cache
roles map[string]*model.Role
configListenerId string
licenseListenerId string
disableConfigWatch bool
configWatcher *utils.ConfigWatcher
asymmetricSigningKey *ecdsa.PrivateKey
htmlTemplateWatcher *utils.HTMLTemplateWatcher
sessionCache *utils.Cache
roles map[string]*model.Role
configListenerId string
licenseListenerId string
disableConfigWatch bool
configWatcher *utils.ConfigWatcher
pluginCommands []*PluginCommand
pluginCommandsLock sync.RWMutex
@@ -86,7 +80,7 @@ var appCount = 0
// New creates a new App. You must call Shutdown when you're done with it.
// XXX: For now, only one at a time is allowed as some resources are still shared.
func New(options ...Option) (outApp *App, outErr error) {
func New(options ...Option) (*App, error) {
appCount++
if appCount > 1 {
panic("Only one App should exist at a time. Did you forget to call Shutdown()?")
@@ -97,17 +91,11 @@ func New(options ...Option) (outApp *App, outErr error) {
Srv: &Server{
Router: mux.NewRouter(),
},
sessionCache: utils.NewLru(model.SESSION_CACHE_SIZE),
configFile: "config.json",
configListeners: make(map[string]func(*model.Config, *model.Config)),
clientConfig: make(map[string]string),
licenseListeners: map[string]func(){},
sessionCache: utils.NewLru(model.SESSION_CACHE_SIZE),
configFile: "config.json",
configListeners: make(map[string]func(*model.Config, *model.Config)),
clientConfig: make(map[string]string),
}
defer func() {
if outErr != nil {
app.Shutdown()
}
}()
for _, option := range options {
option(app)
@@ -130,9 +118,9 @@ func New(options ...Option) (outApp *App, outErr error) {
app.configListenerId = app.AddConfigListener(func(_, _ *model.Config) {
app.configOrLicenseListener()
})
app.licenseListenerId = app.AddLicenseListener(app.configOrLicenseListener)
app.licenseListenerId = utils.AddLicenseListener(app.configOrLicenseListener)
app.regenerateClientConfig()
app.setDefaultRolesBasedOnConfig()
app.SetDefaultRolesBasedOnConfig()
l4g.Info(utils.T("api.server.new_server.init.info"))
@@ -151,10 +139,6 @@ func New(options ...Option) (outApp *App, outErr error) {
}
app.Srv.Store = app.newStore()
if err := app.ensureAsymmetricSigningKey(); err != nil {
return nil, errors.Wrapf(err, "unable to ensure asymmetric signing key")
}
app.initJobs()
app.initBuiltInPlugins()
@@ -173,7 +157,7 @@ func New(options ...Option) (outApp *App, outErr error) {
func (a *App) configOrLicenseListener() {
a.regenerateClientConfig()
a.setDefaultRolesBasedOnConfig()
a.SetDefaultRolesBasedOnConfig()
}
func (a *App) Shutdown() {
@@ -187,9 +171,7 @@ func (a *App) Shutdown() {
a.ShutDownPlugins()
a.WaitForGoroutines()
if a.Srv.Store != nil {
a.Srv.Store.Close()
}
a.Srv.Store.Close()
a.Srv = nil
if a.htmlTemplateWatcher != nil {
@@ -197,7 +179,7 @@ func (a *App) Shutdown() {
}
a.RemoveConfigListener(a.configListenerId)
a.RemoveLicenseListener(a.licenseListenerId)
utils.RemoveLicenseListener(a.licenseListenerId)
l4g.Info(utils.T("api.server.stop_server.stopped.info"))
a.DisableConfigWatch()
@@ -466,5 +448,5 @@ func (a *App) Handle404(w http.ResponseWriter, r *http.Request) {
l4g.Debug("%v: code=404 ip=%v", r.URL.Path, utils.GetIpAddress(r))
utils.RenderWebAppError(w, r, err, a.AsymmetricSigningKey())
utils.RenderWebError(err, w, r)
}

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

@@ -51,8 +51,7 @@ func TestAppRace(t *testing.T) {
a, err := New()
require.NoError(t, err)
a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" })
serverErr := a.StartServer()
require.NoError(t, serverErr)
a.StartServer()
a.Shutdown()
}
}

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

@@ -96,20 +96,15 @@ func setupTestHelper(enterprise bool) *TestHelper {
if testStore != nil {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" })
}
serverErr := th.App.StartServer()
if serverErr != nil {
panic(serverErr)
}
th.App.StartServer()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = prevListenAddress })
th.App.Srv.Store.MarkSystemRanUnitTests()
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = true })
utils.SetIsLicensed(enterprise)
if enterprise {
th.App.SetLicense(model.NewTestLicense())
} else {
th.App.SetLicense(nil)
utils.License().Features.SetDefaults()
}
return th

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

@@ -1359,7 +1359,7 @@ func (a *App) PermanentDeleteChannel(channel *model.Channel) *model.AppError {
// This function is intended for use from the CLI. It is not robust against people joining the channel while the move
// is in progress, and therefore should not be used from the API without first fixing this potential race condition.
func (a *App) MoveChannel(team *model.Team, channel *model.Channel, user *model.User) *model.AppError {
func (a *App) MoveChannel(team *model.Team, channel *model.Channel) *model.AppError {
// Check that all channel members are in the destination team.
if channelMembers, err := a.GetChannelMembersPage(channel.Id, 0, 10000000); err != nil {
return err
@@ -1378,37 +1378,11 @@ func (a *App) MoveChannel(team *model.Team, channel *model.Channel, user *model.
}
}
// keep instance of the previous team
var previousTeam *model.Team
if result := <-a.Srv.Store.Team().Get(channel.TeamId); result.Err != nil {
return result.Err
} else {
previousTeam = result.Data.(*model.Team)
}
// Change the Team ID of the channel.
channel.TeamId = team.Id
if result := <-a.Srv.Store.Channel().Update(channel); result.Err != nil {
return result.Err
}
a.postChannelMoveMessage(user, channel, previousTeam)
return nil
}
func (a *App) postChannelMoveMessage(user *model.User, channel *model.Channel, previousTeam *model.Team) *model.AppError {
post := &model.Post{
ChannelId: channel.Id,
Message: fmt.Sprintf(utils.T("api.team.move_channel.success"), previousTeam.Name),
Type: model.POST_MOVE_CHANNEL,
UserId: user.Id,
Props: model.StringInterface{
"username": user.Username,
},
}
if _, err := a.CreatePost(post, channel, false); err != nil {
return model.NewAppError("postChannelMoveMessage", "api.team.move_channel.post.error", nil, err.Error(), http.StatusInternalServerError)
}
return nil
}

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

@@ -97,7 +97,7 @@ func TestMoveChannel(t *testing.T) {
t.Fatal(err)
}
if err := th.App.MoveChannel(targetTeam, channel1, th.BasicUser); err == nil {
if err := th.App.MoveChannel(targetTeam, channel1); err == nil {
t.Fatal("Should have failed due to mismatched members.")
}
@@ -105,7 +105,7 @@ func TestMoveChannel(t *testing.T) {
t.Fatal(err)
}
if err := th.App.MoveChannel(targetTeam, channel1, th.BasicUser); err != nil {
if err := th.App.MoveChannel(targetTeam, channel1); err != nil {
t.Fatal(err)
}
}

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

@@ -4,12 +4,7 @@
package app
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/md5"
"crypto/rand"
"crypto/x509"
"encoding/base64"
"encoding/json"
"fmt"
"runtime/debug"
@@ -121,91 +116,8 @@ func (a *App) InvokeConfigListeners(old, current *model.Config) {
}
}
// EnsureAsymmetricSigningKey ensures that an asymmetric signing key exists and future calls to
// AsymmetricSigningKey will always return a valid signing key.
func (a *App) ensureAsymmetricSigningKey() error {
if a.asymmetricSigningKey != nil {
return nil
}
var key *model.SystemAsymmetricSigningKey
result := <-a.Srv.Store.System().GetByName(model.SYSTEM_ASYMMETRIC_SIGNING_KEY)
if result.Err == nil {
if err := json.Unmarshal([]byte(result.Data.(*model.System).Value), &key); err != nil {
return err
}
}
// If we don't already have a key, try to generate one.
if key == nil {
newECDSAKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return err
}
newKey := &model.SystemAsymmetricSigningKey{
ECDSAKey: &model.SystemECDSAKey{
Curve: "P-256",
X: newECDSAKey.X,
Y: newECDSAKey.Y,
D: newECDSAKey.D,
},
}
system := &model.System{
Name: model.SYSTEM_ASYMMETRIC_SIGNING_KEY,
}
v, err := json.Marshal(newKey)
if err != nil {
return err
}
system.Value = string(v)
if result = <-a.Srv.Store.System().Save(system); result.Err == nil {
// If we were able to save the key, use it, otherwise ignore the error.
key = newKey
}
}
// If we weren't able to save a new key above, another server must have beat us to it. Get the
// key from the database, and if that fails, error out.
if key == nil {
result := <-a.Srv.Store.System().GetByName(model.SYSTEM_ASYMMETRIC_SIGNING_KEY)
if result.Err != nil {
return result.Err
} else if err := json.Unmarshal([]byte(result.Data.(*model.System).Value), &key); err != nil {
return err
}
}
var curve elliptic.Curve
switch key.ECDSAKey.Curve {
case "P-256":
curve = elliptic.P256()
default:
return fmt.Errorf("unknown curve: " + key.ECDSAKey.Curve)
}
a.asymmetricSigningKey = &ecdsa.PrivateKey{
PublicKey: ecdsa.PublicKey{
Curve: curve,
X: key.ECDSAKey.X,
Y: key.ECDSAKey.Y,
},
D: key.ECDSAKey.D,
}
a.regenerateClientConfig()
return nil
}
// AsymmetricSigningKey will return a private key that can be used for asymmetric signing.
func (a *App) AsymmetricSigningKey() *ecdsa.PrivateKey {
return a.asymmetricSigningKey
}
func (a *App) regenerateClientConfig() {
a.clientConfig = utils.GenerateClientConfig(a.Config(), a.DiagnosticId(), a.License())
if key := a.AsymmetricSigningKey(); key != nil {
der, _ := x509.MarshalPKIXPublicKey(&key.PublicKey)
a.clientConfig["AsymmetricSigningPublicKey"] = base64.StdEncoding.EncodeToString(der)
}
a.clientConfig = utils.GenerateClientConfig(a.Config(), a.DiagnosticId())
clientConfigJSON, _ := json.Marshal(a.clientConfig)
a.clientConfigHash = fmt.Sprintf("%x", md5.Sum(clientConfigJSON))
}
@@ -254,3 +166,11 @@ func (a *App) Desanitize(cfg *model.Config) {
cfg.SqlSettings.DataSourceSearchReplicas[i] = actual.SqlSettings.DataSourceSearchReplicas[i]
}
}
// License returns the currently active license or nil if the application is unlicensed.
func (a *App) License() *model.License {
if utils.IsLicensed() {
return utils.License()
}
return nil
}

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

@@ -6,8 +6,6 @@ package app
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/mattermost/mattermost-server/model"
)
@@ -56,10 +54,3 @@ func TestConfigListener(t *testing.T) {
t.Fatal("listener 2 should've been called")
}
}
func TestAsymmetricSigningKey(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()
assert.NotNil(t, th.App.AsymmetricSigningKey())
assert.NotEmpty(t, th.App.ClientConfig()["AsymmetricSigningPublicKey"])
}

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

@@ -501,7 +501,6 @@ func (a *App) trackConfig() {
a.SendDiagnostic(TRACK_CONFIG_MESSAGE_EXPORT, map[string]interface{}{
"enable_message_export": *cfg.MessageExportSettings.EnableExport,
"export_format": *cfg.MessageExportSettings.ExportFormat,
"daily_run_time": *cfg.MessageExportSettings.DailyRunTime,
"default_export_from_timestamp": *cfg.MessageExportSettings.ExportFromTimestamp,
"batch_size": *cfg.MessageExportSettings.BatchSize,

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

@@ -317,6 +317,5 @@ func (a *App) NewEmailTemplate(name, locale string) *utils.HTMLTemplate {
}
func (a *App) SendMail(to, subject, htmlBody string) *model.AppError {
license := a.License()
return utils.SendMailUsingConfig(to, subject, htmlBody, a.Config(), license != nil && *license.Features.Compliance)
return utils.SendMailUsingConfig(to, subject, htmlBody, a.Config())
}

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

@@ -58,8 +58,7 @@ const (
)
func (a *App) FileBackend() (utils.FileBackend, *model.AppError) {
license := a.License()
return utils.NewFileBackend(&a.Config().FileSettings, license != nil && *license.Features.Compliance)
return utils.NewFileBackend(&a.Config().FileSettings)
}
func (a *App) ReadFile(path string) ([]byte, *model.AppError) {

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

@@ -4,19 +4,16 @@
package app
import (
"crypto/md5"
"fmt"
"net/http"
"strings"
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils"
)
func (a *App) LoadLicense() {
a.SetLicense(nil)
utils.RemoveLicense()
licenseId := ""
if result := <-a.Srv.Store.System().Get(); result.Err == nil {
@@ -39,7 +36,7 @@ func (a *App) LoadLicense() {
if result := <-a.Srv.Store.License().Get(licenseId); result.Err == nil {
record := result.Data.(*model.LicenseRecord)
a.ValidateAndSetLicenseBytes([]byte(record.Bytes))
utils.LoadLicense([]byte(record.Bytes))
l4g.Info("License key valid unlocking enterprise features.")
} else {
l4g.Info(utils.T("mattermost.load_license.find.warn"))
@@ -62,7 +59,7 @@ func (a *App) SaveLicense(licenseBytes []byte) (*model.License, *model.AppError)
}
}
if ok := a.SetLicense(license); !ok {
if ok := utils.SetLicense(license); !ok {
return nil, model.NewAppError("addLicense", model.EXPIRED_LICENSE_ERROR, nil, "", http.StatusBadRequest)
}
@@ -105,115 +102,21 @@ func (a *App) SaveLicense(licenseBytes []byte) (*model.License, *model.AppError)
return license, nil
}
// License returns the currently active license or nil if the application is unlicensed.
func (a *App) License() *model.License {
license, _ := a.licenseValue.Load().(*model.License)
return license
}
func (a *App) SetLicense(license *model.License) bool {
defer func() {
a.setDefaultRolesBasedOnConfig()
for _, listener := range a.licenseListeners {
listener()
}
}()
if license != nil {
license.Features.SetDefaults()
if !license.IsExpired() {
a.licenseValue.Store(license)
a.clientLicenseValue.Store(utils.GetClientLicense(license))
return true
}
}
a.licenseValue.Store((*model.License)(nil))
a.SetClientLicense(map[string]string{"IsLicensed": "false"})
return false
}
func (a *App) ValidateAndSetLicenseBytes(b []byte) {
if success, licenseStr := utils.ValidateLicense(b); success {
license := model.LicenseFromJson(strings.NewReader(licenseStr))
a.SetLicense(license)
return
}
l4g.Warn(utils.T("utils.license.load_license.invalid.warn"))
}
func (a *App) SetClientLicense(m map[string]string) {
a.clientLicenseValue.Store(m)
}
func (a *App) ClientLicense() map[string]string {
clientLicense, _ := a.clientLicenseValue.Load().(map[string]string)
return clientLicense
}
func (a *App) RemoveLicense() *model.AppError {
if license, _ := a.licenseValue.Load().(*model.License); license == nil {
return nil
}
utils.RemoveLicense()
sysVar := &model.System{}
sysVar.Name = model.SYSTEM_ACTIVE_LICENSE_ID
sysVar.Value = ""
if result := <-a.Srv.Store.System().SaveOrUpdate(sysVar); result.Err != nil {
utils.RemoveLicense()
return result.Err
}
a.SetLicense(nil)
a.ReloadConfig()
a.InvalidateAllCaches()
return nil
}
func (a *App) AddLicenseListener(listener func()) string {
id := model.NewId()
a.licenseListeners[id] = listener
return id
}
func (a *App) RemoveLicenseListener(id string) {
delete(a.licenseListeners, id)
}
func (a *App) GetClientLicenseEtag(useSanitized bool) string {
value := ""
lic := a.ClientLicense()
if useSanitized {
lic = a.GetSanitizedClientLicense()
}
for k, v := range lic {
value += fmt.Sprintf("%s:%s;", k, v)
}
return model.Etag(fmt.Sprintf("%x", md5.Sum([]byte(value))))
}
func (a *App) GetSanitizedClientLicense() map[string]string {
sanitizedLicense := make(map[string]string)
for k, v := range a.ClientLicense() {
sanitizedLicense[k] = v
}
delete(sanitizedLicense, "Id")
delete(sanitizedLicense, "Name")
delete(sanitizedLicense, "Email")
delete(sanitizedLicense, "PhoneNumber")
delete(sanitizedLicense, "IssuedAt")
delete(sanitizedLicense, "StartsAt")
delete(sanitizedLicense, "ExpiresAt")
return sanitizedLicense
}

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

@@ -4,9 +4,8 @@
package app
import (
//"github.com/mattermost/mattermost-server/model"
"testing"
"github.com/mattermost/mattermost-server/model"
)
func TestLoadLicense(t *testing.T) {
@@ -38,75 +37,3 @@ func TestRemoveLicense(t *testing.T) {
t.Fatal("should have removed license")
}
}
func TestSetLicense(t *testing.T) {
th := Setup()
defer th.TearDown()
l1 := &model.License{}
l1.Features = &model.Features{}
l1.Customer = &model.Customer{}
l1.StartsAt = model.GetMillis() - 1000
l1.ExpiresAt = model.GetMillis() + 100000
if ok := th.App.SetLicense(l1); !ok {
t.Fatal("license should have worked")
}
l2 := &model.License{}
l2.Features = &model.Features{}
l2.Customer = &model.Customer{}
l2.StartsAt = model.GetMillis() - 1000
l2.ExpiresAt = model.GetMillis() - 100
if ok := th.App.SetLicense(l2); ok {
t.Fatal("license should have failed")
}
l3 := &model.License{}
l3.Features = &model.Features{}
l3.Customer = &model.Customer{}
l3.StartsAt = model.GetMillis() + 10000
l3.ExpiresAt = model.GetMillis() + 100000
if ok := th.App.SetLicense(l3); !ok {
t.Fatal("license should have passed")
}
}
func TestClientLicenseEtag(t *testing.T) {
th := Setup()
defer th.TearDown()
etag1 := th.App.GetClientLicenseEtag(false)
th.App.SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "true"})
etag2 := th.App.GetClientLicenseEtag(false)
if etag1 == etag2 {
t.Fatal("etags should not match")
}
th.App.SetClientLicense(map[string]string{"SomeFeature": "true", "IsLicensed": "false"})
etag3 := th.App.GetClientLicenseEtag(false)
if etag2 == etag3 {
t.Fatal("etags should not match")
}
}
func TestGetSanitizedClientLicense(t *testing.T) {
th := Setup()
defer th.TearDown()
l1 := &model.License{}
l1.Features = &model.Features{}
l1.Customer = &model.Customer{}
l1.Customer.Name = "TestName"
l1.StartsAt = model.GetMillis() - 1000
l1.ExpiresAt = model.GetMillis() + 100000
th.App.SetLicense(l1)
m := th.App.GetSanitizedClientLicense()
if _, ok := m["Name"]; ok {
t.Fatal("should have been sanatized")
}
}

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

@@ -565,7 +565,6 @@ func (a *App) RegisterPluginCommand(pluginId string, command *model.Command) err
TeamId: command.TeamId,
AutoComplete: command.AutoComplete,
AutoCompleteDesc: command.AutoCompleteDesc,
AutoCompleteHint: command.AutoCompleteHint,
DisplayName: command.DisplayName,
}

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

@@ -6,8 +6,6 @@ package app
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
@@ -950,18 +948,6 @@ func (a *App) ImageProxyAdder() func(string) string {
mac.Write([]byte(url))
digest := hex.EncodeToString(mac.Sum(nil))
return proxyURL + digest + "/" + hex.EncodeToString([]byte(url))
case "willnorris/imageproxy":
options := strings.Split(options, "|")
if len(options) > 1 {
mac := hmac.New(sha256.New, []byte(options[1]))
mac.Write([]byte(url))
digest := base64.URLEncoding.EncodeToString(mac.Sum(nil))
if options[0] == "" {
return proxyURL + "s" + digest + "/" + url
}
return proxyURL + options[0] + ",s" + digest + "/" + url
}
return proxyURL + options[0] + "/" + url
}
return url
@@ -984,12 +970,6 @@ func (a *App) ImageProxyRemover() (f func(string) string) {
}
}
}
case "willnorris/imageproxy":
if strings.HasPrefix(url, proxyURL) {
if slash := strings.IndexByte(url[len(proxyURL):], '/'); slash >= 0 {
return url[len(proxyURL)+slash+1:]
}
}
}
return url

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

@@ -210,38 +210,27 @@ func TestImageProxy(t *testing.T) {
ImageURL: "http://mydomain.com/myimage",
ProxiedImageURL: "https://127.0.0.1/f8dace906d23689e8d5b12c3cefbedbf7b9b72f5/687474703a2f2f6d79646f6d61696e2e636f6d2f6d79696d616765",
},
"willnorris/imageproxy": {
ProxyType: "willnorris/imageproxy",
ProxyURL: "https://127.0.0.1",
ProxyOptions: "x1000",
ImageURL: "http://mydomain.com/myimage",
ProxiedImageURL: "https://127.0.0.1/x1000/http://mydomain.com/myimage",
},
"willnorris/imageproxy_SameSite": {
ProxyType: "willnorris/imageproxy",
"atmos/camo_SameSite": {
ProxyType: "atmos/camo",
ProxyURL: "https://127.0.0.1",
ProxyOptions: "foo",
ImageURL: "http://mymattermost.com/myimage",
ProxiedImageURL: "http://mymattermost.com/myimage",
},
"willnorris/imageproxy_PathOnly": {
ProxyType: "willnorris/imageproxy",
"atmos/camo_PathOnly": {
ProxyType: "atmos/camo",
ProxyURL: "https://127.0.0.1",
ProxyOptions: "foo",
ImageURL: "/myimage",
ProxiedImageURL: "/myimage",
},
"willnorris/imageproxy_EmptyImageURL": {
ProxyType: "willnorris/imageproxy",
"atmos/camo_EmptyImageURL": {
ProxyType: "atmos/camo",
ProxyURL: "https://127.0.0.1",
ProxyOptions: "foo",
ImageURL: "",
ProxiedImageURL: "",
},
"willnorris/imageproxy_WithSigning": {
ProxyType: "willnorris/imageproxy",
ProxyURL: "https://127.0.0.1",
ProxyOptions: "x1000|foo",
ImageURL: "http://mydomain.com/myimage",
ProxiedImageURL: "https://127.0.0.1/x1000,sbhHVoG5d60UvnNtGh6Iy6x4PaMmnsh8JfZ7JfErKjGU=/http://mydomain.com/myimage",
},
} {
t.Run(name, func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
@@ -356,27 +345,4 @@ func TestMakeOpenGraphURLsAbsolute(t *testing.T) {
}
})
}
}
var imageProxyBenchmarkSink *model.Post
func BenchmarkPostWithProxyRemovedFromImageURLs(b *testing.B) {
th := Setup().InitBasic()
defer th.TearDown()
th.App.UpdateConfig(func(cfg *model.Config) {
cfg.ServiceSettings.ImageProxyType = model.NewString("willnorris/imageproxy")
cfg.ServiceSettings.ImageProxyOptions = model.NewString("x1000|foo")
cfg.ServiceSettings.ImageProxyURL = model.NewString("https://127.0.0.1")
})
post := &model.Post{
Message: "![foo](http://mydomain.com/myimage)",
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
imageProxyBenchmarkSink = th.App.PostWithProxyAddedToImageURLs(post)
}
}
}

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

@@ -12,6 +12,8 @@ func (a *App) Role(id string) *model.Role {
return a.roles[id]
}
func (a *App) setDefaultRolesBasedOnConfig() {
a.roles = utils.DefaultRolesBasedOnConfig(a.Config(), a.License() != nil)
// Updates the roles based on the app config and the global license check. You may need to invoke
// this when license changes are made.
func (a *App) SetDefaultRolesBasedOnConfig() {
a.roles = utils.DefaultRolesBasedOnConfig(a.Config())
}

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

@@ -17,7 +17,6 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"golang.org/x/crypto/acme/autocert"
"github.com/mattermost/mattermost-server/model"
@@ -117,7 +116,7 @@ func redirectHTTPToHTTPS(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, url.String(), http.StatusFound)
}
func (a *App) StartServer() error {
func (a *App) StartServer() {
l4g.Info(utils.T("api.server.start_server.starting.info"))
var handler http.Handler = &CorsWrapper{a.Config, a.Srv.Router}
@@ -127,7 +126,8 @@ func (a *App) StartServer() error {
rateLimiter, err := NewRateLimiter(&a.Config().RateLimitSettings)
if err != nil {
return err
l4g.Critical(err.Error())
return
}
a.Srv.RateLimiter = rateLimiter
@@ -151,8 +151,8 @@ func (a *App) StartServer() error {
listener, err := net.Listen("tcp", addr)
if err != nil {
errors.Wrapf(err, utils.T("api.server.start_server.starting.critical"), err)
return err
l4g.Critical(utils.T("api.server.start_server.starting.critical"), err)
return
}
a.Srv.ListenAddr = listener.Addr().(*net.TCPAddr)
@@ -214,8 +214,6 @@ func (a *App) StartServer() error {
}
close(a.Srv.didFinishListen)
}()
return nil
}
type tcpKeepAliveListener struct {

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

@@ -1,50 +0,0 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
import (
"testing"
"github.com/mattermost/mattermost-server/model"
"github.com/stretchr/testify/require"
)
func TestStartServerSuccess(t *testing.T) {
a, err := New()
require.NoError(t, err)
a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ListenAddress = ":0" })
serverErr := a.StartServer()
a.Shutdown()
require.NoError(t, serverErr)
}
func TestStartServerRateLimiterCriticalError(t *testing.T) {
a, err := New()
require.NoError(t, err)
// Attempt to use Rate Limiter with an invalid config
a.UpdateConfig(func(cfg *model.Config) {
*cfg.RateLimitSettings.Enable = true
*cfg.RateLimitSettings.MaxBurst = -100
})
serverErr := a.StartServer()
a.Shutdown()
require.Error(t, serverErr)
}
func TestStartServerPortUnavailable(t *testing.T) {
a, err := New()
require.NoError(t, err)
// Attempt to listen on a system-reserved port
a.UpdateConfig(func(cfg *model.Config) {
*cfg.ServiceSettings.ListenAddress = ":21"
})
serverErr := a.StartServer()
a.Shutdown()
require.Error(t, serverErr)
}

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

@@ -6,10 +6,11 @@ package app
import (
"testing"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/model"
)
func TestCache(t *testing.T) {
@@ -47,7 +48,18 @@ func TestGetSessionIdleTimeoutInMinutes(t *testing.T) {
session, _ = th.App.CreateSession(session)
th.App.SetLicense(model.NewTestLicense("compliance"))
isLicensed := utils.IsLicensed()
license := utils.License()
timeout := *th.App.Config().ServiceSettings.SessionIdleTimeoutInMinutes
defer func() {
utils.SetIsLicensed(isLicensed)
utils.SetLicense(license)
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SessionIdleTimeoutInMinutes = timeout })
}()
utils.SetIsLicensed(true)
utils.SetLicense(&model.License{Features: &model.Features{}})
utils.License().Features.SetDefaults()
*utils.License().Features.Compliance = true
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SessionIdleTimeoutInMinutes = 5 })
rsession, err := th.App.GetSession(session.Token)
@@ -110,7 +122,7 @@ func TestGetSessionIdleTimeoutInMinutes(t *testing.T) {
assert.Nil(t, err)
// Test regular session with license off, should not timeout
th.App.SetLicense(nil)
*utils.License().Features.Compliance = false
session = &model.Session{
UserId: model.NewId(),
@@ -124,7 +136,7 @@ func TestGetSessionIdleTimeoutInMinutes(t *testing.T) {
_, err = th.App.GetSession(session.Token)
assert.Nil(t, err)
th.App.SetLicense(model.NewTestLicense("compliance"))
*utils.License().Features.Compliance = true
// Test regular session with timeout set to 0, should not timeout
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SessionIdleTimeoutInMinutes = 0 })