1// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2// See LICENSE.txt for license information.
3
4package app
5
6import (
7	"fmt"
8	"strings"
9	"testing"
10
11	"github.com/stretchr/testify/assert"
12	"github.com/stretchr/testify/require"
13
14	"github.com/mattermost/mattermost-server/v6/model"
15)
16
17func TestCreateBot(t *testing.T) {
18	t.Run("invalid bot", func(t *testing.T) {
19		t.Run("relative to user", func(t *testing.T) {
20			th := Setup(t).InitBasic()
21			defer th.TearDown()
22
23			_, err := th.App.CreateBot(th.Context, &model.Bot{
24				Username:    "invalid username",
25				Description: "a bot",
26				OwnerId:     th.BasicUser.Id,
27			})
28			require.NotNil(t, err)
29			require.Equal(t, "model.user.is_valid.username.app_error", err.Id)
30		})
31
32		t.Run("relative to bot", func(t *testing.T) {
33			th := Setup(t).InitBasic()
34			defer th.TearDown()
35
36			_, err := th.App.CreateBot(th.Context, &model.Bot{
37				Username:    "username",
38				Description: strings.Repeat("x", 1025),
39				OwnerId:     th.BasicUser.Id,
40			})
41			require.NotNil(t, err)
42			require.Equal(t, "model.bot.is_valid.description.app_error", err.Id)
43		})
44
45		t.Run("username contains . character", func(t *testing.T) {
46			th := Setup(t).InitBasic()
47			defer th.TearDown()
48
49			bot, err := th.App.CreateBot(th.Context, &model.Bot{
50				Username:    "username.",
51				Description: "a bot",
52				OwnerId:     th.BasicUser.Id,
53			})
54			require.NotNil(t, err)
55			require.Nil(t, bot)
56			require.Equal(t, "model.user.is_valid.email.app_error", err.Id)
57		})
58	})
59
60	t.Run("create bot", func(t *testing.T) {
61		th := Setup(t).InitBasic()
62		defer th.TearDown()
63
64		bot, err := th.App.CreateBot(th.Context, &model.Bot{
65			Username:    "username",
66			Description: "a bot",
67			OwnerId:     th.BasicUser.Id,
68		})
69		require.Nil(t, err)
70		defer th.App.PermanentDeleteBot(bot.UserId)
71		assert.Equal(t, "username", bot.Username)
72		assert.Equal(t, "a bot", bot.Description)
73		assert.Equal(t, th.BasicUser.Id, bot.OwnerId)
74
75		user, err := th.App.GetUser(bot.UserId)
76		require.Nil(t, err)
77
78		// Check that a post was created to add bot to team and channels
79		channel, err := th.App.getOrCreateDirectChannelWithUser(th.Context, user, th.BasicUser)
80		require.Nil(t, err)
81		posts, err := th.App.GetPosts(channel.Id, 0, 1)
82		require.Nil(t, err)
83
84		postArray := posts.ToSlice()
85		assert.Len(t, postArray, 1)
86		assert.Equal(t, postArray[0].Type, model.PostTypeAddBotTeamsChannels)
87	})
88
89	t.Run("create bot, username already used by a non-bot user", func(t *testing.T) {
90		th := Setup(t).InitBasic()
91		defer th.TearDown()
92
93		_, err := th.App.CreateBot(th.Context, &model.Bot{
94			Username:    th.BasicUser.Username,
95			Description: "a bot",
96			OwnerId:     th.BasicUser.Id,
97		})
98		require.NotNil(t, err)
99		require.Equal(t, "app.user.save.username_exists.app_error", err.Id)
100	})
101}
102
103func TestPatchBot(t *testing.T) {
104	t.Run("invalid patch for user", func(t *testing.T) {
105		th := Setup(t).InitBasic()
106		defer th.TearDown()
107
108		bot, err := th.App.CreateBot(th.Context, &model.Bot{
109			Username:    "username",
110			Description: "a bot",
111			OwnerId:     th.BasicUser.Id,
112		})
113		require.Nil(t, err)
114		defer th.App.PermanentDeleteBot(bot.UserId)
115
116		botPatch := &model.BotPatch{
117			Username:    sToP("invalid username"),
118			DisplayName: sToP("an updated bot"),
119			Description: sToP("updated bot"),
120		}
121
122		_, err = th.App.PatchBot(bot.UserId, botPatch)
123		require.NotNil(t, err)
124		require.Equal(t, "model.user.is_valid.username.app_error", err.Id)
125	})
126
127	t.Run("invalid patch for bot", func(t *testing.T) {
128		th := Setup(t).InitBasic()
129		defer th.TearDown()
130
131		bot, err := th.App.CreateBot(th.Context, &model.Bot{
132			Username:    "username",
133			Description: "a bot",
134			OwnerId:     th.BasicUser.Id,
135		})
136		require.Nil(t, err)
137		defer th.App.PermanentDeleteBot(bot.UserId)
138
139		botPatch := &model.BotPatch{
140			Username:    sToP("username"),
141			DisplayName: sToP("display name"),
142			Description: sToP(strings.Repeat("x", 1025)),
143		}
144
145		_, err = th.App.PatchBot(bot.UserId, botPatch)
146		require.NotNil(t, err)
147		require.Equal(t, "model.bot.is_valid.description.app_error", err.Id)
148	})
149
150	t.Run("patch bot", func(t *testing.T) {
151		th := Setup(t).InitBasic()
152		defer th.TearDown()
153
154		bot := &model.Bot{
155			Username:    "username",
156			DisplayName: "bot",
157			Description: "a bot",
158			OwnerId:     th.BasicUser.Id,
159		}
160
161		createdBot, err := th.App.CreateBot(th.Context, bot)
162		require.Nil(t, err)
163		defer th.App.PermanentDeleteBot(createdBot.UserId)
164
165		botPatch := &model.BotPatch{
166			Username:    sToP("username2"),
167			DisplayName: sToP("updated bot"),
168			Description: sToP("an updated bot"),
169		}
170
171		patchedBot, err := th.App.PatchBot(createdBot.UserId, botPatch)
172		require.Nil(t, err)
173
174		// patchedBot should create a new .UpdateAt time
175		require.NotEqual(t, createdBot.UpdateAt, patchedBot.UpdateAt)
176
177		createdBot.Username = "username2"
178		createdBot.DisplayName = "updated bot"
179		createdBot.Description = "an updated bot"
180		createdBot.UpdateAt = patchedBot.UpdateAt
181		require.Equal(t, createdBot, patchedBot)
182	})
183
184	t.Run("patch bot, username already used by a non-bot user", func(t *testing.T) {
185		th := Setup(t).InitBasic()
186		defer th.TearDown()
187
188		bot, err := th.App.CreateBot(th.Context, &model.Bot{
189			Username:    "username",
190			DisplayName: "bot",
191			Description: "a bot",
192			OwnerId:     th.BasicUser.Id,
193		})
194		require.Nil(t, err)
195		defer th.App.PermanentDeleteBot(bot.UserId)
196
197		botPatch := &model.BotPatch{
198			Username: sToP(th.BasicUser2.Username),
199		}
200
201		_, err = th.App.PatchBot(bot.UserId, botPatch)
202		require.NotNil(t, err)
203		require.Equal(t, "app.user.save.username_exists.app_error", err.Id)
204	})
205}
206
207func TestGetBot(t *testing.T) {
208	th := Setup(t).InitBasic()
209	defer th.TearDown()
210
211	bot1, err := th.App.CreateBot(th.Context, &model.Bot{
212		Username:    "username",
213		Description: "a bot",
214		OwnerId:     th.BasicUser.Id,
215	})
216	require.Nil(t, err)
217	defer th.App.PermanentDeleteBot(bot1.UserId)
218
219	bot2, err := th.App.CreateBot(th.Context, &model.Bot{
220		Username:    "username2",
221		Description: "a second bot",
222		OwnerId:     th.BasicUser.Id,
223	})
224	require.Nil(t, err)
225	defer th.App.PermanentDeleteBot(bot2.UserId)
226
227	deletedBot, err := th.App.CreateBot(th.Context, &model.Bot{
228		Username:    "username3",
229		Description: "a deleted bot",
230		OwnerId:     th.BasicUser.Id,
231	})
232	require.Nil(t, err)
233	deletedBot, err = th.App.UpdateBotActive(th.Context, deletedBot.UserId, false)
234	require.Nil(t, err)
235	defer th.App.PermanentDeleteBot(deletedBot.UserId)
236
237	t.Run("get unknown bot", func(t *testing.T) {
238		_, err := th.App.GetBot(model.NewId(), false)
239		require.NotNil(t, err)
240		require.Equal(t, "store.sql_bot.get.missing.app_error", err.Id)
241	})
242
243	t.Run("get bot1", func(t *testing.T) {
244		bot, err := th.App.GetBot(bot1.UserId, false)
245		require.Nil(t, err)
246		assert.Equal(t, bot1, bot)
247	})
248
249	t.Run("get bot2", func(t *testing.T) {
250		bot, err := th.App.GetBot(bot2.UserId, false)
251		require.Nil(t, err)
252		assert.Equal(t, bot2, bot)
253	})
254
255	t.Run("get deleted bot", func(t *testing.T) {
256		_, err := th.App.GetBot(deletedBot.UserId, false)
257		require.NotNil(t, err)
258		require.Equal(t, "store.sql_bot.get.missing.app_error", err.Id)
259	})
260
261	t.Run("get deleted bot, include deleted", func(t *testing.T) {
262		bot, err := th.App.GetBot(deletedBot.UserId, true)
263		require.Nil(t, err)
264		assert.Equal(t, deletedBot, bot)
265	})
266}
267
268func TestGetBots(t *testing.T) {
269	th := Setup(t)
270	defer th.TearDown()
271
272	OwnerId1 := model.NewId()
273	OwnerId2 := model.NewId()
274
275	bot1, err := th.App.CreateBot(th.Context, &model.Bot{
276		Username:    "username",
277		Description: "a bot",
278		OwnerId:     OwnerId1,
279	})
280	require.Nil(t, err)
281	defer th.App.PermanentDeleteBot(bot1.UserId)
282
283	deletedBot1, err := th.App.CreateBot(th.Context, &model.Bot{
284		Username:    "username4",
285		Description: "a deleted bot",
286		OwnerId:     OwnerId1,
287	})
288	require.Nil(t, err)
289	deletedBot1, err = th.App.UpdateBotActive(th.Context, deletedBot1.UserId, false)
290	require.Nil(t, err)
291	defer th.App.PermanentDeleteBot(deletedBot1.UserId)
292
293	bot2, err := th.App.CreateBot(th.Context, &model.Bot{
294		Username:    "username2",
295		Description: "a second bot",
296		OwnerId:     OwnerId1,
297	})
298	require.Nil(t, err)
299	defer th.App.PermanentDeleteBot(bot2.UserId)
300
301	bot3, err := th.App.CreateBot(th.Context, &model.Bot{
302		Username:    "username3",
303		Description: "a third bot",
304		OwnerId:     OwnerId1,
305	})
306	require.Nil(t, err)
307	defer th.App.PermanentDeleteBot(bot3.UserId)
308
309	bot4, err := th.App.CreateBot(th.Context, &model.Bot{
310		Username:    "username5",
311		Description: "a fourth bot",
312		OwnerId:     OwnerId2,
313	})
314	require.Nil(t, err)
315	defer th.App.PermanentDeleteBot(bot4.UserId)
316
317	deletedBot2, err := th.App.CreateBot(th.Context, &model.Bot{
318		Username:    "username6",
319		Description: "a deleted bot",
320		OwnerId:     OwnerId2,
321	})
322	require.Nil(t, err)
323	deletedBot2, err = th.App.UpdateBotActive(th.Context, deletedBot2.UserId, false)
324	require.Nil(t, err)
325	defer th.App.PermanentDeleteBot(deletedBot2.UserId)
326
327	t.Run("get bots, page=0, perPage=10", func(t *testing.T) {
328		bots, err := th.App.GetBots(&model.BotGetOptions{
329			Page:           0,
330			PerPage:        10,
331			OwnerId:        "",
332			IncludeDeleted: false,
333		})
334		require.Nil(t, err)
335		assert.Equal(t, model.BotList{bot1, bot2, bot3, bot4}, bots)
336	})
337
338	t.Run("get bots, page=0, perPage=1", func(t *testing.T) {
339		bots, err := th.App.GetBots(&model.BotGetOptions{
340			Page:           0,
341			PerPage:        1,
342			OwnerId:        "",
343			IncludeDeleted: false,
344		})
345		require.Nil(t, err)
346		assert.Equal(t, model.BotList{bot1}, bots)
347	})
348
349	t.Run("get bots, page=1, perPage=2", func(t *testing.T) {
350		bots, err := th.App.GetBots(&model.BotGetOptions{
351			Page:           1,
352			PerPage:        2,
353			OwnerId:        "",
354			IncludeDeleted: false,
355		})
356		require.Nil(t, err)
357		assert.Equal(t, model.BotList{bot3, bot4}, bots)
358	})
359
360	t.Run("get bots, page=2, perPage=2", func(t *testing.T) {
361		bots, err := th.App.GetBots(&model.BotGetOptions{
362			Page:           2,
363			PerPage:        2,
364			OwnerId:        "",
365			IncludeDeleted: false,
366		})
367		require.Nil(t, err)
368		assert.Equal(t, model.BotList{}, bots)
369	})
370
371	t.Run("get bots, page=0, perPage=10, include deleted", func(t *testing.T) {
372		bots, err := th.App.GetBots(&model.BotGetOptions{
373			Page:           0,
374			PerPage:        10,
375			OwnerId:        "",
376			IncludeDeleted: true,
377		})
378		require.Nil(t, err)
379		assert.Equal(t, model.BotList{bot1, deletedBot1, bot2, bot3, bot4, deletedBot2}, bots)
380	})
381
382	t.Run("get bots, page=0, perPage=1, include deleted", func(t *testing.T) {
383		bots, err := th.App.GetBots(&model.BotGetOptions{
384			Page:           0,
385			PerPage:        1,
386			OwnerId:        "",
387			IncludeDeleted: true,
388		})
389		require.Nil(t, err)
390		assert.Equal(t, model.BotList{bot1}, bots)
391	})
392
393	t.Run("get bots, page=1, perPage=2, include deleted", func(t *testing.T) {
394		bots, err := th.App.GetBots(&model.BotGetOptions{
395			Page:           1,
396			PerPage:        2,
397			OwnerId:        "",
398			IncludeDeleted: true,
399		})
400		require.Nil(t, err)
401		assert.Equal(t, model.BotList{bot2, bot3}, bots)
402	})
403
404	t.Run("get bots, page=2, perPage=2, include deleted", func(t *testing.T) {
405		bots, err := th.App.GetBots(&model.BotGetOptions{
406			Page:           2,
407			PerPage:        2,
408			OwnerId:        "",
409			IncludeDeleted: true,
410		})
411		require.Nil(t, err)
412		assert.Equal(t, model.BotList{bot4, deletedBot2}, bots)
413	})
414
415	t.Run("get offset=0, limit=10, creator id 1", func(t *testing.T) {
416		bots, err := th.App.GetBots(&model.BotGetOptions{
417			Page:           0,
418			PerPage:        10,
419			OwnerId:        OwnerId1,
420			IncludeDeleted: false,
421		})
422		require.Nil(t, err)
423		require.Equal(t, model.BotList{bot1, bot2, bot3}, bots)
424	})
425
426	t.Run("get offset=0, limit=10, creator id 2", func(t *testing.T) {
427		bots, err := th.App.GetBots(&model.BotGetOptions{
428			Page:           0,
429			PerPage:        10,
430			OwnerId:        OwnerId2,
431			IncludeDeleted: false,
432		})
433		require.Nil(t, err)
434		require.Equal(t, model.BotList{bot4}, bots)
435	})
436
437	t.Run("get offset=0, limit=10, include deleted, creator id 1", func(t *testing.T) {
438		bots, err := th.App.GetBots(&model.BotGetOptions{
439			Page:           0,
440			PerPage:        10,
441			OwnerId:        OwnerId1,
442			IncludeDeleted: true,
443		})
444		require.Nil(t, err)
445		require.Equal(t, model.BotList{bot1, deletedBot1, bot2, bot3}, bots)
446	})
447
448	t.Run("get offset=0, limit=10, include deleted, creator id 2", func(t *testing.T) {
449		bots, err := th.App.GetBots(&model.BotGetOptions{
450			Page:           0,
451			PerPage:        10,
452			OwnerId:        OwnerId2,
453			IncludeDeleted: true,
454		})
455		require.Nil(t, err)
456		require.Equal(t, model.BotList{bot4, deletedBot2}, bots)
457	})
458}
459
460func TestUpdateBotActive(t *testing.T) {
461	t.Run("unknown bot", func(t *testing.T) {
462		th := Setup(t).InitBasic()
463		defer th.TearDown()
464
465		_, err := th.App.UpdateBotActive(th.Context, model.NewId(), false)
466		require.NotNil(t, err)
467		require.Equal(t, "app.user.missing_account.const", err.Id)
468	})
469
470	t.Run("disable/enable bot", func(t *testing.T) {
471		th := Setup(t).InitBasic()
472		defer th.TearDown()
473
474		bot, err := th.App.CreateBot(th.Context, &model.Bot{
475			Username:    "username",
476			Description: "a bot",
477			OwnerId:     th.BasicUser.Id,
478		})
479		require.Nil(t, err)
480		defer th.App.PermanentDeleteBot(bot.UserId)
481
482		disabledBot, err := th.App.UpdateBotActive(th.Context, bot.UserId, false)
483		require.Nil(t, err)
484		require.NotEqual(t, 0, disabledBot.DeleteAt)
485
486		// Disabling should be idempotent
487		disabledBotAgain, err := th.App.UpdateBotActive(th.Context, bot.UserId, false)
488		require.Nil(t, err)
489		require.Equal(t, disabledBot.DeleteAt, disabledBotAgain.DeleteAt)
490
491		reenabledBot, err := th.App.UpdateBotActive(th.Context, bot.UserId, true)
492		require.Nil(t, err)
493		require.EqualValues(t, 0, reenabledBot.DeleteAt)
494
495		// Re-enabling should be idempotent
496		reenabledBotAgain, err := th.App.UpdateBotActive(th.Context, bot.UserId, true)
497		require.Nil(t, err)
498		require.Equal(t, reenabledBot.DeleteAt, reenabledBotAgain.DeleteAt)
499	})
500}
501
502func TestPermanentDeleteBot(t *testing.T) {
503	th := Setup(t).InitBasic()
504	defer th.TearDown()
505
506	bot, err := th.App.CreateBot(th.Context, &model.Bot{
507		Username:    "username",
508		Description: "a bot",
509		OwnerId:     th.BasicUser.Id,
510	})
511	require.Nil(t, err)
512
513	require.Nil(t, th.App.PermanentDeleteBot(bot.UserId))
514
515	_, err = th.App.GetBot(bot.UserId, false)
516	require.NotNil(t, err)
517	require.Equal(t, "store.sql_bot.get.missing.app_error", err.Id)
518}
519
520func TestDisableUserBots(t *testing.T) {
521	th := Setup(t)
522	defer th.TearDown()
523
524	ownerId1 := model.NewId()
525	ownerId2 := model.NewId()
526
527	bots := []*model.Bot{}
528	defer func() {
529		for _, bot := range bots {
530			th.App.PermanentDeleteBot(bot.UserId)
531		}
532	}()
533
534	for i := 0; i < 46; i++ {
535		bot, err := th.App.CreateBot(th.Context, &model.Bot{
536			Username:    fmt.Sprintf("username%v", i),
537			Description: "a bot",
538			OwnerId:     ownerId1,
539		})
540		require.Nil(t, err)
541		bots = append(bots, bot)
542	}
543	require.Len(t, bots, 46)
544
545	u2bot1, err := th.App.CreateBot(th.Context, &model.Bot{
546		Username:    "username_nodisable",
547		Description: "a bot",
548		OwnerId:     ownerId2,
549	})
550	require.Nil(t, err)
551	defer th.App.PermanentDeleteBot(u2bot1.UserId)
552
553	err = th.App.disableUserBots(th.Context, ownerId1)
554	require.Nil(t, err)
555
556	// Check all bots and corrensponding users are disabled for creator 1
557	for _, bot := range bots {
558		retbot, err2 := th.App.GetBot(bot.UserId, true)
559		require.Nil(t, err2)
560		require.NotZero(t, retbot.DeleteAt, bot.Username)
561	}
562
563	// Check bots and corresponding user not disabled for creator 2
564	bot, err := th.App.GetBot(u2bot1.UserId, true)
565	require.Nil(t, err)
566	require.Zero(t, bot.DeleteAt)
567
568	user, err := th.App.GetUser(u2bot1.UserId)
569	require.Nil(t, err)
570	require.Zero(t, user.DeleteAt)
571
572	// Bad id doesn't do anything or break horribly
573	err = th.App.disableUserBots(th.Context, model.NewId())
574	require.Nil(t, err)
575}
576
577func TestNotifySysadminsBotOwnerDisabled(t *testing.T) {
578	th := Setup(t)
579	defer th.TearDown()
580
581	userBots := []*model.Bot{}
582	defer func() {
583		for _, bot := range userBots {
584			th.App.PermanentDeleteBot(bot.UserId)
585		}
586	}()
587
588	// // Create two sysadmins
589	sysadmin1 := model.User{
590		Email:    "sys1@example.com",
591		Nickname: "nn_sysadmin1",
592		Password: "hello1",
593		Username: "un_sysadmin1",
594		Roles:    model.SystemAdminRoleId + " " + model.SystemUserRoleId}
595	_, err := th.App.CreateUser(th.Context, &sysadmin1)
596	require.Nil(t, err, "failed to create user")
597	th.App.UpdateUserRoles(sysadmin1.Id, model.SystemUserRoleId+" "+model.SystemAdminRoleId, false)
598
599	sysadmin2 := model.User{
600		Email:    "sys2@example.com",
601		Nickname: "nn_sysadmin2",
602		Password: "hello1",
603		Username: "un_sysadmin2",
604		Roles:    model.SystemAdminRoleId + " " + model.SystemUserRoleId}
605	_, err = th.App.CreateUser(th.Context, &sysadmin2)
606	require.Nil(t, err, "failed to create user")
607	th.App.UpdateUserRoles(sysadmin2.Id, model.SystemUserRoleId+" "+model.SystemAdminRoleId, false)
608
609	// create user to be disabled
610	user1, err := th.App.CreateUser(th.Context, &model.User{
611		Email:    "user1@example.com",
612		Username: "user1_disabled",
613		Nickname: "user1",
614		Password: "Password1",
615	})
616	require.Nil(t, err, "failed to create user")
617
618	// create user that doesn't own any bots
619	user2, err := th.App.CreateUser(th.Context, &model.User{
620		Email:    "user2@example.com",
621		Username: "user2_disabled",
622		Nickname: "user2",
623		Password: "Password1",
624	})
625	require.Nil(t, err, "failed to create user")
626
627	const numBotsToPrint = 10
628
629	// create bots owned by user (equal to numBotsToPrint)
630	var bot *model.Bot
631	for i := 0; i < numBotsToPrint; i++ {
632		bot, err = th.App.CreateBot(th.Context, &model.Bot{
633			Username:    fmt.Sprintf("bot%v", i),
634			Description: "a bot",
635			OwnerId:     user1.Id,
636		})
637		require.Nil(t, err)
638		userBots = append(userBots, bot)
639	}
640	assert.Len(t, userBots, 10)
641
642	// get DM channels for sysadmin1 and sysadmin2
643	channelSys1, appErr := th.App.GetOrCreateDirectChannel(th.Context, sysadmin1.Id, sysadmin1.Id)
644	require.Nil(t, appErr)
645	channelSys2, appErr := th.App.GetOrCreateDirectChannel(th.Context, sysadmin2.Id, sysadmin2.Id)
646	require.Nil(t, appErr)
647
648	// send notification for user without bots
649	err = th.App.notifySysadminsBotOwnerDeactivated(th.Context, user2.Id)
650	require.Nil(t, err)
651
652	// get posts from sysadmin1 and sysadmin2 DM channels
653	posts1, err := th.App.GetPosts(channelSys1.Id, 0, 5)
654	require.Nil(t, err)
655	assert.Empty(t, posts1.Order)
656
657	posts2, err := th.App.GetPosts(channelSys2.Id, 0, 5)
658	require.Nil(t, err)
659	assert.Empty(t, posts2.Order)
660
661	// send notification for user with bots
662	err = th.App.notifySysadminsBotOwnerDeactivated(th.Context, user1.Id)
663	require.Nil(t, err)
664
665	// get posts from sysadmin1  and sysadmin2 DM channels
666	posts1, err = th.App.GetPosts(channelSys1.Id, 0, 5)
667	require.Nil(t, err)
668	assert.Len(t, posts1.Order, 1)
669
670	posts2, err = th.App.GetPosts(channelSys2.Id, 0, 5)
671	require.Nil(t, err)
672	assert.Len(t, posts2.Order, 1)
673
674	post := posts1.Posts[posts1.Order[0]].Message
675	assert.Equal(t, "user1_disabled was deactivated. They managed the following bot accounts which have now been disabled.\n\n* bot0\n* bot1\n* bot2\n* bot3\n* bot4\n* bot5\n* bot6\n* bot7\n* bot8\n* bot9\nYou can take ownership of each bot by enabling it at **Integrations > Bot Accounts** and creating new tokens for the bot.\n\nFor more information, see our [documentation](https://docs.mattermost.com/developer/bot-accounts.html#what-happens-when-a-user-who-owns-bot-accounts-is-disabled).", post)
676
677	// print all bots
678	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.DisableBotsWhenOwnerIsDeactivated = true })
679	message := th.App.getDisableBotSysadminMessage(user1, userBots)
680	assert.Equal(t, "user1_disabled was deactivated. They managed the following bot accounts which have now been disabled.\n\n* bot0\n* bot1\n* bot2\n* bot3\n* bot4\n* bot5\n* bot6\n* bot7\n* bot8\n* bot9\nYou can take ownership of each bot by enabling it at **Integrations > Bot Accounts** and creating new tokens for the bot.\n\nFor more information, see our [documentation](https://docs.mattermost.com/developer/bot-accounts.html#what-happens-when-a-user-who-owns-bot-accounts-is-disabled).", message)
681
682	// print all bots
683	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.DisableBotsWhenOwnerIsDeactivated = false })
684	message = th.App.getDisableBotSysadminMessage(user1, userBots)
685	assert.Equal(t, "user1_disabled was deactivated. They managed the following bot accounts which are still enabled.\n\n* bot0\n* bot1\n* bot2\n* bot3\n* bot4\n* bot5\n* bot6\n* bot7\n* bot8\n* bot9\n\nWe strongly recommend you to take ownership of each bot by re-enabling it at **Integrations > Bot Accounts** and creating new tokens for the bot.\n\nFor more information, see our [documentation](https://docs.mattermost.com/developer/bot-accounts.html#what-happens-when-a-user-who-owns-bot-accounts-is-disabled).\n\nIf you want bot accounts to disable automatically after owner deactivation, set “Disable bot accounts when owner is deactivated” in **System Console > Integrations > Bot Accounts** to true.", message)
686
687	// create additional bot to go over the printable limit
688	for i := numBotsToPrint; i < numBotsToPrint+1; i++ {
689		bot, err = th.App.CreateBot(th.Context, &model.Bot{
690			Username:    fmt.Sprintf("bot%v", i),
691			Description: "a bot",
692			OwnerId:     user1.Id,
693		})
694		require.Nil(t, err)
695		userBots = append(userBots, bot)
696	}
697	assert.Len(t, userBots, 11)
698
699	// truncate number bots printed
700	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.DisableBotsWhenOwnerIsDeactivated = true })
701	message = th.App.getDisableBotSysadminMessage(user1, userBots)
702	assert.Equal(t, "user1_disabled was deactivated. They managed 11 bot accounts which have now been disabled, including the following:\n\n* bot0\n* bot1\n* bot2\n* bot3\n* bot4\n* bot5\n* bot6\n* bot7\n* bot8\n* bot9\nYou can take ownership of each bot by enabling it at **Integrations > Bot Accounts** and creating new tokens for the bot.\n\nFor more information, see our [documentation](https://docs.mattermost.com/developer/bot-accounts.html#what-happens-when-a-user-who-owns-bot-accounts-is-disabled).", message)
703
704	// truncate number bots printed
705	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.DisableBotsWhenOwnerIsDeactivated = false })
706	message = th.App.getDisableBotSysadminMessage(user1, userBots)
707	assert.Equal(t, "user1_disabled was deactivated. They managed 11 bot accounts which are still enabled, including the following:\n\n* bot0\n* bot1\n* bot2\n* bot3\n* bot4\n* bot5\n* bot6\n* bot7\n* bot8\n* bot9\nWe strongly recommend you to take ownership of each bot by re-enabling it at **Integrations > Bot Accounts** and creating new tokens for the bot.\n\nFor more information, see our [documentation](https://docs.mattermost.com/developer/bot-accounts.html#what-happens-when-a-user-who-owns-bot-accounts-is-disabled).\n\nIf you want bot accounts to disable automatically after owner deactivation, set “Disable bot accounts when owner is deactivated” in **System Console > Integrations > Bot Accounts** to true.", message)
708}
709
710func TestConvertUserToBot(t *testing.T) {
711	t.Run("invalid user", func(t *testing.T) {
712		t.Run("invalid user id", func(t *testing.T) {
713			th := Setup(t).InitBasic()
714			defer th.TearDown()
715
716			_, err := th.App.ConvertUserToBot(&model.User{
717				Username: "username",
718				Id:       "",
719			})
720			require.NotNil(t, err)
721			require.Equal(t, "model.bot.is_valid.user_id.app_error", err.Id)
722		})
723
724		t.Run("invalid username", func(t *testing.T) {
725			th := Setup(t).InitBasic()
726			defer th.TearDown()
727
728			_, err := th.App.ConvertUserToBot(&model.User{
729				Username: "invalid username",
730				Id:       th.BasicUser.Id,
731			})
732			require.NotNil(t, err)
733			require.Equal(t, "model.bot.is_valid.username.app_error", err.Id)
734		})
735	})
736
737	t.Run("valid user", func(t *testing.T) {
738		th := Setup(t).InitBasic()
739		defer th.TearDown()
740
741		bot, err := th.App.ConvertUserToBot(&model.User{
742			Username: "username",
743			Id:       th.BasicUser.Id,
744		})
745		require.Nil(t, err)
746		defer th.App.PermanentDeleteBot(bot.UserId)
747		assert.Equal(t, "username", bot.Username)
748		assert.Equal(t, th.BasicUser.Id, bot.OwnerId)
749	})
750}
751
752func TestGetSystemBot(t *testing.T) {
753	t.Run("An error should be returned if there are no sysadmins in the instance", func(t *testing.T) {
754		th := Setup(t).InitBasic()
755		defer th.TearDown()
756
757		require.Nil(t, th.App.PermanentDeleteAllUsers(th.Context))
758
759		_, err := th.App.GetSystemBot()
760		require.NotNil(t, err)
761		require.Equal(t, "app.bot.get_system_bot.empty_admin_list.app_error", err.Id)
762	})
763
764	th := Setup(t).InitBasic()
765	defer th.TearDown()
766
767	t.Run("The bot should be created the first time it's retrieved", func(t *testing.T) {
768		// assert no bot with username exists
769		_, err := th.App.GetUserByUsername(model.BotSystemBotUsername)
770		require.NotNil(t, err)
771
772		bot, err := th.App.GetSystemBot()
773		require.Nil(t, err)
774		require.Equal(t, bot.Username, model.BotSystemBotUsername)
775	})
776
777	t.Run("The bot should be correctly retrieved if it exists already", func(t *testing.T) {
778		// assert that the bot is now present
779		botUser, err := th.App.GetUserByUsername(model.BotSystemBotUsername)
780		require.Nil(t, err)
781		require.True(t, botUser.IsBot)
782
783		bot, err := th.App.GetSystemBot()
784		require.Nil(t, err)
785		require.Equal(t, bot.Username, model.BotSystemBotUsername)
786		require.Equal(t, bot.UserId, botUser.Id)
787	})
788}
789
790func sToP(s string) *string {
791	return &s
792}
793