github.com/mattermost/mattermost-server/v5@v5.39.3/api4/user_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package api4
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"os"
    10  	"regexp"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/dgryski/dgoogauth"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/mock"
    18  	"github.com/stretchr/testify/require"
    19  
    20  	"github.com/mattermost/mattermost-server/v5/app"
    21  	"github.com/mattermost/mattermost-server/v5/einterfaces/mocks"
    22  	"github.com/mattermost/mattermost-server/v5/model"
    23  	"github.com/mattermost/mattermost-server/v5/shared/mail"
    24  	"github.com/mattermost/mattermost-server/v5/utils/testutils"
    25  
    26  	_ "github.com/mattermost/mattermost-server/v5/model/gitlab"
    27  )
    28  
    29  func TestCreateUser(t *testing.T) {
    30  	th := Setup(t)
    31  	defer th.TearDown()
    32  
    33  	user := model.User{
    34  		Email:         th.GenerateTestEmail(),
    35  		Nickname:      "Corey Hulen",
    36  		Password:      "hello1",
    37  		Username:      GenerateTestUsername(),
    38  		Roles:         model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID,
    39  		EmailVerified: true,
    40  	}
    41  
    42  	ruser, resp := th.Client.CreateUser(&user)
    43  	CheckNoError(t, resp)
    44  	CheckCreatedStatus(t, resp)
    45  	// Creating a user as a regular user with verified flag should not verify the new user.
    46  	require.False(t, ruser.EmailVerified)
    47  
    48  	_, _ = th.Client.Login(user.Email, user.Password)
    49  
    50  	require.Equal(t, user.Nickname, ruser.Nickname, "nickname didn't match")
    51  	require.Equal(t, model.SYSTEM_USER_ROLE_ID, ruser.Roles, "did not clear roles")
    52  
    53  	CheckUserSanitization(t, ruser)
    54  
    55  	_, resp = th.Client.CreateUser(ruser)
    56  	CheckBadRequestStatus(t, resp)
    57  
    58  	ruser.Id = ""
    59  	ruser.Username = GenerateTestUsername()
    60  	ruser.Password = "passwd1"
    61  	_, resp = th.Client.CreateUser(ruser)
    62  	CheckErrorMessage(t, resp, "app.user.save.email_exists.app_error")
    63  	CheckBadRequestStatus(t, resp)
    64  
    65  	ruser.Email = th.GenerateTestEmail()
    66  	ruser.Username = user.Username
    67  	_, resp = th.Client.CreateUser(ruser)
    68  	CheckErrorMessage(t, resp, "app.user.save.username_exists.app_error")
    69  	CheckBadRequestStatus(t, resp)
    70  
    71  	ruser.Email = ""
    72  	_, resp = th.Client.CreateUser(ruser)
    73  	CheckErrorMessage(t, resp, "model.user.is_valid.email.app_error")
    74  	CheckBadRequestStatus(t, resp)
    75  
    76  	ruser.Username = "testinvalid+++"
    77  	_, resp = th.Client.CreateUser(ruser)
    78  	CheckErrorMessage(t, resp, "model.user.is_valid.username.app_error")
    79  	CheckBadRequestStatus(t, resp)
    80  
    81  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = false })
    82  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserCreation = false })
    83  
    84  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
    85  		user2 := &model.User{Email: th.GenerateTestEmail(), Password: "Password1", Username: GenerateTestUsername(), EmailVerified: true}
    86  		ruser2, resp := client.CreateUser(user2)
    87  		CheckNoError(t, resp)
    88  		// Creating a user as sysadmin should verify the user with the EmailVerified flag.
    89  		require.True(t, ruser2.EmailVerified)
    90  
    91  		r, err := client.DoApiPost("/users", "garbage")
    92  		require.NotNil(t, err, "should have errored")
    93  		assert.Equal(t, http.StatusBadRequest, r.StatusCode)
    94  	})
    95  
    96  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
    97  		email := th.GenerateTestEmail()
    98  		user2 := &model.User{Email: email, Password: "Password1", Username: GenerateTestUsername(), EmailVerified: true}
    99  		_, resp := client.CreateUser(user2)
   100  		CheckNoError(t, resp)
   101  		_, appErr := th.App.GetUserByUsername(user2.Username)
   102  		require.Nil(t, appErr)
   103  
   104  		user3 := &model.User{Email: fmt.Sprintf(" %s  ", email), Password: "Password1", Username: GenerateTestUsername(), EmailVerified: true}
   105  		_, resp = client.CreateUser(user3)
   106  		CheckBadRequestStatus(t, resp)
   107  		_, appErr = th.App.GetUserByUsername(user3.Username)
   108  		require.NotNil(t, appErr)
   109  	}, "Should not be able to create two users with the same email but spaces in it")
   110  }
   111  
   112  func TestCreateUserInputFilter(t *testing.T) {
   113  	th := Setup(t)
   114  	defer th.TearDown()
   115  
   116  	t.Run("DomainRestriction", func(t *testing.T) {
   117  
   118  		enableAPIUserDeletion := th.App.Config().ServiceSettings.EnableAPIUserDeletion
   119  		th.App.UpdateConfig(func(cfg *model.Config) {
   120  			*cfg.TeamSettings.EnableOpenServer = true
   121  			*cfg.TeamSettings.EnableUserCreation = true
   122  			*cfg.TeamSettings.RestrictCreationToDomains = "mattermost.com"
   123  			*cfg.ServiceSettings.EnableAPIUserDeletion = true
   124  		})
   125  
   126  		defer th.App.UpdateConfig(func(cfg *model.Config) {
   127  			*cfg.TeamSettings.RestrictCreationToDomains = ""
   128  			*cfg.ServiceSettings.EnableAPIUserDeletion = *enableAPIUserDeletion
   129  		})
   130  
   131  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   132  			user := &model.User{Email: "foobar+testdomainrestriction@mattermost.com", Password: "Password1", Username: GenerateTestUsername()}
   133  			u, resp := client.CreateUser(user) // we need the returned created user to use its Id for deletion.
   134  			CheckNoError(t, resp)
   135  			_, resp = client.PermanentDeleteUser(u.Id)
   136  			CheckNoError(t, resp)
   137  		}, "ValidUser")
   138  
   139  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   140  			user := &model.User{Email: "foobar+testdomainrestriction@mattermost.org", Password: "Password1", Username: GenerateTestUsername()}
   141  			_, resp := client.CreateUser(user)
   142  			CheckBadRequestStatus(t, resp)
   143  		}, "InvalidEmail")
   144  
   145  		t.Run("ValidAuthServiceFilter", func(t *testing.T) {
   146  			t.Run("SystemAdminClient", func(t *testing.T) {
   147  				user := &model.User{
   148  					Email:       "foobar+testdomainrestriction@mattermost.org",
   149  					Username:    GenerateTestUsername(),
   150  					AuthService: "ldap",
   151  					AuthData:    model.NewString("999099"),
   152  				}
   153  				u, resp := th.SystemAdminClient.CreateUser(user)
   154  				CheckNoError(t, resp)
   155  				_, resp = th.SystemAdminClient.PermanentDeleteUser(u.Id)
   156  				CheckNoError(t, resp)
   157  			})
   158  			t.Run("LocalClient", func(t *testing.T) {
   159  				user := &model.User{
   160  					Email:       "foobar+testdomainrestrictionlocalclient@mattermost.org",
   161  					Username:    GenerateTestUsername(),
   162  					AuthService: "ldap",
   163  					AuthData:    model.NewString("999100"),
   164  				}
   165  				u, resp := th.LocalClient.CreateUser(user)
   166  				CheckNoError(t, resp)
   167  				_, resp = th.LocalClient.PermanentDeleteUser(u.Id)
   168  				CheckNoError(t, resp)
   169  			})
   170  		})
   171  
   172  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   173  			user := &model.User{Email: "foobar+testdomainrestriction@mattermost.org", Password: "Password1", Username: GenerateTestUsername(), AuthService: "ldap"}
   174  			_, resp := th.Client.CreateUser(user)
   175  			CheckBadRequestStatus(t, resp)
   176  		}, "InvalidAuthServiceFilter")
   177  	})
   178  
   179  	t.Run("Roles", func(t *testing.T) {
   180  		th.App.UpdateConfig(func(cfg *model.Config) {
   181  			*cfg.TeamSettings.EnableOpenServer = true
   182  			*cfg.TeamSettings.EnableUserCreation = true
   183  			*cfg.TeamSettings.RestrictCreationToDomains = ""
   184  			*cfg.ServiceSettings.EnableAPIUserDeletion = true
   185  		})
   186  
   187  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   188  			emailAddr := "foobar+testinvalidrole@mattermost.com"
   189  			user := &model.User{Email: emailAddr, Password: "Password1", Username: GenerateTestUsername(), Roles: "system_user system_admin"}
   190  			_, resp := client.CreateUser(user)
   191  			CheckNoError(t, resp)
   192  			ruser, err := th.App.GetUserByEmail(emailAddr)
   193  			require.Nil(t, err)
   194  			assert.NotEqual(t, ruser.Roles, "system_user system_admin")
   195  			_, resp = client.PermanentDeleteUser(ruser.Id)
   196  			CheckNoError(t, resp)
   197  		}, "InvalidRole")
   198  	})
   199  
   200  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   201  		th.App.UpdateConfig(func(cfg *model.Config) {
   202  			*cfg.TeamSettings.EnableOpenServer = true
   203  			*cfg.TeamSettings.EnableUserCreation = true
   204  		})
   205  		user := &model.User{Id: "AAAAAAAAAAAAAAAAAAAAAAAAAA", Email: "foobar+testinvalidid@mattermost.com", Password: "Password1", Username: GenerateTestUsername(), Roles: "system_user system_admin"}
   206  		_, resp := client.CreateUser(user)
   207  		CheckBadRequestStatus(t, resp)
   208  	}, "InvalidId")
   209  }
   210  
   211  func TestCreateUserWithToken(t *testing.T) {
   212  	th := Setup(t).InitBasic()
   213  	defer th.TearDown()
   214  
   215  	t.Run("CreateWithTokenHappyPath", func(t *testing.T) {
   216  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   217  		token := model.NewToken(
   218  			app.TokenTypeTeamInvitation,
   219  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   220  		)
   221  		require.NoError(t, th.App.Srv().Store.Token().Save(token))
   222  
   223  		ruser, resp := th.Client.CreateUserWithToken(&user, token.Token)
   224  		CheckNoError(t, resp)
   225  		CheckCreatedStatus(t, resp)
   226  
   227  		th.Client.Login(user.Email, user.Password)
   228  		require.Equal(t, user.Nickname, ruser.Nickname)
   229  		require.Equal(t, model.SYSTEM_USER_ROLE_ID, ruser.Roles, "should clear roles")
   230  		CheckUserSanitization(t, ruser)
   231  		_, err := th.App.Srv().Store.Token().GetByToken(token.Token)
   232  		require.Error(t, err, "The token must be deleted after being used")
   233  
   234  		teams, appErr := th.App.GetTeamsForUser(ruser.Id)
   235  		require.Nil(t, appErr)
   236  		require.NotEmpty(t, teams, "The user must have teams")
   237  		require.Equal(t, th.BasicTeam.Id, teams[0].Id, "The user joined team must be the team provided.")
   238  	})
   239  
   240  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   241  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   242  		token := model.NewToken(
   243  			app.TokenTypeTeamInvitation,
   244  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   245  		)
   246  		require.NoError(t, th.App.Srv().Store.Token().Save(token))
   247  
   248  		ruser, resp := client.CreateUserWithToken(&user, token.Token)
   249  		CheckNoError(t, resp)
   250  		CheckCreatedStatus(t, resp)
   251  
   252  		th.Client.Login(user.Email, user.Password)
   253  		require.Equal(t, user.Nickname, ruser.Nickname)
   254  		require.Equal(t, model.SYSTEM_USER_ROLE_ID, ruser.Roles, "should clear roles")
   255  		CheckUserSanitization(t, ruser)
   256  		_, err := th.App.Srv().Store.Token().GetByToken(token.Token)
   257  		require.Error(t, err, "The token must be deleted after being used")
   258  
   259  		teams, appErr := th.App.GetTeamsForUser(ruser.Id)
   260  		require.Nil(t, appErr)
   261  		require.NotEmpty(t, teams, "The user must have teams")
   262  		require.Equal(t, th.BasicTeam.Id, teams[0].Id, "The user joined team must be the team provided.")
   263  	}, "CreateWithTokenHappyPath")
   264  
   265  	t.Run("NoToken", func(t *testing.T) {
   266  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   267  		token := model.NewToken(
   268  			app.TokenTypeTeamInvitation,
   269  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   270  		)
   271  		require.NoError(t, th.App.Srv().Store.Token().Save(token))
   272  		defer th.App.DeleteToken(token)
   273  
   274  		_, resp := th.Client.CreateUserWithToken(&user, "")
   275  		CheckBadRequestStatus(t, resp)
   276  		CheckErrorMessage(t, resp, "api.user.create_user.missing_token.app_error")
   277  	})
   278  
   279  	t.Run("TokenExpired", func(t *testing.T) {
   280  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   281  		timeNow := time.Now()
   282  		past49Hours := timeNow.Add(-49*time.Hour).UnixNano() / int64(time.Millisecond)
   283  		token := model.NewToken(
   284  			app.TokenTypeTeamInvitation,
   285  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   286  		)
   287  		token.CreateAt = past49Hours
   288  		require.NoError(t, th.App.Srv().Store.Token().Save(token))
   289  		defer th.App.DeleteToken(token)
   290  
   291  		_, resp := th.Client.CreateUserWithToken(&user, token.Token)
   292  		CheckBadRequestStatus(t, resp)
   293  		CheckErrorMessage(t, resp, "api.user.create_user.signup_link_expired.app_error")
   294  	})
   295  
   296  	t.Run("WrongToken", func(t *testing.T) {
   297  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   298  
   299  		_, resp := th.Client.CreateUserWithToken(&user, "wrong")
   300  		CheckNotFoundStatus(t, resp)
   301  		CheckErrorMessage(t, resp, "api.user.create_user.signup_link_invalid.app_error")
   302  	})
   303  
   304  	t.Run("EnableUserCreationDisable", func(t *testing.T) {
   305  
   306  		enableUserCreation := th.App.Config().TeamSettings.EnableUserCreation
   307  		defer func() {
   308  			th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.EnableUserCreation = enableUserCreation })
   309  		}()
   310  
   311  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   312  
   313  		token := model.NewToken(
   314  			app.TokenTypeTeamInvitation,
   315  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   316  		)
   317  		require.NoError(t, th.App.Srv().Store.Token().Save(token))
   318  		defer th.App.DeleteToken(token)
   319  
   320  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserCreation = false })
   321  
   322  		_, resp := th.Client.CreateUserWithToken(&user, token.Token)
   323  		CheckNotImplementedStatus(t, resp)
   324  		CheckErrorMessage(t, resp, "api.user.create_user.signup_email_disabled.app_error")
   325  
   326  	})
   327  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   328  		enableUserCreation := th.App.Config().TeamSettings.EnableUserCreation
   329  		defer th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.EnableUserCreation = enableUserCreation })
   330  
   331  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   332  
   333  		token := model.NewToken(
   334  			app.TokenTypeTeamInvitation,
   335  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   336  		)
   337  		require.NoError(t, th.App.Srv().Store.Token().Save(token))
   338  		defer th.App.DeleteToken(token)
   339  
   340  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserCreation = false })
   341  
   342  		_, resp := client.CreateUserWithToken(&user, token.Token)
   343  		CheckNotImplementedStatus(t, resp)
   344  		CheckErrorMessage(t, resp, "api.user.create_user.signup_email_disabled.app_error")
   345  	}, "EnableUserCreationDisable")
   346  
   347  	t.Run("EnableOpenServerDisable", func(t *testing.T) {
   348  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   349  
   350  		token := model.NewToken(
   351  			app.TokenTypeTeamInvitation,
   352  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   353  		)
   354  		require.NoError(t, th.App.Srv().Store.Token().Save(token))
   355  
   356  		enableOpenServer := th.App.Config().TeamSettings.EnableOpenServer
   357  		defer func() {
   358  			th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.EnableOpenServer = enableOpenServer })
   359  		}()
   360  
   361  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = false })
   362  
   363  		ruser, resp := th.Client.CreateUserWithToken(&user, token.Token)
   364  		CheckNoError(t, resp)
   365  		CheckCreatedStatus(t, resp)
   366  
   367  		th.Client.Login(user.Email, user.Password)
   368  		require.Equal(t, user.Nickname, ruser.Nickname)
   369  		require.Equal(t, model.SYSTEM_USER_ROLE_ID, ruser.Roles, "should clear roles")
   370  		CheckUserSanitization(t, ruser)
   371  		_, err := th.App.Srv().Store.Token().GetByToken(token.Token)
   372  		require.Error(t, err, "The token must be deleted after be used")
   373  	})
   374  }
   375  
   376  func TestCreateUserWebSocketEvent(t *testing.T) {
   377  	th := Setup(t).InitBasic()
   378  	defer th.TearDown()
   379  
   380  	t.Run("guest should not received new_user event but user should", func(t *testing.T) {
   381  		th.App.Srv().SetLicense(model.NewTestLicense("guests"))
   382  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.Enable = true })
   383  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.AllowEmailAccounts = true })
   384  
   385  		id := model.NewId()
   386  		guestPassword := "Pa$$word11"
   387  		guest := &model.User{
   388  			Email:         "success+" + id + "@simulator.amazonses.com",
   389  			Username:      "un_" + id,
   390  			Nickname:      "nn_" + id,
   391  			Password:      guestPassword,
   392  			EmailVerified: true,
   393  		}
   394  
   395  		guest, err := th.App.CreateGuest(th.Context, guest)
   396  		require.Nil(t, err)
   397  
   398  		_, _, err = th.App.AddUserToTeam(th.Context, th.BasicTeam.Id, guest.Id, "")
   399  		require.Nil(t, err)
   400  
   401  		_, err = th.App.AddUserToChannel(guest, th.BasicChannel, false)
   402  		require.Nil(t, err)
   403  
   404  		guestClient := th.CreateClient()
   405  
   406  		_, resp := guestClient.Login(guest.Email, guestPassword)
   407  		require.Nil(t, resp.Error)
   408  
   409  		guestWSClient, err := th.CreateWebSocketClientWithClient(guestClient)
   410  		require.Nil(t, err)
   411  		defer guestWSClient.Close()
   412  		guestWSClient.Listen()
   413  
   414  		userWSClient, err := th.CreateWebSocketClient()
   415  		require.Nil(t, err)
   416  		defer userWSClient.Close()
   417  		userWSClient.Listen()
   418  
   419  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   420  
   421  		inviteId := th.BasicTeam.InviteId
   422  
   423  		_, resp = th.Client.CreateUserWithInviteId(&user, inviteId)
   424  		CheckNoError(t, resp)
   425  		CheckCreatedStatus(t, resp)
   426  
   427  		var userHasReceived bool
   428  		var guestHasReceived bool
   429  
   430  		func() {
   431  			for {
   432  				select {
   433  				case ev := <-userWSClient.EventChannel:
   434  					if ev.EventType() == model.WEBSOCKET_EVENT_NEW_USER {
   435  						userHasReceived = true
   436  					}
   437  				case ev := <-guestWSClient.EventChannel:
   438  					if ev.EventType() == model.WEBSOCKET_EVENT_NEW_USER {
   439  						guestHasReceived = true
   440  					}
   441  				case <-time.After(2 * time.Second):
   442  					return
   443  				}
   444  			}
   445  		}()
   446  
   447  		require.Truef(t, userHasReceived, "User should have received %s event", model.WEBSOCKET_EVENT_NEW_USER)
   448  		require.Falsef(t, guestHasReceived, "Guest should not have received %s event", model.WEBSOCKET_EVENT_NEW_USER)
   449  	})
   450  }
   451  
   452  func TestCreateUserWithInviteId(t *testing.T) {
   453  	th := Setup(t).InitBasic()
   454  	defer th.TearDown()
   455  
   456  	t.Run("CreateWithInviteIdHappyPath", func(t *testing.T) {
   457  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   458  
   459  		inviteId := th.BasicTeam.InviteId
   460  
   461  		ruser, resp := th.Client.CreateUserWithInviteId(&user, inviteId)
   462  		CheckNoError(t, resp)
   463  		CheckCreatedStatus(t, resp)
   464  
   465  		th.Client.Login(user.Email, user.Password)
   466  		require.Equal(t, user.Nickname, ruser.Nickname)
   467  		require.Equal(t, model.SYSTEM_USER_ROLE_ID, ruser.Roles, "should clear roles")
   468  		CheckUserSanitization(t, ruser)
   469  	})
   470  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   471  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   472  
   473  		inviteId := th.BasicTeam.InviteId
   474  
   475  		ruser, resp := client.CreateUserWithInviteId(&user, inviteId)
   476  		CheckNoError(t, resp)
   477  		CheckCreatedStatus(t, resp)
   478  
   479  		th.Client.Login(user.Email, user.Password)
   480  		require.Equal(t, user.Nickname, ruser.Nickname)
   481  		require.Equal(t, model.SYSTEM_USER_ROLE_ID, ruser.Roles, "should clear roles")
   482  		CheckUserSanitization(t, ruser)
   483  	}, "CreateWithInviteIdHappyPath")
   484  
   485  	t.Run("GroupConstrainedTeam", func(t *testing.T) {
   486  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   487  
   488  		th.BasicTeam.GroupConstrained = model.NewBool(true)
   489  		team, err := th.App.UpdateTeam(th.BasicTeam)
   490  		require.Nil(t, err)
   491  
   492  		defer func() {
   493  			th.BasicTeam.GroupConstrained = model.NewBool(false)
   494  			_, err = th.App.UpdateTeam(th.BasicTeam)
   495  			require.Nil(t, err)
   496  		}()
   497  
   498  		inviteID := team.InviteId
   499  
   500  		_, resp := th.Client.CreateUserWithInviteId(&user, inviteID)
   501  		require.Equal(t, "app.team.invite_id.group_constrained.error", resp.Error.Id)
   502  	})
   503  
   504  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   505  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   506  
   507  		th.BasicTeam.GroupConstrained = model.NewBool(true)
   508  		team, err := th.App.UpdateTeam(th.BasicTeam)
   509  		require.Nil(t, err)
   510  
   511  		defer func() {
   512  			th.BasicTeam.GroupConstrained = model.NewBool(false)
   513  			_, err = th.App.UpdateTeam(th.BasicTeam)
   514  			require.Nil(t, err)
   515  		}()
   516  
   517  		inviteID := team.InviteId
   518  
   519  		_, resp := client.CreateUserWithInviteId(&user, inviteID)
   520  		require.Equal(t, "app.team.invite_id.group_constrained.error", resp.Error.Id)
   521  	}, "GroupConstrainedTeam")
   522  
   523  	t.Run("WrongInviteId", func(t *testing.T) {
   524  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   525  
   526  		inviteId := model.NewId()
   527  
   528  		_, resp := th.Client.CreateUserWithInviteId(&user, inviteId)
   529  		CheckNotFoundStatus(t, resp)
   530  		CheckErrorMessage(t, resp, "app.team.get_by_invite_id.finding.app_error")
   531  	})
   532  
   533  	t.Run("NoInviteId", func(t *testing.T) {
   534  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   535  
   536  		_, resp := th.Client.CreateUserWithInviteId(&user, "")
   537  		CheckBadRequestStatus(t, resp)
   538  		CheckErrorMessage(t, resp, "api.user.create_user.missing_invite_id.app_error")
   539  	})
   540  
   541  	t.Run("ExpiredInviteId", func(t *testing.T) {
   542  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   543  
   544  		inviteId := th.BasicTeam.InviteId
   545  
   546  		_, resp := th.SystemAdminClient.RegenerateTeamInviteId(th.BasicTeam.Id)
   547  		CheckNoError(t, resp)
   548  
   549  		_, resp = th.Client.CreateUserWithInviteId(&user, inviteId)
   550  		CheckNotFoundStatus(t, resp)
   551  		CheckErrorMessage(t, resp, "app.team.get_by_invite_id.finding.app_error")
   552  	})
   553  
   554  	t.Run("EnableUserCreationDisable", func(t *testing.T) {
   555  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   556  
   557  		enableUserCreation := th.App.Config().TeamSettings.EnableUserCreation
   558  		defer func() {
   559  			th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.EnableUserCreation = enableUserCreation })
   560  		}()
   561  
   562  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserCreation = false })
   563  
   564  		inviteId := th.BasicTeam.InviteId
   565  
   566  		_, resp := th.Client.CreateUserWithInviteId(&user, inviteId)
   567  		CheckNotImplementedStatus(t, resp)
   568  		CheckErrorMessage(t, resp, "api.user.create_user.signup_email_disabled.app_error")
   569  	})
   570  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   571  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   572  
   573  		enableUserCreation := th.App.Config().TeamSettings.EnableUserCreation
   574  		defer th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.EnableUserCreation = enableUserCreation })
   575  
   576  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserCreation = false })
   577  
   578  		inviteId := th.BasicTeam.InviteId
   579  		_, resp := client.CreateUserWithInviteId(&user, inviteId)
   580  		CheckNotImplementedStatus(t, resp)
   581  		CheckErrorMessage(t, resp, "api.user.create_user.signup_email_disabled.app_error")
   582  	}, "EnableUserCreationDisable")
   583  
   584  	t.Run("EnableOpenServerDisable", func(t *testing.T) {
   585  		user := model.User{Email: th.GenerateTestEmail(), Nickname: "Corey Hulen", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
   586  
   587  		enableOpenServer := th.App.Config().TeamSettings.EnableOpenServer
   588  		defer func() {
   589  			th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.EnableOpenServer = enableOpenServer })
   590  		}()
   591  
   592  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableOpenServer = false })
   593  
   594  		team, res := th.SystemAdminClient.RegenerateTeamInviteId(th.BasicTeam.Id)
   595  		assert.Nil(t, res.Error)
   596  		inviteId := team.InviteId
   597  
   598  		ruser, resp := th.Client.CreateUserWithInviteId(&user, inviteId)
   599  		CheckNoError(t, resp)
   600  		CheckCreatedStatus(t, resp)
   601  
   602  		th.Client.Login(user.Email, user.Password)
   603  		require.Equal(t, user.Nickname, ruser.Nickname)
   604  		require.Equal(t, model.SYSTEM_USER_ROLE_ID, ruser.Roles, "should clear roles")
   605  		CheckUserSanitization(t, ruser)
   606  	})
   607  }
   608  
   609  func TestGetMe(t *testing.T) {
   610  	th := Setup(t).InitBasic()
   611  	defer th.TearDown()
   612  
   613  	ruser, resp := th.Client.GetMe("")
   614  	CheckNoError(t, resp)
   615  
   616  	require.Equal(t, th.BasicUser.Id, ruser.Id)
   617  
   618  	th.Client.Logout()
   619  	_, resp = th.Client.GetMe("")
   620  	CheckUnauthorizedStatus(t, resp)
   621  }
   622  
   623  func TestGetUser(t *testing.T) {
   624  	th := Setup(t)
   625  	defer th.TearDown()
   626  
   627  	user := th.CreateUser()
   628  	user.Props = map[string]string{"testpropkey": "testpropvalue"}
   629  
   630  	th.App.UpdateUser(user, false)
   631  
   632  	th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
   633  		ruser, resp := client.GetUser(user.Id, "")
   634  		CheckNoError(t, resp)
   635  		CheckUserSanitization(t, ruser)
   636  
   637  		require.Equal(t, user.Email, ruser.Email)
   638  
   639  		assert.NotNil(t, ruser.Props)
   640  		assert.Equal(t, ruser.Props["testpropkey"], "testpropvalue")
   641  		require.False(t, ruser.IsBot)
   642  
   643  		ruser, resp = client.GetUser(user.Id, resp.Etag)
   644  		CheckEtag(t, ruser, resp)
   645  
   646  		_, resp = client.GetUser("junk", "")
   647  		CheckBadRequestStatus(t, resp)
   648  
   649  		_, resp = client.GetUser(model.NewId(), "")
   650  		CheckNotFoundStatus(t, resp)
   651  	})
   652  
   653  	// Check against privacy config settings
   654  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowEmailAddress = false })
   655  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowFullName = false })
   656  
   657  	ruser, resp := th.Client.GetUser(user.Id, "")
   658  	CheckNoError(t, resp)
   659  
   660  	require.Empty(t, ruser.Email, "email should be blank")
   661  	require.Empty(t, ruser.FirstName, "first name should be blank")
   662  	require.Empty(t, ruser.LastName, "last name should be blank")
   663  
   664  	th.Client.Logout()
   665  	_, resp = th.Client.GetUser(user.Id, "")
   666  	CheckUnauthorizedStatus(t, resp)
   667  
   668  	// System admins should ignore privacy settings
   669  	ruser, _ = th.SystemAdminClient.GetUser(user.Id, resp.Etag)
   670  	require.NotEmpty(t, ruser.Email, "email should not be blank")
   671  	require.NotEmpty(t, ruser.FirstName, "first name should not be blank")
   672  	require.NotEmpty(t, ruser.LastName, "last name should not be blank")
   673  }
   674  
   675  func TestGetUserWithAcceptedTermsOfServiceForOtherUser(t *testing.T) {
   676  	th := Setup(t)
   677  	defer th.TearDown()
   678  
   679  	user := th.CreateUser()
   680  
   681  	tos, _ := th.App.CreateTermsOfService("Dummy TOS", user.Id)
   682  
   683  	th.App.UpdateUser(user, false)
   684  
   685  	ruser, resp := th.Client.GetUser(user.Id, "")
   686  	CheckNoError(t, resp)
   687  	CheckUserSanitization(t, ruser)
   688  
   689  	require.Equal(t, user.Email, ruser.Email)
   690  
   691  	assert.Empty(t, ruser.TermsOfServiceId)
   692  
   693  	th.App.SaveUserTermsOfService(user.Id, tos.Id, true)
   694  
   695  	ruser, resp = th.Client.GetUser(user.Id, "")
   696  	CheckNoError(t, resp)
   697  	CheckUserSanitization(t, ruser)
   698  
   699  	require.Equal(t, user.Email, ruser.Email)
   700  
   701  	// user TOS data cannot be fetched for other users by non-admin users
   702  	assert.Empty(t, ruser.TermsOfServiceId)
   703  }
   704  
   705  func TestGetUserWithAcceptedTermsOfService(t *testing.T) {
   706  	th := Setup(t).InitBasic()
   707  	defer th.TearDown()
   708  
   709  	user := th.BasicUser
   710  
   711  	tos, _ := th.App.CreateTermsOfService("Dummy TOS", user.Id)
   712  
   713  	ruser, resp := th.Client.GetUser(user.Id, "")
   714  	CheckNoError(t, resp)
   715  	CheckUserSanitization(t, ruser)
   716  
   717  	require.Equal(t, user.Email, ruser.Email)
   718  
   719  	assert.Empty(t, ruser.TermsOfServiceId)
   720  
   721  	th.App.SaveUserTermsOfService(user.Id, tos.Id, true)
   722  
   723  	ruser, resp = th.Client.GetUser(user.Id, "")
   724  	CheckNoError(t, resp)
   725  	CheckUserSanitization(t, ruser)
   726  
   727  	require.Equal(t, user.Email, ruser.Email)
   728  
   729  	// a user can view their own TOS details
   730  	assert.Equal(t, tos.Id, ruser.TermsOfServiceId)
   731  }
   732  
   733  func TestGetUserWithAcceptedTermsOfServiceWithAdminUser(t *testing.T) {
   734  	th := Setup(t).InitBasic()
   735  	th.LoginSystemAdmin()
   736  	defer th.TearDown()
   737  
   738  	user := th.BasicUser
   739  
   740  	tos, _ := th.App.CreateTermsOfService("Dummy TOS", user.Id)
   741  
   742  	ruser, resp := th.SystemAdminClient.GetUser(user.Id, "")
   743  	CheckNoError(t, resp)
   744  	CheckUserSanitization(t, ruser)
   745  
   746  	require.Equal(t, user.Email, ruser.Email)
   747  
   748  	assert.Empty(t, ruser.TermsOfServiceId)
   749  
   750  	th.App.SaveUserTermsOfService(user.Id, tos.Id, true)
   751  
   752  	ruser, resp = th.SystemAdminClient.GetUser(user.Id, "")
   753  	CheckNoError(t, resp)
   754  	CheckUserSanitization(t, ruser)
   755  
   756  	require.Equal(t, user.Email, ruser.Email)
   757  
   758  	// admin can view anyone's TOS details
   759  	assert.Equal(t, tos.Id, ruser.TermsOfServiceId)
   760  }
   761  
   762  func TestGetBotUser(t *testing.T) {
   763  	th := Setup(t).InitBasic()
   764  	defer th.TearDown()
   765  
   766  	defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
   767  
   768  	th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
   769  	th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.TEAM_USER_ROLE_ID, false)
   770  
   771  	th.App.UpdateConfig(func(cfg *model.Config) {
   772  		*cfg.ServiceSettings.EnableBotAccountCreation = true
   773  	})
   774  
   775  	bot := &model.Bot{
   776  		Username:    GenerateTestUsername(),
   777  		DisplayName: "a bot",
   778  		Description: "bot",
   779  	}
   780  
   781  	createdBot, resp := th.Client.CreateBot(bot)
   782  	CheckCreatedStatus(t, resp)
   783  	defer th.App.PermanentDeleteBot(createdBot.UserId)
   784  
   785  	botUser, resp := th.Client.GetUser(createdBot.UserId, "")
   786  	CheckNoError(t, resp)
   787  	require.Equal(t, bot.Username, botUser.Username)
   788  	require.True(t, botUser.IsBot)
   789  }
   790  
   791  func TestGetUserByUsername(t *testing.T) {
   792  	th := Setup(t).InitBasic()
   793  	defer th.TearDown()
   794  
   795  	user := th.BasicUser
   796  
   797  	th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
   798  		ruser, resp := client.GetUserByUsername(user.Username, "")
   799  		CheckNoError(t, resp)
   800  		CheckUserSanitization(t, ruser)
   801  
   802  		require.Equal(t, user.Email, ruser.Email)
   803  
   804  		ruser, resp = client.GetUserByUsername(user.Username, resp.Etag)
   805  		CheckEtag(t, ruser, resp)
   806  
   807  		_, resp = client.GetUserByUsername(GenerateTestUsername(), "")
   808  		CheckNotFoundStatus(t, resp)
   809  	})
   810  
   811  	// Check against privacy config settings
   812  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowEmailAddress = false })
   813  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowFullName = false })
   814  
   815  	ruser, resp := th.Client.GetUserByUsername(th.BasicUser2.Username, "")
   816  	CheckNoError(t, resp)
   817  
   818  	require.Empty(t, ruser.Email, "email should be blank")
   819  	require.Empty(t, ruser.FirstName, "first name should be blank")
   820  	require.Empty(t, ruser.LastName, "last name should be blank")
   821  
   822  	ruser, resp = th.Client.GetUserByUsername(th.BasicUser.Username, "")
   823  	CheckNoError(t, resp)
   824  	require.NotEmpty(t, ruser.NotifyProps, "notify props should be sent")
   825  
   826  	th.Client.Logout()
   827  	_, resp = th.Client.GetUserByUsername(user.Username, "")
   828  	CheckUnauthorizedStatus(t, resp)
   829  
   830  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   831  		// System admins should ignore privacy settings
   832  		ruser, _ = client.GetUserByUsername(user.Username, resp.Etag)
   833  		require.NotEmpty(t, ruser.Email, "email should not be blank")
   834  		require.NotEmpty(t, ruser.FirstName, "first name should not be blank")
   835  		require.NotEmpty(t, ruser.LastName, "last name should not be blank")
   836  	})
   837  }
   838  
   839  func TestGetUserByUsernameWithAcceptedTermsOfService(t *testing.T) {
   840  	th := Setup(t).InitBasic()
   841  	defer th.TearDown()
   842  
   843  	user := th.BasicUser
   844  
   845  	ruser, resp := th.Client.GetUserByUsername(user.Username, "")
   846  	CheckNoError(t, resp)
   847  	CheckUserSanitization(t, ruser)
   848  
   849  	require.Equal(t, user.Email, ruser.Email)
   850  
   851  	tos, _ := th.App.CreateTermsOfService("Dummy TOS", user.Id)
   852  	th.App.SaveUserTermsOfService(ruser.Id, tos.Id, true)
   853  
   854  	ruser, resp = th.Client.GetUserByUsername(user.Username, "")
   855  	CheckNoError(t, resp)
   856  	CheckUserSanitization(t, ruser)
   857  
   858  	require.Equal(t, user.Email, ruser.Email)
   859  
   860  	require.Equal(t, tos.Id, ruser.TermsOfServiceId, "Terms of service ID should match")
   861  }
   862  
   863  func TestSaveUserTermsOfService(t *testing.T) {
   864  	th := Setup(t)
   865  	defer th.TearDown()
   866  
   867  	t.Run("Invalid data", func(t *testing.T) {
   868  		resp, err := th.Client.DoApiPost("/users/"+th.BasicUser.Id+"/terms_of_service", "{}")
   869  		require.NotNil(t, err)
   870  		assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
   871  	})
   872  }
   873  
   874  func TestGetUserByEmail(t *testing.T) {
   875  	th := Setup(t)
   876  	defer th.TearDown()
   877  
   878  	user := th.CreateUser()
   879  	userWithSlash, resp := th.SystemAdminClient.CreateUser(&model.User{
   880  		Email:    "email/with/slashes@example.com",
   881  		Username: GenerateTestUsername(),
   882  		Password: "Pa$$word11",
   883  	})
   884  	require.Nil(t, resp.Error)
   885  
   886  	th.App.UpdateConfig(func(cfg *model.Config) {
   887  		*cfg.PrivacySettings.ShowEmailAddress = true
   888  		*cfg.PrivacySettings.ShowFullName = true
   889  	})
   890  
   891  	th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
   892  		t.Run("should be able to get another user by email", func(t *testing.T) {
   893  			ruser, resp := client.GetUserByEmail(user.Email, "")
   894  			CheckNoError(t, resp)
   895  			CheckUserSanitization(t, ruser)
   896  
   897  			require.Equal(t, user.Email, ruser.Email)
   898  		})
   899  
   900  		t.Run("Get user with a / character in the email", func(t *testing.T) {
   901  			ruser, resp := client.GetUserByEmail(userWithSlash.Email, "")
   902  			require.Nil(t, resp.Error)
   903  			require.Equal(t, ruser.Id, userWithSlash.Id)
   904  		})
   905  
   906  		t.Run("should return not modified when provided with a matching etag", func(t *testing.T) {
   907  			_, resp := client.GetUserByEmail(user.Email, "")
   908  			CheckNoError(t, resp)
   909  
   910  			ruser, resp := client.GetUserByEmail(user.Email, resp.Etag)
   911  			CheckEtag(t, ruser, resp)
   912  		})
   913  
   914  		t.Run("should return bad request when given an invalid email", func(t *testing.T) {
   915  			_, resp := client.GetUserByEmail(GenerateTestUsername(), "")
   916  			CheckBadRequestStatus(t, resp)
   917  		})
   918  
   919  		t.Run("should return 404 when given a non-existent email", func(t *testing.T) {
   920  			_, resp := client.GetUserByEmail(th.GenerateTestEmail(), "")
   921  			CheckNotFoundStatus(t, resp)
   922  		})
   923  	})
   924  
   925  	t.Run("should sanitize full name for non-admin based on privacy settings", func(t *testing.T) {
   926  		th.App.UpdateConfig(func(cfg *model.Config) {
   927  			*cfg.PrivacySettings.ShowEmailAddress = true
   928  			*cfg.PrivacySettings.ShowFullName = false
   929  		})
   930  
   931  		ruser, resp := th.Client.GetUserByEmail(user.Email, "")
   932  		CheckNoError(t, resp)
   933  		assert.Equal(t, "", ruser.FirstName, "first name should be blank")
   934  		assert.Equal(t, "", ruser.LastName, "last name should be blank")
   935  
   936  		th.App.UpdateConfig(func(cfg *model.Config) {
   937  			*cfg.PrivacySettings.ShowFullName = true
   938  		})
   939  
   940  		ruser, resp = th.Client.GetUserByEmail(user.Email, "")
   941  		CheckNoError(t, resp)
   942  		assert.NotEqual(t, "", ruser.FirstName, "first name should be set")
   943  		assert.NotEqual(t, "", ruser.LastName, "last name should be set")
   944  	})
   945  
   946  	t.Run("should return forbidden for non-admin when privacy settings hide email", func(t *testing.T) {
   947  		th.App.UpdateConfig(func(cfg *model.Config) {
   948  			*cfg.PrivacySettings.ShowEmailAddress = false
   949  		})
   950  
   951  		_, resp := th.Client.GetUserByEmail(user.Email, "")
   952  		CheckForbiddenStatus(t, resp)
   953  
   954  		th.App.UpdateConfig(func(cfg *model.Config) {
   955  			*cfg.PrivacySettings.ShowEmailAddress = true
   956  		})
   957  
   958  		ruser, resp := th.Client.GetUserByEmail(user.Email, "")
   959  		CheckNoError(t, resp)
   960  		assert.Equal(t, user.Email, ruser.Email, "email should be set")
   961  	})
   962  
   963  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
   964  		t.Run("should not sanitize full name for admin, regardless of privacy settings", func(t *testing.T) {
   965  			th.App.UpdateConfig(func(cfg *model.Config) {
   966  				*cfg.PrivacySettings.ShowEmailAddress = true
   967  				*cfg.PrivacySettings.ShowFullName = false
   968  			})
   969  
   970  			ruser, resp := client.GetUserByEmail(user.Email, "")
   971  			CheckNoError(t, resp)
   972  			assert.NotEqual(t, "", ruser.FirstName, "first name should be set")
   973  			assert.NotEqual(t, "", ruser.LastName, "last name should be set")
   974  
   975  			th.App.UpdateConfig(func(cfg *model.Config) {
   976  				*cfg.PrivacySettings.ShowFullName = true
   977  			})
   978  
   979  			ruser, resp = client.GetUserByEmail(user.Email, "")
   980  			CheckNoError(t, resp)
   981  			assert.NotEqual(t, "", ruser.FirstName, "first name should be set")
   982  			assert.NotEqual(t, "", ruser.LastName, "last name should be set")
   983  		})
   984  
   985  		t.Run("should always return email for admin, regardless of privacy settings", func(t *testing.T) {
   986  			th.App.UpdateConfig(func(cfg *model.Config) {
   987  				*cfg.PrivacySettings.ShowEmailAddress = false
   988  			})
   989  
   990  			ruser, resp := client.GetUserByEmail(user.Email, "")
   991  			CheckNoError(t, resp)
   992  			assert.Equal(t, user.Email, ruser.Email, "email should be set")
   993  
   994  			th.App.UpdateConfig(func(cfg *model.Config) {
   995  				*cfg.PrivacySettings.ShowEmailAddress = true
   996  			})
   997  
   998  			ruser, resp = client.GetUserByEmail(user.Email, "")
   999  			CheckNoError(t, resp)
  1000  			assert.Equal(t, user.Email, ruser.Email, "email should be set")
  1001  		})
  1002  	})
  1003  }
  1004  
  1005  func TestSearchUsers(t *testing.T) {
  1006  	th := Setup(t).InitBasic()
  1007  	defer th.TearDown()
  1008  
  1009  	search := &model.UserSearch{Term: th.BasicUser.Username}
  1010  
  1011  	users, resp := th.Client.SearchUsers(search)
  1012  	CheckNoError(t, resp)
  1013  
  1014  	require.True(t, findUserInList(th.BasicUser.Id, users), "should have found user")
  1015  
  1016  	_, err := th.App.UpdateActive(th.Context, th.BasicUser2, false)
  1017  	require.Nil(t, err)
  1018  
  1019  	search.Term = th.BasicUser2.Username
  1020  	search.AllowInactive = false
  1021  
  1022  	users, resp = th.Client.SearchUsers(search)
  1023  	CheckNoError(t, resp)
  1024  
  1025  	require.False(t, findUserInList(th.BasicUser2.Id, users), "should not have found user")
  1026  
  1027  	search.AllowInactive = true
  1028  
  1029  	users, resp = th.Client.SearchUsers(search)
  1030  	CheckNoError(t, resp)
  1031  
  1032  	require.True(t, findUserInList(th.BasicUser2.Id, users), "should have found user")
  1033  
  1034  	search.Term = th.BasicUser.Username
  1035  	search.AllowInactive = false
  1036  	search.TeamId = th.BasicTeam.Id
  1037  
  1038  	users, resp = th.Client.SearchUsers(search)
  1039  	CheckNoError(t, resp)
  1040  
  1041  	require.True(t, findUserInList(th.BasicUser.Id, users), "should have found user")
  1042  
  1043  	search.NotInChannelId = th.BasicChannel.Id
  1044  
  1045  	users, resp = th.Client.SearchUsers(search)
  1046  	CheckNoError(t, resp)
  1047  
  1048  	require.False(t, findUserInList(th.BasicUser.Id, users), "should not have found user")
  1049  
  1050  	search.TeamId = ""
  1051  	search.NotInChannelId = ""
  1052  	search.InChannelId = th.BasicChannel.Id
  1053  
  1054  	users, resp = th.Client.SearchUsers(search)
  1055  	CheckNoError(t, resp)
  1056  
  1057  	require.True(t, findUserInList(th.BasicUser.Id, users), "should have found user")
  1058  
  1059  	search.InChannelId = ""
  1060  	search.NotInChannelId = th.BasicChannel.Id
  1061  	_, resp = th.Client.SearchUsers(search)
  1062  	CheckBadRequestStatus(t, resp)
  1063  
  1064  	search.NotInChannelId = model.NewId()
  1065  	search.TeamId = model.NewId()
  1066  	_, resp = th.Client.SearchUsers(search)
  1067  	CheckForbiddenStatus(t, resp)
  1068  
  1069  	search.NotInChannelId = ""
  1070  	search.TeamId = model.NewId()
  1071  	_, resp = th.Client.SearchUsers(search)
  1072  	CheckForbiddenStatus(t, resp)
  1073  
  1074  	search.InChannelId = model.NewId()
  1075  	search.TeamId = ""
  1076  	_, resp = th.Client.SearchUsers(search)
  1077  	CheckForbiddenStatus(t, resp)
  1078  
  1079  	// Test search for users not in any team
  1080  	search.TeamId = ""
  1081  	search.NotInChannelId = ""
  1082  	search.InChannelId = ""
  1083  	search.NotInTeamId = th.BasicTeam.Id
  1084  
  1085  	users, resp = th.Client.SearchUsers(search)
  1086  	CheckNoError(t, resp)
  1087  
  1088  	require.False(t, findUserInList(th.BasicUser.Id, users), "should not have found user")
  1089  
  1090  	oddUser := th.CreateUser()
  1091  	search.Term = oddUser.Username
  1092  
  1093  	users, resp = th.Client.SearchUsers(search)
  1094  	CheckNoError(t, resp)
  1095  
  1096  	require.True(t, findUserInList(oddUser.Id, users), "should have found user")
  1097  
  1098  	_, resp = th.SystemAdminClient.AddTeamMember(th.BasicTeam.Id, oddUser.Id)
  1099  	CheckNoError(t, resp)
  1100  
  1101  	users, resp = th.Client.SearchUsers(search)
  1102  	CheckNoError(t, resp)
  1103  
  1104  	require.False(t, findUserInList(oddUser.Id, users), "should not have found user")
  1105  
  1106  	search.NotInTeamId = model.NewId()
  1107  	_, resp = th.Client.SearchUsers(search)
  1108  	CheckForbiddenStatus(t, resp)
  1109  
  1110  	search.Term = th.BasicUser.Username
  1111  
  1112  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowEmailAddress = false })
  1113  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowFullName = false })
  1114  
  1115  	_, err = th.App.UpdateActive(th.Context, th.BasicUser2, true)
  1116  	require.Nil(t, err)
  1117  
  1118  	search.InChannelId = ""
  1119  	search.NotInTeamId = ""
  1120  	search.Term = th.BasicUser2.Email
  1121  	users, resp = th.Client.SearchUsers(search)
  1122  	CheckNoError(t, resp)
  1123  
  1124  	require.False(t, findUserInList(th.BasicUser2.Id, users), "should not have found user")
  1125  
  1126  	search.Term = th.BasicUser2.FirstName
  1127  	users, resp = th.Client.SearchUsers(search)
  1128  	CheckNoError(t, resp)
  1129  
  1130  	require.False(t, findUserInList(th.BasicUser2.Id, users), "should not have found user")
  1131  
  1132  	search.Term = th.BasicUser2.LastName
  1133  	users, resp = th.Client.SearchUsers(search)
  1134  	CheckNoError(t, resp)
  1135  
  1136  	require.False(t, findUserInList(th.BasicUser2.Id, users), "should not have found user")
  1137  
  1138  	search.Term = th.BasicUser.FirstName
  1139  	search.InChannelId = th.BasicChannel.Id
  1140  	search.NotInChannelId = th.BasicChannel.Id
  1141  	search.TeamId = th.BasicTeam.Id
  1142  	users, resp = th.SystemAdminClient.SearchUsers(search)
  1143  	CheckNoError(t, resp)
  1144  
  1145  	require.True(t, findUserInList(th.BasicUser.Id, users), "should have found user")
  1146  
  1147  	id := model.NewId()
  1148  	group, err := th.App.CreateGroup(&model.Group{
  1149  		DisplayName: "dn-foo_" + id,
  1150  		Name:        model.NewString("name" + id),
  1151  		Source:      model.GroupSourceLdap,
  1152  		Description: "description_" + id,
  1153  		RemoteId:    model.NewId(),
  1154  	})
  1155  	assert.Nil(t, err)
  1156  
  1157  	search = &model.UserSearch{Term: th.BasicUser.Username, InGroupId: group.Id}
  1158  	t.Run("Requires ldap license when searching in group", func(t *testing.T) {
  1159  		_, resp = th.SystemAdminClient.SearchUsers(search)
  1160  		CheckNotImplementedStatus(t, resp)
  1161  	})
  1162  
  1163  	th.App.Srv().SetLicense(model.NewTestLicense("ldap"))
  1164  
  1165  	t.Run("Requires manage system permission when searching for users in a group", func(t *testing.T) {
  1166  		_, resp = th.Client.SearchUsers(search)
  1167  		CheckForbiddenStatus(t, resp)
  1168  	})
  1169  
  1170  	t.Run("Returns empty list when no users found searching for users in a group", func(t *testing.T) {
  1171  		users, resp = th.SystemAdminClient.SearchUsers(search)
  1172  		CheckNoError(t, resp)
  1173  		require.Empty(t, users)
  1174  	})
  1175  
  1176  	_, err = th.App.UpsertGroupMember(group.Id, th.BasicUser.Id)
  1177  	assert.Nil(t, err)
  1178  
  1179  	t.Run("Returns user in group user found in group", func(t *testing.T) {
  1180  		users, resp = th.SystemAdminClient.SearchUsers(search)
  1181  		CheckNoError(t, resp)
  1182  		require.Equal(t, users[0].Id, th.BasicUser.Id)
  1183  	})
  1184  }
  1185  
  1186  func findUserInList(id string, users []*model.User) bool {
  1187  	for _, user := range users {
  1188  		if user.Id == id {
  1189  			return true
  1190  		}
  1191  	}
  1192  	return false
  1193  }
  1194  
  1195  func TestAutocompleteUsersInChannel(t *testing.T) {
  1196  	th := Setup(t).InitBasic()
  1197  	defer th.TearDown()
  1198  	teamId := th.BasicTeam.Id
  1199  	channelId := th.BasicChannel.Id
  1200  	username := th.BasicUser.Username
  1201  	newUser := th.CreateUser()
  1202  
  1203  	tt := []struct {
  1204  		Name            string
  1205  		TeamId          string
  1206  		ChannelId       string
  1207  		Username        string
  1208  		ExpectedResults int
  1209  		MoreThan        bool
  1210  		ShouldFail      bool
  1211  	}{
  1212  		{
  1213  			"Autocomplete in channel for specific username",
  1214  			teamId,
  1215  			channelId,
  1216  			username,
  1217  			1,
  1218  			false,
  1219  			false,
  1220  		},
  1221  		{
  1222  			"Search for not valid username",
  1223  			teamId,
  1224  			channelId,
  1225  			"amazonses",
  1226  			0,
  1227  			false,
  1228  			false,
  1229  		},
  1230  		{
  1231  			"Search for all users",
  1232  			teamId,
  1233  			channelId,
  1234  			"",
  1235  			2,
  1236  			true,
  1237  			false,
  1238  		},
  1239  		{
  1240  			"Fail when the teamId is not provided",
  1241  			"",
  1242  			channelId,
  1243  			"",
  1244  			2,
  1245  			true,
  1246  			true,
  1247  		},
  1248  	}
  1249  
  1250  	for _, tc := range tt {
  1251  		t.Run(tc.Name, func(t *testing.T) {
  1252  			th.LoginBasic()
  1253  			rusers, resp := th.Client.AutocompleteUsersInChannel(tc.TeamId, tc.ChannelId, tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1254  			if tc.ShouldFail {
  1255  				CheckErrorMessage(t, resp, "api.user.autocomplete_users.missing_team_id.app_error")
  1256  			} else {
  1257  				CheckNoError(t, resp)
  1258  				if tc.MoreThan {
  1259  					assert.True(t, len(rusers.Users) >= tc.ExpectedResults)
  1260  				} else {
  1261  					assert.Len(t, rusers.Users, tc.ExpectedResults)
  1262  				}
  1263  			}
  1264  
  1265  			th.Client.Logout()
  1266  			_, resp = th.Client.AutocompleteUsersInChannel(tc.TeamId, tc.ChannelId, tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1267  			CheckUnauthorizedStatus(t, resp)
  1268  
  1269  			th.Client.Login(newUser.Email, newUser.Password)
  1270  			_, resp = th.Client.AutocompleteUsersInChannel(tc.TeamId, tc.ChannelId, tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1271  			CheckForbiddenStatus(t, resp)
  1272  		})
  1273  	}
  1274  
  1275  	t.Run("Check against privacy config settings", func(t *testing.T) {
  1276  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowFullName = false })
  1277  
  1278  		th.LoginBasic()
  1279  		rusers, resp := th.Client.AutocompleteUsersInChannel(teamId, channelId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1280  		CheckNoError(t, resp)
  1281  
  1282  		assert.Equal(t, rusers.Users[0].FirstName, "", "should not show first/last name")
  1283  		assert.Equal(t, rusers.Users[0].LastName, "", "should not show first/last name")
  1284  	})
  1285  
  1286  	t.Run("Check OutOfChannel results with/without VIEW_MEMBERS permissions", func(t *testing.T) {
  1287  		permissionsUser := th.CreateUser()
  1288  		th.SystemAdminClient.DemoteUserToGuest(permissionsUser.Id)
  1289  		permissionsUser.Roles = "system_guest"
  1290  		th.LinkUserToTeam(permissionsUser, th.BasicTeam)
  1291  		th.AddUserToChannel(permissionsUser, th.BasicChannel)
  1292  
  1293  		otherUser := th.CreateUser()
  1294  		th.LinkUserToTeam(otherUser, th.BasicTeam)
  1295  
  1296  		th.Client.Login(permissionsUser.Email, permissionsUser.Password)
  1297  
  1298  		rusers, resp := th.Client.AutocompleteUsersInChannel(teamId, channelId, "", model.USER_SEARCH_DEFAULT_LIMIT, "")
  1299  		CheckNoError(t, resp)
  1300  		assert.Len(t, rusers.OutOfChannel, 1)
  1301  
  1302  		defaultRolePermissions := th.SaveDefaultRolePermissions()
  1303  		defer func() {
  1304  			th.RestoreDefaultRolePermissions(defaultRolePermissions)
  1305  		}()
  1306  
  1307  		th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.SYSTEM_USER_ROLE_ID)
  1308  		th.RemovePermissionFromRole(model.PERMISSION_VIEW_MEMBERS.Id, model.TEAM_USER_ROLE_ID)
  1309  
  1310  		rusers, resp = th.Client.AutocompleteUsersInChannel(teamId, channelId, "", model.USER_SEARCH_DEFAULT_LIMIT, "")
  1311  		CheckNoError(t, resp)
  1312  		assert.Empty(t, rusers.OutOfChannel)
  1313  
  1314  		th.App.GetOrCreateDirectChannel(th.Context, permissionsUser.Id, otherUser.Id)
  1315  
  1316  		rusers, resp = th.Client.AutocompleteUsersInChannel(teamId, channelId, "", model.USER_SEARCH_DEFAULT_LIMIT, "")
  1317  		CheckNoError(t, resp)
  1318  		assert.Len(t, rusers.OutOfChannel, 1)
  1319  	})
  1320  
  1321  	t.Run("user must have access to team id, especially when it does not match channel's team id", func(t *testing.T) {
  1322  		_, resp := th.Client.AutocompleteUsersInChannel("otherTeamId", channelId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1323  		CheckErrorMessage(t, resp, "api.context.permissions.app_error")
  1324  	})
  1325  }
  1326  
  1327  func TestAutocompleteUsersInTeam(t *testing.T) {
  1328  	th := Setup(t).InitBasic()
  1329  	defer th.TearDown()
  1330  	teamId := th.BasicTeam.Id
  1331  	username := th.BasicUser.Username
  1332  	newUser := th.CreateUser()
  1333  
  1334  	tt := []struct {
  1335  		Name            string
  1336  		TeamId          string
  1337  		Username        string
  1338  		ExpectedResults int
  1339  		MoreThan        bool
  1340  	}{
  1341  		{
  1342  			"specific username",
  1343  			teamId,
  1344  			username,
  1345  			1,
  1346  			false,
  1347  		},
  1348  		{
  1349  			"not valid username",
  1350  			teamId,
  1351  			"amazonses",
  1352  			0,
  1353  			false,
  1354  		},
  1355  		{
  1356  			"all users in team",
  1357  			teamId,
  1358  			"",
  1359  			2,
  1360  			true,
  1361  		},
  1362  	}
  1363  
  1364  	for _, tc := range tt {
  1365  		t.Run(tc.Name, func(t *testing.T) {
  1366  			th.LoginBasic()
  1367  			rusers, resp := th.Client.AutocompleteUsersInTeam(tc.TeamId, tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1368  			CheckNoError(t, resp)
  1369  			if tc.MoreThan {
  1370  				assert.True(t, len(rusers.Users) >= tc.ExpectedResults)
  1371  			} else {
  1372  				assert.Len(t, rusers.Users, tc.ExpectedResults)
  1373  			}
  1374  			th.Client.Logout()
  1375  			_, resp = th.Client.AutocompleteUsersInTeam(tc.TeamId, tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1376  			CheckUnauthorizedStatus(t, resp)
  1377  
  1378  			th.Client.Login(newUser.Email, newUser.Password)
  1379  			_, resp = th.Client.AutocompleteUsersInTeam(tc.TeamId, tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1380  			CheckForbiddenStatus(t, resp)
  1381  		})
  1382  	}
  1383  
  1384  	t.Run("Check against privacy config settings", func(t *testing.T) {
  1385  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowFullName = false })
  1386  
  1387  		th.LoginBasic()
  1388  		rusers, resp := th.Client.AutocompleteUsersInTeam(teamId, username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1389  		CheckNoError(t, resp)
  1390  
  1391  		assert.Equal(t, rusers.Users[0].FirstName, "", "should not show first/last name")
  1392  		assert.Equal(t, rusers.Users[0].LastName, "", "should not show first/last name")
  1393  	})
  1394  }
  1395  
  1396  func TestAutocompleteUsers(t *testing.T) {
  1397  	th := Setup(t).InitBasic()
  1398  	defer th.TearDown()
  1399  	username := th.BasicUser.Username
  1400  	newUser := th.CreateUser()
  1401  
  1402  	tt := []struct {
  1403  		Name            string
  1404  		Username        string
  1405  		ExpectedResults int
  1406  		MoreThan        bool
  1407  	}{
  1408  		{
  1409  			"specific username",
  1410  			username,
  1411  			1,
  1412  			false,
  1413  		},
  1414  		{
  1415  			"not valid username",
  1416  			"amazonses",
  1417  			0,
  1418  			false,
  1419  		},
  1420  		{
  1421  			"all users in team",
  1422  			"",
  1423  			2,
  1424  			true,
  1425  		},
  1426  	}
  1427  
  1428  	for _, tc := range tt {
  1429  		t.Run(tc.Name, func(t *testing.T) {
  1430  			th.LoginBasic()
  1431  			rusers, resp := th.Client.AutocompleteUsers(tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1432  			CheckNoError(t, resp)
  1433  			if tc.MoreThan {
  1434  				assert.True(t, len(rusers.Users) >= tc.ExpectedResults)
  1435  			} else {
  1436  				assert.Len(t, rusers.Users, tc.ExpectedResults)
  1437  			}
  1438  
  1439  			th.Client.Logout()
  1440  			_, resp = th.Client.AutocompleteUsers(tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1441  			CheckUnauthorizedStatus(t, resp)
  1442  
  1443  			th.Client.Login(newUser.Email, newUser.Password)
  1444  			_, resp = th.Client.AutocompleteUsers(tc.Username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1445  			CheckNoError(t, resp)
  1446  		})
  1447  	}
  1448  
  1449  	t.Run("Check against privacy config settings", func(t *testing.T) {
  1450  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowFullName = false })
  1451  
  1452  		th.LoginBasic()
  1453  		rusers, resp := th.Client.AutocompleteUsers(username, model.USER_SEARCH_DEFAULT_LIMIT, "")
  1454  		CheckNoError(t, resp)
  1455  
  1456  		assert.Equal(t, rusers.Users[0].FirstName, "", "should not show first/last name")
  1457  		assert.Equal(t, rusers.Users[0].LastName, "", "should not show first/last name")
  1458  	})
  1459  }
  1460  
  1461  func TestGetProfileImage(t *testing.T) {
  1462  	th := Setup(t).InitBasic()
  1463  	defer th.TearDown()
  1464  
  1465  	// recreate basic user
  1466  	th.BasicUser = th.CreateUser()
  1467  	th.LoginBasic()
  1468  	user := th.BasicUser
  1469  
  1470  	data, resp := th.Client.GetProfileImage(user.Id, "")
  1471  	CheckNoError(t, resp)
  1472  	require.NotEmpty(t, data, "should not be empty")
  1473  
  1474  	_, resp = th.Client.GetProfileImage(user.Id, resp.Etag)
  1475  	require.NotEqual(t, http.StatusNotModified, resp.StatusCode, "should not hit etag")
  1476  
  1477  	_, resp = th.Client.GetProfileImage("junk", "")
  1478  	CheckBadRequestStatus(t, resp)
  1479  
  1480  	_, resp = th.Client.GetProfileImage(model.NewId(), "")
  1481  	CheckNotFoundStatus(t, resp)
  1482  
  1483  	th.Client.Logout()
  1484  	_, resp = th.Client.GetProfileImage(user.Id, "")
  1485  	CheckUnauthorizedStatus(t, resp)
  1486  
  1487  	_, resp = th.SystemAdminClient.GetProfileImage(user.Id, "")
  1488  	CheckNoError(t, resp)
  1489  
  1490  	info := &model.FileInfo{Path: "/users/" + user.Id + "/profile.png"}
  1491  	err := th.cleanupTestFile(info)
  1492  	require.NoError(t, err)
  1493  }
  1494  
  1495  func TestGetUsersByIds(t *testing.T) {
  1496  	th := Setup(t).InitBasic()
  1497  	defer th.TearDown()
  1498  
  1499  	th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  1500  		t.Run("should return the user", func(t *testing.T) {
  1501  			users, resp := client.GetUsersByIds([]string{th.BasicUser.Id})
  1502  
  1503  			CheckNoError(t, resp)
  1504  
  1505  			assert.Equal(t, th.BasicUser.Id, users[0].Id)
  1506  			CheckUserSanitization(t, users[0])
  1507  		})
  1508  
  1509  		t.Run("should return error when no IDs are specified", func(t *testing.T) {
  1510  			_, resp := client.GetUsersByIds([]string{})
  1511  
  1512  			CheckBadRequestStatus(t, resp)
  1513  		})
  1514  
  1515  		t.Run("should not return an error for invalid IDs", func(t *testing.T) {
  1516  			users, resp := client.GetUsersByIds([]string{"junk"})
  1517  
  1518  			CheckNoError(t, resp)
  1519  			require.Empty(t, users, "no users should be returned")
  1520  		})
  1521  
  1522  		t.Run("should still return users for valid IDs when invalid IDs are specified", func(t *testing.T) {
  1523  			users, resp := client.GetUsersByIds([]string{"junk", th.BasicUser.Id})
  1524  
  1525  			CheckNoError(t, resp)
  1526  
  1527  			require.Len(t, users, 1, "1 user should be returned")
  1528  		})
  1529  	})
  1530  
  1531  	t.Run("should return error when not logged in", func(t *testing.T) {
  1532  		th.Client.Logout()
  1533  
  1534  		_, resp := th.Client.GetUsersByIds([]string{th.BasicUser.Id})
  1535  		CheckUnauthorizedStatus(t, resp)
  1536  	})
  1537  }
  1538  
  1539  func TestGetUsersByIdsWithOptions(t *testing.T) {
  1540  	t.Run("should only return specified users that have been updated since the given time", func(t *testing.T) {
  1541  		th := Setup(t)
  1542  		defer th.TearDown()
  1543  
  1544  		// Users before the timestamp shouldn't be returned
  1545  		user1, err := th.App.CreateUser(th.Context, &model.User{Email: th.GenerateTestEmail(), Username: model.NewId(), Password: model.NewId()})
  1546  		require.Nil(t, err)
  1547  
  1548  		user2, err := th.App.CreateUser(th.Context, &model.User{Email: th.GenerateTestEmail(), Username: model.NewId(), Password: model.NewId()})
  1549  		require.Nil(t, err)
  1550  
  1551  		// Users not in the list of IDs shouldn't be returned
  1552  		_, err = th.App.CreateUser(th.Context, &model.User{Email: th.GenerateTestEmail(), Username: model.NewId(), Password: model.NewId()})
  1553  		require.Nil(t, err)
  1554  
  1555  		users, resp := th.Client.GetUsersByIdsWithOptions([]string{user1.Id, user2.Id}, &model.UserGetByIdsOptions{
  1556  			Since: user2.UpdateAt - 1,
  1557  		})
  1558  
  1559  		assert.Nil(t, resp.Error)
  1560  		assert.Len(t, users, 1)
  1561  		assert.Equal(t, users[0].Id, user2.Id)
  1562  	})
  1563  }
  1564  
  1565  func TestGetUsersByGroupChannelIds(t *testing.T) {
  1566  	th := Setup(t).InitBasic()
  1567  	defer th.TearDown()
  1568  
  1569  	gc1, err := th.App.CreateGroupChannel([]string{th.BasicUser.Id, th.SystemAdminUser.Id, th.TeamAdminUser.Id}, th.BasicUser.Id)
  1570  	require.Nil(t, err)
  1571  
  1572  	usersByChannelId, resp := th.Client.GetUsersByGroupChannelIds([]string{gc1.Id})
  1573  	CheckNoError(t, resp)
  1574  
  1575  	users, ok := usersByChannelId[gc1.Id]
  1576  	assert.True(t, ok)
  1577  	userIds := []string{}
  1578  	for _, user := range users {
  1579  		userIds = append(userIds, user.Id)
  1580  	}
  1581  
  1582  	require.ElementsMatch(t, []string{th.SystemAdminUser.Id, th.TeamAdminUser.Id}, userIds)
  1583  
  1584  	th.LoginBasic2()
  1585  	usersByChannelId, resp = th.Client.GetUsersByGroupChannelIds([]string{gc1.Id})
  1586  	CheckNoError(t, resp)
  1587  
  1588  	_, ok = usersByChannelId[gc1.Id]
  1589  	require.False(t, ok)
  1590  
  1591  	th.Client.Logout()
  1592  	_, resp = th.Client.GetUsersByGroupChannelIds([]string{gc1.Id})
  1593  	CheckUnauthorizedStatus(t, resp)
  1594  }
  1595  
  1596  func TestGetUsersByUsernames(t *testing.T) {
  1597  	th := Setup(t).InitBasic()
  1598  	defer th.TearDown()
  1599  
  1600  	users, resp := th.Client.GetUsersByUsernames([]string{th.BasicUser.Username})
  1601  	CheckNoError(t, resp)
  1602  
  1603  	require.Equal(t, th.BasicUser.Id, users[0].Id)
  1604  	CheckUserSanitization(t, users[0])
  1605  
  1606  	_, resp = th.Client.GetUsersByIds([]string{})
  1607  	CheckBadRequestStatus(t, resp)
  1608  
  1609  	users, resp = th.Client.GetUsersByUsernames([]string{"junk"})
  1610  	CheckNoError(t, resp)
  1611  	require.Empty(t, users, "no users should be returned")
  1612  
  1613  	users, resp = th.Client.GetUsersByUsernames([]string{"junk", th.BasicUser.Username})
  1614  	CheckNoError(t, resp)
  1615  	require.Len(t, users, 1, "1 user should be returned")
  1616  
  1617  	th.Client.Logout()
  1618  	_, resp = th.Client.GetUsersByUsernames([]string{th.BasicUser.Username})
  1619  	CheckUnauthorizedStatus(t, resp)
  1620  }
  1621  
  1622  func TestGetTotalUsersStat(t *testing.T) {
  1623  	th := Setup(t)
  1624  	defer th.TearDown()
  1625  
  1626  	total, _ := th.Server.Store.User().Count(model.UserCountOptions{
  1627  		IncludeDeleted:     false,
  1628  		IncludeBotAccounts: true,
  1629  	})
  1630  
  1631  	rstats, resp := th.Client.GetTotalUsersStats("")
  1632  	CheckNoError(t, resp)
  1633  
  1634  	require.Equal(t, total, rstats.TotalUsersCount)
  1635  }
  1636  
  1637  func TestUpdateUser(t *testing.T) {
  1638  	th := Setup(t)
  1639  	defer th.TearDown()
  1640  
  1641  	user := th.CreateUser()
  1642  	th.Client.Login(user.Email, user.Password)
  1643  
  1644  	user.Nickname = "Joram Wilander"
  1645  	user.Roles = model.SYSTEM_USER_ROLE_ID
  1646  	user.LastPasswordUpdate = 123
  1647  
  1648  	ruser, resp := th.Client.UpdateUser(user)
  1649  	CheckNoError(t, resp)
  1650  	CheckUserSanitization(t, ruser)
  1651  
  1652  	require.Equal(t, "Joram Wilander", ruser.Nickname, "Nickname should update properly")
  1653  	require.Equal(t, model.SYSTEM_USER_ROLE_ID, ruser.Roles, "Roles should not update")
  1654  	require.NotEqual(t, 123, ruser.LastPasswordUpdate, "LastPasswordUpdate should not update")
  1655  
  1656  	ruser.Email = th.GenerateTestEmail()
  1657  	_, resp = th.Client.UpdateUser(ruser)
  1658  	CheckBadRequestStatus(t, resp)
  1659  
  1660  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  1661  		ruser.Email = th.GenerateTestEmail()
  1662  		_, resp = client.UpdateUser(user)
  1663  		CheckNoError(t, resp)
  1664  	})
  1665  
  1666  	ruser.Password = user.Password
  1667  	ruser, resp = th.Client.UpdateUser(ruser)
  1668  	CheckNoError(t, resp)
  1669  	CheckUserSanitization(t, ruser)
  1670  
  1671  	ruser.Id = "junk"
  1672  	_, resp = th.Client.UpdateUser(ruser)
  1673  	CheckBadRequestStatus(t, resp)
  1674  
  1675  	ruser.Id = model.NewId()
  1676  	_, resp = th.Client.UpdateUser(ruser)
  1677  	CheckForbiddenStatus(t, resp)
  1678  
  1679  	r, err := th.Client.DoApiPut("/users/"+ruser.Id, "garbage")
  1680  	require.NotNil(t, err)
  1681  	require.Equal(t, http.StatusBadRequest, r.StatusCode)
  1682  
  1683  	session, _ := th.App.GetSession(th.Client.AuthToken)
  1684  	session.IsOAuth = true
  1685  	th.App.AddSessionToCache(session)
  1686  
  1687  	ruser.Id = user.Id
  1688  	ruser.Email = th.GenerateTestEmail()
  1689  	_, resp = th.Client.UpdateUser(ruser)
  1690  	CheckForbiddenStatus(t, resp)
  1691  
  1692  	th.Client.Logout()
  1693  	_, resp = th.Client.UpdateUser(user)
  1694  	CheckUnauthorizedStatus(t, resp)
  1695  
  1696  	th.LoginBasic()
  1697  	_, resp = th.Client.UpdateUser(user)
  1698  	CheckForbiddenStatus(t, resp)
  1699  
  1700  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  1701  		_, resp = client.UpdateUser(user)
  1702  		CheckNoError(t, resp)
  1703  	})
  1704  }
  1705  
  1706  func TestPatchUser(t *testing.T) {
  1707  	th := Setup(t).InitBasic()
  1708  	defer th.TearDown()
  1709  
  1710  	user := th.CreateUser()
  1711  	th.Client.Login(user.Email, user.Password)
  1712  
  1713  	t.Run("Timezone limit error", func(t *testing.T) {
  1714  		patch := &model.UserPatch{}
  1715  		patch.Timezone = model.StringMap{}
  1716  		patch.Timezone["manualTimezone"] = string(make([]byte, model.USER_TIMEZONE_MAX_RUNES))
  1717  		ruser, resp := th.Client.PatchUser(user.Id, patch)
  1718  		CheckBadRequestStatus(t, resp)
  1719  		require.Equal(t, "model.user.is_valid.timezone_limit.app_error", resp.Error.Id)
  1720  		require.Nil(t, ruser)
  1721  	})
  1722  
  1723  	patch := &model.UserPatch{}
  1724  	patch.Password = model.NewString("testpassword")
  1725  	patch.Nickname = model.NewString("Joram Wilander")
  1726  	patch.FirstName = model.NewString("Joram")
  1727  	patch.LastName = model.NewString("Wilander")
  1728  	patch.Position = new(string)
  1729  	patch.NotifyProps = model.StringMap{}
  1730  	patch.NotifyProps["comment"] = "somethingrandom"
  1731  	patch.Timezone = model.StringMap{}
  1732  	patch.Timezone["useAutomaticTimezone"] = "true"
  1733  	patch.Timezone["automaticTimezone"] = "America/New_York"
  1734  	patch.Timezone["manualTimezone"] = ""
  1735  
  1736  	ruser, resp := th.Client.PatchUser(user.Id, patch)
  1737  	CheckNoError(t, resp)
  1738  	CheckUserSanitization(t, ruser)
  1739  
  1740  	require.Equal(t, "Joram Wilander", ruser.Nickname, "Nickname should update properly")
  1741  	require.Equal(t, "Joram", ruser.FirstName, "FirstName should update properly")
  1742  	require.Equal(t, "Wilander", ruser.LastName, "LastName should update properly")
  1743  	require.Empty(t, ruser.Position, "Position should update properly")
  1744  	require.Equal(t, user.Username, ruser.Username, "Username should not update")
  1745  	require.Empty(t, ruser.Password, "Password should not be returned")
  1746  	require.Equal(t, "somethingrandom", ruser.NotifyProps["comment"], "NotifyProps should update properly")
  1747  	require.Equal(t, "true", ruser.Timezone["useAutomaticTimezone"], "useAutomaticTimezone should update properly")
  1748  	require.Equal(t, "America/New_York", ruser.Timezone["automaticTimezone"], "automaticTimezone should update properly")
  1749  	require.Empty(t, ruser.Timezone["manualTimezone"], "manualTimezone should update properly")
  1750  
  1751  	err := th.App.CheckPasswordAndAllCriteria(ruser, *patch.Password, "")
  1752  	require.NotNil(t, err, "Password should not match")
  1753  
  1754  	currentPassword := user.Password
  1755  	user, err = th.App.GetUser(ruser.Id)
  1756  	require.Nil(t, err)
  1757  
  1758  	err = th.App.CheckPasswordAndAllCriteria(user, currentPassword, "")
  1759  	require.Nil(t, err, "Password should still match")
  1760  
  1761  	patch = &model.UserPatch{}
  1762  	patch.Email = model.NewString(th.GenerateTestEmail())
  1763  
  1764  	_, resp = th.Client.PatchUser(user.Id, patch)
  1765  	CheckBadRequestStatus(t, resp)
  1766  
  1767  	patch.Password = model.NewString(currentPassword)
  1768  	ruser, resp = th.Client.PatchUser(user.Id, patch)
  1769  	CheckNoError(t, resp)
  1770  
  1771  	require.Equal(t, *patch.Email, ruser.Email, "Email should update properly")
  1772  
  1773  	patch.Username = model.NewString(th.BasicUser2.Username)
  1774  	_, resp = th.Client.PatchUser(user.Id, patch)
  1775  	CheckBadRequestStatus(t, resp)
  1776  
  1777  	patch.Username = nil
  1778  
  1779  	_, resp = th.Client.PatchUser("junk", patch)
  1780  	CheckBadRequestStatus(t, resp)
  1781  
  1782  	ruser.Id = model.NewId()
  1783  	_, resp = th.Client.PatchUser(model.NewId(), patch)
  1784  	CheckForbiddenStatus(t, resp)
  1785  
  1786  	r, err := th.Client.DoApiPut("/users/"+user.Id+"/patch", "garbage")
  1787  	require.NotNil(t, err)
  1788  	require.Equal(t, http.StatusBadRequest, r.StatusCode)
  1789  
  1790  	session, _ := th.App.GetSession(th.Client.AuthToken)
  1791  	session.IsOAuth = true
  1792  	th.App.AddSessionToCache(session)
  1793  
  1794  	patch.Email = model.NewString(th.GenerateTestEmail())
  1795  	_, resp = th.Client.PatchUser(user.Id, patch)
  1796  	CheckForbiddenStatus(t, resp)
  1797  
  1798  	th.Client.Logout()
  1799  	_, resp = th.Client.PatchUser(user.Id, patch)
  1800  	CheckUnauthorizedStatus(t, resp)
  1801  
  1802  	th.LoginBasic()
  1803  	_, resp = th.Client.PatchUser(user.Id, patch)
  1804  	CheckForbiddenStatus(t, resp)
  1805  
  1806  	_, resp = th.SystemAdminClient.PatchUser(user.Id, patch)
  1807  	CheckNoError(t, resp)
  1808  }
  1809  
  1810  func TestUserUnicodeNames(t *testing.T) {
  1811  	th := Setup(t)
  1812  	defer th.TearDown()
  1813  	Client := th.Client
  1814  
  1815  	t.Run("create user unicode", func(t *testing.T) {
  1816  		user := model.User{
  1817  			Email:     th.GenerateTestEmail(),
  1818  			FirstName: "Andrew\u202e",
  1819  			LastName:  "\ufeffWiggin",
  1820  			Nickname:  "Ender\u2028 Wiggin",
  1821  			Password:  "hello1",
  1822  			Username:  "\ufeffwiggin77",
  1823  			Roles:     model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
  1824  
  1825  		ruser, resp := Client.CreateUser(&user)
  1826  		CheckNoError(t, resp)
  1827  		CheckCreatedStatus(t, resp)
  1828  
  1829  		_, _ = Client.Login(user.Email, user.Password)
  1830  
  1831  		require.Equal(t, "wiggin77", ruser.Username, "Bad Unicode not filtered from username")
  1832  		require.Equal(t, "Andrew Wiggin", ruser.GetDisplayName(model.SHOW_FULLNAME), "Bad Unicode not filtered from displayname")
  1833  		require.Equal(t, "Ender Wiggin", ruser.Nickname, "Bad Unicode not filtered from nickname")
  1834  	})
  1835  
  1836  	t.Run("update user unicode", func(t *testing.T) {
  1837  		user := th.CreateUser()
  1838  		Client.Login(user.Email, user.Password)
  1839  
  1840  		user.Username = "wiggin\ufff9"
  1841  		user.Nickname = "Ender\u0340 \ufffcWiggin"
  1842  		user.FirstName = "Andrew\ufff9"
  1843  		user.LastName = "Wig\u206fgin"
  1844  
  1845  		ruser, resp := Client.UpdateUser(user)
  1846  		CheckNoError(t, resp)
  1847  
  1848  		require.Equal(t, "wiggin", ruser.Username, "bad unicode should be filtered from username")
  1849  		require.Equal(t, "Ender Wiggin", ruser.Nickname, "bad unicode should be filtered from nickname")
  1850  		require.Equal(t, "Andrew Wiggin", ruser.GetDisplayName(model.SHOW_FULLNAME), "bad unicode should be filtered from display name")
  1851  	})
  1852  
  1853  	t.Run("patch user unicode", func(t *testing.T) {
  1854  		user := th.CreateUser()
  1855  		Client.Login(user.Email, user.Password)
  1856  
  1857  		patch := &model.UserPatch{}
  1858  		patch.Nickname = model.NewString("\U000E0000Ender\u206d Wiggin\U000E007F")
  1859  		patch.FirstName = model.NewString("\U0001d173Andrew\U0001d17a")
  1860  		patch.LastName = model.NewString("\u2028Wiggin\u2029")
  1861  
  1862  		ruser, resp := Client.PatchUser(user.Id, patch)
  1863  		CheckNoError(t, resp)
  1864  		CheckUserSanitization(t, ruser)
  1865  
  1866  		require.Equal(t, "Ender Wiggin", ruser.Nickname, "Bad unicode should be filtered from nickname")
  1867  		require.Equal(t, "Andrew", ruser.FirstName, "Bad unicode should be filtered from first name")
  1868  		require.Equal(t, "Wiggin", ruser.LastName, "Bad unicode should be filtered from last name")
  1869  		require.Equal(t, "Andrew Wiggin", ruser.GetDisplayName(model.SHOW_FULLNAME), "Bad unicode should be filtered from display name")
  1870  	})
  1871  }
  1872  
  1873  func TestUpdateUserAuth(t *testing.T) {
  1874  	th := Setup(t)
  1875  	defer th.TearDown()
  1876  
  1877  	team := th.CreateTeamWithClient(th.SystemAdminClient)
  1878  
  1879  	user := th.CreateUser()
  1880  
  1881  	th.LinkUserToTeam(user, team)
  1882  	_, err := th.App.Srv().Store.User().VerifyEmail(user.Id, user.Email)
  1883  	require.NoError(t, err)
  1884  
  1885  	userAuth := &model.UserAuth{}
  1886  	userAuth.AuthData = user.AuthData
  1887  	userAuth.AuthService = user.AuthService
  1888  	userAuth.Password = user.Password
  1889  
  1890  	// Regular user can not use endpoint
  1891  	_, respErr := th.SystemAdminClient.UpdateUserAuth(user.Id, userAuth)
  1892  	require.NotNil(t, respErr, "Shouldn't have permissions. Only Admins")
  1893  
  1894  	userAuth.AuthData = model.NewString("test@test.com")
  1895  	userAuth.AuthService = model.USER_AUTH_SERVICE_SAML
  1896  	userAuth.Password = "newpassword"
  1897  	ruser, resp := th.SystemAdminClient.UpdateUserAuth(user.Id, userAuth)
  1898  	CheckNoError(t, resp)
  1899  
  1900  	// AuthData and AuthService are set, password is set to empty
  1901  	require.Equal(t, *userAuth.AuthData, *ruser.AuthData)
  1902  	require.Equal(t, model.USER_AUTH_SERVICE_SAML, ruser.AuthService)
  1903  	require.Empty(t, ruser.Password)
  1904  
  1905  	// When AuthData or AuthService are empty, password must be valid
  1906  	userAuth.AuthData = user.AuthData
  1907  	userAuth.AuthService = ""
  1908  	userAuth.Password = "1"
  1909  	_, respErr = th.SystemAdminClient.UpdateUserAuth(user.Id, userAuth)
  1910  	require.NotNil(t, respErr)
  1911  
  1912  	// Regular user can not use endpoint
  1913  	user2 := th.CreateUser()
  1914  	th.LinkUserToTeam(user2, team)
  1915  	_, err = th.App.Srv().Store.User().VerifyEmail(user2.Id, user2.Email)
  1916  	require.NoError(t, err)
  1917  
  1918  	th.SystemAdminClient.Login(user2.Email, "passwd1")
  1919  
  1920  	userAuth.AuthData = user.AuthData
  1921  	userAuth.AuthService = user.AuthService
  1922  	userAuth.Password = user.Password
  1923  	_, respErr = th.SystemAdminClient.UpdateUserAuth(user.Id, userAuth)
  1924  	require.NotNil(t, respErr, "Should have errored")
  1925  }
  1926  
  1927  func TestDeleteUser(t *testing.T) {
  1928  	th := Setup(t).InitBasic()
  1929  	defer th.TearDown()
  1930  
  1931  	th.LoginBasic()
  1932  	_, resp := th.Client.DeleteUser(th.SystemAdminUser.Id)
  1933  	CheckForbiddenStatus(t, resp)
  1934  
  1935  	th.Client.Logout()
  1936  	_, resp = th.Client.DeleteUser(th.BasicUser.Id)
  1937  	CheckUnauthorizedStatus(t, resp)
  1938  
  1939  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
  1940  		_, resp = c.DeleteUser(model.NewId())
  1941  		CheckNotFoundStatus(t, resp)
  1942  
  1943  		_, resp = c.DeleteUser("junk")
  1944  		CheckBadRequestStatus(t, resp)
  1945  
  1946  		userToDelete := th.CreateUser()
  1947  		_, resp = c.DeleteUser(userToDelete.Id)
  1948  		CheckNoError(t, resp)
  1949  	})
  1950  
  1951  	selfDeleteUser := th.CreateUser()
  1952  	th.LoginBasic()
  1953  	_, resp = th.Client.DeleteUser(selfDeleteUser.Id)
  1954  	CheckForbiddenStatus(t, resp)
  1955  
  1956  	th.Client.Login(selfDeleteUser.Email, selfDeleteUser.Password)
  1957  	th.App.UpdateConfig(func(c *model.Config) {
  1958  		*c.TeamSettings.EnableUserDeactivation = false
  1959  	})
  1960  	_, resp = th.Client.DeleteUser(selfDeleteUser.Id)
  1961  	CheckUnauthorizedStatus(t, resp)
  1962  
  1963  	th.App.UpdateConfig(func(c *model.Config) {
  1964  		*c.TeamSettings.EnableUserDeactivation = true
  1965  	})
  1966  	_, resp = th.Client.DeleteUser(selfDeleteUser.Id)
  1967  	CheckNoError(t, resp)
  1968  }
  1969  
  1970  func TestPermanentDeleteUser(t *testing.T) {
  1971  	th := Setup(t).InitBasic()
  1972  	defer th.TearDown()
  1973  
  1974  	enableAPIUserDeletion := *th.App.Config().ServiceSettings.EnableAPIUserDeletion
  1975  	defer func() {
  1976  		th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableAPIUserDeletion = &enableAPIUserDeletion })
  1977  	}()
  1978  
  1979  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = false })
  1980  
  1981  	userToDelete := th.CreateUser()
  1982  
  1983  	t.Run("Permanent deletion not available through API if EnableAPIUserDeletion is not set", func(t *testing.T) {
  1984  		_, resp := th.SystemAdminClient.PermanentDeleteUser(userToDelete.Id)
  1985  		CheckUnauthorizedStatus(t, resp)
  1986  	})
  1987  
  1988  	t.Run("Permanent deletion available through local mode even if EnableAPIUserDeletion is not set", func(t *testing.T) {
  1989  		ok, resp := th.LocalClient.PermanentDeleteUser(userToDelete.Id)
  1990  		CheckNoError(t, resp)
  1991  		assert.True(t, ok)
  1992  	})
  1993  
  1994  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableAPIUserDeletion = true })
  1995  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
  1996  		userToDelete = th.CreateUser()
  1997  		ok, resp := c.PermanentDeleteUser(userToDelete.Id)
  1998  		CheckNoError(t, resp)
  1999  		assert.True(t, ok)
  2000  
  2001  		_, err := th.App.GetTeam(userToDelete.Id)
  2002  		assert.NotNil(t, err)
  2003  
  2004  		ok, resp = c.PermanentDeleteUser("junk")
  2005  		CheckBadRequestStatus(t, resp)
  2006  		require.False(t, ok, "should have returned false")
  2007  	}, "Permanent deletion with EnableAPIUserDeletion set")
  2008  }
  2009  
  2010  func TestPermanentDeleteAllUsers(t *testing.T) {
  2011  	th := Setup(t).InitBasic()
  2012  	defer th.TearDown()
  2013  
  2014  	t.Run("The endpoint should not be available for neither normal nor sysadmin users", func(t *testing.T) {
  2015  		_, resp := th.Client.PermanentDeleteAllUsers()
  2016  		CheckNotFoundStatus(t, resp)
  2017  
  2018  		_, resp = th.SystemAdminClient.PermanentDeleteAllUsers()
  2019  		CheckNotFoundStatus(t, resp)
  2020  	})
  2021  
  2022  	t.Run("The endpoint should permanently delete all users", func(t *testing.T) {
  2023  		// Basic user creates a team and a channel
  2024  		team, err := th.App.CreateTeamWithUser(th.Context, &model.Team{
  2025  			DisplayName: "User Created Team",
  2026  			Name:        "user-created-team",
  2027  			Email:       "usercreatedteam@test.com",
  2028  			Type:        model.TEAM_OPEN,
  2029  		}, th.BasicUser.Id)
  2030  		require.Nil(t, err)
  2031  
  2032  		channel, err := th.App.CreateChannelWithUser(th.Context, &model.Channel{
  2033  			DisplayName: "User Created Channel",
  2034  			Name:        "user-created-channel",
  2035  			Type:        model.CHANNEL_OPEN,
  2036  			TeamId:      team.Id,
  2037  		}, th.BasicUser.Id)
  2038  		require.Nil(t, err)
  2039  
  2040  		// Check that we have users and posts in the database
  2041  		users, nErr := th.App.Srv().Store.User().GetAll()
  2042  		require.NoError(t, nErr)
  2043  		require.Greater(t, len(users), 0)
  2044  
  2045  		postCount, nErr := th.App.Srv().Store.Post().AnalyticsPostCount("", false, false)
  2046  		require.NoError(t, nErr)
  2047  		require.Greater(t, postCount, int64(0))
  2048  
  2049  		// Delete all users and their posts
  2050  		_, resp := th.LocalClient.PermanentDeleteAllUsers()
  2051  		require.Nil(t, resp.Error)
  2052  
  2053  		// Check that both user and post tables are empty
  2054  		users, nErr = th.App.Srv().Store.User().GetAll()
  2055  		require.NoError(t, nErr)
  2056  		require.Len(t, users, 0)
  2057  
  2058  		postCount, nErr = th.App.Srv().Store.Post().AnalyticsPostCount("", false, false)
  2059  		require.NoError(t, nErr)
  2060  		require.Equal(t, postCount, int64(0))
  2061  
  2062  		// Check that the channel and team created by the user were not deleted
  2063  		rTeam, err := th.App.GetTeam(team.Id)
  2064  		require.Nil(t, err)
  2065  		require.NotNil(t, rTeam)
  2066  
  2067  		rChannel, err := th.App.GetChannel(channel.Id)
  2068  		require.Nil(t, err)
  2069  		require.NotNil(t, rChannel)
  2070  	})
  2071  }
  2072  
  2073  func TestUpdateUserRoles(t *testing.T) {
  2074  	th := Setup(t).InitBasic()
  2075  	defer th.TearDown()
  2076  
  2077  	_, resp := th.Client.UpdateUserRoles(th.SystemAdminUser.Id, model.SYSTEM_USER_ROLE_ID)
  2078  	CheckForbiddenStatus(t, resp)
  2079  
  2080  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  2081  		_, resp = client.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID)
  2082  		CheckNoError(t, resp)
  2083  
  2084  		_, resp = client.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_ADMIN_ROLE_ID)
  2085  		CheckNoError(t, resp)
  2086  
  2087  		_, resp = client.UpdateUserRoles(th.BasicUser.Id, "junk")
  2088  		CheckBadRequestStatus(t, resp)
  2089  
  2090  		_, resp = client.UpdateUserRoles("junk", model.SYSTEM_USER_ROLE_ID)
  2091  		CheckBadRequestStatus(t, resp)
  2092  
  2093  		_, resp = client.UpdateUserRoles(model.NewId(), model.SYSTEM_USER_ROLE_ID)
  2094  		CheckBadRequestStatus(t, resp)
  2095  	})
  2096  }
  2097  
  2098  func assertExpectedWebsocketEvent(t *testing.T, client *model.WebSocketClient, event string, test func(*model.WebSocketEvent)) {
  2099  	for {
  2100  		select {
  2101  		case resp, ok := <-client.EventChannel:
  2102  			require.Truef(t, ok, "channel closed before receiving expected event %s", event)
  2103  			if resp.EventType() == event {
  2104  				test(resp)
  2105  				return
  2106  			}
  2107  		case <-time.After(5 * time.Second):
  2108  			require.Failf(t, "failed to receive expected event %s", event)
  2109  		}
  2110  	}
  2111  }
  2112  
  2113  func assertWebsocketEventUserUpdatedWithEmail(t *testing.T, client *model.WebSocketClient, email string) {
  2114  	assertExpectedWebsocketEvent(t, client, model.WEBSOCKET_EVENT_USER_UPDATED, func(event *model.WebSocketEvent) {
  2115  		eventUser, ok := event.GetData()["user"].(*model.User)
  2116  		require.True(t, ok, "expected user")
  2117  		assert.Equal(t, email, eventUser.Email)
  2118  	})
  2119  }
  2120  
  2121  func TestUpdateUserActive(t *testing.T) {
  2122  	t.Run("not activating more users when cloud license users at limit", func(t *testing.T) {
  2123  		// create 5 active users
  2124  		th := Setup(t).InitBasic()
  2125  		defer th.TearDown()
  2126  
  2127  		cloudMock := &mocks.CloudInterface{}
  2128  		cloudMock.Mock.On(
  2129  			"GetSubscription", mock.Anything,
  2130  		).Return(&model.Subscription{
  2131  			ID:         "MySubscriptionID",
  2132  			CustomerID: "MyCustomer",
  2133  			ProductID:  "SomeProductId",
  2134  			AddOns:     []string{},
  2135  			StartAt:    1000000000,
  2136  			EndAt:      2000000000,
  2137  			CreateAt:   1000000000,
  2138  			Seats:      100,
  2139  			DNS:        "some.dns.server",
  2140  			IsPaidTier: "false",
  2141  		}, nil)
  2142  
  2143  		th.App.Srv().SetLicense(model.NewTestLicense("cloud"))
  2144  		th.App.Srv().Cloud = cloudMock
  2145  
  2146  		user := th.BasicUser
  2147  
  2148  		th.App.UpdateConfig(func(cfg *model.Config) {
  2149  			*cfg.TeamSettings.EnableUserDeactivation = true
  2150  			*cfg.ExperimentalSettings.CloudUserLimit = 4
  2151  		})
  2152  
  2153  		// deactivate 5th user, now we have 4 active users and are at limit
  2154  		pass, resp := th.SystemAdminClient.UpdateUserActive(user.Id, false)
  2155  		CheckNoError(t, resp)
  2156  		require.True(t, pass)
  2157  
  2158  		// try and reactivate 5th user, not allowed because it exceeds the set cloud user limit
  2159  		pass, resp = th.SystemAdminClient.UpdateUserActive(user.Id, true)
  2160  		CheckBadRequestStatus(t, resp)
  2161  		require.False(t, pass)
  2162  		require.Equal(t, resp.Error.Message, "Unable to activate more users as the cloud account is over capacity.")
  2163  	})
  2164  	t.Run("basic tests", func(t *testing.T) {
  2165  		th := Setup(t).InitBasic()
  2166  		defer th.TearDown()
  2167  
  2168  		user := th.BasicUser
  2169  
  2170  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserDeactivation = true })
  2171  		pass, resp := th.Client.UpdateUserActive(user.Id, false)
  2172  		CheckNoError(t, resp)
  2173  
  2174  		require.True(t, pass)
  2175  
  2176  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserDeactivation = false })
  2177  		pass, resp = th.Client.UpdateUserActive(user.Id, false)
  2178  		CheckUnauthorizedStatus(t, resp)
  2179  
  2180  		require.False(t, pass)
  2181  
  2182  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserDeactivation = true })
  2183  		pass, resp = th.Client.UpdateUserActive(user.Id, false)
  2184  		CheckUnauthorizedStatus(t, resp)
  2185  
  2186  		require.False(t, pass)
  2187  
  2188  		th.LoginBasic2()
  2189  
  2190  		_, resp = th.Client.UpdateUserActive(user.Id, true)
  2191  		CheckForbiddenStatus(t, resp)
  2192  
  2193  		_, resp = th.Client.UpdateUserActive(GenerateTestId(), true)
  2194  		CheckForbiddenStatus(t, resp)
  2195  
  2196  		_, resp = th.Client.UpdateUserActive("junk", true)
  2197  		CheckBadRequestStatus(t, resp)
  2198  
  2199  		th.Client.Logout()
  2200  
  2201  		_, resp = th.Client.UpdateUserActive(user.Id, true)
  2202  		CheckUnauthorizedStatus(t, resp)
  2203  
  2204  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  2205  			_, resp := client.UpdateUserActive(user.Id, true)
  2206  			CheckNoError(t, resp)
  2207  
  2208  			_, resp = client.UpdateUserActive(user.Id, false)
  2209  			CheckNoError(t, resp)
  2210  
  2211  			authData := model.NewId()
  2212  			_, err := th.App.Srv().Store.User().UpdateAuthData(user.Id, "random", &authData, "", true)
  2213  			require.NoError(t, err)
  2214  
  2215  			_, resp = client.UpdateUserActive(user.Id, false)
  2216  			CheckNoError(t, resp)
  2217  		})
  2218  	})
  2219  
  2220  	t.Run("websocket events", func(t *testing.T) {
  2221  		th := Setup(t).InitBasic()
  2222  		defer th.TearDown()
  2223  
  2224  		user := th.BasicUser2
  2225  
  2226  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.EnableUserDeactivation = true })
  2227  
  2228  		webSocketClient, err := th.CreateWebSocketClient()
  2229  		assert.Nil(t, err)
  2230  		defer webSocketClient.Close()
  2231  
  2232  		webSocketClient.Listen()
  2233  
  2234  		time.Sleep(300 * time.Millisecond)
  2235  		resp := <-webSocketClient.ResponseChannel
  2236  		require.Equal(t, model.STATUS_OK, resp.Status)
  2237  
  2238  		adminWebSocketClient, err := th.CreateWebSocketSystemAdminClient()
  2239  		assert.Nil(t, err)
  2240  		defer adminWebSocketClient.Close()
  2241  
  2242  		adminWebSocketClient.Listen()
  2243  
  2244  		time.Sleep(300 * time.Millisecond)
  2245  		resp = <-adminWebSocketClient.ResponseChannel
  2246  		require.Equal(t, model.STATUS_OK, resp.Status)
  2247  
  2248  		// Verify that both admins and regular users see the email when privacy settings allow same,
  2249  		// and confirm event is fired for SystemAdmin and Local mode
  2250  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowEmailAddress = true })
  2251  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  2252  			_, respErr := client.UpdateUserActive(user.Id, false)
  2253  			CheckNoError(t, respErr)
  2254  
  2255  			assertWebsocketEventUserUpdatedWithEmail(t, webSocketClient, user.Email)
  2256  			assertWebsocketEventUserUpdatedWithEmail(t, adminWebSocketClient, user.Email)
  2257  		})
  2258  
  2259  		// Verify that only admins see the email when privacy settings hide emails,
  2260  		// and confirm event is fired for SystemAdmin and Local mode
  2261  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  2262  			th.App.UpdateConfig(func(cfg *model.Config) { *cfg.PrivacySettings.ShowEmailAddress = false })
  2263  			_, respErr := client.UpdateUserActive(user.Id, true)
  2264  			CheckNoError(t, respErr)
  2265  
  2266  			assertWebsocketEventUserUpdatedWithEmail(t, webSocketClient, "")
  2267  			assertWebsocketEventUserUpdatedWithEmail(t, adminWebSocketClient, user.Email)
  2268  		})
  2269  	})
  2270  
  2271  	t.Run("activate guest should fail when guests feature is disable", func(t *testing.T) {
  2272  		th := Setup(t).InitBasic()
  2273  		defer th.TearDown()
  2274  
  2275  		id := model.NewId()
  2276  		guest := &model.User{
  2277  			Email:         "success+" + id + "@simulator.amazonses.com",
  2278  			Username:      "un_" + id,
  2279  			Nickname:      "nn_" + id,
  2280  			Password:      "Password1",
  2281  			EmailVerified: true,
  2282  		}
  2283  		user, err := th.App.CreateGuest(th.Context, guest)
  2284  		require.Nil(t, err)
  2285  		th.App.UpdateActive(th.Context, user, false)
  2286  
  2287  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.Enable = false })
  2288  		defer th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.Enable = true })
  2289  
  2290  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  2291  			_, resp := client.UpdateUserActive(user.Id, true)
  2292  			CheckUnauthorizedStatus(t, resp)
  2293  		})
  2294  	})
  2295  
  2296  	t.Run("activate guest should work when guests feature is enabled", func(t *testing.T) {
  2297  		th := Setup(t).InitBasic()
  2298  		defer th.TearDown()
  2299  
  2300  		id := model.NewId()
  2301  		guest := &model.User{
  2302  			Email:         "success+" + id + "@simulator.amazonses.com",
  2303  			Username:      "un_" + id,
  2304  			Nickname:      "nn_" + id,
  2305  			Password:      "Password1",
  2306  			EmailVerified: true,
  2307  		}
  2308  		user, err := th.App.CreateGuest(th.Context, guest)
  2309  		require.Nil(t, err)
  2310  		th.App.UpdateActive(th.Context, user, false)
  2311  
  2312  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.Enable = true })
  2313  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  2314  			_, resp := client.UpdateUserActive(user.Id, true)
  2315  			CheckNoError(t, resp)
  2316  		})
  2317  	})
  2318  }
  2319  
  2320  func TestGetUsers(t *testing.T) {
  2321  	th := Setup(t)
  2322  	defer th.TearDown()
  2323  
  2324  	th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  2325  		rusers, resp := client.GetUsers(0, 60, "")
  2326  		CheckNoError(t, resp)
  2327  		for _, u := range rusers {
  2328  			CheckUserSanitization(t, u)
  2329  		}
  2330  
  2331  		rusers, resp = client.GetUsers(0, 1, "")
  2332  		CheckNoError(t, resp)
  2333  		require.Len(t, rusers, 1, "should be 1 per page")
  2334  
  2335  		rusers, resp = client.GetUsers(1, 1, "")
  2336  		CheckNoError(t, resp)
  2337  		require.Len(t, rusers, 1, "should be 1 per page")
  2338  
  2339  		rusers, resp = client.GetUsers(10000, 100, "")
  2340  		CheckNoError(t, resp)
  2341  		require.Empty(t, rusers, "should be no users")
  2342  
  2343  		// Check default params for page and per_page
  2344  		_, err := client.DoApiGet("/users", "")
  2345  		require.Nil(t, err)
  2346  	})
  2347  
  2348  	th.Client.Logout()
  2349  	_, resp := th.Client.GetUsers(0, 60, "")
  2350  	CheckUnauthorizedStatus(t, resp)
  2351  }
  2352  
  2353  func TestGetNewUsersInTeam(t *testing.T) {
  2354  	th := Setup(t).InitBasic()
  2355  	defer th.TearDown()
  2356  	teamId := th.BasicTeam.Id
  2357  
  2358  	rusers, resp := th.Client.GetNewUsersInTeam(teamId, 0, 60, "")
  2359  	CheckNoError(t, resp)
  2360  
  2361  	lastCreateAt := model.GetMillis()
  2362  	for _, u := range rusers {
  2363  		require.LessOrEqual(t, u.CreateAt, lastCreateAt, "right sorting")
  2364  		lastCreateAt = u.CreateAt
  2365  		CheckUserSanitization(t, u)
  2366  	}
  2367  
  2368  	rusers, resp = th.Client.GetNewUsersInTeam(teamId, 1, 1, "")
  2369  	CheckNoError(t, resp)
  2370  	require.Len(t, rusers, 1, "should be 1 per page")
  2371  
  2372  	th.Client.Logout()
  2373  	_, resp = th.Client.GetNewUsersInTeam(teamId, 1, 1, "")
  2374  	CheckUnauthorizedStatus(t, resp)
  2375  }
  2376  
  2377  func TestGetRecentlyActiveUsersInTeam(t *testing.T) {
  2378  	th := Setup(t).InitBasic()
  2379  	defer th.TearDown()
  2380  	teamId := th.BasicTeam.Id
  2381  
  2382  	th.App.SetStatusOnline(th.BasicUser.Id, true)
  2383  
  2384  	rusers, resp := th.Client.GetRecentlyActiveUsersInTeam(teamId, 0, 60, "")
  2385  	CheckNoError(t, resp)
  2386  
  2387  	for _, u := range rusers {
  2388  		require.NotZero(t, u.LastActivityAt, "should return last activity at")
  2389  		CheckUserSanitization(t, u)
  2390  	}
  2391  
  2392  	rusers, resp = th.Client.GetRecentlyActiveUsersInTeam(teamId, 0, 1, "")
  2393  	CheckNoError(t, resp)
  2394  	require.Len(t, rusers, 1, "should be 1 per page")
  2395  
  2396  	th.Client.Logout()
  2397  	_, resp = th.Client.GetRecentlyActiveUsersInTeam(teamId, 0, 1, "")
  2398  	CheckUnauthorizedStatus(t, resp)
  2399  }
  2400  
  2401  func TestGetActiveUsersInTeam(t *testing.T) {
  2402  	th := Setup(t).InitBasic()
  2403  	defer th.TearDown()
  2404  	teamId := th.BasicTeam.Id
  2405  
  2406  	th.SystemAdminClient.UpdateUserActive(th.BasicUser2.Id, false)
  2407  	rusers, resp := th.Client.GetActiveUsersInTeam(teamId, 0, 60, "")
  2408  	CheckNoError(t, resp)
  2409  
  2410  	require.NotZero(t, len(rusers))
  2411  	for _, u := range rusers {
  2412  		require.Zero(t, u.DeleteAt, "should not be deleted")
  2413  		require.NotEqual(t, th.BasicUser2.Id, "should not include deactivated user")
  2414  		CheckUserSanitization(t, u)
  2415  	}
  2416  
  2417  	rusers, resp = th.Client.GetActiveUsersInTeam(teamId, 0, 1, "")
  2418  	CheckNoError(t, resp)
  2419  	require.Len(t, rusers, 1, "should be 1 per page")
  2420  
  2421  	// Check case where we have supplied both active and inactive flags
  2422  	_, err := th.Client.DoApiGet("/users?inactive=true&active=true", "")
  2423  	require.NotNil(t, err)
  2424  
  2425  	th.Client.Logout()
  2426  	_, resp = th.Client.GetActiveUsersInTeam(teamId, 0, 1, "")
  2427  	CheckUnauthorizedStatus(t, resp)
  2428  }
  2429  
  2430  func TestGetUsersWithoutTeam(t *testing.T) {
  2431  	th := Setup(t).InitBasic()
  2432  	defer th.TearDown()
  2433  
  2434  	_, resp := th.Client.GetUsersWithoutTeam(0, 100, "")
  2435  	require.NotNil(t, resp.Error, "should prevent non-admin user from getting users without a team")
  2436  
  2437  	// These usernames need to appear in the first 100 users for this to work
  2438  
  2439  	user, resp := th.Client.CreateUser(&model.User{
  2440  		Username: "a000000000" + model.NewId(),
  2441  		Email:    "success+" + model.NewId() + "@simulator.amazonses.com",
  2442  		Password: "Password1",
  2443  	})
  2444  	CheckNoError(t, resp)
  2445  	th.LinkUserToTeam(user, th.BasicTeam)
  2446  	defer th.App.Srv().Store.User().PermanentDelete(user.Id)
  2447  
  2448  	user2, resp := th.Client.CreateUser(&model.User{
  2449  		Username: "a000000001" + model.NewId(),
  2450  		Email:    "success+" + model.NewId() + "@simulator.amazonses.com",
  2451  		Password: "Password1",
  2452  	})
  2453  	CheckNoError(t, resp)
  2454  	defer th.App.Srv().Store.User().PermanentDelete(user2.Id)
  2455  
  2456  	rusers, resp := th.SystemAdminClient.GetUsersWithoutTeam(0, 100, "")
  2457  	CheckNoError(t, resp)
  2458  
  2459  	found1 := false
  2460  	found2 := false
  2461  
  2462  	for _, u := range rusers {
  2463  		if u.Id == user.Id {
  2464  			found1 = true
  2465  		} else if u.Id == user2.Id {
  2466  			found2 = true
  2467  		}
  2468  	}
  2469  
  2470  	require.False(t, found1, "should not return user that as a team")
  2471  	require.True(t, found2, "should return user that has no teams")
  2472  }
  2473  
  2474  func TestGetUsersInTeam(t *testing.T) {
  2475  	th := Setup(t).InitBasic()
  2476  	defer th.TearDown()
  2477  	teamId := th.BasicTeam.Id
  2478  
  2479  	rusers, resp := th.Client.GetUsersInTeam(teamId, 0, 60, "")
  2480  	CheckNoError(t, resp)
  2481  	for _, u := range rusers {
  2482  		CheckUserSanitization(t, u)
  2483  	}
  2484  
  2485  	rusers, resp = th.Client.GetUsersInTeam(teamId, 0, 60, resp.Etag)
  2486  	CheckEtag(t, rusers, resp)
  2487  
  2488  	rusers, resp = th.Client.GetUsersInTeam(teamId, 0, 1, "")
  2489  	CheckNoError(t, resp)
  2490  	require.Len(t, rusers, 1, "should be 1 per page")
  2491  
  2492  	rusers, resp = th.Client.GetUsersInTeam(teamId, 1, 1, "")
  2493  	CheckNoError(t, resp)
  2494  	require.Len(t, rusers, 1, "should be 1 per page")
  2495  
  2496  	rusers, resp = th.Client.GetUsersInTeam(teamId, 10000, 100, "")
  2497  	CheckNoError(t, resp)
  2498  	require.Empty(t, rusers, "should be no users")
  2499  
  2500  	th.Client.Logout()
  2501  	_, resp = th.Client.GetUsersInTeam(teamId, 0, 60, "")
  2502  	CheckUnauthorizedStatus(t, resp)
  2503  
  2504  	user := th.CreateUser()
  2505  	th.Client.Login(user.Email, user.Password)
  2506  	_, resp = th.Client.GetUsersInTeam(teamId, 0, 60, "")
  2507  	CheckForbiddenStatus(t, resp)
  2508  
  2509  	_, resp = th.SystemAdminClient.GetUsersInTeam(teamId, 0, 60, "")
  2510  	CheckNoError(t, resp)
  2511  }
  2512  
  2513  func TestGetUsersNotInTeam(t *testing.T) {
  2514  	th := Setup(t).InitBasic()
  2515  	defer th.TearDown()
  2516  	teamId := th.BasicTeam.Id
  2517  
  2518  	rusers, resp := th.Client.GetUsersNotInTeam(teamId, 0, 60, "")
  2519  	CheckNoError(t, resp)
  2520  	for _, u := range rusers {
  2521  		CheckUserSanitization(t, u)
  2522  	}
  2523  	require.Len(t, rusers, 2, "should be 2 users in total")
  2524  
  2525  	rusers, resp = th.Client.GetUsersNotInTeam(teamId, 0, 60, resp.Etag)
  2526  	CheckEtag(t, rusers, resp)
  2527  
  2528  	rusers, resp = th.Client.GetUsersNotInTeam(teamId, 0, 1, "")
  2529  	CheckNoError(t, resp)
  2530  	require.Len(t, rusers, 1, "should be 1 per page")
  2531  
  2532  	rusers, resp = th.Client.GetUsersNotInTeam(teamId, 2, 1, "")
  2533  	CheckNoError(t, resp)
  2534  	require.Empty(t, rusers, "should be no users")
  2535  
  2536  	rusers, resp = th.Client.GetUsersNotInTeam(teamId, 10000, 100, "")
  2537  	CheckNoError(t, resp)
  2538  	require.Empty(t, rusers, "should be no users")
  2539  
  2540  	th.Client.Logout()
  2541  	_, resp = th.Client.GetUsersNotInTeam(teamId, 0, 60, "")
  2542  	CheckUnauthorizedStatus(t, resp)
  2543  
  2544  	user := th.CreateUser()
  2545  	th.Client.Login(user.Email, user.Password)
  2546  	_, resp = th.Client.GetUsersNotInTeam(teamId, 0, 60, "")
  2547  	CheckForbiddenStatus(t, resp)
  2548  
  2549  	_, resp = th.SystemAdminClient.GetUsersNotInTeam(teamId, 0, 60, "")
  2550  	CheckNoError(t, resp)
  2551  }
  2552  
  2553  func TestGetUsersInChannel(t *testing.T) {
  2554  	th := Setup(t).InitBasic()
  2555  	defer th.TearDown()
  2556  	channelId := th.BasicChannel.Id
  2557  
  2558  	rusers, resp := th.Client.GetUsersInChannel(channelId, 0, 60, "")
  2559  	CheckNoError(t, resp)
  2560  	for _, u := range rusers {
  2561  		CheckUserSanitization(t, u)
  2562  	}
  2563  
  2564  	rusers, resp = th.Client.GetUsersInChannel(channelId, 0, 1, "")
  2565  	CheckNoError(t, resp)
  2566  	require.Len(t, rusers, 1, "should be 1 per page")
  2567  
  2568  	rusers, resp = th.Client.GetUsersInChannel(channelId, 1, 1, "")
  2569  	CheckNoError(t, resp)
  2570  	require.Len(t, rusers, 1, "should be 1 per page")
  2571  
  2572  	rusers, resp = th.Client.GetUsersInChannel(channelId, 10000, 100, "")
  2573  	CheckNoError(t, resp)
  2574  	require.Empty(t, rusers, "should be no users")
  2575  
  2576  	th.Client.Logout()
  2577  	_, resp = th.Client.GetUsersInChannel(channelId, 0, 60, "")
  2578  	CheckUnauthorizedStatus(t, resp)
  2579  
  2580  	user := th.CreateUser()
  2581  	th.Client.Login(user.Email, user.Password)
  2582  	_, resp = th.Client.GetUsersInChannel(channelId, 0, 60, "")
  2583  	CheckForbiddenStatus(t, resp)
  2584  
  2585  	_, resp = th.SystemAdminClient.GetUsersInChannel(channelId, 0, 60, "")
  2586  	CheckNoError(t, resp)
  2587  }
  2588  
  2589  func TestGetUsersNotInChannel(t *testing.T) {
  2590  	th := Setup(t).InitBasic()
  2591  	defer th.TearDown()
  2592  	teamId := th.BasicTeam.Id
  2593  	channelId := th.BasicChannel.Id
  2594  
  2595  	user := th.CreateUser()
  2596  	th.LinkUserToTeam(user, th.BasicTeam)
  2597  
  2598  	rusers, resp := th.Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "")
  2599  	CheckNoError(t, resp)
  2600  	for _, u := range rusers {
  2601  		CheckUserSanitization(t, u)
  2602  	}
  2603  
  2604  	rusers, resp = th.Client.GetUsersNotInChannel(teamId, channelId, 0, 1, "")
  2605  	CheckNoError(t, resp)
  2606  	require.Len(t, rusers, 1, "should be 1 per page")
  2607  
  2608  	rusers, resp = th.Client.GetUsersNotInChannel(teamId, channelId, 10000, 100, "")
  2609  	CheckNoError(t, resp)
  2610  	require.Empty(t, rusers, "should be no users")
  2611  
  2612  	th.Client.Logout()
  2613  	_, resp = th.Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "")
  2614  	CheckUnauthorizedStatus(t, resp)
  2615  
  2616  	th.Client.Login(user.Email, user.Password)
  2617  	_, resp = th.Client.GetUsersNotInChannel(teamId, channelId, 0, 60, "")
  2618  	CheckForbiddenStatus(t, resp)
  2619  
  2620  	_, resp = th.SystemAdminClient.GetUsersNotInChannel(teamId, channelId, 0, 60, "")
  2621  	CheckNoError(t, resp)
  2622  }
  2623  
  2624  func TestGetUsersInGroup(t *testing.T) {
  2625  	th := Setup(t).InitBasic()
  2626  	defer th.TearDown()
  2627  
  2628  	id := model.NewId()
  2629  	group, err := th.App.CreateGroup(&model.Group{
  2630  		DisplayName: "dn-foo_" + id,
  2631  		Name:        model.NewString("name" + id),
  2632  		Source:      model.GroupSourceLdap,
  2633  		Description: "description_" + id,
  2634  		RemoteId:    model.NewId(),
  2635  	})
  2636  	assert.Nil(t, err)
  2637  
  2638  	var response *model.Response
  2639  	var users []*model.User
  2640  
  2641  	t.Run("Requires ldap license", func(t *testing.T) {
  2642  		_, response = th.SystemAdminClient.GetUsersInGroup(group.Id, 0, 60, "")
  2643  		CheckNotImplementedStatus(t, response)
  2644  	})
  2645  
  2646  	th.App.Srv().SetLicense(model.NewTestLicense("ldap"))
  2647  
  2648  	t.Run("Requires manage system permission to access users in group", func(t *testing.T) {
  2649  		th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  2650  		_, response = th.Client.GetUsersInGroup(group.Id, 0, 60, "")
  2651  		CheckForbiddenStatus(t, response)
  2652  	})
  2653  
  2654  	user1, err := th.App.CreateUser(th.Context, &model.User{Email: th.GenerateTestEmail(), Nickname: "test user1", Password: "test-password-1", Username: "test-user-1", Roles: model.SYSTEM_USER_ROLE_ID})
  2655  	assert.Nil(t, err)
  2656  	_, err = th.App.UpsertGroupMember(group.Id, user1.Id)
  2657  	assert.Nil(t, err)
  2658  
  2659  	t.Run("Returns users in group when called by system admin", func(t *testing.T) {
  2660  		users, response = th.SystemAdminClient.GetUsersInGroup(group.Id, 0, 60, "")
  2661  		CheckNoError(t, response)
  2662  		assert.Equal(t, users[0].Id, user1.Id)
  2663  	})
  2664  
  2665  	t.Run("Returns no users when pagination out of range", func(t *testing.T) {
  2666  		users, response = th.SystemAdminClient.GetUsersInGroup(group.Id, 5, 60, "")
  2667  		CheckNoError(t, response)
  2668  		assert.Empty(t, users)
  2669  	})
  2670  }
  2671  
  2672  func TestUpdateUserMfa(t *testing.T) {
  2673  	th := Setup(t).InitBasic()
  2674  	defer th.TearDown()
  2675  
  2676  	th.App.Srv().SetLicense(model.NewTestLicense("mfa"))
  2677  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = true })
  2678  
  2679  	session, _ := th.App.GetSession(th.Client.AuthToken)
  2680  	session.IsOAuth = true
  2681  	th.App.AddSessionToCache(session)
  2682  
  2683  	_, resp := th.Client.UpdateUserMfa(th.BasicUser.Id, "12345", false)
  2684  	CheckForbiddenStatus(t, resp)
  2685  
  2686  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  2687  		_, resp := client.UpdateUserMfa(th.BasicUser.Id, "12345", false)
  2688  		CheckNoError(t, resp)
  2689  	})
  2690  }
  2691  
  2692  // CheckUserMfa is deprecated and should not be used anymore, it will be disabled by default in version 6.0
  2693  func TestCheckUserMfa(t *testing.T) {
  2694  	th := Setup(t).InitBasic()
  2695  	defer th.TearDown()
  2696  
  2697  	th.App.UpdateConfig(func(c *model.Config) {
  2698  		*c.ServiceSettings.DisableLegacyMFA = false
  2699  	})
  2700  
  2701  	required, resp := th.Client.CheckUserMfa(th.BasicUser.Email)
  2702  	CheckNoError(t, resp)
  2703  
  2704  	require.False(t, required, "mfa not active")
  2705  
  2706  	_, resp = th.Client.CheckUserMfa("")
  2707  	CheckBadRequestStatus(t, resp)
  2708  
  2709  	th.Client.Logout()
  2710  
  2711  	required, resp = th.Client.CheckUserMfa(th.BasicUser.Email)
  2712  	CheckNoError(t, resp)
  2713  
  2714  	require.False(t, required, "mfa not active")
  2715  
  2716  	th.App.Srv().SetLicense(model.NewTestLicense("mfa"))
  2717  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = true })
  2718  
  2719  	th.LoginBasic()
  2720  
  2721  	required, resp = th.Client.CheckUserMfa(th.BasicUser.Email)
  2722  	CheckNoError(t, resp)
  2723  
  2724  	require.False(t, required, "mfa not active")
  2725  
  2726  	th.Client.Logout()
  2727  
  2728  	required, resp = th.Client.CheckUserMfa(th.BasicUser.Email)
  2729  	CheckNoError(t, resp)
  2730  
  2731  	require.False(t, required, "mfa not active")
  2732  
  2733  	th.App.UpdateConfig(func(c *model.Config) {
  2734  		*c.ServiceSettings.DisableLegacyMFA = true
  2735  	})
  2736  
  2737  	_, resp = th.Client.CheckUserMfa(th.BasicUser.Email)
  2738  	CheckNotFoundStatus(t, resp)
  2739  }
  2740  
  2741  func TestUserLoginMFAFlow(t *testing.T) {
  2742  	th := Setup(t).InitBasic()
  2743  	defer th.TearDown()
  2744  
  2745  	th.App.UpdateConfig(func(c *model.Config) {
  2746  		*c.ServiceSettings.DisableLegacyMFA = true
  2747  		*c.ServiceSettings.EnableMultifactorAuthentication = true
  2748  	})
  2749  
  2750  	t.Run("WithoutMFA", func(t *testing.T) {
  2751  		_, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  2752  		CheckNoError(t, resp)
  2753  	})
  2754  
  2755  	t.Run("WithInvalidMFA", func(t *testing.T) {
  2756  		secret, err := th.App.GenerateMfaSecret(th.BasicUser.Id)
  2757  		assert.Nil(t, err)
  2758  
  2759  		// Fake user has MFA enabled
  2760  		nErr := th.Server.Store.User().UpdateMfaActive(th.BasicUser.Id, true)
  2761  		require.NoError(t, nErr)
  2762  
  2763  		nErr = th.Server.Store.User().UpdateMfaActive(th.BasicUser.Id, true)
  2764  		require.NoError(t, nErr)
  2765  
  2766  		nErr = th.Server.Store.User().UpdateMfaSecret(th.BasicUser.Id, secret.Secret)
  2767  		require.NoError(t, nErr)
  2768  
  2769  		user, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  2770  		CheckErrorMessage(t, resp, "mfa.validate_token.authenticate.app_error")
  2771  		assert.Nil(t, user)
  2772  
  2773  		user, resp = th.Client.LoginWithMFA(th.BasicUser.Email, th.BasicUser.Password, "")
  2774  		CheckErrorMessage(t, resp, "mfa.validate_token.authenticate.app_error")
  2775  		assert.Nil(t, user)
  2776  
  2777  		user, resp = th.Client.LoginWithMFA(th.BasicUser.Email, th.BasicUser.Password, "abcdefgh")
  2778  		CheckErrorMessage(t, resp, "mfa.validate_token.authenticate.app_error")
  2779  		assert.Nil(t, user)
  2780  
  2781  		secret2, err := th.App.GenerateMfaSecret(th.BasicUser2.Id)
  2782  		assert.Nil(t, err)
  2783  		user, resp = th.Client.LoginWithMFA(th.BasicUser.Email, th.BasicUser.Password, secret2.Secret)
  2784  		CheckErrorMessage(t, resp, "mfa.validate_token.authenticate.app_error")
  2785  		assert.Nil(t, user)
  2786  	})
  2787  
  2788  	t.Run("WithCorrectMFA", func(t *testing.T) {
  2789  		secret, err := th.App.GenerateMfaSecret(th.BasicUser.Id)
  2790  		assert.Nil(t, err)
  2791  
  2792  		// Fake user has MFA enabled
  2793  		nErr := th.Server.Store.User().UpdateMfaActive(th.BasicUser.Id, true)
  2794  		require.NoError(t, nErr)
  2795  
  2796  		nErr = th.Server.Store.User().UpdateMfaSecret(th.BasicUser.Id, secret.Secret)
  2797  		require.NoError(t, nErr)
  2798  
  2799  		code := dgoogauth.ComputeCode(secret.Secret, time.Now().UTC().Unix()/30)
  2800  
  2801  		user, resp := th.Client.LoginWithMFA(th.BasicUser.Email, th.BasicUser.Password, fmt.Sprintf("%06d", code))
  2802  		CheckNoError(t, resp)
  2803  		assert.NotNil(t, user)
  2804  	})
  2805  }
  2806  
  2807  func TestGenerateMfaSecret(t *testing.T) {
  2808  	th := Setup(t).InitBasic()
  2809  	defer th.TearDown()
  2810  
  2811  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = false })
  2812  
  2813  	_, resp := th.Client.GenerateMfaSecret(th.BasicUser.Id)
  2814  	CheckNotImplementedStatus(t, resp)
  2815  
  2816  	_, resp = th.SystemAdminClient.GenerateMfaSecret(th.BasicUser.Id)
  2817  	CheckNotImplementedStatus(t, resp)
  2818  
  2819  	_, resp = th.Client.GenerateMfaSecret("junk")
  2820  	CheckBadRequestStatus(t, resp)
  2821  
  2822  	th.App.Srv().SetLicense(model.NewTestLicense("mfa"))
  2823  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = true })
  2824  
  2825  	_, resp = th.Client.GenerateMfaSecret(model.NewId())
  2826  	CheckForbiddenStatus(t, resp)
  2827  
  2828  	session, _ := th.App.GetSession(th.Client.AuthToken)
  2829  	session.IsOAuth = true
  2830  	th.App.AddSessionToCache(session)
  2831  
  2832  	_, resp = th.Client.GenerateMfaSecret(th.BasicUser.Id)
  2833  	CheckForbiddenStatus(t, resp)
  2834  
  2835  	th.Client.Logout()
  2836  
  2837  	_, resp = th.Client.GenerateMfaSecret(th.BasicUser.Id)
  2838  	CheckUnauthorizedStatus(t, resp)
  2839  }
  2840  
  2841  func TestUpdateUserPassword(t *testing.T) {
  2842  	th := Setup(t).InitBasic()
  2843  	defer th.TearDown()
  2844  
  2845  	password := "newpassword1"
  2846  	pass, resp := th.Client.UpdateUserPassword(th.BasicUser.Id, th.BasicUser.Password, password)
  2847  	CheckNoError(t, resp)
  2848  
  2849  	require.True(t, pass)
  2850  
  2851  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, password, "")
  2852  	CheckBadRequestStatus(t, resp)
  2853  
  2854  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, password, "junk")
  2855  	CheckBadRequestStatus(t, resp)
  2856  
  2857  	_, resp = th.Client.UpdateUserPassword("junk", password, password)
  2858  	CheckBadRequestStatus(t, resp)
  2859  
  2860  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, "", password)
  2861  	CheckBadRequestStatus(t, resp)
  2862  
  2863  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, "junk", password)
  2864  	CheckBadRequestStatus(t, resp)
  2865  
  2866  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, password, th.BasicUser.Password)
  2867  	CheckNoError(t, resp)
  2868  
  2869  	th.Client.Logout()
  2870  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, password, password)
  2871  	CheckUnauthorizedStatus(t, resp)
  2872  
  2873  	th.LoginBasic2()
  2874  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, password, password)
  2875  	CheckForbiddenStatus(t, resp)
  2876  
  2877  	th.LoginBasic()
  2878  
  2879  	// Test lockout
  2880  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.MaximumLoginAttempts = 2 })
  2881  
  2882  	// Fail twice
  2883  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, "badpwd", "newpwd")
  2884  	CheckBadRequestStatus(t, resp)
  2885  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, "badpwd", "newpwd")
  2886  	CheckBadRequestStatus(t, resp)
  2887  
  2888  	// Should fail because account is locked out
  2889  	_, resp = th.Client.UpdateUserPassword(th.BasicUser.Id, th.BasicUser.Password, "newpwd")
  2890  	CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error")
  2891  	CheckUnauthorizedStatus(t, resp)
  2892  
  2893  	// System admin can update another user's password
  2894  	adminSetPassword := "pwdsetbyadmin"
  2895  	pass, resp = th.SystemAdminClient.UpdateUserPassword(th.BasicUser.Id, "", adminSetPassword)
  2896  	CheckNoError(t, resp)
  2897  
  2898  	require.True(t, pass)
  2899  
  2900  	_, resp = th.Client.Login(th.BasicUser.Email, adminSetPassword)
  2901  	CheckNoError(t, resp)
  2902  }
  2903  
  2904  func TestUpdateUserHashedPassword(t *testing.T) {
  2905  	th := Setup(t).InitBasic()
  2906  	defer th.TearDown()
  2907  	client := th.Client
  2908  
  2909  	password := "SuperSecurePass23!"
  2910  	passwordHash := "$2a$10$CiS1iWVPUj7rQNdY6XW53.DmaPLsETIvmW2p0asp4Dqpofs10UL5W"
  2911  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  2912  		pass, resp := client.UpdateUserHashedPassword(th.BasicUser.Id, passwordHash)
  2913  		CheckNoError(t, resp)
  2914  		require.True(t, pass)
  2915  	})
  2916  
  2917  	_, resp := client.Login(th.BasicUser.Email, password)
  2918  	CheckNoError(t, resp)
  2919  
  2920  	// Standard users should never be updating their passwords with already-
  2921  	// hashed passwords.
  2922  	pass, resp := client.UpdateUserHashedPassword(th.BasicUser.Id, passwordHash)
  2923  	CheckUnauthorizedStatus(t, resp)
  2924  	require.False(t, pass)
  2925  }
  2926  
  2927  func TestResetPassword(t *testing.T) {
  2928  	t.Skip("test disabled during old build server changes, should be investigated")
  2929  
  2930  	th := Setup(t).InitBasic()
  2931  	defer th.TearDown()
  2932  	th.Client.Logout()
  2933  	user := th.BasicUser
  2934  	// Delete all the messages before check the reset password
  2935  	mail.DeleteMailBox(user.Email)
  2936  	th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  2937  		success, resp := client.SendPasswordResetEmail(user.Email)
  2938  		CheckNoError(t, resp)
  2939  		require.True(t, success, "should succeed")
  2940  		_, resp = client.SendPasswordResetEmail("")
  2941  		CheckBadRequestStatus(t, resp)
  2942  		// Should not leak whether the email is attached to an account or not
  2943  		success, resp = client.SendPasswordResetEmail("notreal@example.com")
  2944  		CheckNoError(t, resp)
  2945  		require.True(t, success, "should succeed")
  2946  	})
  2947  	// Check if the email was send to the right email address and the recovery key match
  2948  	var resultsMailbox mail.JSONMessageHeaderInbucket
  2949  	err := mail.RetryInbucket(5, func() error {
  2950  		var err error
  2951  		resultsMailbox, err = mail.GetMailBox(user.Email)
  2952  		return err
  2953  	})
  2954  	if err != nil {
  2955  		t.Log(err)
  2956  		t.Log("No email was received, maybe due load on the server. Disabling this verification")
  2957  	}
  2958  	var recoveryTokenString string
  2959  	if err == nil && len(resultsMailbox) > 0 {
  2960  		require.Contains(t, resultsMailbox[0].To[0], user.Email, "Correct To recipient")
  2961  		resultsEmail, mailErr := mail.GetMessageFromMailbox(user.Email, resultsMailbox[0].ID)
  2962  		require.NoError(t, mailErr)
  2963  		loc := strings.Index(resultsEmail.Body.Text, "token=")
  2964  		require.NotEqual(t, -1, loc, "Code should be found in email")
  2965  		loc += 6
  2966  		recoveryTokenString = resultsEmail.Body.Text[loc : loc+model.TOKEN_SIZE]
  2967  	}
  2968  	recoveryToken, err := th.App.Srv().Store.Token().GetByToken(recoveryTokenString)
  2969  	require.NoError(t, err, "Recovery token not found (%s)", recoveryTokenString)
  2970  
  2971  	_, resp := th.Client.ResetPassword(recoveryToken.Token, "")
  2972  	CheckBadRequestStatus(t, resp)
  2973  	_, resp = th.Client.ResetPassword(recoveryToken.Token, "newp")
  2974  	CheckBadRequestStatus(t, resp)
  2975  	_, resp = th.Client.ResetPassword("", "newpwd")
  2976  	CheckBadRequestStatus(t, resp)
  2977  	_, resp = th.Client.ResetPassword("junk", "newpwd")
  2978  	CheckBadRequestStatus(t, resp)
  2979  	code := ""
  2980  	for i := 0; i < model.TOKEN_SIZE; i++ {
  2981  		code += "a"
  2982  	}
  2983  	_, resp = th.Client.ResetPassword(code, "newpwd")
  2984  	CheckBadRequestStatus(t, resp)
  2985  	success, resp := th.Client.ResetPassword(recoveryToken.Token, "newpwd")
  2986  	CheckNoError(t, resp)
  2987  	require.True(t, success)
  2988  	th.Client.Login(user.Email, "newpwd")
  2989  	th.Client.Logout()
  2990  	_, resp = th.Client.ResetPassword(recoveryToken.Token, "newpwd")
  2991  	CheckBadRequestStatus(t, resp)
  2992  	authData := model.NewId()
  2993  	_, err = th.App.Srv().Store.User().UpdateAuthData(user.Id, "random", &authData, "", true)
  2994  	require.NoError(t, err)
  2995  	th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  2996  		_, resp = client.SendPasswordResetEmail(user.Email)
  2997  		CheckBadRequestStatus(t, resp)
  2998  	})
  2999  }
  3000  
  3001  func TestGetSessions(t *testing.T) {
  3002  	th := Setup(t).InitBasic()
  3003  	defer th.TearDown()
  3004  
  3005  	user := th.BasicUser
  3006  
  3007  	th.Client.Login(user.Email, user.Password)
  3008  
  3009  	sessions, resp := th.Client.GetSessions(user.Id, "")
  3010  	for _, session := range sessions {
  3011  		require.Equal(t, user.Id, session.UserId, "user id should match session user id")
  3012  	}
  3013  	CheckNoError(t, resp)
  3014  
  3015  	_, resp = th.Client.RevokeSession("junk", model.NewId())
  3016  	CheckBadRequestStatus(t, resp)
  3017  
  3018  	_, resp = th.Client.GetSessions(th.BasicUser2.Id, "")
  3019  	CheckForbiddenStatus(t, resp)
  3020  
  3021  	_, resp = th.Client.GetSessions(model.NewId(), "")
  3022  	CheckForbiddenStatus(t, resp)
  3023  
  3024  	th.Client.Logout()
  3025  	_, resp = th.Client.GetSessions(th.BasicUser2.Id, "")
  3026  	CheckUnauthorizedStatus(t, resp)
  3027  
  3028  	_, resp = th.SystemAdminClient.GetSessions(user.Id, "")
  3029  	CheckNoError(t, resp)
  3030  
  3031  	_, resp = th.SystemAdminClient.GetSessions(th.BasicUser2.Id, "")
  3032  	CheckNoError(t, resp)
  3033  
  3034  	_, resp = th.SystemAdminClient.GetSessions(model.NewId(), "")
  3035  	CheckNoError(t, resp)
  3036  }
  3037  
  3038  func TestRevokeSessions(t *testing.T) {
  3039  	th := Setup(t).InitBasic()
  3040  	defer th.TearDown()
  3041  
  3042  	user := th.BasicUser
  3043  	th.Client.Login(user.Email, user.Password)
  3044  	sessions, _ := th.Client.GetSessions(user.Id, "")
  3045  	require.NotZero(t, len(sessions), "sessions should exist")
  3046  	for _, session := range sessions {
  3047  		require.Equal(t, user.Id, session.UserId, "user id does not match session user id")
  3048  	}
  3049  	session := sessions[0]
  3050  
  3051  	_, resp := th.Client.RevokeSession(user.Id, model.NewId())
  3052  	CheckBadRequestStatus(t, resp)
  3053  
  3054  	_, resp = th.Client.RevokeSession(th.BasicUser2.Id, model.NewId())
  3055  	CheckForbiddenStatus(t, resp)
  3056  
  3057  	_, resp = th.Client.RevokeSession("junk", model.NewId())
  3058  	CheckBadRequestStatus(t, resp)
  3059  
  3060  	status, resp := th.Client.RevokeSession(user.Id, session.Id)
  3061  	require.True(t, status, "user session revoke successfully")
  3062  	CheckNoError(t, resp)
  3063  
  3064  	th.LoginBasic()
  3065  
  3066  	sessions, _ = th.App.GetSessions(th.SystemAdminUser.Id)
  3067  	session = sessions[0]
  3068  
  3069  	_, resp = th.Client.RevokeSession(user.Id, session.Id)
  3070  	CheckBadRequestStatus(t, resp)
  3071  
  3072  	th.Client.Logout()
  3073  	_, resp = th.Client.RevokeSession(user.Id, model.NewId())
  3074  	CheckUnauthorizedStatus(t, resp)
  3075  
  3076  	_, resp = th.SystemAdminClient.RevokeSession(user.Id, model.NewId())
  3077  	CheckBadRequestStatus(t, resp)
  3078  
  3079  	sessions, _ = th.SystemAdminClient.GetSessions(th.SystemAdminUser.Id, "")
  3080  	require.NotEmpty(t, sessions, "sessions should exist")
  3081  	for _, session := range sessions {
  3082  		require.Equal(t, th.SystemAdminUser.Id, session.UserId, "user id should match session user id")
  3083  	}
  3084  	session = sessions[0]
  3085  
  3086  	_, resp = th.SystemAdminClient.RevokeSession(th.SystemAdminUser.Id, session.Id)
  3087  	CheckNoError(t, resp)
  3088  }
  3089  
  3090  func TestRevokeAllSessions(t *testing.T) {
  3091  	th := Setup(t).InitBasic()
  3092  	defer th.TearDown()
  3093  
  3094  	user := th.BasicUser
  3095  	th.Client.Login(user.Email, user.Password)
  3096  
  3097  	_, resp := th.Client.RevokeAllSessions(th.BasicUser2.Id)
  3098  	CheckForbiddenStatus(t, resp)
  3099  
  3100  	_, resp = th.Client.RevokeAllSessions("junk" + user.Id)
  3101  	CheckBadRequestStatus(t, resp)
  3102  
  3103  	status, resp := th.Client.RevokeAllSessions(user.Id)
  3104  	require.True(t, status, "user all sessions revoke unsuccessful")
  3105  	CheckNoError(t, resp)
  3106  
  3107  	th.Client.Logout()
  3108  	_, resp = th.Client.RevokeAllSessions(user.Id)
  3109  	CheckUnauthorizedStatus(t, resp)
  3110  
  3111  	th.Client.Login(user.Email, user.Password)
  3112  
  3113  	sessions, _ := th.Client.GetSessions(user.Id, "")
  3114  	require.NotEmpty(t, sessions, "session should exist")
  3115  
  3116  	_, resp = th.Client.RevokeAllSessions(user.Id)
  3117  	CheckNoError(t, resp)
  3118  
  3119  	sessions, _ = th.SystemAdminClient.GetSessions(user.Id, "")
  3120  	require.Empty(t, sessions, "no sessions should exist for user")
  3121  
  3122  	_, resp = th.Client.RevokeAllSessions(user.Id)
  3123  	CheckUnauthorizedStatus(t, resp)
  3124  }
  3125  
  3126  func TestRevokeSessionsFromAllUsers(t *testing.T) {
  3127  	th := Setup(t).InitBasic()
  3128  	defer th.TearDown()
  3129  
  3130  	user := th.BasicUser
  3131  	th.Client.Login(user.Email, user.Password)
  3132  	_, resp := th.Client.RevokeSessionsFromAllUsers()
  3133  	CheckForbiddenStatus(t, resp)
  3134  
  3135  	th.Client.Logout()
  3136  	_, resp = th.Client.RevokeSessionsFromAllUsers()
  3137  	CheckUnauthorizedStatus(t, resp)
  3138  
  3139  	th.Client.Login(user.Email, user.Password)
  3140  	admin := th.SystemAdminUser
  3141  	th.Client.Login(admin.Email, admin.Password)
  3142  	sessions, err := th.Server.Store.Session().GetSessions(user.Id)
  3143  	require.NotEmpty(t, sessions)
  3144  	require.NoError(t, err)
  3145  	sessions, err = th.Server.Store.Session().GetSessions(admin.Id)
  3146  	require.NotEmpty(t, sessions)
  3147  	require.NoError(t, err)
  3148  	_, resp = th.Client.RevokeSessionsFromAllUsers()
  3149  	CheckNoError(t, resp)
  3150  
  3151  	// All sessions were revoked, so making the same call
  3152  	// again will fail due to lack of a session.
  3153  	_, resp = th.Client.RevokeSessionsFromAllUsers()
  3154  	CheckUnauthorizedStatus(t, resp)
  3155  
  3156  	sessions, err = th.Server.Store.Session().GetSessions(user.Id)
  3157  	require.Empty(t, sessions)
  3158  	require.NoError(t, err)
  3159  
  3160  	sessions, err = th.Server.Store.Session().GetSessions(admin.Id)
  3161  	require.Empty(t, sessions)
  3162  	require.NoError(t, err)
  3163  
  3164  }
  3165  
  3166  func TestAttachDeviceId(t *testing.T) {
  3167  	th := Setup(t).InitBasic()
  3168  	defer th.TearDown()
  3169  
  3170  	deviceId := model.PUSH_NOTIFY_APPLE + ":1234567890"
  3171  
  3172  	t.Run("success", func(t *testing.T) {
  3173  		testCases := []struct {
  3174  			Description                   string
  3175  			SiteURL                       string
  3176  			ExpectedSetCookieHeaderRegexp string
  3177  		}{
  3178  			{"no subpath", "http://localhost:8065", "^MMAUTHTOKEN=[a-z0-9]+; Path=/"},
  3179  			{"subpath", "http://localhost:8065/subpath", "^MMAUTHTOKEN=[a-z0-9]+; Path=/subpath"},
  3180  		}
  3181  
  3182  		for _, tc := range testCases {
  3183  			t.Run(tc.Description, func(t *testing.T) {
  3184  
  3185  				th.App.UpdateConfig(func(cfg *model.Config) {
  3186  					*cfg.ServiceSettings.SiteURL = tc.SiteURL
  3187  				})
  3188  
  3189  				pass, resp := th.Client.AttachDeviceId(deviceId)
  3190  				CheckNoError(t, resp)
  3191  
  3192  				cookies := resp.Header.Get("Set-Cookie")
  3193  				assert.Regexp(t, tc.ExpectedSetCookieHeaderRegexp, cookies)
  3194  				assert.True(t, pass)
  3195  
  3196  				sessions, err := th.App.GetSessions(th.BasicUser.Id)
  3197  				require.Nil(t, err)
  3198  				assert.Equal(t, deviceId, sessions[0].DeviceId, "Missing device Id")
  3199  			})
  3200  		}
  3201  	})
  3202  
  3203  	t.Run("invalid device id", func(t *testing.T) {
  3204  		_, resp := th.Client.AttachDeviceId("")
  3205  		CheckBadRequestStatus(t, resp)
  3206  	})
  3207  
  3208  	t.Run("not logged in", func(t *testing.T) {
  3209  		th.Client.Logout()
  3210  
  3211  		_, resp := th.Client.AttachDeviceId("")
  3212  		CheckUnauthorizedStatus(t, resp)
  3213  	})
  3214  }
  3215  
  3216  func TestGetUserAudits(t *testing.T) {
  3217  	th := Setup(t).InitBasic()
  3218  	defer th.TearDown()
  3219  	user := th.BasicUser
  3220  
  3221  	audits, resp := th.Client.GetUserAudits(user.Id, 0, 100, "")
  3222  	for _, audit := range audits {
  3223  		require.Equal(t, user.Id, audit.UserId, "user id should match audit user id")
  3224  	}
  3225  	CheckNoError(t, resp)
  3226  
  3227  	_, resp = th.Client.GetUserAudits(th.BasicUser2.Id, 0, 100, "")
  3228  	CheckForbiddenStatus(t, resp)
  3229  
  3230  	th.Client.Logout()
  3231  	_, resp = th.Client.GetUserAudits(user.Id, 0, 100, "")
  3232  	CheckUnauthorizedStatus(t, resp)
  3233  
  3234  	_, resp = th.SystemAdminClient.GetUserAudits(user.Id, 0, 100, "")
  3235  	CheckNoError(t, resp)
  3236  }
  3237  
  3238  func TestVerifyUserEmail(t *testing.T) {
  3239  	th := Setup(t)
  3240  	defer th.TearDown()
  3241  
  3242  	email := th.GenerateTestEmail()
  3243  	user := model.User{Email: email, Nickname: "Darth Vader", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_ADMIN_ROLE_ID + " " + model.SYSTEM_USER_ROLE_ID}
  3244  
  3245  	ruser, _ := th.Client.CreateUser(&user)
  3246  
  3247  	token, err := th.App.Srv().EmailService.CreateVerifyEmailToken(ruser.Id, email)
  3248  	require.Nil(t, err, "Unable to create email verify token")
  3249  
  3250  	_, resp := th.Client.VerifyUserEmail(token.Token)
  3251  	CheckNoError(t, resp)
  3252  
  3253  	_, resp = th.Client.VerifyUserEmail(GenerateTestId())
  3254  	CheckBadRequestStatus(t, resp)
  3255  
  3256  	_, resp = th.Client.VerifyUserEmail("")
  3257  	CheckBadRequestStatus(t, resp)
  3258  }
  3259  
  3260  func TestSendVerificationEmail(t *testing.T) {
  3261  	th := Setup(t).InitBasic()
  3262  	defer th.TearDown()
  3263  
  3264  	pass, resp := th.Client.SendVerificationEmail(th.BasicUser.Email)
  3265  	CheckNoError(t, resp)
  3266  
  3267  	require.True(t, pass, "should have passed")
  3268  
  3269  	_, resp = th.Client.SendVerificationEmail("")
  3270  	CheckBadRequestStatus(t, resp)
  3271  
  3272  	// Even non-existent emails should return 200 OK
  3273  	_, resp = th.Client.SendVerificationEmail(th.GenerateTestEmail())
  3274  	CheckNoError(t, resp)
  3275  
  3276  	th.Client.Logout()
  3277  	_, resp = th.Client.SendVerificationEmail(th.BasicUser.Email)
  3278  	CheckNoError(t, resp)
  3279  }
  3280  
  3281  func TestSetProfileImage(t *testing.T) {
  3282  	th := Setup(t).InitBasic()
  3283  	defer th.TearDown()
  3284  	user := th.BasicUser
  3285  
  3286  	data, err := testutils.ReadTestFile("test.png")
  3287  	require.NoError(t, err)
  3288  
  3289  	ok, resp := th.Client.SetProfileImage(user.Id, data)
  3290  	require.Truef(t, ok, "%v", resp.Error)
  3291  	CheckNoError(t, resp)
  3292  
  3293  	ok, resp = th.Client.SetProfileImage(model.NewId(), data)
  3294  	require.False(t, ok, "Should return false, set profile image not allowed")
  3295  	CheckForbiddenStatus(t, resp)
  3296  
  3297  	// status code returns either forbidden or unauthorized
  3298  	// note: forbidden is set as default at Client4.SetProfileImage when request is terminated early by server
  3299  	th.Client.Logout()
  3300  	_, resp = th.Client.SetProfileImage(user.Id, data)
  3301  	if resp.StatusCode == http.StatusForbidden {
  3302  		CheckForbiddenStatus(t, resp)
  3303  	} else if resp.StatusCode == http.StatusUnauthorized {
  3304  		CheckUnauthorizedStatus(t, resp)
  3305  	} else {
  3306  		require.Fail(t, "Should have failed either forbidden or unauthorized")
  3307  	}
  3308  
  3309  	buser, appErr := th.App.GetUser(user.Id)
  3310  	require.Nil(t, appErr)
  3311  
  3312  	_, resp = th.SystemAdminClient.SetProfileImage(user.Id, data)
  3313  	CheckNoError(t, resp)
  3314  
  3315  	ruser, appErr := th.App.GetUser(user.Id)
  3316  	require.Nil(t, appErr)
  3317  	assert.True(t, buser.LastPictureUpdate < ruser.LastPictureUpdate, "Picture should have updated for user")
  3318  
  3319  	info := &model.FileInfo{Path: "users/" + user.Id + "/profile.png"}
  3320  	err = th.cleanupTestFile(info)
  3321  	require.NoError(t, err)
  3322  }
  3323  
  3324  func TestSetDefaultProfileImage(t *testing.T) {
  3325  	th := Setup(t).InitBasic()
  3326  	defer th.TearDown()
  3327  	user := th.BasicUser
  3328  
  3329  	ok, resp := th.Client.SetDefaultProfileImage(user.Id)
  3330  	require.True(t, ok)
  3331  	CheckNoError(t, resp)
  3332  
  3333  	ok, resp = th.Client.SetDefaultProfileImage(model.NewId())
  3334  	require.False(t, ok, "Should return false, set profile image not allowed")
  3335  	CheckForbiddenStatus(t, resp)
  3336  
  3337  	// status code returns either forbidden or unauthorized
  3338  	// note: forbidden is set as default at Client4.SetDefaultProfileImage when request is terminated early by server
  3339  	th.Client.Logout()
  3340  	_, resp = th.Client.SetDefaultProfileImage(user.Id)
  3341  	if resp.StatusCode == http.StatusForbidden {
  3342  		CheckForbiddenStatus(t, resp)
  3343  	} else if resp.StatusCode == http.StatusUnauthorized {
  3344  		CheckUnauthorizedStatus(t, resp)
  3345  	} else {
  3346  		require.Fail(t, "Should have failed either forbidden or unauthorized")
  3347  	}
  3348  
  3349  	_, resp = th.SystemAdminClient.SetDefaultProfileImage(user.Id)
  3350  	CheckNoError(t, resp)
  3351  
  3352  	ruser, err := th.App.GetUser(user.Id)
  3353  	require.Nil(t, err)
  3354  	assert.Equal(t, int64(0), ruser.LastPictureUpdate, "Picture should have resetted to default")
  3355  
  3356  	info := &model.FileInfo{Path: "users/" + user.Id + "/profile.png"}
  3357  	cleanupErr := th.cleanupTestFile(info)
  3358  	require.NoError(t, cleanupErr)
  3359  }
  3360  
  3361  func TestLogin(t *testing.T) {
  3362  	th := Setup(t).InitBasic()
  3363  	defer th.TearDown()
  3364  	th.Client.Logout()
  3365  
  3366  	th.App.UpdateConfig(func(cfg *model.Config) {
  3367  		*cfg.ServiceSettings.EnableBotAccountCreation = true
  3368  	})
  3369  
  3370  	t.Run("missing password", func(t *testing.T) {
  3371  		_, resp := th.Client.Login(th.BasicUser.Email, "")
  3372  		CheckErrorMessage(t, resp, "api.user.login.blank_pwd.app_error")
  3373  	})
  3374  
  3375  	t.Run("unknown user", func(t *testing.T) {
  3376  		_, resp := th.Client.Login("unknown", th.BasicUser.Password)
  3377  		CheckErrorMessage(t, resp, "api.user.login.invalid_credentials_email_username")
  3378  	})
  3379  
  3380  	t.Run("valid login", func(t *testing.T) {
  3381  		user, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3382  		CheckNoError(t, resp)
  3383  		assert.Equal(t, user.Id, th.BasicUser.Id)
  3384  	})
  3385  
  3386  	t.Run("bot login rejected", func(t *testing.T) {
  3387  		bot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  3388  			Username: "bot",
  3389  		})
  3390  		CheckNoError(t, resp)
  3391  
  3392  		botUser, resp := th.SystemAdminClient.GetUser(bot.UserId, "")
  3393  		CheckNoError(t, resp)
  3394  
  3395  		changed, resp := th.SystemAdminClient.UpdateUserPassword(bot.UserId, "", "password")
  3396  		CheckNoError(t, resp)
  3397  		require.True(t, changed)
  3398  
  3399  		_, resp = th.Client.Login(botUser.Email, "password")
  3400  		CheckErrorMessage(t, resp, "api.user.login.bot_login_forbidden.app_error")
  3401  	})
  3402  
  3403  	t.Run("login with terms_of_service set", func(t *testing.T) {
  3404  		termsOfService, err := th.App.CreateTermsOfService("terms of service", th.BasicUser.Id)
  3405  		require.Nil(t, err)
  3406  
  3407  		success, resp := th.Client.RegisterTermsOfServiceAction(th.BasicUser.Id, termsOfService.Id, true)
  3408  		CheckNoError(t, resp)
  3409  		assert.True(t, *success)
  3410  
  3411  		userTermsOfService, resp := th.Client.GetUserTermsOfService(th.BasicUser.Id, "")
  3412  		CheckNoError(t, resp)
  3413  
  3414  		user, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3415  		CheckNoError(t, resp)
  3416  		assert.Equal(t, user.Id, th.BasicUser.Id)
  3417  		assert.Equal(t, user.TermsOfServiceId, userTermsOfService.TermsOfServiceId)
  3418  		assert.Equal(t, user.TermsOfServiceCreateAt, userTermsOfService.CreateAt)
  3419  	})
  3420  }
  3421  
  3422  func TestLoginWithLag(t *testing.T) {
  3423  	th := Setup(t).InitBasic()
  3424  	defer th.TearDown()
  3425  	th.Client.Logout()
  3426  
  3427  	t.Run("with replication lag, caches cleared", func(t *testing.T) {
  3428  		if !replicaFlag {
  3429  			t.Skipf("requires test flag: -mysql-replica")
  3430  		}
  3431  
  3432  		if *th.App.Srv().Config().SqlSettings.DriverName != model.DATABASE_DRIVER_MYSQL {
  3433  			t.Skipf("requires %q database driver", model.DATABASE_DRIVER_MYSQL)
  3434  		}
  3435  
  3436  		mainHelper.SQLStore.UpdateLicense(model.NewTestLicense("ldap"))
  3437  		mainHelper.ToggleReplicasOff()
  3438  
  3439  		err := th.App.RevokeAllSessions(th.BasicUser.Id)
  3440  		require.Nil(t, err)
  3441  
  3442  		mainHelper.ToggleReplicasOn()
  3443  		defer mainHelper.ToggleReplicasOff()
  3444  
  3445  		cmdErr := mainHelper.SetReplicationLagForTesting(5)
  3446  		require.NoError(t, cmdErr)
  3447  		defer mainHelper.SetReplicationLagForTesting(0)
  3448  
  3449  		_, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3450  		CheckNoError(t, resp)
  3451  
  3452  		err = th.App.Srv().InvalidateAllCaches()
  3453  		require.Nil(t, err)
  3454  
  3455  		session, err := th.App.GetSession(th.Client.AuthToken)
  3456  		require.Nil(t, err)
  3457  		require.NotNil(t, session)
  3458  	})
  3459  }
  3460  
  3461  func TestLoginCookies(t *testing.T) {
  3462  	t.Run("should return cookies with X-Requested-With header", func(t *testing.T) {
  3463  		th := Setup(t).InitBasic()
  3464  		defer th.TearDown()
  3465  
  3466  		th.Client.HttpHeader[model.HEADER_REQUESTED_WITH] = model.HEADER_REQUESTED_WITH_XML
  3467  
  3468  		user, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3469  
  3470  		sessionCookie := ""
  3471  		userCookie := ""
  3472  		csrfCookie := ""
  3473  
  3474  		for _, cookie := range resp.Header["Set-Cookie"] {
  3475  			if match := regexp.MustCompile("^" + model.SESSION_COOKIE_TOKEN + "=([a-z0-9]+)").FindStringSubmatch(cookie); match != nil {
  3476  				sessionCookie = match[1]
  3477  			} else if match := regexp.MustCompile("^" + model.SESSION_COOKIE_USER + "=([a-z0-9]+)").FindStringSubmatch(cookie); match != nil {
  3478  				userCookie = match[1]
  3479  			} else if match := regexp.MustCompile("^" + model.SESSION_COOKIE_CSRF + "=([a-z0-9]+)").FindStringSubmatch(cookie); match != nil {
  3480  				csrfCookie = match[1]
  3481  			}
  3482  		}
  3483  
  3484  		session, _ := th.App.GetSession(th.Client.AuthToken)
  3485  
  3486  		assert.Equal(t, th.Client.AuthToken, sessionCookie)
  3487  		assert.Equal(t, user.Id, userCookie)
  3488  		assert.Equal(t, session.GetCSRF(), csrfCookie)
  3489  	})
  3490  
  3491  	t.Run("should not return cookies without X-Requested-With header", func(t *testing.T) {
  3492  		th := Setup(t).InitBasic()
  3493  		defer th.TearDown()
  3494  
  3495  		_, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3496  
  3497  		assert.Empty(t, resp.Header.Get("Set-Cookie"))
  3498  	})
  3499  
  3500  	t.Run("should include subpath in path", func(t *testing.T) {
  3501  		th := Setup(t).InitBasic()
  3502  		defer th.TearDown()
  3503  
  3504  		th.Client.HttpHeader[model.HEADER_REQUESTED_WITH] = model.HEADER_REQUESTED_WITH_XML
  3505  
  3506  		testCases := []struct {
  3507  			Description                   string
  3508  			SiteURL                       string
  3509  			ExpectedSetCookieHeaderRegexp string
  3510  		}{
  3511  			{"no subpath", "http://localhost:8065", "^MMAUTHTOKEN=[a-z0-9]+; Path=/"},
  3512  			{"subpath", "http://localhost:8065/subpath", "^MMAUTHTOKEN=[a-z0-9]+; Path=/subpath"},
  3513  		}
  3514  
  3515  		for _, tc := range testCases {
  3516  			t.Run(tc.Description, func(t *testing.T) {
  3517  				th.App.UpdateConfig(func(cfg *model.Config) {
  3518  					*cfg.ServiceSettings.SiteURL = tc.SiteURL
  3519  				})
  3520  
  3521  				user, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3522  				CheckNoError(t, resp)
  3523  				assert.Equal(t, user.Id, th.BasicUser.Id)
  3524  
  3525  				cookies := resp.Header.Get("Set-Cookie")
  3526  				assert.Regexp(t, tc.ExpectedSetCookieHeaderRegexp, cookies)
  3527  			})
  3528  		}
  3529  	})
  3530  }
  3531  
  3532  func TestCBALogin(t *testing.T) {
  3533  	t.Run("primary", func(t *testing.T) {
  3534  		th := Setup(t).InitBasic()
  3535  		defer th.TearDown()
  3536  		th.App.Srv().SetLicense(model.NewTestLicense("saml"))
  3537  
  3538  		th.App.UpdateConfig(func(cfg *model.Config) {
  3539  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  3540  		})
  3541  
  3542  		th.App.UpdateConfig(func(cfg *model.Config) {
  3543  			*cfg.ExperimentalSettings.ClientSideCertEnable = true
  3544  			*cfg.ExperimentalSettings.ClientSideCertCheck = model.CLIENT_SIDE_CERT_CHECK_PRIMARY_AUTH
  3545  		})
  3546  
  3547  		t.Run("missing cert header", func(t *testing.T) {
  3548  			th.Client.Logout()
  3549  			_, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3550  			CheckBadRequestStatus(t, resp)
  3551  		})
  3552  
  3553  		t.Run("missing cert subject", func(t *testing.T) {
  3554  			th.Client.Logout()
  3555  			th.Client.HttpHeader["X-SSL-Client-Cert"] = "valid_cert_fake"
  3556  			_, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3557  			CheckBadRequestStatus(t, resp)
  3558  		})
  3559  
  3560  		t.Run("emails mismatch", func(t *testing.T) {
  3561  			th.Client.Logout()
  3562  			th.Client.HttpHeader["X-SSL-Client-Cert-Subject-DN"] = "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=mis_match" + th.BasicUser.Email
  3563  			_, resp := th.Client.Login(th.BasicUser.Email, "")
  3564  			CheckUnauthorizedStatus(t, resp)
  3565  		})
  3566  
  3567  		t.Run("successful cba login", func(t *testing.T) {
  3568  			th.Client.HttpHeader["X-SSL-Client-Cert-Subject-DN"] = "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=" + th.BasicUser.Email
  3569  			user, resp := th.Client.Login(th.BasicUser.Email, "")
  3570  			CheckNoError(t, resp)
  3571  			require.NotNil(t, user)
  3572  			require.Equal(t, th.BasicUser.Id, user.Id)
  3573  		})
  3574  
  3575  		t.Run("bot login rejected", func(t *testing.T) {
  3576  			bot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  3577  				Username: "bot",
  3578  			})
  3579  			CheckNoError(t, resp)
  3580  
  3581  			botUser, resp := th.SystemAdminClient.GetUser(bot.UserId, "")
  3582  			CheckNoError(t, resp)
  3583  
  3584  			th.Client.HttpHeader["X-SSL-Client-Cert-Subject-DN"] = "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=" + botUser.Email
  3585  
  3586  			_, resp = th.Client.Login(botUser.Email, "")
  3587  			CheckErrorMessage(t, resp, "api.user.login.bot_login_forbidden.app_error")
  3588  		})
  3589  	})
  3590  
  3591  	t.Run("secondary", func(t *testing.T) {
  3592  		th := Setup(t).InitBasic()
  3593  		defer th.TearDown()
  3594  		th.App.Srv().SetLicense(model.NewTestLicense("saml"))
  3595  
  3596  		th.App.UpdateConfig(func(cfg *model.Config) {
  3597  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  3598  		})
  3599  
  3600  		th.Client.HttpHeader["X-SSL-Client-Cert"] = "valid_cert_fake"
  3601  
  3602  		th.App.UpdateConfig(func(cfg *model.Config) {
  3603  			*cfg.ExperimentalSettings.ClientSideCertEnable = true
  3604  			*cfg.ExperimentalSettings.ClientSideCertCheck = model.CLIENT_SIDE_CERT_CHECK_SECONDARY_AUTH
  3605  		})
  3606  
  3607  		t.Run("password required", func(t *testing.T) {
  3608  			th.Client.HttpHeader["X-SSL-Client-Cert-Subject-DN"] = "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=" + th.BasicUser.Email
  3609  			_, resp := th.Client.Login(th.BasicUser.Email, "")
  3610  			CheckBadRequestStatus(t, resp)
  3611  		})
  3612  
  3613  		t.Run("successful cba login with password", func(t *testing.T) {
  3614  			th.Client.HttpHeader["X-SSL-Client-Cert-Subject-DN"] = "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=" + th.BasicUser.Email
  3615  			user, resp := th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3616  			CheckNoError(t, resp)
  3617  			require.NotNil(t, user)
  3618  			require.Equal(t, th.BasicUser.Id, user.Id)
  3619  		})
  3620  
  3621  		t.Run("bot login rejected", func(t *testing.T) {
  3622  			bot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  3623  				Username: "bot",
  3624  			})
  3625  			CheckNoError(t, resp)
  3626  
  3627  			botUser, resp := th.SystemAdminClient.GetUser(bot.UserId, "")
  3628  			CheckNoError(t, resp)
  3629  
  3630  			changed, resp := th.SystemAdminClient.UpdateUserPassword(bot.UserId, "", "password")
  3631  			CheckNoError(t, resp)
  3632  			require.True(t, changed)
  3633  
  3634  			th.Client.HttpHeader["X-SSL-Client-Cert-Subject-DN"] = "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, CN=www.freesoft.org/emailAddress=" + botUser.Email
  3635  
  3636  			_, resp = th.Client.Login(botUser.Email, "password")
  3637  			CheckErrorMessage(t, resp, "api.user.login.bot_login_forbidden.app_error")
  3638  		})
  3639  	})
  3640  }
  3641  
  3642  func TestSwitchAccount(t *testing.T) {
  3643  	th := Setup(t).InitBasic()
  3644  	defer th.TearDown()
  3645  
  3646  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GitLabSettings.Enable = true })
  3647  
  3648  	th.Client.Logout()
  3649  
  3650  	sr := &model.SwitchRequest{
  3651  		CurrentService: model.USER_AUTH_SERVICE_EMAIL,
  3652  		NewService:     model.USER_AUTH_SERVICE_GITLAB,
  3653  		Email:          th.BasicUser.Email,
  3654  		Password:       th.BasicUser.Password,
  3655  	}
  3656  
  3657  	link, resp := th.Client.SwitchAccountType(sr)
  3658  	CheckNoError(t, resp)
  3659  
  3660  	require.NotEmpty(t, link, "bad link")
  3661  
  3662  	th.App.Srv().SetLicense(model.NewTestLicense())
  3663  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ExperimentalEnableAuthenticationTransfer = false })
  3664  
  3665  	sr = &model.SwitchRequest{
  3666  		CurrentService: model.USER_AUTH_SERVICE_EMAIL,
  3667  		NewService:     model.USER_AUTH_SERVICE_GITLAB,
  3668  	}
  3669  
  3670  	_, resp = th.Client.SwitchAccountType(sr)
  3671  	CheckForbiddenStatus(t, resp)
  3672  
  3673  	th.LoginBasic()
  3674  
  3675  	sr = &model.SwitchRequest{
  3676  		CurrentService: model.USER_AUTH_SERVICE_SAML,
  3677  		NewService:     model.USER_AUTH_SERVICE_EMAIL,
  3678  		Email:          th.BasicUser.Email,
  3679  		NewPassword:    th.BasicUser.Password,
  3680  	}
  3681  
  3682  	_, resp = th.Client.SwitchAccountType(sr)
  3683  	CheckForbiddenStatus(t, resp)
  3684  
  3685  	sr = &model.SwitchRequest{
  3686  		CurrentService: model.USER_AUTH_SERVICE_EMAIL,
  3687  		NewService:     model.USER_AUTH_SERVICE_LDAP,
  3688  	}
  3689  
  3690  	_, resp = th.Client.SwitchAccountType(sr)
  3691  	CheckForbiddenStatus(t, resp)
  3692  
  3693  	sr = &model.SwitchRequest{
  3694  		CurrentService: model.USER_AUTH_SERVICE_LDAP,
  3695  		NewService:     model.USER_AUTH_SERVICE_EMAIL,
  3696  	}
  3697  
  3698  	_, resp = th.Client.SwitchAccountType(sr)
  3699  	CheckForbiddenStatus(t, resp)
  3700  
  3701  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.ExperimentalEnableAuthenticationTransfer = true })
  3702  
  3703  	th.LoginBasic()
  3704  
  3705  	fakeAuthData := model.NewId()
  3706  	_, err := th.App.Srv().Store.User().UpdateAuthData(th.BasicUser.Id, model.USER_AUTH_SERVICE_GITLAB, &fakeAuthData, th.BasicUser.Email, true)
  3707  	require.NoError(t, err)
  3708  
  3709  	sr = &model.SwitchRequest{
  3710  		CurrentService: model.USER_AUTH_SERVICE_GITLAB,
  3711  		NewService:     model.USER_AUTH_SERVICE_EMAIL,
  3712  		Email:          th.BasicUser.Email,
  3713  		NewPassword:    th.BasicUser.Password,
  3714  	}
  3715  
  3716  	link, resp = th.Client.SwitchAccountType(sr)
  3717  	CheckNoError(t, resp)
  3718  
  3719  	require.Equal(t, "/login?extra=signin_change", link)
  3720  
  3721  	th.Client.Logout()
  3722  	_, resp = th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  3723  	CheckNoError(t, resp)
  3724  	th.Client.Logout()
  3725  
  3726  	sr = &model.SwitchRequest{
  3727  		CurrentService: model.USER_AUTH_SERVICE_GITLAB,
  3728  		NewService:     model.SERVICE_GOOGLE,
  3729  	}
  3730  
  3731  	_, resp = th.Client.SwitchAccountType(sr)
  3732  	CheckBadRequestStatus(t, resp)
  3733  
  3734  	sr = &model.SwitchRequest{
  3735  		CurrentService: model.USER_AUTH_SERVICE_EMAIL,
  3736  		NewService:     model.USER_AUTH_SERVICE_GITLAB,
  3737  		Password:       th.BasicUser.Password,
  3738  	}
  3739  
  3740  	_, resp = th.Client.SwitchAccountType(sr)
  3741  	CheckNotFoundStatus(t, resp)
  3742  
  3743  	sr = &model.SwitchRequest{
  3744  		CurrentService: model.USER_AUTH_SERVICE_EMAIL,
  3745  		NewService:     model.USER_AUTH_SERVICE_GITLAB,
  3746  		Email:          th.BasicUser.Email,
  3747  	}
  3748  
  3749  	_, resp = th.Client.SwitchAccountType(sr)
  3750  	CheckUnauthorizedStatus(t, resp)
  3751  
  3752  	sr = &model.SwitchRequest{
  3753  		CurrentService: model.USER_AUTH_SERVICE_GITLAB,
  3754  		NewService:     model.USER_AUTH_SERVICE_EMAIL,
  3755  		Email:          th.BasicUser.Email,
  3756  		NewPassword:    th.BasicUser.Password,
  3757  	}
  3758  
  3759  	_, resp = th.Client.SwitchAccountType(sr)
  3760  	CheckUnauthorizedStatus(t, resp)
  3761  }
  3762  
  3763  func assertToken(t *testing.T, th *TestHelper, token *model.UserAccessToken, expectedUserId string) {
  3764  	t.Helper()
  3765  
  3766  	oldSessionToken := th.Client.AuthToken
  3767  	defer func() { th.Client.AuthToken = oldSessionToken }()
  3768  
  3769  	th.Client.AuthToken = token.Token
  3770  	ruser, resp := th.Client.GetMe("")
  3771  	CheckNoError(t, resp)
  3772  
  3773  	assert.Equal(t, expectedUserId, ruser.Id, "returned wrong user")
  3774  }
  3775  
  3776  func assertInvalidToken(t *testing.T, th *TestHelper, token *model.UserAccessToken) {
  3777  	t.Helper()
  3778  
  3779  	oldSessionToken := th.Client.AuthToken
  3780  	defer func() { th.Client.AuthToken = oldSessionToken }()
  3781  
  3782  	th.Client.AuthToken = token.Token
  3783  	_, resp := th.Client.GetMe("")
  3784  	CheckUnauthorizedStatus(t, resp)
  3785  }
  3786  
  3787  func TestCreateUserAccessToken(t *testing.T) {
  3788  	t.Run("create token without permission", func(t *testing.T) {
  3789  		th := Setup(t).InitBasic()
  3790  		defer th.TearDown()
  3791  
  3792  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3793  
  3794  		_, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  3795  		CheckForbiddenStatus(t, resp)
  3796  	})
  3797  
  3798  	t.Run("system admin and local mode can create access token", func(t *testing.T) {
  3799  		th := Setup(t).InitBasic()
  3800  		defer th.TearDown()
  3801  
  3802  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3803  
  3804  		th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  3805  			rtoken, resp := client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  3806  			CheckNoError(t, resp)
  3807  
  3808  			assert.Equal(t, th.BasicUser.Id, rtoken.UserId, "wrong user id")
  3809  			assert.NotEmpty(t, rtoken.Token, "token should not be empty")
  3810  			assert.NotEmpty(t, rtoken.Id, "id should not be empty")
  3811  			assert.Equal(t, "test token", rtoken.Description, "description did not match")
  3812  			assert.True(t, rtoken.IsActive, "token should be active")
  3813  			assertToken(t, th, rtoken, th.BasicUser.Id)
  3814  		})
  3815  	})
  3816  
  3817  	t.Run("create token for invalid user id", func(t *testing.T) {
  3818  		th := Setup(t).InitBasic()
  3819  		defer th.TearDown()
  3820  
  3821  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3822  
  3823  		th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  3824  			_, resp := client.CreateUserAccessToken("notarealuserid", "test token")
  3825  			CheckBadRequestStatus(t, resp)
  3826  		})
  3827  	})
  3828  
  3829  	t.Run("create token with invalid value", func(t *testing.T) {
  3830  		th := Setup(t).InitBasic()
  3831  		defer th.TearDown()
  3832  
  3833  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3834  
  3835  		th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  3836  			_, resp := client.CreateUserAccessToken(th.BasicUser.Id, "")
  3837  			CheckBadRequestStatus(t, resp)
  3838  		})
  3839  	})
  3840  
  3841  	t.Run("create token with user access tokens disabled", func(t *testing.T) {
  3842  		th := Setup(t).InitBasic()
  3843  		defer th.TearDown()
  3844  
  3845  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = false })
  3846  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  3847  
  3848  		th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  3849  			_, resp := client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  3850  			CheckNotImplementedStatus(t, resp)
  3851  		})
  3852  	})
  3853  
  3854  	t.Run("create user access token", func(t *testing.T) {
  3855  		th := Setup(t).InitBasic()
  3856  		defer th.TearDown()
  3857  
  3858  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3859  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  3860  
  3861  		rtoken, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  3862  		CheckNoError(t, resp)
  3863  
  3864  		assert.Equal(t, th.BasicUser.Id, rtoken.UserId, "wrong user id")
  3865  		assert.NotEmpty(t, rtoken.Token, "token should not be empty")
  3866  		assert.NotEmpty(t, rtoken.Id, "id should not be empty")
  3867  		assert.Equal(t, "test token", rtoken.Description, "description did not match")
  3868  		assert.True(t, rtoken.IsActive, "token should be active")
  3869  
  3870  		assertToken(t, th, rtoken, th.BasicUser.Id)
  3871  	})
  3872  
  3873  	t.Run("create user access token as second user, without permission", func(t *testing.T) {
  3874  		th := Setup(t).InitBasic()
  3875  		defer th.TearDown()
  3876  
  3877  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3878  
  3879  		_, resp := th.Client.CreateUserAccessToken(th.BasicUser2.Id, "test token")
  3880  		CheckForbiddenStatus(t, resp)
  3881  	})
  3882  
  3883  	t.Run("create user access token for basic user as as system admin", func(t *testing.T) {
  3884  		th := Setup(t).InitBasic()
  3885  		defer th.TearDown()
  3886  
  3887  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3888  
  3889  		rtoken, resp := th.SystemAdminClient.CreateUserAccessToken(th.BasicUser.Id, "test token")
  3890  		CheckNoError(t, resp)
  3891  		assert.Equal(t, th.BasicUser.Id, rtoken.UserId)
  3892  
  3893  		oldSessionToken := th.Client.AuthToken
  3894  		defer func() { th.Client.AuthToken = oldSessionToken }()
  3895  
  3896  		assertToken(t, th, rtoken, th.BasicUser.Id)
  3897  	})
  3898  
  3899  	t.Run("create access token as oauth session", func(t *testing.T) {
  3900  		th := Setup(t).InitBasic()
  3901  		defer th.TearDown()
  3902  
  3903  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3904  
  3905  		session, _ := th.App.GetSession(th.Client.AuthToken)
  3906  		session.IsOAuth = true
  3907  		th.App.AddSessionToCache(session)
  3908  
  3909  		_, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  3910  		CheckForbiddenStatus(t, resp)
  3911  	})
  3912  
  3913  	t.Run("create access token for bot created by user", func(t *testing.T) {
  3914  		th := Setup(t).InitBasic()
  3915  		defer th.TearDown()
  3916  
  3917  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3918  
  3919  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  3920  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  3921  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  3922  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  3923  		th.App.UpdateConfig(func(cfg *model.Config) {
  3924  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  3925  		})
  3926  
  3927  		createdBot, resp := th.Client.CreateBot(&model.Bot{
  3928  			Username:    GenerateTestUsername(),
  3929  			DisplayName: "a bot",
  3930  			Description: "bot",
  3931  		})
  3932  		CheckCreatedStatus(t, resp)
  3933  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  3934  
  3935  		t.Run("without MANAGE_BOT permission", func(t *testing.T) {
  3936  			th.RemovePermissionFromRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  3937  
  3938  			_, resp = th.Client.CreateUserAccessToken(createdBot.UserId, "test token")
  3939  			CheckForbiddenStatus(t, resp)
  3940  		})
  3941  
  3942  		t.Run("with MANAGE_BOTS permission", func(t *testing.T) {
  3943  			th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  3944  
  3945  			token, resp := th.Client.CreateUserAccessToken(createdBot.UserId, "test token")
  3946  			CheckNoError(t, resp)
  3947  			assert.Equal(t, createdBot.UserId, token.UserId)
  3948  			assertToken(t, th, token, createdBot.UserId)
  3949  		})
  3950  	})
  3951  
  3952  	t.Run("create access token for bot created by another user, only having MANAGE_BOTS permission", func(t *testing.T) {
  3953  		th := Setup(t).InitBasic()
  3954  		defer th.TearDown()
  3955  
  3956  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3957  
  3958  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  3959  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  3960  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  3961  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  3962  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  3963  		th.App.UpdateConfig(func(cfg *model.Config) {
  3964  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  3965  		})
  3966  
  3967  		createdBot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  3968  			Username:    GenerateTestUsername(),
  3969  			DisplayName: "a bot",
  3970  			Description: "bot",
  3971  		})
  3972  		CheckCreatedStatus(t, resp)
  3973  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  3974  
  3975  		t.Run("only having MANAGE_BOTS permission", func(t *testing.T) {
  3976  			_, resp = th.Client.CreateUserAccessToken(createdBot.UserId, "test token")
  3977  			CheckForbiddenStatus(t, resp)
  3978  		})
  3979  
  3980  		t.Run("with MANAGE_OTHERS_BOTS permission", func(t *testing.T) {
  3981  			th.AddPermissionToRole(model.PERMISSION_MANAGE_OTHERS_BOTS.Id, model.TEAM_USER_ROLE_ID)
  3982  
  3983  			rtoken, resp := th.Client.CreateUserAccessToken(createdBot.UserId, "test token")
  3984  			CheckNoError(t, resp)
  3985  			assert.Equal(t, createdBot.UserId, rtoken.UserId)
  3986  
  3987  			assertToken(t, th, rtoken, createdBot.UserId)
  3988  		})
  3989  	})
  3990  }
  3991  
  3992  func TestGetUserAccessToken(t *testing.T) {
  3993  	t.Run("get for invalid user id", func(t *testing.T) {
  3994  		th := Setup(t).InitBasic()
  3995  		defer th.TearDown()
  3996  
  3997  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  3998  
  3999  		_, resp := th.Client.GetUserAccessToken("123")
  4000  		CheckBadRequestStatus(t, resp)
  4001  	})
  4002  
  4003  	t.Run("get for unknown user id", func(t *testing.T) {
  4004  		th := Setup(t).InitBasic()
  4005  		defer th.TearDown()
  4006  
  4007  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4008  
  4009  		_, resp := th.Client.GetUserAccessToken(model.NewId())
  4010  		CheckForbiddenStatus(t, resp)
  4011  	})
  4012  
  4013  	t.Run("get my token", func(t *testing.T) {
  4014  		th := Setup(t).InitBasic()
  4015  		defer th.TearDown()
  4016  
  4017  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4018  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4019  
  4020  		token, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  4021  		CheckNoError(t, resp)
  4022  
  4023  		rtoken, resp := th.Client.GetUserAccessToken(token.Id)
  4024  		CheckNoError(t, resp)
  4025  
  4026  		assert.Equal(t, th.BasicUser.Id, rtoken.UserId, "wrong user id")
  4027  		assert.Empty(t, rtoken.Token, "token should be blank")
  4028  		assert.NotEmpty(t, rtoken.Id, "id should not be empty")
  4029  		assert.Equal(t, "test token", rtoken.Description, "description did not match")
  4030  	})
  4031  
  4032  	t.Run("get user token as system admin", func(t *testing.T) {
  4033  		th := Setup(t).InitBasic()
  4034  		defer th.TearDown()
  4035  
  4036  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4037  
  4038  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4039  
  4040  		token, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  4041  		CheckNoError(t, resp)
  4042  
  4043  		rtoken, resp := th.SystemAdminClient.GetUserAccessToken(token.Id)
  4044  		CheckNoError(t, resp)
  4045  
  4046  		assert.Equal(t, th.BasicUser.Id, rtoken.UserId, "wrong user id")
  4047  		assert.Empty(t, rtoken.Token, "token should be blank")
  4048  		assert.NotEmpty(t, rtoken.Id, "id should not be empty")
  4049  		assert.Equal(t, "test token", rtoken.Description, "description did not match")
  4050  	})
  4051  
  4052  	t.Run("get token for bot created by user", func(t *testing.T) {
  4053  		th := Setup(t).InitBasic()
  4054  		defer th.TearDown()
  4055  
  4056  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4057  
  4058  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  4059  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  4060  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4061  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4062  		th.AddPermissionToRole(model.PERMISSION_READ_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4063  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  4064  		th.App.UpdateConfig(func(cfg *model.Config) {
  4065  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  4066  		})
  4067  
  4068  		createdBot, resp := th.Client.CreateBot(&model.Bot{
  4069  			Username:    GenerateTestUsername(),
  4070  			DisplayName: "a bot",
  4071  			Description: "bot",
  4072  		})
  4073  		CheckCreatedStatus(t, resp)
  4074  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  4075  
  4076  		token, resp := th.Client.CreateUserAccessToken(createdBot.UserId, "test token")
  4077  		CheckNoError(t, resp)
  4078  
  4079  		t.Run("without MANAGE_BOTS permission", func(t *testing.T) {
  4080  			th.RemovePermissionFromRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4081  
  4082  			_, resp := th.Client.GetUserAccessToken(token.Id)
  4083  			CheckForbiddenStatus(t, resp)
  4084  		})
  4085  
  4086  		t.Run("with MANAGE_BOTS permission", func(t *testing.T) {
  4087  			th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4088  
  4089  			returnedToken, resp := th.Client.GetUserAccessToken(token.Id)
  4090  			CheckNoError(t, resp)
  4091  
  4092  			// Actual token won't be returned.
  4093  			returnedToken.Token = token.Token
  4094  			assert.Equal(t, token, returnedToken)
  4095  		})
  4096  	})
  4097  
  4098  	t.Run("get token for bot created by another user", func(t *testing.T) {
  4099  		th := Setup(t).InitBasic()
  4100  		defer th.TearDown()
  4101  
  4102  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4103  
  4104  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  4105  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  4106  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4107  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4108  		th.AddPermissionToRole(model.PERMISSION_READ_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4109  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  4110  		th.App.UpdateConfig(func(cfg *model.Config) {
  4111  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  4112  		})
  4113  
  4114  		createdBot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  4115  			Username:    GenerateTestUsername(),
  4116  			DisplayName: "a bot",
  4117  			Description: "bot",
  4118  		})
  4119  		CheckCreatedStatus(t, resp)
  4120  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  4121  
  4122  		token, resp := th.SystemAdminClient.CreateUserAccessToken(createdBot.UserId, "test token")
  4123  		CheckNoError(t, resp)
  4124  
  4125  		t.Run("only having MANAGE_BOTS permission", func(t *testing.T) {
  4126  			_, resp = th.Client.GetUserAccessToken(token.Id)
  4127  			CheckForbiddenStatus(t, resp)
  4128  		})
  4129  
  4130  		t.Run("with MANAGE_OTHERS_BOTS permission", func(t *testing.T) {
  4131  			th.AddPermissionToRole(model.PERMISSION_MANAGE_OTHERS_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4132  
  4133  			returnedToken, resp := th.Client.GetUserAccessToken(token.Id)
  4134  			CheckNoError(t, resp)
  4135  
  4136  			// Actual token won't be returned.
  4137  			returnedToken.Token = token.Token
  4138  			assert.Equal(t, token, returnedToken)
  4139  		})
  4140  	})
  4141  }
  4142  
  4143  func TestGetUserAccessTokensForUser(t *testing.T) {
  4144  	t.Run("multiple tokens, offset 0, limit 100", func(t *testing.T) {
  4145  		th := Setup(t).InitBasic()
  4146  		defer th.TearDown()
  4147  
  4148  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4149  
  4150  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4151  
  4152  		_, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  4153  		CheckNoError(t, resp)
  4154  
  4155  		_, resp = th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token 2")
  4156  		CheckNoError(t, resp)
  4157  
  4158  		th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  4159  			rtokens, resp := client.GetUserAccessTokensForUser(th.BasicUser.Id, 0, 100)
  4160  			CheckNoError(t, resp)
  4161  
  4162  			assert.Len(t, rtokens, 2, "should have 2 tokens")
  4163  			for _, uat := range rtokens {
  4164  				assert.Equal(t, th.BasicUser.Id, uat.UserId, "wrong user id")
  4165  			}
  4166  		})
  4167  	})
  4168  
  4169  	t.Run("multiple tokens, offset 1, limit 1", func(t *testing.T) {
  4170  		th := Setup(t).InitBasic()
  4171  		defer th.TearDown()
  4172  
  4173  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4174  
  4175  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4176  
  4177  		_, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  4178  		CheckNoError(t, resp)
  4179  
  4180  		_, resp = th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token 2")
  4181  		CheckNoError(t, resp)
  4182  
  4183  		th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  4184  			rtokens, resp := client.GetUserAccessTokensForUser(th.BasicUser.Id, 1, 1)
  4185  			CheckNoError(t, resp)
  4186  
  4187  			assert.Len(t, rtokens, 1, "should have 1 tokens")
  4188  			for _, uat := range rtokens {
  4189  				assert.Equal(t, th.BasicUser.Id, uat.UserId, "wrong user id")
  4190  			}
  4191  		})
  4192  	})
  4193  }
  4194  
  4195  func TestGetUserAccessTokens(t *testing.T) {
  4196  	t.Run("GetUserAccessTokens, not a system admin", func(t *testing.T) {
  4197  		th := Setup(t).InitBasic()
  4198  		defer th.TearDown()
  4199  
  4200  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4201  
  4202  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4203  
  4204  		_, resp := th.Client.GetUserAccessTokens(0, 100)
  4205  		CheckForbiddenStatus(t, resp)
  4206  	})
  4207  
  4208  	t.Run("GetUserAccessTokens, as a system admin, page 1, perPage 1", func(t *testing.T) {
  4209  		th := Setup(t).InitBasic()
  4210  		defer th.TearDown()
  4211  
  4212  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4213  
  4214  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4215  
  4216  		_, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token 2")
  4217  		CheckNoError(t, resp)
  4218  
  4219  		_, resp = th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token 2")
  4220  		CheckNoError(t, resp)
  4221  
  4222  		rtokens, resp := th.SystemAdminClient.GetUserAccessTokens(1, 1)
  4223  		CheckNoError(t, resp)
  4224  
  4225  		assert.Len(t, rtokens, 1, "should have 1 token")
  4226  	})
  4227  
  4228  	t.Run("GetUserAccessTokens, as a system admin, page 0, perPage 2", func(t *testing.T) {
  4229  		th := Setup(t).InitBasic()
  4230  		defer th.TearDown()
  4231  
  4232  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4233  
  4234  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4235  
  4236  		_, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token 2")
  4237  		CheckNoError(t, resp)
  4238  
  4239  		_, resp = th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token 2")
  4240  		CheckNoError(t, resp)
  4241  
  4242  		rtokens, resp := th.SystemAdminClient.GetUserAccessTokens(0, 2)
  4243  		CheckNoError(t, resp)
  4244  
  4245  		assert.Len(t, rtokens, 2, "should have 2 tokens")
  4246  	})
  4247  }
  4248  
  4249  func TestSearchUserAccessToken(t *testing.T) {
  4250  	th := Setup(t).InitBasic()
  4251  	defer th.TearDown()
  4252  
  4253  	testDescription := "test token"
  4254  
  4255  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4256  
  4257  	th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4258  	token, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, testDescription)
  4259  	CheckNoError(t, resp)
  4260  
  4261  	_, resp = th.Client.SearchUserAccessTokens(&model.UserAccessTokenSearch{Term: token.Id})
  4262  	CheckForbiddenStatus(t, resp)
  4263  
  4264  	rtokens, resp := th.SystemAdminClient.SearchUserAccessTokens(&model.UserAccessTokenSearch{Term: th.BasicUser.Id})
  4265  	CheckNoError(t, resp)
  4266  
  4267  	require.Len(t, rtokens, 1, "should have 1 token")
  4268  
  4269  	rtokens, resp = th.SystemAdminClient.SearchUserAccessTokens(&model.UserAccessTokenSearch{Term: token.Id})
  4270  	CheckNoError(t, resp)
  4271  
  4272  	require.Len(t, rtokens, 1, "should have 1 token")
  4273  
  4274  	rtokens, resp = th.SystemAdminClient.SearchUserAccessTokens(&model.UserAccessTokenSearch{Term: th.BasicUser.Username})
  4275  	CheckNoError(t, resp)
  4276  
  4277  	require.Len(t, rtokens, 1, "should have 1 token")
  4278  
  4279  	rtokens, resp = th.SystemAdminClient.SearchUserAccessTokens(&model.UserAccessTokenSearch{Term: "not found"})
  4280  	CheckNoError(t, resp)
  4281  
  4282  	require.Empty(t, rtokens, "should have 1 tokens")
  4283  }
  4284  
  4285  func TestRevokeUserAccessToken(t *testing.T) {
  4286  	t.Run("revoke user token", func(t *testing.T) {
  4287  		th := Setup(t).InitBasic()
  4288  		defer th.TearDown()
  4289  
  4290  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4291  
  4292  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4293  		th.TestForAllClients(t, func(t *testing.T, client *model.Client4) {
  4294  			token, resp := client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  4295  			CheckNoError(t, resp)
  4296  			assertToken(t, th, token, th.BasicUser.Id)
  4297  
  4298  			ok, resp := client.RevokeUserAccessToken(token.Id)
  4299  			CheckNoError(t, resp)
  4300  			assert.True(t, ok, "should have passed")
  4301  
  4302  			assertInvalidToken(t, th, token)
  4303  		})
  4304  	})
  4305  
  4306  	t.Run("revoke token belonging to another user", func(t *testing.T) {
  4307  		th := Setup(t).InitBasic()
  4308  		defer th.TearDown()
  4309  
  4310  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4311  
  4312  		token, resp := th.SystemAdminClient.CreateUserAccessToken(th.BasicUser2.Id, "test token")
  4313  		CheckNoError(t, resp)
  4314  
  4315  		ok, resp := th.Client.RevokeUserAccessToken(token.Id)
  4316  		CheckForbiddenStatus(t, resp)
  4317  		assert.False(t, ok, "should have failed")
  4318  	})
  4319  
  4320  	t.Run("revoke token for bot created by user", func(t *testing.T) {
  4321  		th := Setup(t).InitBasic()
  4322  		defer th.TearDown()
  4323  
  4324  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4325  
  4326  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  4327  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  4328  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4329  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4330  		th.AddPermissionToRole(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4331  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  4332  		th.App.UpdateConfig(func(cfg *model.Config) {
  4333  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  4334  		})
  4335  
  4336  		createdBot, resp := th.Client.CreateBot(&model.Bot{
  4337  			Username:    GenerateTestUsername(),
  4338  			DisplayName: "a bot",
  4339  			Description: "bot",
  4340  		})
  4341  		CheckCreatedStatus(t, resp)
  4342  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  4343  
  4344  		token, resp := th.Client.CreateUserAccessToken(createdBot.UserId, "test token")
  4345  		CheckNoError(t, resp)
  4346  
  4347  		t.Run("without MANAGE_BOTS permission", func(t *testing.T) {
  4348  			th.RemovePermissionFromRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4349  
  4350  			_, resp := th.Client.RevokeUserAccessToken(token.Id)
  4351  			CheckForbiddenStatus(t, resp)
  4352  		})
  4353  
  4354  		t.Run("with MANAGE_BOTS permission", func(t *testing.T) {
  4355  			th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4356  
  4357  			ok, resp := th.Client.RevokeUserAccessToken(token.Id)
  4358  			CheckNoError(t, resp)
  4359  			assert.True(t, ok, "should have passed")
  4360  		})
  4361  	})
  4362  
  4363  	t.Run("revoke token for bot created by another user", func(t *testing.T) {
  4364  		th := Setup(t).InitBasic()
  4365  		defer th.TearDown()
  4366  
  4367  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4368  
  4369  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  4370  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  4371  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4372  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4373  		th.AddPermissionToRole(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4374  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  4375  		th.App.UpdateConfig(func(cfg *model.Config) {
  4376  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  4377  		})
  4378  
  4379  		createdBot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  4380  			Username:    GenerateTestUsername(),
  4381  			DisplayName: "a bot",
  4382  			Description: "bot",
  4383  		})
  4384  		CheckCreatedStatus(t, resp)
  4385  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  4386  
  4387  		token, resp := th.SystemAdminClient.CreateUserAccessToken(createdBot.UserId, "test token")
  4388  		CheckNoError(t, resp)
  4389  
  4390  		t.Run("only having MANAGE_BOTS permission", func(t *testing.T) {
  4391  			_, resp = th.Client.RevokeUserAccessToken(token.Id)
  4392  			CheckForbiddenStatus(t, resp)
  4393  		})
  4394  
  4395  		t.Run("with MANAGE_OTHERS_BOTS permission", func(t *testing.T) {
  4396  			th.AddPermissionToRole(model.PERMISSION_MANAGE_OTHERS_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4397  
  4398  			ok, resp := th.Client.RevokeUserAccessToken(token.Id)
  4399  			CheckNoError(t, resp)
  4400  			assert.True(t, ok, "should have passed")
  4401  		})
  4402  	})
  4403  }
  4404  
  4405  func TestDisableUserAccessToken(t *testing.T) {
  4406  	t.Run("disable user token", func(t *testing.T) {
  4407  		th := Setup(t).InitBasic()
  4408  		defer th.TearDown()
  4409  
  4410  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4411  
  4412  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4413  		token, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  4414  		CheckNoError(t, resp)
  4415  		assertToken(t, th, token, th.BasicUser.Id)
  4416  
  4417  		ok, resp := th.Client.DisableUserAccessToken(token.Id)
  4418  		CheckNoError(t, resp)
  4419  		assert.True(t, ok, "should have passed")
  4420  
  4421  		assertInvalidToken(t, th, token)
  4422  	})
  4423  
  4424  	t.Run("disable token belonging to another user", func(t *testing.T) {
  4425  		th := Setup(t).InitBasic()
  4426  		defer th.TearDown()
  4427  
  4428  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4429  
  4430  		token, resp := th.SystemAdminClient.CreateUserAccessToken(th.BasicUser2.Id, "test token")
  4431  		CheckNoError(t, resp)
  4432  
  4433  		ok, resp := th.Client.DisableUserAccessToken(token.Id)
  4434  		CheckForbiddenStatus(t, resp)
  4435  		assert.False(t, ok, "should have failed")
  4436  	})
  4437  
  4438  	t.Run("disable token for bot created by user", func(t *testing.T) {
  4439  		th := Setup(t).InitBasic()
  4440  		defer th.TearDown()
  4441  
  4442  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4443  
  4444  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  4445  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  4446  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4447  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4448  		th.AddPermissionToRole(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4449  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  4450  		th.App.UpdateConfig(func(cfg *model.Config) {
  4451  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  4452  		})
  4453  
  4454  		createdBot, resp := th.Client.CreateBot(&model.Bot{
  4455  			Username:    GenerateTestUsername(),
  4456  			DisplayName: "a bot",
  4457  			Description: "bot",
  4458  		})
  4459  		CheckCreatedStatus(t, resp)
  4460  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  4461  
  4462  		token, resp := th.Client.CreateUserAccessToken(createdBot.UserId, "test token")
  4463  		CheckNoError(t, resp)
  4464  
  4465  		t.Run("without MANAGE_BOTS permission", func(t *testing.T) {
  4466  			th.RemovePermissionFromRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4467  
  4468  			_, resp := th.Client.DisableUserAccessToken(token.Id)
  4469  			CheckForbiddenStatus(t, resp)
  4470  		})
  4471  
  4472  		t.Run("with MANAGE_BOTS permission", func(t *testing.T) {
  4473  			th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4474  
  4475  			ok, resp := th.Client.DisableUserAccessToken(token.Id)
  4476  			CheckNoError(t, resp)
  4477  			assert.True(t, ok, "should have passed")
  4478  		})
  4479  	})
  4480  
  4481  	t.Run("disable token for bot created by another user", func(t *testing.T) {
  4482  		th := Setup(t).InitBasic()
  4483  		defer th.TearDown()
  4484  
  4485  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4486  
  4487  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  4488  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  4489  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4490  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4491  		th.AddPermissionToRole(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4492  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  4493  		th.App.UpdateConfig(func(cfg *model.Config) {
  4494  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  4495  		})
  4496  
  4497  		createdBot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  4498  			Username:    GenerateTestUsername(),
  4499  			DisplayName: "a bot",
  4500  			Description: "bot",
  4501  		})
  4502  		CheckCreatedStatus(t, resp)
  4503  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  4504  
  4505  		token, resp := th.SystemAdminClient.CreateUserAccessToken(createdBot.UserId, "test token")
  4506  		CheckNoError(t, resp)
  4507  
  4508  		t.Run("only having MANAGE_BOTS permission", func(t *testing.T) {
  4509  			_, resp = th.Client.DisableUserAccessToken(token.Id)
  4510  			CheckForbiddenStatus(t, resp)
  4511  		})
  4512  
  4513  		t.Run("with MANAGE_OTHERS_BOTS permission", func(t *testing.T) {
  4514  			th.AddPermissionToRole(model.PERMISSION_MANAGE_OTHERS_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4515  
  4516  			ok, resp := th.Client.DisableUserAccessToken(token.Id)
  4517  			CheckNoError(t, resp)
  4518  			assert.True(t, ok, "should have passed")
  4519  		})
  4520  	})
  4521  }
  4522  
  4523  func TestEnableUserAccessToken(t *testing.T) {
  4524  	t.Run("enable user token", func(t *testing.T) {
  4525  		th := Setup(t).InitBasic()
  4526  		defer th.TearDown()
  4527  
  4528  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4529  
  4530  		th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4531  		token, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, "test token")
  4532  		CheckNoError(t, resp)
  4533  		assertToken(t, th, token, th.BasicUser.Id)
  4534  
  4535  		ok, resp := th.Client.DisableUserAccessToken(token.Id)
  4536  		CheckNoError(t, resp)
  4537  		assert.True(t, ok, "should have passed")
  4538  
  4539  		assertInvalidToken(t, th, token)
  4540  
  4541  		ok, resp = th.Client.EnableUserAccessToken(token.Id)
  4542  		CheckNoError(t, resp)
  4543  		assert.True(t, ok, "should have passed")
  4544  
  4545  		assertToken(t, th, token, th.BasicUser.Id)
  4546  	})
  4547  
  4548  	t.Run("enable token belonging to another user", func(t *testing.T) {
  4549  		th := Setup(t).InitBasic()
  4550  		defer th.TearDown()
  4551  
  4552  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4553  
  4554  		token, resp := th.SystemAdminClient.CreateUserAccessToken(th.BasicUser2.Id, "test token")
  4555  		CheckNoError(t, resp)
  4556  
  4557  		ok, resp := th.SystemAdminClient.DisableUserAccessToken(token.Id)
  4558  		CheckNoError(t, resp)
  4559  		assert.True(t, ok, "should have passed")
  4560  
  4561  		ok, resp = th.Client.DisableUserAccessToken(token.Id)
  4562  		CheckForbiddenStatus(t, resp)
  4563  		assert.False(t, ok, "should have failed")
  4564  	})
  4565  
  4566  	t.Run("enable token for bot created by user", func(t *testing.T) {
  4567  		th := Setup(t).InitBasic()
  4568  		defer th.TearDown()
  4569  
  4570  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4571  
  4572  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  4573  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  4574  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4575  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4576  		th.AddPermissionToRole(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4577  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  4578  		th.App.UpdateConfig(func(cfg *model.Config) {
  4579  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  4580  		})
  4581  
  4582  		createdBot, resp := th.Client.CreateBot(&model.Bot{
  4583  			Username:    GenerateTestUsername(),
  4584  			DisplayName: "a bot",
  4585  			Description: "bot",
  4586  		})
  4587  		CheckCreatedStatus(t, resp)
  4588  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  4589  
  4590  		token, resp := th.Client.CreateUserAccessToken(createdBot.UserId, "test token")
  4591  		CheckNoError(t, resp)
  4592  
  4593  		ok, resp := th.Client.DisableUserAccessToken(token.Id)
  4594  		CheckNoError(t, resp)
  4595  		assert.True(t, ok, "should have passed")
  4596  
  4597  		t.Run("without MANAGE_BOTS permission", func(t *testing.T) {
  4598  			th.RemovePermissionFromRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4599  
  4600  			_, resp := th.Client.EnableUserAccessToken(token.Id)
  4601  			CheckForbiddenStatus(t, resp)
  4602  		})
  4603  
  4604  		t.Run("with MANAGE_BOTS permission", func(t *testing.T) {
  4605  			th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4606  
  4607  			ok, resp := th.Client.EnableUserAccessToken(token.Id)
  4608  			CheckNoError(t, resp)
  4609  			assert.True(t, ok, "should have passed")
  4610  		})
  4611  	})
  4612  
  4613  	t.Run("enable token for bot created by another user", func(t *testing.T) {
  4614  		th := Setup(t).InitBasic()
  4615  		defer th.TearDown()
  4616  
  4617  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4618  
  4619  		defer th.RestoreDefaultRolePermissions(th.SaveDefaultRolePermissions())
  4620  		th.AddPermissionToRole(model.PERMISSION_CREATE_BOT.Id, model.TEAM_USER_ROLE_ID)
  4621  		th.AddPermissionToRole(model.PERMISSION_MANAGE_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4622  		th.AddPermissionToRole(model.PERMISSION_CREATE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4623  		th.AddPermissionToRole(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN.Id, model.TEAM_USER_ROLE_ID)
  4624  		th.App.UpdateUserRoles(th.BasicUser.Id, model.TEAM_USER_ROLE_ID, false)
  4625  		th.App.UpdateConfig(func(cfg *model.Config) {
  4626  			*cfg.ServiceSettings.EnableBotAccountCreation = true
  4627  		})
  4628  
  4629  		createdBot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  4630  			Username:    GenerateTestUsername(),
  4631  			DisplayName: "a bot",
  4632  			Description: "bot",
  4633  		})
  4634  		CheckCreatedStatus(t, resp)
  4635  		defer th.App.PermanentDeleteBot(createdBot.UserId)
  4636  
  4637  		token, resp := th.SystemAdminClient.CreateUserAccessToken(createdBot.UserId, "test token")
  4638  		CheckNoError(t, resp)
  4639  
  4640  		ok, resp := th.SystemAdminClient.DisableUserAccessToken(token.Id)
  4641  		CheckNoError(t, resp)
  4642  		assert.True(t, ok, "should have passed")
  4643  
  4644  		t.Run("only having MANAGE_BOTS permission", func(t *testing.T) {
  4645  			_, resp := th.Client.EnableUserAccessToken(token.Id)
  4646  			CheckForbiddenStatus(t, resp)
  4647  		})
  4648  
  4649  		t.Run("with MANAGE_OTHERS_BOTS permission", func(t *testing.T) {
  4650  			th.AddPermissionToRole(model.PERMISSION_MANAGE_OTHERS_BOTS.Id, model.TEAM_USER_ROLE_ID)
  4651  
  4652  			ok, resp := th.Client.EnableUserAccessToken(token.Id)
  4653  			CheckNoError(t, resp)
  4654  			assert.True(t, ok, "should have passed")
  4655  		})
  4656  	})
  4657  }
  4658  
  4659  func TestUserAccessTokenInactiveUser(t *testing.T) {
  4660  	th := Setup(t).InitBasic()
  4661  	defer th.TearDown()
  4662  
  4663  	testDescription := "test token"
  4664  
  4665  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4666  
  4667  	th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4668  	token, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, testDescription)
  4669  	CheckNoError(t, resp)
  4670  
  4671  	th.Client.AuthToken = token.Token
  4672  	_, resp = th.Client.GetMe("")
  4673  	CheckNoError(t, resp)
  4674  
  4675  	th.App.UpdateActive(th.Context, th.BasicUser, false)
  4676  
  4677  	_, resp = th.Client.GetMe("")
  4678  	CheckUnauthorizedStatus(t, resp)
  4679  }
  4680  
  4681  func TestUserAccessTokenDisableConfig(t *testing.T) {
  4682  	th := Setup(t).InitBasic()
  4683  	defer th.TearDown()
  4684  
  4685  	testDescription := "test token"
  4686  
  4687  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = true })
  4688  
  4689  	th.App.UpdateUserRoles(th.BasicUser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_USER_ACCESS_TOKEN_ROLE_ID, false)
  4690  	token, resp := th.Client.CreateUserAccessToken(th.BasicUser.Id, testDescription)
  4691  	CheckNoError(t, resp)
  4692  
  4693  	oldSessionToken := th.Client.AuthToken
  4694  	th.Client.AuthToken = token.Token
  4695  	_, resp = th.Client.GetMe("")
  4696  	CheckNoError(t, resp)
  4697  
  4698  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableUserAccessTokens = false })
  4699  
  4700  	_, resp = th.Client.GetMe("")
  4701  	CheckUnauthorizedStatus(t, resp)
  4702  
  4703  	th.Client.AuthToken = oldSessionToken
  4704  	_, resp = th.Client.GetMe("")
  4705  	CheckNoError(t, resp)
  4706  }
  4707  
  4708  func TestUserAccessTokenDisableConfigBotsExcluded(t *testing.T) {
  4709  	th := Setup(t)
  4710  	defer th.TearDown()
  4711  
  4712  	th.App.UpdateConfig(func(cfg *model.Config) {
  4713  		*cfg.ServiceSettings.EnableBotAccountCreation = true
  4714  		*cfg.ServiceSettings.EnableUserAccessTokens = false
  4715  	})
  4716  
  4717  	bot, resp := th.SystemAdminClient.CreateBot(&model.Bot{
  4718  		Username:    GenerateTestUsername(),
  4719  		DisplayName: "a bot",
  4720  		Description: "bot",
  4721  	})
  4722  	CheckCreatedStatus(t, resp)
  4723  
  4724  	rtoken, resp := th.SystemAdminClient.CreateUserAccessToken(bot.UserId, "test token")
  4725  	th.Client.AuthToken = rtoken.Token
  4726  	CheckNoError(t, resp)
  4727  
  4728  	_, resp = th.Client.GetMe("")
  4729  	CheckNoError(t, resp)
  4730  }
  4731  
  4732  func TestGetUsersByStatus(t *testing.T) {
  4733  	th := Setup(t)
  4734  	defer th.TearDown()
  4735  
  4736  	team, err := th.App.CreateTeam(th.Context, &model.Team{
  4737  		DisplayName: "dn_" + model.NewId(),
  4738  		Name:        GenerateTestTeamName(),
  4739  		Email:       th.GenerateTestEmail(),
  4740  		Type:        model.TEAM_OPEN,
  4741  	})
  4742  
  4743  	require.Nil(t, err, "failed to create team")
  4744  
  4745  	channel, err := th.App.CreateChannel(th.Context, &model.Channel{
  4746  		DisplayName: "dn_" + model.NewId(),
  4747  		Name:        "name_" + model.NewId(),
  4748  		Type:        model.CHANNEL_OPEN,
  4749  		TeamId:      team.Id,
  4750  		CreatorId:   model.NewId(),
  4751  	}, false)
  4752  	require.Nil(t, err, "failed to create channel")
  4753  
  4754  	createUserWithStatus := func(username string, status string) *model.User {
  4755  		id := model.NewId()
  4756  
  4757  		user, err := th.App.CreateUser(th.Context, &model.User{
  4758  			Email:    "success+" + id + "@simulator.amazonses.com",
  4759  			Username: "un_" + username + "_" + id,
  4760  			Nickname: "nn_" + id,
  4761  			Password: "Password1",
  4762  		})
  4763  		require.Nil(t, err, "failed to create user")
  4764  
  4765  		th.LinkUserToTeam(user, team)
  4766  		th.AddUserToChannel(user, channel)
  4767  
  4768  		th.App.SaveAndBroadcastStatus(&model.Status{
  4769  			UserId: user.Id,
  4770  			Status: status,
  4771  			Manual: true,
  4772  		})
  4773  
  4774  		return user
  4775  	}
  4776  
  4777  	// Creating these out of order in case that affects results
  4778  	offlineUser1 := createUserWithStatus("offline1", model.STATUS_OFFLINE)
  4779  	offlineUser2 := createUserWithStatus("offline2", model.STATUS_OFFLINE)
  4780  	awayUser1 := createUserWithStatus("away1", model.STATUS_AWAY)
  4781  	awayUser2 := createUserWithStatus("away2", model.STATUS_AWAY)
  4782  	onlineUser1 := createUserWithStatus("online1", model.STATUS_ONLINE)
  4783  	onlineUser2 := createUserWithStatus("online2", model.STATUS_ONLINE)
  4784  	dndUser1 := createUserWithStatus("dnd1", model.STATUS_DND)
  4785  	dndUser2 := createUserWithStatus("dnd2", model.STATUS_DND)
  4786  
  4787  	client := th.CreateClient()
  4788  	_, resp := client.Login(onlineUser2.Username, "Password1")
  4789  	require.Nil(t, resp.Error)
  4790  
  4791  	t.Run("sorting by status then alphabetical", func(t *testing.T) {
  4792  		usersByStatus, resp := client.GetUsersInChannelByStatus(channel.Id, 0, 8, "")
  4793  		require.Nil(t, resp.Error)
  4794  
  4795  		expectedUsersByStatus := []*model.User{
  4796  			onlineUser1,
  4797  			onlineUser2,
  4798  			awayUser1,
  4799  			awayUser2,
  4800  			dndUser1,
  4801  			dndUser2,
  4802  			offlineUser1,
  4803  			offlineUser2,
  4804  		}
  4805  		require.Equal(t, len(expectedUsersByStatus), len(usersByStatus))
  4806  
  4807  		for i := range usersByStatus {
  4808  			require.Equal(t, expectedUsersByStatus[i].Id, usersByStatus[i].Id)
  4809  		}
  4810  	})
  4811  
  4812  	t.Run("paging", func(t *testing.T) {
  4813  		usersByStatus, resp := client.GetUsersInChannelByStatus(channel.Id, 0, 3, "")
  4814  		require.Nil(t, resp.Error)
  4815  		require.Len(t, usersByStatus, 3)
  4816  		require.Equal(t, onlineUser1.Id, usersByStatus[0].Id, "online users first")
  4817  		require.Equal(t, onlineUser2.Id, usersByStatus[1].Id, "online users first")
  4818  		require.Equal(t, awayUser1.Id, usersByStatus[2].Id, "expected to receive away users second")
  4819  
  4820  		usersByStatus, resp = client.GetUsersInChannelByStatus(channel.Id, 1, 3, "")
  4821  		require.Nil(t, resp.Error)
  4822  
  4823  		require.Equal(t, awayUser2.Id, usersByStatus[0].Id, "expected to receive away users second")
  4824  		require.Equal(t, dndUser1.Id, usersByStatus[1].Id, "expected to receive dnd users third")
  4825  		require.Equal(t, dndUser2.Id, usersByStatus[2].Id, "expected to receive dnd users third")
  4826  
  4827  		usersByStatus, resp = client.GetUsersInChannelByStatus(channel.Id, 1, 4, "")
  4828  		require.Nil(t, resp.Error)
  4829  
  4830  		require.Len(t, usersByStatus, 4)
  4831  		require.Equal(t, dndUser1.Id, usersByStatus[0].Id, "expected to receive dnd users third")
  4832  		require.Equal(t, dndUser2.Id, usersByStatus[1].Id, "expected to receive dnd users third")
  4833  
  4834  		require.Equal(t, offlineUser1.Id, usersByStatus[2].Id, "expected to receive offline users last")
  4835  		require.Equal(t, offlineUser2.Id, usersByStatus[3].Id, "expected to receive offline users last")
  4836  	})
  4837  }
  4838  
  4839  func TestRegisterTermsOfServiceAction(t *testing.T) {
  4840  	th := Setup(t).InitBasic()
  4841  	defer th.TearDown()
  4842  
  4843  	success, resp := th.Client.RegisterTermsOfServiceAction(th.BasicUser.Id, "st_1", true)
  4844  	CheckErrorMessage(t, resp, "app.terms_of_service.get.no_rows.app_error")
  4845  	assert.Nil(t, success)
  4846  
  4847  	termsOfService, err := th.App.CreateTermsOfService("terms of service", th.BasicUser.Id)
  4848  	require.Nil(t, err)
  4849  
  4850  	success, resp = th.Client.RegisterTermsOfServiceAction(th.BasicUser.Id, termsOfService.Id, true)
  4851  	CheckNoError(t, resp)
  4852  
  4853  	assert.True(t, *success)
  4854  	_, err = th.App.GetUser(th.BasicUser.Id)
  4855  	require.Nil(t, err)
  4856  }
  4857  
  4858  func TestGetUserTermsOfService(t *testing.T) {
  4859  	th := Setup(t).InitBasic()
  4860  	defer th.TearDown()
  4861  
  4862  	_, resp := th.Client.GetUserTermsOfService(th.BasicUser.Id, "")
  4863  	CheckErrorMessage(t, resp, "app.user_terms_of_service.get_by_user.no_rows.app_error")
  4864  
  4865  	termsOfService, err := th.App.CreateTermsOfService("terms of service", th.BasicUser.Id)
  4866  	require.Nil(t, err)
  4867  
  4868  	success, resp := th.Client.RegisterTermsOfServiceAction(th.BasicUser.Id, termsOfService.Id, true)
  4869  	CheckNoError(t, resp)
  4870  	assert.True(t, *success)
  4871  
  4872  	userTermsOfService, resp := th.Client.GetUserTermsOfService(th.BasicUser.Id, "")
  4873  	CheckNoError(t, resp)
  4874  
  4875  	assert.Equal(t, th.BasicUser.Id, userTermsOfService.UserId)
  4876  	assert.Equal(t, termsOfService.Id, userTermsOfService.TermsOfServiceId)
  4877  	assert.NotEmpty(t, userTermsOfService.CreateAt)
  4878  }
  4879  
  4880  func TestLoginErrorMessage(t *testing.T) {
  4881  	th := Setup(t).InitBasic()
  4882  	defer th.TearDown()
  4883  
  4884  	_, resp := th.Client.Logout()
  4885  	CheckNoError(t, resp)
  4886  
  4887  	// Email and Username enabled
  4888  	th.App.UpdateConfig(func(cfg *model.Config) {
  4889  		*cfg.EmailSettings.EnableSignInWithEmail = true
  4890  		*cfg.EmailSettings.EnableSignInWithUsername = true
  4891  	})
  4892  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4893  	CheckErrorMessage(t, resp, "api.user.login.invalid_credentials_email_username")
  4894  
  4895  	// Email enabled
  4896  	th.App.UpdateConfig(func(cfg *model.Config) {
  4897  		*cfg.EmailSettings.EnableSignInWithEmail = true
  4898  		*cfg.EmailSettings.EnableSignInWithUsername = false
  4899  	})
  4900  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4901  	CheckErrorMessage(t, resp, "api.user.login.invalid_credentials_email")
  4902  
  4903  	// Username enabled
  4904  	th.App.UpdateConfig(func(cfg *model.Config) {
  4905  		*cfg.EmailSettings.EnableSignInWithEmail = false
  4906  		*cfg.EmailSettings.EnableSignInWithUsername = true
  4907  	})
  4908  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4909  	CheckErrorMessage(t, resp, "api.user.login.invalid_credentials_username")
  4910  
  4911  	// SAML/SSO enabled
  4912  	th.App.UpdateConfig(func(cfg *model.Config) {
  4913  		*cfg.SamlSettings.Enable = true
  4914  		*cfg.SamlSettings.Verify = false
  4915  		*cfg.SamlSettings.Encrypt = false
  4916  		*cfg.SamlSettings.IdpUrl = "https://localhost/adfs/ls"
  4917  		*cfg.SamlSettings.IdpDescriptorUrl = "https://localhost/adfs/services/trust"
  4918  		*cfg.SamlSettings.IdpMetadataUrl = "https://localhost/adfs/metadata"
  4919  		*cfg.SamlSettings.ServiceProviderIdentifier = "https://localhost/login/sso/saml"
  4920  		*cfg.SamlSettings.AssertionConsumerServiceURL = "https://localhost/login/sso/saml"
  4921  		*cfg.SamlSettings.IdpCertificateFile = app.SamlIdpCertificateName
  4922  		*cfg.SamlSettings.PrivateKeyFile = app.SamlPrivateKeyName
  4923  		*cfg.SamlSettings.PublicCertificateFile = app.SamlPublicCertificateName
  4924  		*cfg.SamlSettings.EmailAttribute = "Email"
  4925  		*cfg.SamlSettings.UsernameAttribute = "Username"
  4926  		*cfg.SamlSettings.FirstNameAttribute = "FirstName"
  4927  		*cfg.SamlSettings.LastNameAttribute = "LastName"
  4928  		*cfg.SamlSettings.NicknameAttribute = ""
  4929  		*cfg.SamlSettings.PositionAttribute = ""
  4930  		*cfg.SamlSettings.LocaleAttribute = ""
  4931  	})
  4932  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4933  	CheckErrorMessage(t, resp, "api.user.login.invalid_credentials_sso")
  4934  }
  4935  
  4936  func TestLoginLockout(t *testing.T) {
  4937  	th := Setup(t).InitBasic()
  4938  	defer th.TearDown()
  4939  
  4940  	_, resp := th.Client.Logout()
  4941  	CheckNoError(t, resp)
  4942  
  4943  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.MaximumLoginAttempts = 3 })
  4944  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableMultifactorAuthentication = true })
  4945  
  4946  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4947  	CheckErrorMessage(t, resp, "api.user.login.invalid_credentials_email_username")
  4948  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4949  	CheckErrorMessage(t, resp, "api.user.login.invalid_credentials_email_username")
  4950  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4951  	CheckErrorMessage(t, resp, "api.user.login.invalid_credentials_email_username")
  4952  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4953  	CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error")
  4954  	_, resp = th.Client.Login(th.BasicUser.Email, "wrong")
  4955  	CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error")
  4956  
  4957  	//Check if lock is active
  4958  	_, resp = th.Client.Login(th.BasicUser.Email, th.BasicUser.Password)
  4959  	CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error")
  4960  
  4961  	// Fake user has MFA enabled
  4962  	err := th.Server.Store.User().UpdateMfaActive(th.BasicUser2.Id, true)
  4963  	require.NoError(t, err)
  4964  	_, resp = th.Client.LoginWithMFA(th.BasicUser2.Email, th.BasicUser2.Password, "000000")
  4965  	CheckErrorMessage(t, resp, "api.user.check_user_mfa.bad_code.app_error")
  4966  	_, resp = th.Client.LoginWithMFA(th.BasicUser2.Email, th.BasicUser2.Password, "000000")
  4967  	CheckErrorMessage(t, resp, "api.user.check_user_mfa.bad_code.app_error")
  4968  	_, resp = th.Client.LoginWithMFA(th.BasicUser2.Email, th.BasicUser2.Password, "000000")
  4969  	CheckErrorMessage(t, resp, "api.user.check_user_mfa.bad_code.app_error")
  4970  	_, resp = th.Client.LoginWithMFA(th.BasicUser2.Email, th.BasicUser2.Password, "000000")
  4971  	CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error")
  4972  	_, resp = th.Client.LoginWithMFA(th.BasicUser2.Email, th.BasicUser2.Password, "000000")
  4973  	CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error")
  4974  
  4975  	// Fake user has MFA disabled
  4976  	err = th.Server.Store.User().UpdateMfaActive(th.BasicUser2.Id, false)
  4977  	require.NoError(t, err)
  4978  
  4979  	//Check if lock is active
  4980  	_, resp = th.Client.Login(th.BasicUser2.Email, th.BasicUser2.Password)
  4981  	CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error")
  4982  }
  4983  
  4984  func TestDemoteUserToGuest(t *testing.T) {
  4985  	th := Setup(t).InitBasic()
  4986  	defer th.TearDown()
  4987  
  4988  	enableGuestAccounts := *th.App.Config().GuestAccountsSettings.Enable
  4989  	defer func() {
  4990  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.Enable = enableGuestAccounts })
  4991  		th.App.Srv().RemoveLicense()
  4992  	}()
  4993  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.Enable = true })
  4994  	th.App.Srv().SetLicense(model.NewTestLicense())
  4995  
  4996  	user := th.BasicUser
  4997  
  4998  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
  4999  		_, respErr := c.GetUser(user.Id, "")
  5000  		CheckNoError(t, respErr)
  5001  
  5002  		_, respErr = c.DemoteUserToGuest(user.Id)
  5003  		CheckNoError(t, respErr)
  5004  
  5005  		defer require.Nil(t, th.App.PromoteGuestToUser(th.Context, user, ""))
  5006  	}, "demote a user to guest")
  5007  
  5008  	t.Run("websocket update user event", func(t *testing.T) {
  5009  		webSocketClient, err := th.CreateWebSocketClient()
  5010  		assert.Nil(t, err)
  5011  		defer webSocketClient.Close()
  5012  
  5013  		webSocketClient.Listen()
  5014  
  5015  		time.Sleep(300 * time.Millisecond)
  5016  		resp := <-webSocketClient.ResponseChannel
  5017  		require.Equal(t, model.STATUS_OK, resp.Status)
  5018  
  5019  		adminWebSocketClient, err := th.CreateWebSocketSystemAdminClient()
  5020  		assert.Nil(t, err)
  5021  		defer adminWebSocketClient.Close()
  5022  
  5023  		adminWebSocketClient.Listen()
  5024  
  5025  		time.Sleep(300 * time.Millisecond)
  5026  		resp = <-adminWebSocketClient.ResponseChannel
  5027  		require.Equal(t, model.STATUS_OK, resp.Status)
  5028  
  5029  		_, respErr := th.SystemAdminClient.GetUser(user.Id, "")
  5030  		CheckNoError(t, respErr)
  5031  		_, respErr = th.SystemAdminClient.DemoteUserToGuest(user.Id)
  5032  		CheckNoError(t, respErr)
  5033  		defer th.SystemAdminClient.PromoteGuestToUser(user.Id)
  5034  
  5035  		assertExpectedWebsocketEvent(t, webSocketClient, model.WEBSOCKET_EVENT_USER_UPDATED, func(event *model.WebSocketEvent) {
  5036  			eventUser, ok := event.GetData()["user"].(*model.User)
  5037  			require.True(t, ok, "expected user")
  5038  			assert.Equal(t, "system_guest", eventUser.Roles)
  5039  		})
  5040  		assertExpectedWebsocketEvent(t, adminWebSocketClient, model.WEBSOCKET_EVENT_USER_UPDATED, func(event *model.WebSocketEvent) {
  5041  			eventUser, ok := event.GetData()["user"].(*model.User)
  5042  			require.True(t, ok, "expected user")
  5043  			assert.Equal(t, "system_guest", eventUser.Roles)
  5044  		})
  5045  	})
  5046  }
  5047  
  5048  func TestPromoteGuestToUser(t *testing.T) {
  5049  	th := Setup(t).InitBasic()
  5050  	defer th.TearDown()
  5051  
  5052  	enableGuestAccounts := *th.App.Config().GuestAccountsSettings.Enable
  5053  	defer func() {
  5054  		th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.Enable = enableGuestAccounts })
  5055  		th.App.Srv().RemoveLicense()
  5056  	}()
  5057  	th.App.UpdateConfig(func(cfg *model.Config) { *cfg.GuestAccountsSettings.Enable = true })
  5058  	th.App.Srv().SetLicense(model.NewTestLicense())
  5059  
  5060  	user := th.BasicUser
  5061  	th.App.UpdateUserRoles(user.Id, model.SYSTEM_GUEST_ROLE_ID, false)
  5062  
  5063  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, c *model.Client4) {
  5064  		_, respErr := c.GetUser(user.Id, "")
  5065  		CheckNoError(t, respErr)
  5066  
  5067  		_, respErr = c.PromoteGuestToUser(user.Id)
  5068  		CheckNoError(t, respErr)
  5069  
  5070  		defer require.Nil(t, th.App.DemoteUserToGuest(user))
  5071  	}, "promete a guest to user")
  5072  
  5073  	t.Run("websocket update user event", func(t *testing.T) {
  5074  		webSocketClient, err := th.CreateWebSocketClient()
  5075  		assert.Nil(t, err)
  5076  		defer webSocketClient.Close()
  5077  
  5078  		webSocketClient.Listen()
  5079  
  5080  		time.Sleep(300 * time.Millisecond)
  5081  		resp := <-webSocketClient.ResponseChannel
  5082  		require.Equal(t, model.STATUS_OK, resp.Status)
  5083  
  5084  		adminWebSocketClient, err := th.CreateWebSocketSystemAdminClient()
  5085  		assert.Nil(t, err)
  5086  		defer adminWebSocketClient.Close()
  5087  
  5088  		adminWebSocketClient.Listen()
  5089  
  5090  		time.Sleep(300 * time.Millisecond)
  5091  		resp = <-adminWebSocketClient.ResponseChannel
  5092  		require.Equal(t, model.STATUS_OK, resp.Status)
  5093  
  5094  		_, respErr := th.SystemAdminClient.GetUser(user.Id, "")
  5095  		CheckNoError(t, respErr)
  5096  		_, respErr = th.SystemAdminClient.PromoteGuestToUser(user.Id)
  5097  		CheckNoError(t, respErr)
  5098  		defer th.SystemAdminClient.DemoteUserToGuest(user.Id)
  5099  
  5100  		assertExpectedWebsocketEvent(t, webSocketClient, model.WEBSOCKET_EVENT_USER_UPDATED, func(event *model.WebSocketEvent) {
  5101  			eventUser, ok := event.GetData()["user"].(*model.User)
  5102  			require.True(t, ok, "expected user")
  5103  			assert.Equal(t, "system_user", eventUser.Roles)
  5104  		})
  5105  		assertExpectedWebsocketEvent(t, adminWebSocketClient, model.WEBSOCKET_EVENT_USER_UPDATED, func(event *model.WebSocketEvent) {
  5106  			eventUser, ok := event.GetData()["user"].(*model.User)
  5107  			require.True(t, ok, "expected user")
  5108  			assert.Equal(t, "system_user", eventUser.Roles)
  5109  		})
  5110  	})
  5111  }
  5112  
  5113  func TestVerifyUserEmailWithoutToken(t *testing.T) {
  5114  	th := Setup(t)
  5115  	defer th.TearDown()
  5116  
  5117  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  5118  		email := th.GenerateTestEmail()
  5119  		user := model.User{Email: email, Nickname: "Darth Vader", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_USER_ROLE_ID}
  5120  		ruser, _ := th.Client.CreateUser(&user)
  5121  
  5122  		vuser, resp := client.VerifyUserEmailWithoutToken(ruser.Id)
  5123  		require.Nil(t, resp.Error)
  5124  		require.Equal(t, ruser.Id, vuser.Id)
  5125  	}, "Should verify a new user")
  5126  
  5127  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  5128  		vuser, resp := client.VerifyUserEmailWithoutToken("randomId")
  5129  		require.NotNil(t, resp.Error)
  5130  		CheckErrorMessage(t, resp, "api.context.invalid_url_param.app_error")
  5131  		require.Nil(t, vuser)
  5132  	}, "Should not be able to find user")
  5133  
  5134  	t.Run("Should not be able to verify user due to permissions", func(t *testing.T) {
  5135  		user := th.CreateUser()
  5136  		vuser, resp := th.Client.VerifyUserEmailWithoutToken(user.Id)
  5137  		require.NotNil(t, resp.Error)
  5138  		CheckErrorMessage(t, resp, "api.context.permissions.app_error")
  5139  		require.Nil(t, vuser)
  5140  	})
  5141  }
  5142  
  5143  func TestGetKnownUsers(t *testing.T) {
  5144  	th := Setup(t)
  5145  	defer th.TearDown()
  5146  
  5147  	t1, err := th.App.CreateTeam(th.Context, &model.Team{
  5148  		DisplayName: "dn_" + model.NewId(),
  5149  		Name:        GenerateTestTeamName(),
  5150  		Email:       th.GenerateTestEmail(),
  5151  		Type:        model.TEAM_OPEN,
  5152  	})
  5153  	require.Nil(t, err, "failed to create team")
  5154  
  5155  	t2, err := th.App.CreateTeam(th.Context, &model.Team{
  5156  		DisplayName: "dn_" + model.NewId(),
  5157  		Name:        GenerateTestTeamName(),
  5158  		Email:       th.GenerateTestEmail(),
  5159  		Type:        model.TEAM_OPEN,
  5160  	})
  5161  	require.Nil(t, err, "failed to create team")
  5162  
  5163  	t3, err := th.App.CreateTeam(th.Context, &model.Team{
  5164  		DisplayName: "dn_" + model.NewId(),
  5165  		Name:        GenerateTestTeamName(),
  5166  		Email:       th.GenerateTestEmail(),
  5167  		Type:        model.TEAM_OPEN,
  5168  	})
  5169  	require.Nil(t, err, "failed to create team")
  5170  
  5171  	c1, err := th.App.CreateChannel(th.Context, &model.Channel{
  5172  		DisplayName: "dn_" + model.NewId(),
  5173  		Name:        "name_" + model.NewId(),
  5174  		Type:        model.CHANNEL_OPEN,
  5175  		TeamId:      t1.Id,
  5176  		CreatorId:   model.NewId(),
  5177  	}, false)
  5178  	require.Nil(t, err, "failed to create channel")
  5179  
  5180  	c2, err := th.App.CreateChannel(th.Context, &model.Channel{
  5181  		DisplayName: "dn_" + model.NewId(),
  5182  		Name:        "name_" + model.NewId(),
  5183  		Type:        model.CHANNEL_OPEN,
  5184  		TeamId:      t2.Id,
  5185  		CreatorId:   model.NewId(),
  5186  	}, false)
  5187  	require.Nil(t, err, "failed to create channel")
  5188  
  5189  	c3, err := th.App.CreateChannel(th.Context, &model.Channel{
  5190  		DisplayName: "dn_" + model.NewId(),
  5191  		Name:        "name_" + model.NewId(),
  5192  		Type:        model.CHANNEL_OPEN,
  5193  		TeamId:      t3.Id,
  5194  		CreatorId:   model.NewId(),
  5195  	}, false)
  5196  	require.Nil(t, err, "failed to create channel")
  5197  
  5198  	u1 := th.CreateUser()
  5199  	defer th.App.PermanentDeleteUser(th.Context, u1)
  5200  	u2 := th.CreateUser()
  5201  	defer th.App.PermanentDeleteUser(th.Context, u2)
  5202  	u3 := th.CreateUser()
  5203  	defer th.App.PermanentDeleteUser(th.Context, u3)
  5204  	u4 := th.CreateUser()
  5205  	defer th.App.PermanentDeleteUser(th.Context, u4)
  5206  
  5207  	th.LinkUserToTeam(u1, t1)
  5208  	th.LinkUserToTeam(u1, t2)
  5209  	th.LinkUserToTeam(u2, t1)
  5210  	th.LinkUserToTeam(u3, t2)
  5211  	th.LinkUserToTeam(u4, t3)
  5212  
  5213  	th.App.AddUserToChannel(u1, c1, false)
  5214  	th.App.AddUserToChannel(u1, c2, false)
  5215  	th.App.AddUserToChannel(u2, c1, false)
  5216  	th.App.AddUserToChannel(u3, c2, false)
  5217  	th.App.AddUserToChannel(u4, c3, false)
  5218  
  5219  	t.Run("get know users sharing no channels", func(t *testing.T) {
  5220  		_, _ = th.Client.Login(u4.Email, u4.Password)
  5221  		userIds, resp := th.Client.GetKnownUsers()
  5222  		CheckNoError(t, resp)
  5223  		assert.Empty(t, userIds)
  5224  	})
  5225  
  5226  	t.Run("get know users sharing one channel", func(t *testing.T) {
  5227  		_, _ = th.Client.Login(u3.Email, u3.Password)
  5228  		userIds, resp := th.Client.GetKnownUsers()
  5229  		CheckNoError(t, resp)
  5230  		assert.Len(t, userIds, 1)
  5231  		assert.Equal(t, userIds[0], u1.Id)
  5232  	})
  5233  
  5234  	t.Run("get know users sharing multiple channels", func(t *testing.T) {
  5235  		_, _ = th.Client.Login(u1.Email, u1.Password)
  5236  		userIds, resp := th.Client.GetKnownUsers()
  5237  		CheckNoError(t, resp)
  5238  		assert.Len(t, userIds, 2)
  5239  		assert.ElementsMatch(t, userIds, []string{u2.Id, u3.Id})
  5240  	})
  5241  }
  5242  
  5243  func TestPublishUserTyping(t *testing.T) {
  5244  	th := Setup(t).InitBasic()
  5245  	defer th.TearDown()
  5246  
  5247  	tr := model.TypingRequest{
  5248  		ChannelId: th.BasicChannel.Id,
  5249  		ParentId:  "randomparentid",
  5250  	}
  5251  
  5252  	t.Run("should return ok for non-system admin when triggering typing event for own user", func(t *testing.T) {
  5253  		_, resp := th.Client.PublishUserTyping(th.BasicUser.Id, tr)
  5254  		CheckNoError(t, resp)
  5255  	})
  5256  
  5257  	t.Run("should return ok for system admin when triggering typing event for own user", func(t *testing.T) {
  5258  		th.LinkUserToTeam(th.SystemAdminUser, th.BasicTeam)
  5259  		th.AddUserToChannel(th.SystemAdminUser, th.BasicChannel)
  5260  
  5261  		_, resp := th.SystemAdminClient.PublishUserTyping(th.SystemAdminUser.Id, tr)
  5262  		CheckNoError(t, resp)
  5263  	})
  5264  
  5265  	t.Run("should return forbidden for non-system admin when triggering a typing event for a different user", func(t *testing.T) {
  5266  		_, resp := th.Client.PublishUserTyping(th.BasicUser2.Id, tr)
  5267  		CheckForbiddenStatus(t, resp)
  5268  	})
  5269  
  5270  	t.Run("should return bad request when triggering a typing event for an invalid user id", func(t *testing.T) {
  5271  		_, resp := th.Client.PublishUserTyping("invalid", tr)
  5272  		CheckErrorMessage(t, resp, "api.context.invalid_url_param.app_error")
  5273  		CheckBadRequestStatus(t, resp)
  5274  	})
  5275  
  5276  	t.Run("should send typing event via websocket when triggering a typing event for a user with a common channel", func(t *testing.T) {
  5277  		webSocketClient, err := th.CreateWebSocketClient()
  5278  		assert.Nil(t, err)
  5279  		defer webSocketClient.Close()
  5280  
  5281  		webSocketClient.Listen()
  5282  
  5283  		time.Sleep(300 * time.Millisecond)
  5284  		wsResp := <-webSocketClient.ResponseChannel
  5285  		require.Equal(t, model.STATUS_OK, wsResp.Status)
  5286  
  5287  		_, resp := th.SystemAdminClient.PublishUserTyping(th.BasicUser2.Id, tr)
  5288  		CheckNoError(t, resp)
  5289  
  5290  		assertExpectedWebsocketEvent(t, webSocketClient, model.WEBSOCKET_EVENT_TYPING, func(resp *model.WebSocketEvent) {
  5291  			assert.Equal(t, th.BasicChannel.Id, resp.GetBroadcast().ChannelId)
  5292  
  5293  			eventUserId, ok := resp.GetData()["user_id"].(string)
  5294  			require.True(t, ok, "expected user_id")
  5295  			assert.Equal(t, th.BasicUser2.Id, eventUserId)
  5296  
  5297  			eventParentId, ok := resp.GetData()["parent_id"].(string)
  5298  			require.True(t, ok, "expected parent_id")
  5299  			assert.Equal(t, "randomparentid", eventParentId)
  5300  		})
  5301  	})
  5302  
  5303  	th.Server.Busy.Set(time.Second * 10)
  5304  
  5305  	t.Run("should return service unavailable for non-system admin user when triggering a typing event and server busy", func(t *testing.T) {
  5306  		_, resp := th.Client.PublishUserTyping("invalid", tr)
  5307  		CheckErrorMessage(t, resp, "api.context.server_busy.app_error")
  5308  		CheckServiceUnavailableStatus(t, resp)
  5309  	})
  5310  
  5311  	t.Run("should return service unavailable for system admin user when triggering a typing event and server busy", func(t *testing.T) {
  5312  		_, resp := th.SystemAdminClient.PublishUserTyping(th.SystemAdminUser.Id, tr)
  5313  		CheckErrorMessage(t, resp, "api.context.server_busy.app_error")
  5314  		CheckServiceUnavailableStatus(t, resp)
  5315  	})
  5316  }
  5317  
  5318  func TestConvertUserToBot(t *testing.T) {
  5319  	th := Setup(t).InitBasic()
  5320  	defer th.TearDown()
  5321  
  5322  	bot, resp := th.Client.ConvertUserToBot(th.BasicUser.Id)
  5323  	CheckForbiddenStatus(t, resp)
  5324  	require.Nil(t, bot)
  5325  
  5326  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  5327  		user := model.User{Email: th.GenerateTestEmail(), Username: GenerateTestUsername(), Password: "password"}
  5328  
  5329  		ruser, resp := client.CreateUser(&user)
  5330  		CheckNoError(t, resp)
  5331  		CheckCreatedStatus(t, resp)
  5332  
  5333  		bot, resp = client.ConvertUserToBot(ruser.Id)
  5334  		CheckNoError(t, resp)
  5335  		require.NotNil(t, bot)
  5336  		require.Equal(t, bot.UserId, ruser.Id)
  5337  
  5338  		bot, resp = client.GetBot(bot.UserId, "")
  5339  		CheckNoError(t, resp)
  5340  		require.NotNil(t, bot)
  5341  	})
  5342  }
  5343  
  5344  func TestMigrateAuthToLDAP(t *testing.T) {
  5345  	th := Setup(t).InitBasic()
  5346  	defer th.TearDown()
  5347  
  5348  	_, err := th.Client.MigrateAuthToLdap("email", "a", false)
  5349  	CheckForbiddenStatus(t, err)
  5350  
  5351  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  5352  		_, err = client.MigrateAuthToLdap("email", "a", false)
  5353  		CheckNotImplementedStatus(t, err)
  5354  	})
  5355  }
  5356  
  5357  func TestMigrateAuthToSAML(t *testing.T) {
  5358  	th := Setup(t).InitBasic()
  5359  	defer th.TearDown()
  5360  
  5361  	_, err := th.Client.MigrateAuthToSaml("email", map[string]string{"1": "a"}, true)
  5362  	CheckForbiddenStatus(t, err)
  5363  
  5364  	th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
  5365  		_, err = client.MigrateAuthToSaml("email", map[string]string{"1": "a"}, true)
  5366  		CheckNotImplementedStatus(t, err)
  5367  	})
  5368  }
  5369  func TestUpdatePassword(t *testing.T) {
  5370  	th := Setup(t)
  5371  	defer th.TearDown()
  5372  
  5373  	t.Run("Forbidden when request performed by system user on a system admin", func(t *testing.T) {
  5374  		res := th.Client.UpdatePassword(th.SystemAdminUser.Id, "Pa$$word11", "foobar")
  5375  		CheckForbiddenStatus(t, res)
  5376  	})
  5377  
  5378  	t.Run("OK when request performed by system user with requisite system permission, except if requested user is system admin", func(t *testing.T) {
  5379  		th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_USERS.Id, model.SYSTEM_USER_ROLE_ID)
  5380  		defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_USERS.Id, model.SYSTEM_USER_ROLE_ID)
  5381  
  5382  		res := th.Client.UpdatePassword(th.TeamAdminUser.Id, "Pa$$word11", "foobar")
  5383  		CheckOKStatus(t, res)
  5384  
  5385  		res = th.Client.UpdatePassword(th.SystemAdminUser.Id, "Pa$$word11", "foobar")
  5386  		CheckForbiddenStatus(t, res)
  5387  	})
  5388  
  5389  	t.Run("OK when request performed by system admin, even if requested user is system admin", func(t *testing.T) {
  5390  		res := th.SystemAdminClient.UpdatePassword(th.SystemAdminUser.Id, "Pa$$word11", "foobar")
  5391  		CheckOKStatus(t, res)
  5392  	})
  5393  }
  5394  
  5395  func TestGetThreadsForUser(t *testing.T) {
  5396  	th := Setup(t).InitBasic()
  5397  	defer th.TearDown()
  5398  	os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
  5399  	defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
  5400  
  5401  	th.App.UpdateConfig(func(cfg *model.Config) {
  5402  		*cfg.ServiceSettings.ThreadAutoFollow = true
  5403  		*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
  5404  	})
  5405  	t.Run("empty", func(t *testing.T) {
  5406  		Client := th.Client
  5407  
  5408  		_, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5409  		CheckNoError(t, resp)
  5410  		CheckCreatedStatus(t, resp)
  5411  
  5412  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5413  
  5414  		uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
  5415  		require.Nil(t, resp.Error)
  5416  		require.Len(t, uss.Threads, 0)
  5417  	})
  5418  
  5419  	t.Run("no params, 1 thread", func(t *testing.T) {
  5420  		Client := th.Client
  5421  
  5422  		rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5423  		CheckNoError(t, resp)
  5424  		CheckCreatedStatus(t, resp)
  5425  		_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  5426  		CheckNoError(t, resp2)
  5427  		CheckCreatedStatus(t, resp2)
  5428  
  5429  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5430  
  5431  		uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
  5432  		require.Nil(t, resp.Error)
  5433  		require.Len(t, uss.Threads, 1)
  5434  		require.Equal(t, uss.Threads[0].PostId, rpost.Id)
  5435  		require.Equal(t, uss.Threads[0].ReplyCount, int64(1))
  5436  	})
  5437  
  5438  	t.Run("extended, 1 thread", func(t *testing.T) {
  5439  		Client := th.Client
  5440  
  5441  		rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5442  		CheckNoError(t, resp)
  5443  		CheckCreatedStatus(t, resp)
  5444  		_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  5445  		CheckNoError(t, resp2)
  5446  		CheckCreatedStatus(t, resp2)
  5447  
  5448  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5449  
  5450  		uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5451  			Extended: true,
  5452  		})
  5453  		require.Nil(t, resp.Error)
  5454  		require.Len(t, uss.Threads, 1)
  5455  		require.Equal(t, uss.Threads[0].PostId, rpost.Id)
  5456  		require.Equal(t, uss.Threads[0].ReplyCount, int64(1))
  5457  		require.Equal(t, uss.Threads[0].Participants[0].Id, th.BasicUser.Id)
  5458  	})
  5459  
  5460  	t.Run("deleted, 1 thread", func(t *testing.T) {
  5461  		Client := th.Client
  5462  
  5463  		rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5464  		CheckNoError(t, resp)
  5465  		CheckCreatedStatus(t, resp)
  5466  		_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  5467  		CheckNoError(t, resp2)
  5468  		CheckCreatedStatus(t, resp2)
  5469  
  5470  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5471  
  5472  		uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5473  			Deleted: false,
  5474  		})
  5475  		require.Nil(t, resp.Error)
  5476  		require.Len(t, uss.Threads, 1)
  5477  		require.Equal(t, uss.Threads[0].PostId, rpost.Id)
  5478  		require.Equal(t, uss.Threads[0].ReplyCount, int64(1))
  5479  		require.Equal(t, uss.Threads[0].Participants[0].Id, th.BasicUser.Id)
  5480  
  5481  		res, resp2 := th.Client.DeletePost(rpost.Id)
  5482  		require.True(t, res)
  5483  		require.Nil(t, resp2.Error)
  5484  
  5485  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5486  			Deleted: false,
  5487  		})
  5488  		require.Nil(t, resp.Error)
  5489  		require.Len(t, uss.Threads, 0)
  5490  
  5491  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5492  			Deleted: true,
  5493  		})
  5494  		require.Nil(t, resp.Error)
  5495  		require.Len(t, uss.Threads, 1)
  5496  		require.Greater(t, uss.Threads[0].Post.DeleteAt, int64(0))
  5497  
  5498  	})
  5499  
  5500  	t.Run("paged, 30 threads", func(t *testing.T) {
  5501  		Client := th.Client
  5502  
  5503  		var rootIds []*model.Post
  5504  		for i := 0; i < 30; i++ {
  5505  			time.Sleep(1)
  5506  			rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5507  			CheckNoError(t, resp)
  5508  			CheckCreatedStatus(t, resp)
  5509  			rootIds = append(rootIds, rpost)
  5510  			time.Sleep(1)
  5511  			_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  5512  			CheckNoError(t, resp2)
  5513  			CheckCreatedStatus(t, resp2)
  5514  		}
  5515  
  5516  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5517  
  5518  		uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5519  			Deleted: false,
  5520  		})
  5521  		require.Nil(t, resp.Error)
  5522  		require.Len(t, uss.Threads, 30)
  5523  		require.Len(t, rootIds, 30)
  5524  		require.Equal(t, uss.Threads[0].PostId, rootIds[29].Id)
  5525  		require.Equal(t, uss.Threads[0].ReplyCount, int64(1))
  5526  		require.Equal(t, uss.Threads[0].Participants[0].Id, th.BasicUser.Id)
  5527  	})
  5528  
  5529  	t.Run("paged, 10 threads before/after", func(t *testing.T) {
  5530  		Client := th.Client
  5531  
  5532  		var rootIds []*model.Post
  5533  		for i := 0; i < 30; i++ {
  5534  			time.Sleep(1)
  5535  			rpost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: fmt.Sprintf("testMsg-%d", i)})
  5536  			rootIds = append(rootIds, rpost)
  5537  			time.Sleep(1)
  5538  			postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: fmt.Sprintf("testReply-%d", i), RootId: rpost.Id})
  5539  		}
  5540  		rootId := rootIds[15].Id // middle point
  5541  		rootIdBefore := rootIds[14].Id
  5542  		rootIdAfter := rootIds[16].Id
  5543  
  5544  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5545  
  5546  		uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5547  			Deleted:  false,
  5548  			PageSize: 10,
  5549  			Before:   rootId,
  5550  		})
  5551  
  5552  		require.Nil(t, resp.Error)
  5553  		require.Len(t, uss.Threads, 10)
  5554  		require.Equal(t, rootIdBefore, uss.Threads[0].PostId)
  5555  
  5556  		uss2, resp2 := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5557  			Deleted:  false,
  5558  			PageSize: 10,
  5559  			After:    rootId,
  5560  		})
  5561  		require.Nil(t, resp2.Error)
  5562  		require.Len(t, uss2.Threads, 10)
  5563  
  5564  		require.Equal(t, rootIdAfter, uss2.Threads[0].PostId)
  5565  
  5566  		uss3, resp3 := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5567  			Deleted:  false,
  5568  			PageSize: 10,
  5569  			After:    rootId + "__bad",
  5570  		})
  5571  		require.Nil(t, resp3.Error)
  5572  		require.NotNil(t, uss3.Threads)
  5573  		require.Len(t, uss3.Threads, 0)
  5574  	})
  5575  
  5576  	t.Run("editing or reacting to reply post does not make thread unread", func(t *testing.T) {
  5577  		Client := th.Client
  5578  
  5579  		rootPost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "root post"})
  5580  		replyPost, _ := postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "reply post", RootId: rootPost.Id})
  5581  		uss, resp := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5582  			Deleted: false,
  5583  		})
  5584  		CheckNoError(t, resp)
  5585  		require.Equal(t, uss.TotalUnreadThreads, int64(1))
  5586  		require.Equal(t, uss.Threads[0].PostId, rootPost.Id)
  5587  
  5588  		_, resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, th.BasicChannel.TeamId, rootPost.Id, model.GetMillis())
  5589  		CheckNoError(t, resp)
  5590  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5591  			Deleted: false,
  5592  		})
  5593  		CheckNoError(t, resp)
  5594  		require.Equal(t, uss.TotalUnreadThreads, int64(0))
  5595  
  5596  		// edit post
  5597  		editedReplyPostMessage := "edited " + replyPost.Message
  5598  		_, resp = th.SystemAdminClient.PatchPost(replyPost.Id, &model.PostPatch{Message: &editedReplyPostMessage})
  5599  		CheckNoError(t, resp)
  5600  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5601  			Deleted: false,
  5602  		})
  5603  		CheckNoError(t, resp)
  5604  		require.Equal(t, uss.TotalUnreadThreads, int64(0))
  5605  
  5606  		// react to post
  5607  		reaction := &model.Reaction{
  5608  			UserId:    th.SystemAdminUser.Id,
  5609  			PostId:    replyPost.Id,
  5610  			EmojiName: "smile",
  5611  		}
  5612  		_, resp = th.SystemAdminClient.SaveReaction(reaction)
  5613  		CheckNoError(t, resp)
  5614  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5615  			Deleted: false,
  5616  		})
  5617  		CheckNoError(t, resp)
  5618  		require.Equal(t, uss.TotalUnreadThreads, int64(0))
  5619  	})
  5620  }
  5621  
  5622  func TestThreadSocketEvents(t *testing.T) {
  5623  	th := Setup(t).InitBasic()
  5624  	defer th.TearDown()
  5625  	os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
  5626  	defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
  5627  
  5628  	th.ConfigStore.SetReadOnlyFF(false)
  5629  	defer th.ConfigStore.SetReadOnlyFF(true)
  5630  
  5631  	th.App.UpdateConfig(func(cfg *model.Config) {
  5632  		*cfg.ServiceSettings.ThreadAutoFollow = true
  5633  		*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
  5634  	})
  5635  
  5636  	userWSClient, err := th.CreateWebSocketClient()
  5637  	require.Nil(t, err)
  5638  	defer userWSClient.Close()
  5639  	userWSClient.Listen()
  5640  
  5641  	Client := th.Client
  5642  
  5643  	rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5644  	CheckNoError(t, resp)
  5645  	CheckCreatedStatus(t, resp)
  5646  
  5647  	_, err = th.App.CreatePostAsUser(th.Context, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", UserId: th.BasicUser2.Id, RootId: rpost.Id}, th.Context.Session().Id, false)
  5648  	require.Nil(t, err)
  5649  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5650  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser2.Id)
  5651  
  5652  	t.Run("Listed for update event", func(t *testing.T) {
  5653  		var caught bool
  5654  		func() {
  5655  			for {
  5656  				select {
  5657  				case ev := <-userWSClient.EventChannel:
  5658  					if ev.EventType() == model.WEBSOCKET_EVENT_THREAD_UPDATED {
  5659  						caught = true
  5660  						thread, err := model.ThreadResponseFromJson(ev.GetData()["thread"].(string))
  5661  						require.NoError(t, err)
  5662  						for _, p := range thread.Participants {
  5663  							if p.Id != th.BasicUser.Id && p.Id != th.BasicUser2.Id {
  5664  								require.Fail(t, "invalid participants")
  5665  							}
  5666  						}
  5667  					}
  5668  				case <-time.After(1 * time.Second):
  5669  					return
  5670  				}
  5671  			}
  5672  		}()
  5673  		require.Truef(t, caught, "User should have received %s event", model.WEBSOCKET_EVENT_THREAD_UPDATED)
  5674  	})
  5675  
  5676  	resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rpost.Id, false)
  5677  	CheckNoError(t, resp)
  5678  	CheckOKStatus(t, resp)
  5679  
  5680  	t.Run("Listed for follow event", func(t *testing.T) {
  5681  		var caught bool
  5682  		func() {
  5683  			for {
  5684  				select {
  5685  				case ev := <-userWSClient.EventChannel:
  5686  					if ev.EventType() == model.WEBSOCKET_EVENT_THREAD_FOLLOW_CHANGED {
  5687  						caught = true
  5688  						require.Equal(t, ev.GetData()["state"], false)
  5689  						require.Equal(t, ev.GetData()["reply_count"], float64(1))
  5690  					}
  5691  				case <-time.After(1 * time.Second):
  5692  					return
  5693  				}
  5694  			}
  5695  		}()
  5696  		require.Truef(t, caught, "User should have received %s event", model.WEBSOCKET_EVENT_THREAD_FOLLOW_CHANGED)
  5697  	})
  5698  
  5699  	_, resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, th.BasicTeam.Id, rpost.Id, 123)
  5700  	CheckNoError(t, resp)
  5701  	CheckOKStatus(t, resp)
  5702  
  5703  	t.Run("Listed for read event", func(t *testing.T) {
  5704  		var caught bool
  5705  		func() {
  5706  			for {
  5707  				select {
  5708  				case ev := <-userWSClient.EventChannel:
  5709  					if ev.EventType() == model.WEBSOCKET_EVENT_THREAD_READ_CHANGED {
  5710  						caught = true
  5711  						require.EqualValues(t, ev.GetData()["timestamp"], 123)
  5712  					}
  5713  				case <-time.After(1 * time.Second):
  5714  					return
  5715  				}
  5716  			}
  5717  		}()
  5718  
  5719  		require.Truef(t, caught, "User should have received %s event", model.WEBSOCKET_EVENT_THREAD_READ_CHANGED)
  5720  	})
  5721  
  5722  }
  5723  
  5724  func TestFollowThreads(t *testing.T) {
  5725  	th := Setup(t).InitBasic()
  5726  	defer th.TearDown()
  5727  
  5728  	t.Run("1 thread", func(t *testing.T) {
  5729  		Client := th.Client
  5730  
  5731  		rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5732  		CheckNoError(t, resp)
  5733  		CheckCreatedStatus(t, resp)
  5734  		_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  5735  		CheckNoError(t, resp2)
  5736  		CheckCreatedStatus(t, resp2)
  5737  
  5738  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5739  		var uss *model.Threads
  5740  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5741  			Deleted: false,
  5742  		})
  5743  		CheckNoError(t, resp)
  5744  		require.Len(t, uss.Threads, 1)
  5745  
  5746  		resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rpost.Id, false)
  5747  		CheckNoError(t, resp)
  5748  		CheckOKStatus(t, resp)
  5749  
  5750  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5751  			Deleted: false,
  5752  		})
  5753  		CheckNoError(t, resp)
  5754  		require.Len(t, uss.Threads, 0)
  5755  
  5756  		resp = th.Client.UpdateThreadFollowForUser(th.BasicUser.Id, th.BasicTeam.Id, rpost.Id, true)
  5757  		CheckNoError(t, resp)
  5758  		CheckOKStatus(t, resp)
  5759  
  5760  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5761  			Deleted: false,
  5762  		})
  5763  		CheckNoError(t, resp)
  5764  		require.Len(t, uss.Threads, 1)
  5765  		require.GreaterOrEqual(t, uss.Threads[0].LastViewedAt, uss.Threads[0].LastReplyAt)
  5766  
  5767  	})
  5768  }
  5769  
  5770  func checkThreadListReplies(t *testing.T, th *TestHelper, client *model.Client4, userId string, expectedReplies, expectedThreads int, options *model.GetUserThreadsOpts) (*model.Threads, *model.Response) {
  5771  	opts := model.GetUserThreadsOpts{}
  5772  	if options != nil {
  5773  		opts = *options
  5774  	}
  5775  	u, r := client.GetUserThreads(userId, th.BasicTeam.Id, opts)
  5776  	CheckNoError(t, r)
  5777  	require.Len(t, u.Threads, expectedThreads)
  5778  
  5779  	count := int64(0)
  5780  	sum := int64(0)
  5781  	for _, thr := range u.Threads {
  5782  		if thr.UnreadReplies > 0 {
  5783  			count += 1
  5784  		}
  5785  		sum += thr.UnreadReplies
  5786  	}
  5787  	require.EqualValues(t, expectedReplies, sum, "expectedReplies don't match")
  5788  	require.Equal(t, count, u.TotalUnreadThreads, "TotalUnreadThreads don't match")
  5789  
  5790  	return u, r
  5791  }
  5792  
  5793  func postAndCheck(t *testing.T, client *model.Client4, post *model.Post) (*model.Post, *model.Response) {
  5794  	p, resp := client.CreatePost(post)
  5795  	CheckNoError(t, resp)
  5796  	CheckCreatedStatus(t, resp)
  5797  	return p, resp
  5798  }
  5799  
  5800  func TestMaintainUnreadRepliesInThread(t *testing.T) {
  5801  	th := Setup(t).InitBasic()
  5802  	defer th.TearDown()
  5803  	os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
  5804  	defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
  5805  	th.App.UpdateConfig(func(cfg *model.Config) {
  5806  		*cfg.ServiceSettings.ThreadAutoFollow = true
  5807  		*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
  5808  	})
  5809  
  5810  	Client := th.Client
  5811  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5812  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.SystemAdminUser.Id)
  5813  
  5814  	// create a post by regular user
  5815  	rpost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5816  	// reply with another
  5817  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  5818  
  5819  	// regular user should have one thread with one reply
  5820  	checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 1, 1, nil)
  5821  
  5822  	// add another reply by regular user
  5823  	postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply2", RootId: rpost.Id})
  5824  
  5825  	// replying to the thread clears reply count, so it should be 0
  5826  	checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 0, 1, nil)
  5827  
  5828  	// the other user should have 1 reply - the reply from the regular user
  5829  	checkThreadListReplies(t, th, th.SystemAdminClient, th.SystemAdminUser.Id, 1, 1, nil)
  5830  
  5831  	// mark all as read for user
  5832  	resp := th.Client.UpdateThreadsReadForUser(th.BasicUser.Id, th.BasicTeam.Id)
  5833  	CheckNoError(t, resp)
  5834  	CheckOKStatus(t, resp)
  5835  
  5836  	// reply count should be 0
  5837  	checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 0, 1, nil)
  5838  
  5839  	// mark other user's read state
  5840  	_, resp = th.SystemAdminClient.UpdateThreadReadForUser(th.SystemAdminUser.Id, th.BasicTeam.Id, rpost.Id, model.GetMillis())
  5841  	CheckNoError(t, resp)
  5842  	CheckOKStatus(t, resp)
  5843  
  5844  	// get unread only, should return nothing
  5845  	checkThreadListReplies(t, th, th.SystemAdminClient, th.SystemAdminUser.Id, 0, 0, &model.GetUserThreadsOpts{Unread: true})
  5846  
  5847  	// restore unread to an old date
  5848  	_, resp = th.SystemAdminClient.UpdateThreadReadForUser(th.SystemAdminUser.Id, th.BasicTeam.Id, rpost.Id, 123)
  5849  	CheckNoError(t, resp)
  5850  	CheckOKStatus(t, resp)
  5851  
  5852  	// should have 2 unread replies now
  5853  	checkThreadListReplies(t, th, th.SystemAdminClient, th.SystemAdminUser.Id, 2, 1, &model.GetUserThreadsOpts{Unread: true})
  5854  
  5855  }
  5856  
  5857  func TestThreadCounts(t *testing.T) {
  5858  	th := Setup(t).InitBasic()
  5859  	defer th.TearDown()
  5860  	os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
  5861  	defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
  5862  	th.App.UpdateConfig(func(cfg *model.Config) {
  5863  		*cfg.ServiceSettings.ThreadAutoFollow = true
  5864  		*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
  5865  	})
  5866  
  5867  	Client := th.Client
  5868  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5869  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.SystemAdminUser.Id)
  5870  
  5871  	// create a post by regular user
  5872  	rpost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5873  	// reply with another
  5874  	time.Sleep(1)
  5875  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  5876  
  5877  	// create another post by regular user
  5878  	time.Sleep(1)
  5879  	rpost2, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testMsg1"})
  5880  	// reply with another 2 times
  5881  	time.Sleep(1)
  5882  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testReply2", RootId: rpost2.Id})
  5883  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testReply22", RootId: rpost2.Id})
  5884  
  5885  	// regular user should have two threads with 3 replies total
  5886  	checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 3, 2, &model.GetUserThreadsOpts{
  5887  		Deleted: false,
  5888  	})
  5889  
  5890  	// delete first thread
  5891  	th.App.Srv().Store.Post().Delete(rpost.Id, model.GetMillis(), th.BasicUser.Id)
  5892  
  5893  	// we should now have 1 thread with 2 replies
  5894  	checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 2, 1, &model.GetUserThreadsOpts{
  5895  		Deleted: false,
  5896  	})
  5897  	// with Deleted we should get the same as before deleting
  5898  	checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 3, 2, &model.GetUserThreadsOpts{
  5899  		Deleted: true,
  5900  	})
  5901  }
  5902  
  5903  func TestSingleThreadGet(t *testing.T) {
  5904  	th := Setup(t).InitBasic()
  5905  	defer th.TearDown()
  5906  	os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
  5907  	defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
  5908  	th.App.UpdateConfig(func(cfg *model.Config) {
  5909  		*cfg.ServiceSettings.ThreadAutoFollow = true
  5910  		*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
  5911  	})
  5912  
  5913  	Client := th.Client
  5914  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5915  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.SystemAdminUser.Id)
  5916  
  5917  	// create a post by regular user
  5918  	rpost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5919  	// reply with another
  5920  	time.Sleep(1)
  5921  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  5922  
  5923  	// create another thread to check that we are not returning it by mistake
  5924  	rpost2, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testMsg2"})
  5925  	time.Sleep(1)
  5926  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testReply", RootId: rpost2.Id})
  5927  
  5928  	// regular user should have two threads with 3 replies total
  5929  	threads, _ := checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 2, 2, nil)
  5930  
  5931  	tr, resp := th.Client.GetUserThread(th.BasicUser.Id, th.BasicTeam.Id, threads.Threads[0].PostId, false)
  5932  	CheckNoError(t, resp)
  5933  	require.NotNil(t, tr)
  5934  	require.Equal(t, threads.Threads[0].PostId, tr.PostId)
  5935  	require.Empty(t, tr.Participants[0].Username)
  5936  
  5937  	tr, resp = th.Client.GetUserThread(th.BasicUser.Id, th.BasicTeam.Id, threads.Threads[0].PostId, true)
  5938  	CheckNoError(t, resp)
  5939  	require.NotEmpty(t, tr.Participants[0].Username)
  5940  }
  5941  
  5942  func TestMaintainUnreadMentionsInThread(t *testing.T) {
  5943  	th := Setup(t).InitBasic()
  5944  	defer th.TearDown()
  5945  	Client := th.Client
  5946  	os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
  5947  	defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
  5948  	th.App.UpdateConfig(func(cfg *model.Config) {
  5949  		*cfg.ServiceSettings.ThreadAutoFollow = true
  5950  		*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
  5951  	})
  5952  	checkThreadList := func(client *model.Client4, userId string, expectedMentions, expectedThreads int) (*model.Threads, *model.Response) {
  5953  		uss, resp := client.GetUserThreads(userId, th.BasicTeam.Id, model.GetUserThreadsOpts{
  5954  			Deleted: false,
  5955  		})
  5956  		CheckNoError(t, resp)
  5957  
  5958  		require.Len(t, uss.Threads, expectedThreads)
  5959  		sum := int64(0)
  5960  		for _, thr := range uss.Threads {
  5961  			sum += thr.UnreadMentions
  5962  		}
  5963  		require.Equal(t, sum, uss.TotalUnreadMentions)
  5964  		require.EqualValues(t, expectedMentions, uss.TotalUnreadMentions)
  5965  
  5966  		return uss, resp
  5967  	}
  5968  
  5969  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  5970  	defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.SystemAdminUser.Id)
  5971  
  5972  	// create regular post
  5973  	rpost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  5974  	// create reply and mention the original poster and another user
  5975  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply @" + th.BasicUser.Username + " and @" + th.BasicUser2.Username, RootId: rpost.Id})
  5976  
  5977  	// basic user 1 was mentioned 1 time
  5978  	checkThreadList(th.Client, th.BasicUser.Id, 1, 1)
  5979  	// basic user 2 was mentioned 1 time
  5980  	checkThreadList(th.SystemAdminClient, th.BasicUser2.Id, 1, 1)
  5981  
  5982  	// test self mention, shouldn't increase mention count
  5983  	postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply @" + th.BasicUser.Username, RootId: rpost.Id})
  5984  	// count shouldn't increase
  5985  	checkThreadList(th.Client, th.BasicUser.Id, 1, 1)
  5986  
  5987  	// test DM
  5988  	dm := th.CreateDmChannel(th.SystemAdminUser)
  5989  	dm_root_post, _ := postAndCheck(t, Client, &model.Post{ChannelId: dm.Id, Message: "hi @" + th.SystemAdminUser.Username})
  5990  
  5991  	// no changes
  5992  	checkThreadList(th.Client, th.BasicUser.Id, 1, 1)
  5993  
  5994  	// post reply by the same user
  5995  	postAndCheck(t, Client, &model.Post{ChannelId: dm.Id, Message: "how are you", RootId: dm_root_post.Id})
  5996  
  5997  	// thread created
  5998  	checkThreadList(th.Client, th.BasicUser.Id, 1, 2)
  5999  
  6000  	// post two replies by another user, without mentions. mention count should still increase since this is a DM
  6001  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: dm.Id, Message: "msg1", RootId: dm_root_post.Id})
  6002  	postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: dm.Id, Message: "msg2", RootId: dm_root_post.Id})
  6003  	// expect increment by two mentions
  6004  	checkThreadList(th.Client, th.BasicUser.Id, 3, 2)
  6005  }
  6006  
  6007  func TestReadThreads(t *testing.T) {
  6008  	th := Setup(t).InitBasic()
  6009  	defer th.TearDown()
  6010  	os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
  6011  	defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
  6012  	th.App.UpdateConfig(func(cfg *model.Config) {
  6013  		*cfg.ServiceSettings.ThreadAutoFollow = true
  6014  		*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
  6015  	})
  6016  	Client := th.Client
  6017  	t.Run("all threads", func(t *testing.T) {
  6018  
  6019  		rpost, resp := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg"})
  6020  		CheckNoError(t, resp)
  6021  		CheckCreatedStatus(t, resp)
  6022  		_, resp2 := Client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
  6023  		CheckNoError(t, resp2)
  6024  		CheckCreatedStatus(t, resp2)
  6025  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  6026  
  6027  		var uss, uss2 *model.Threads
  6028  		uss, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  6029  			Deleted: false,
  6030  		})
  6031  		CheckNoError(t, resp)
  6032  		require.Len(t, uss.Threads, 1)
  6033  
  6034  		time.Sleep(1)
  6035  		resp = th.Client.UpdateThreadsReadForUser(th.BasicUser.Id, th.BasicTeam.Id)
  6036  		CheckNoError(t, resp)
  6037  		CheckOKStatus(t, resp)
  6038  
  6039  		uss2, resp = th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{
  6040  			Deleted: false,
  6041  		})
  6042  		CheckNoError(t, resp)
  6043  		require.Len(t, uss2.Threads, 1)
  6044  		require.Greater(t, uss2.Threads[0].LastViewedAt, uss.Threads[0].LastViewedAt)
  6045  	})
  6046  
  6047  	t.Run("1 thread", func(t *testing.T) {
  6048  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.BasicUser.Id)
  6049  		defer th.App.Srv().Store.Post().PermanentDeleteByUser(th.SystemAdminUser.Id)
  6050  
  6051  		rpost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsgC1"})
  6052  		postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReplyC1", RootId: rpost.Id})
  6053  
  6054  		rrpost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testMsgC2"})
  6055  		postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testReplyC2", RootId: rrpost.Id})
  6056  
  6057  		uss, _ := checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 2, 2, nil)
  6058  
  6059  		_, resp := th.Client.UpdateThreadReadForUser(th.BasicUser.Id, th.BasicTeam.Id, rrpost.Id, model.GetMillis()+10)
  6060  		CheckNoError(t, resp)
  6061  		CheckOKStatus(t, resp)
  6062  
  6063  		uss2, _ := checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 1, 2, nil)
  6064  		require.Greater(t, uss2.Threads[0].LastViewedAt, uss.Threads[0].LastViewedAt)
  6065  
  6066  		timestamp := model.GetMillis()
  6067  		_, resp = th.Client.UpdateThreadReadForUser(th.BasicUser.Id, th.BasicTeam.Id, rrpost.Id, timestamp)
  6068  		CheckNoError(t, resp)
  6069  		CheckOKStatus(t, resp)
  6070  
  6071  		uss3, _ := checkThreadListReplies(t, th, th.Client, th.BasicUser.Id, 1, 2, nil)
  6072  		require.Equal(t, uss3.Threads[0].LastViewedAt, timestamp)
  6073  	})
  6074  }
  6075  
  6076  func TestMarkThreadUnreadMentionCount(t *testing.T) {
  6077  	th := Setup(t).InitBasic()
  6078  	defer th.TearDown()
  6079  	os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
  6080  	defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
  6081  	th.App.UpdateConfig(func(cfg *model.Config) {
  6082  		*cfg.ServiceSettings.ThreadAutoFollow = true
  6083  		*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
  6084  	})
  6085  	Client := th.Client
  6086  
  6087  	channel := th.BasicChannel
  6088  	user := th.BasicUser
  6089  	user2 := th.BasicUser2
  6090  	appErr := th.App.JoinChannel(th.Context, channel, user.Id)
  6091  	require.Nil(t, appErr)
  6092  	appErr = th.App.JoinChannel(th.Context, channel, user2.Id)
  6093  	require.Nil(t, appErr)
  6094  
  6095  	rpost, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testMsg @" + th.BasicUser2.Username})
  6096  	time.Sleep(1)
  6097  	reply, _ := postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply1", RootId: rpost.Id})
  6098  	time.Sleep(1)
  6099  	postAndCheck(t, Client, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply2", RootId: rpost.Id})
  6100  
  6101  	th.SystemAdminClient.UpdateThreadReadForUser(th.BasicUser2.Id, th.BasicTeam.Id, rpost.Id, model.GetMillis())
  6102  
  6103  	u, _ := th.SystemAdminClient.GetUserThreads(th.BasicUser2.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
  6104  	require.EqualValues(t, 0, u.TotalUnreadMentions)
  6105  
  6106  	th.SystemAdminClient.UpdateThreadReadForUser(th.BasicUser2.Id, th.BasicTeam.Id, rpost.Id, rpost.CreateAt)
  6107  
  6108  	u, _ = th.SystemAdminClient.GetUserThreads(th.BasicUser2.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
  6109  	require.EqualValues(t, 1, u.TotalUnreadMentions)
  6110  
  6111  	th.SystemAdminClient.UpdateThreadReadForUser(th.BasicUser2.Id, th.BasicTeam.Id, rpost.Id, reply.CreateAt)
  6112  
  6113  	u, _ = th.SystemAdminClient.GetUserThreads(th.BasicUser2.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
  6114  	require.EqualValues(t, 0, u.TotalUnreadMentions)
  6115  }
  6116  
  6117  func TestPatchAndUpdateWithProviderAttributes(t *testing.T) {
  6118  	t.Run("LDAP user", func(t *testing.T) {
  6119  		th := SetupEnterprise(t).InitBasic()
  6120  		defer th.TearDown()
  6121  		user := th.CreateUserWithAuth(model.USER_AUTH_SERVICE_LDAP)
  6122  		ldapMock := &mocks.LdapInterface{}
  6123  		ldapMock.Mock.On(
  6124  			"CheckProviderAttributes",
  6125  			mock.Anything, // app.AppIface
  6126  			mock.Anything, // *model.User
  6127  			mock.Anything, // *model.Patch
  6128  		).Return("")
  6129  		th.App.Srv().Ldap = ldapMock
  6130  		// CheckProviderAttributes should be called for both Patch and Update
  6131  		th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{})
  6132  		ldapMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1)
  6133  		th.SystemAdminClient.UpdateUser(user)
  6134  		ldapMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 2)
  6135  	})
  6136  	t.Run("SAML user", func(t *testing.T) {
  6137  		t.Run("with LDAP sync", func(t *testing.T) {
  6138  			th := SetupEnterprise(t).InitBasic()
  6139  			defer th.TearDown()
  6140  			th.SetupLdapConfig()
  6141  			th.SetupSamlConfig()
  6142  			th.App.UpdateConfig(func(cfg *model.Config) {
  6143  				*cfg.SamlSettings.EnableSyncWithLdap = true
  6144  			})
  6145  			user := th.CreateUserWithAuth(model.USER_AUTH_SERVICE_SAML)
  6146  			ldapMock := &mocks.LdapInterface{}
  6147  			ldapMock.Mock.On(
  6148  				"CheckProviderAttributes", mock.Anything, mock.Anything, mock.Anything,
  6149  			).Return("")
  6150  			th.App.Srv().Ldap = ldapMock
  6151  			th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{})
  6152  			ldapMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1)
  6153  			th.SystemAdminClient.UpdateUser(user)
  6154  			ldapMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 2)
  6155  		})
  6156  		t.Run("without LDAP sync", func(t *testing.T) {
  6157  			th := SetupEnterprise(t).InitBasic()
  6158  			defer th.TearDown()
  6159  			user := th.CreateUserWithAuth(model.USER_AUTH_SERVICE_SAML)
  6160  			samlMock := &mocks.SamlInterface{}
  6161  			samlMock.Mock.On(
  6162  				"CheckProviderAttributes", mock.Anything, mock.Anything, mock.Anything,
  6163  			).Return("")
  6164  			th.App.Srv().Saml = samlMock
  6165  			th.SystemAdminClient.PatchUser(user.Id, &model.UserPatch{})
  6166  			samlMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 1)
  6167  			th.SystemAdminClient.UpdateUser(user)
  6168  			samlMock.AssertNumberOfCalls(t, "CheckProviderAttributes", 2)
  6169  		})
  6170  	})
  6171  	t.Run("OpenID user", func(t *testing.T) {
  6172  		th := SetupEnterprise(t).InitBasic()
  6173  		defer th.TearDown()
  6174  		user := th.CreateUserWithAuth(model.SERVICE_OPENID)
  6175  		// OAUTH users cannot change these fields
  6176  		for _, fieldName := range []string{
  6177  			"FirstName",
  6178  			"LastName",
  6179  		} {
  6180  			patch := user.ToPatch()
  6181  			patch.SetField(fieldName, "something new")
  6182  			conflictField := th.App.CheckProviderAttributes(user, patch)
  6183  			require.NotEqual(t, "", conflictField)
  6184  		}
  6185  	})
  6186  	t.Run("Patch username", func(t *testing.T) {
  6187  		th := SetupEnterprise(t).InitBasic()
  6188  		defer th.TearDown()
  6189  		// For non-email users, the username must be changed through the provider
  6190  		for _, authService := range []string{
  6191  			model.USER_AUTH_SERVICE_LDAP,
  6192  			model.USER_AUTH_SERVICE_SAML,
  6193  			model.SERVICE_OPENID,
  6194  		} {
  6195  			user := th.CreateUserWithAuth(authService)
  6196  			patch := &model.UserPatch{Username: model.NewString("something new")}
  6197  			conflictField := th.App.CheckProviderAttributes(user, patch)
  6198  			require.NotEqual(t, "", conflictField)
  6199  		}
  6200  	})
  6201  }
  6202  
  6203  func TestSetProfileImageWithProviderAttributes(t *testing.T) {
  6204  	data, err := testutils.ReadTestFile("test.png")
  6205  	require.NoError(t, err)
  6206  
  6207  	type imageTestCase struct {
  6208  		testName      string
  6209  		ldapAttrIsSet bool
  6210  		shouldPass    bool
  6211  	}
  6212  
  6213  	doImageTest := func(t *testing.T, th *TestHelper, user *model.User, testCase imageTestCase) {
  6214  		client := th.SystemAdminClient
  6215  		t.Run(testCase.testName, func(t *testing.T) {
  6216  			th.App.UpdateConfig(func(cfg *model.Config) {
  6217  				if testCase.ldapAttrIsSet {
  6218  					*cfg.LdapSettings.PictureAttribute = "jpegPhoto"
  6219  				} else {
  6220  					*cfg.LdapSettings.PictureAttribute = ""
  6221  				}
  6222  			})
  6223  			ok, resp := client.SetProfileImage(user.Id, data)
  6224  			if testCase.shouldPass {
  6225  				require.True(t, ok)
  6226  				CheckNoError(t, resp)
  6227  			} else {
  6228  				require.False(t, ok)
  6229  				checkHTTPStatus(t, resp, http.StatusConflict, true)
  6230  			}
  6231  		})
  6232  	}
  6233  	doCleanup := func(t *testing.T, th *TestHelper, user *model.User) {
  6234  		info := &model.FileInfo{Path: "users/" + user.Id + "/profile.png"}
  6235  		err = th.cleanupTestFile(info)
  6236  		require.NoError(t, err)
  6237  	}
  6238  
  6239  	t.Run("LDAP user", func(t *testing.T) {
  6240  		testCases := []imageTestCase{
  6241  			{"profile picture attribute is set", true, false},
  6242  			{"profile picture attribute is not set", false, true},
  6243  		}
  6244  		th := SetupEnterprise(t).InitBasic()
  6245  		defer th.TearDown()
  6246  		th.SetupLdapConfig()
  6247  		user := th.CreateUserWithAuth(model.USER_AUTH_SERVICE_LDAP)
  6248  		for _, testCase := range testCases {
  6249  			doImageTest(t, th, user, testCase)
  6250  		}
  6251  		doCleanup(t, th, user)
  6252  	})
  6253  
  6254  	t.Run("SAML user", func(t *testing.T) {
  6255  		th := SetupEnterprise(t).InitBasic()
  6256  		defer th.TearDown()
  6257  		th.SetupLdapConfig()
  6258  		th.SetupSamlConfig()
  6259  		user := th.CreateUserWithAuth(model.USER_AUTH_SERVICE_SAML)
  6260  
  6261  		t.Run("with LDAP sync", func(t *testing.T) {
  6262  			th.App.UpdateConfig(func(cfg *model.Config) {
  6263  				*cfg.SamlSettings.EnableSyncWithLdap = true
  6264  			})
  6265  			testCases := []imageTestCase{
  6266  				{"profile picture attribute is set", true, false},
  6267  				{"profile picture attribute is not set", false, true},
  6268  			}
  6269  			for _, testCase := range testCases {
  6270  				doImageTest(t, th, user, testCase)
  6271  			}
  6272  		})
  6273  		t.Run("without LDAP sync", func(t *testing.T) {
  6274  			th.App.UpdateConfig(func(cfg *model.Config) {
  6275  				*cfg.SamlSettings.EnableSyncWithLdap = false
  6276  			})
  6277  			testCases := []imageTestCase{
  6278  				{"profile picture attribute is set", true, true},
  6279  				{"profile picture attribute is not set", false, true},
  6280  			}
  6281  			for _, testCase := range testCases {
  6282  				doImageTest(t, th, user, testCase)
  6283  			}
  6284  		})
  6285  		doCleanup(t, th, user)
  6286  	})
  6287  }