1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2// See LICENSE.txt for license information.
3
4package app
5
6import (
7	"strconv"
8	"testing"
9	"time"
10
11	"github.com/stretchr/testify/assert"
12	"github.com/stretchr/testify/mock"
13
14	"github.com/mattermost/mattermost-server/v6/model"
15	"github.com/mattermost/mattermost-server/v6/store/storetest/mocks"
16	"github.com/mattermost/mattermost-server/v6/utils"
17)
18
19func TestConfigListener(t *testing.T) {
20	th := Setup(t)
21	defer th.TearDown()
22
23	originalSiteName := th.App.Config().TeamSettings.SiteName
24
25	listenerCalled := false
26	listener := func(oldConfig *model.Config, newConfig *model.Config) {
27		assert.False(t, listenerCalled, "listener called twice")
28
29		assert.Equal(t, *originalSiteName, *oldConfig.TeamSettings.SiteName, "old config contains incorrect site name")
30		assert.Equal(t, "test123", *newConfig.TeamSettings.SiteName, "new config contains incorrect site name")
31
32		listenerCalled = true
33	}
34	listenerId := th.App.AddConfigListener(listener)
35	defer th.App.RemoveConfigListener(listenerId)
36
37	listener2Called := false
38	listener2 := func(oldConfig *model.Config, newConfig *model.Config) {
39		assert.False(t, listener2Called, "listener2 called twice")
40
41		listener2Called = true
42	}
43	listener2Id := th.App.AddConfigListener(listener2)
44	defer th.App.RemoveConfigListener(listener2Id)
45
46	th.App.UpdateConfig(func(cfg *model.Config) {
47		*cfg.TeamSettings.SiteName = "test123"
48	})
49
50	assert.True(t, listenerCalled, "listener should've been called")
51	assert.True(t, listener2Called, "listener 2 should've been called")
52}
53
54func TestAsymmetricSigningKey(t *testing.T) {
55	th := SetupWithStoreMock(t)
56	defer th.TearDown()
57	assert.NotNil(t, th.App.AsymmetricSigningKey())
58	assert.NotEmpty(t, th.App.ClientConfig()["AsymmetricSigningPublicKey"])
59}
60
61func TestPostActionCookieSecret(t *testing.T) {
62	th := SetupWithStoreMock(t)
63	defer th.TearDown()
64	assert.Equal(t, 32, len(th.App.PostActionCookieSecret()))
65}
66
67func TestClientConfigWithComputed(t *testing.T) {
68	th := SetupWithStoreMock(t)
69	defer th.TearDown()
70
71	mockStore := th.App.Srv().Store.(*mocks.Store)
72	mockUserStore := mocks.UserStore{}
73	mockUserStore.On("Count", mock.Anything).Return(int64(10), nil)
74	mockPostStore := mocks.PostStore{}
75	mockPostStore.On("GetMaxPostSize").Return(65535, nil)
76	mockSystemStore := mocks.SystemStore{}
77	mockSystemStore.On("GetByName", "UpgradedFromTE").Return(&model.System{Name: "UpgradedFromTE", Value: "false"}, nil)
78	mockSystemStore.On("GetByName", "InstallationDate").Return(&model.System{Name: "InstallationDate", Value: "10"}, nil)
79	mockStore.On("User").Return(&mockUserStore)
80	mockStore.On("Post").Return(&mockPostStore)
81	mockStore.On("System").Return(&mockSystemStore)
82
83	config := th.App.ClientConfigWithComputed()
84	_, ok := config["NoAccounts"]
85	assert.True(t, ok, "expected NoAccounts in returned config")
86	_, ok = config["MaxPostSize"]
87	assert.True(t, ok, "expected MaxPostSize in returned config")
88}
89
90func TestEnsureInstallationDate(t *testing.T) {
91	th := Setup(t)
92	defer th.TearDown()
93
94	tt := []struct {
95		Name                     string
96		PrevInstallationDate     *int64
97		UsersCreationDates       []int64
98		ExpectedInstallationDate *int64
99	}{
100		{
101			Name:                     "New installation: no users, no installation date",
102			PrevInstallationDate:     nil,
103			UsersCreationDates:       nil,
104			ExpectedInstallationDate: model.NewInt64(utils.MillisFromTime(time.Now())),
105		},
106		{
107			Name:                     "Old installation: users, no installation date",
108			PrevInstallationDate:     nil,
109			UsersCreationDates:       []int64{10000000000, 30000000000, 20000000000},
110			ExpectedInstallationDate: model.NewInt64(10000000000),
111		},
112		{
113			Name:                     "New installation, second run: no users, installation date",
114			PrevInstallationDate:     model.NewInt64(80000000000),
115			UsersCreationDates:       []int64{10000000000, 30000000000, 20000000000},
116			ExpectedInstallationDate: model.NewInt64(80000000000),
117		},
118		{
119			Name:                     "Old installation already updated: users, installation date",
120			PrevInstallationDate:     model.NewInt64(90000000000),
121			UsersCreationDates:       []int64{10000000000, 30000000000, 20000000000},
122			ExpectedInstallationDate: model.NewInt64(90000000000),
123		},
124	}
125
126	for _, tc := range tt {
127		t.Run(tc.Name, func(t *testing.T) {
128			sqlStore := th.GetSqlStore()
129			sqlStore.GetMaster().Exec("DELETE FROM Users")
130
131			for _, createAt := range tc.UsersCreationDates {
132				user := th.CreateUser()
133				user.CreateAt = createAt
134				sqlStore.GetMaster().Exec("UPDATE Users SET CreateAt = :CreateAt WHERE Id = :UserId", map[string]interface{}{"CreateAt": createAt, "UserId": user.Id})
135			}
136
137			if tc.PrevInstallationDate == nil {
138				th.App.Srv().Store.System().PermanentDeleteByName(model.SystemInstallationDateKey)
139			} else {
140				th.App.Srv().Store.System().SaveOrUpdate(&model.System{
141					Name:  model.SystemInstallationDateKey,
142					Value: strconv.FormatInt(*tc.PrevInstallationDate, 10),
143				})
144			}
145
146			err := th.App.Srv().ensureInstallationDate()
147
148			if tc.ExpectedInstallationDate == nil {
149				assert.Error(t, err)
150			} else {
151				assert.NoError(t, err)
152
153				data, err := th.App.Srv().Store.System().GetByName(model.SystemInstallationDateKey)
154				assert.NoError(t, err)
155				value, _ := strconv.ParseInt(data.Value, 10, 64)
156				assert.True(t, *tc.ExpectedInstallationDate <= value && *tc.ExpectedInstallationDate+1000 >= value)
157			}
158
159			sqlStore.GetMaster().Exec("DELETE FROM Users")
160		})
161	}
162}
163