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