github.com/jlevesy/mattermost-server@v5.3.2-0.20181003190404-7468f35cb0c8+incompatible/app/user_test.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"image"
    10  	"image/color"
    11  	"math/rand"
    12  	"strings"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  
    19  	"github.com/mattermost/mattermost-server/einterfaces"
    20  	"github.com/mattermost/mattermost-server/model"
    21  	"github.com/mattermost/mattermost-server/model/gitlab"
    22  )
    23  
    24  func TestIsUsernameTaken(t *testing.T) {
    25  	th := Setup().InitBasic()
    26  	defer th.TearDown()
    27  
    28  	user := th.BasicUser
    29  	taken := th.App.IsUsernameTaken(user.Username)
    30  
    31  	if !taken {
    32  		t.Logf("the username '%v' should be taken", user.Username)
    33  		t.FailNow()
    34  	}
    35  
    36  	newUsername := "randomUsername"
    37  	taken = th.App.IsUsernameTaken(newUsername)
    38  
    39  	if taken {
    40  		t.Logf("the username '%v' should not be taken", newUsername)
    41  		t.FailNow()
    42  	}
    43  }
    44  
    45  func TestCheckUserDomain(t *testing.T) {
    46  	th := Setup().InitBasic()
    47  	defer th.TearDown()
    48  
    49  	user := th.BasicUser
    50  
    51  	cases := []struct {
    52  		domains string
    53  		matched bool
    54  	}{
    55  		{"simulator.amazonses.com", true},
    56  		{"gmail.com", false},
    57  		{"", true},
    58  		{"gmail.com simulator.amazonses.com", true},
    59  	}
    60  	for _, c := range cases {
    61  		matched := CheckUserDomain(user, c.domains)
    62  		if matched != c.matched {
    63  			if c.matched {
    64  				t.Logf("'%v' should have matched '%v'", user.Email, c.domains)
    65  			} else {
    66  				t.Logf("'%v' should not have matched '%v'", user.Email, c.domains)
    67  			}
    68  			t.FailNow()
    69  		}
    70  	}
    71  }
    72  
    73  func TestCreateOAuthUser(t *testing.T) {
    74  	th := Setup().InitBasic()
    75  	defer th.TearDown()
    76  
    77  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
    78  	glUser := oauthgitlab.GitLabUser{Id: int64(r.Intn(1000)) + 1, Username: "o" + model.NewId(), Email: model.NewId() + "@simulator.amazonses.com", Name: "Joram Wilander"}
    79  
    80  	json := glUser.ToJson()
    81  	user, err := th.App.CreateOAuthUser(model.USER_AUTH_SERVICE_GITLAB, strings.NewReader(json), th.BasicTeam.Id)
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	if user.Username != glUser.Username {
    87  		t.Fatal("usernames didn't match")
    88  	}
    89  
    90  	th.App.PermanentDeleteUser(user)
    91  
    92  	*th.App.Config().TeamSettings.EnableUserCreation = false
    93  
    94  	_, err = th.App.CreateOAuthUser(model.USER_AUTH_SERVICE_GITLAB, strings.NewReader(json), th.BasicTeam.Id)
    95  	if err == nil {
    96  		t.Fatal("should have failed - user creation disabled")
    97  	}
    98  }
    99  
   100  func TestCreateProfileImage(t *testing.T) {
   101  	b, err := CreateProfileImage("Corey Hulen", "eo1zkdr96pdj98pjmq8zy35wba", "nunito-bold.ttf")
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  
   106  	rdr := bytes.NewReader(b)
   107  	img, _, err2 := image.Decode(rdr)
   108  	if err2 != nil {
   109  		t.Fatal(err)
   110  	}
   111  
   112  	colorful := color.RGBA{116, 49, 196, 255}
   113  
   114  	if img.At(1, 1) != colorful {
   115  		t.Fatal("Failed to create correct color")
   116  	}
   117  }
   118  
   119  func TestSetDefaultProfileImage(t *testing.T) {
   120  	th := Setup().InitBasic()
   121  	defer th.TearDown()
   122  
   123  	err := th.App.SetDefaultProfileImage(&model.User{
   124  		Id:       model.NewId(),
   125  		Username: "notvaliduser",
   126  	})
   127  	require.Error(t, err)
   128  
   129  	user := th.BasicUser
   130  
   131  	err = th.App.SetDefaultProfileImage(user)
   132  	require.Nil(t, err)
   133  
   134  	user = getUserFromDB(th.App, user.Id, t)
   135  	assert.Equal(t, int64(0), user.LastPictureUpdate)
   136  }
   137  
   138  func TestUpdateUserToRestrictedDomain(t *testing.T) {
   139  	th := Setup()
   140  	defer th.TearDown()
   141  
   142  	user := th.CreateUser()
   143  	defer th.App.PermanentDeleteUser(user)
   144  
   145  	th.App.UpdateConfig(func(cfg *model.Config) {
   146  		cfg.TeamSettings.RestrictCreationToDomains = "foo.com"
   147  	})
   148  
   149  	_, err := th.App.UpdateUser(user, false)
   150  	assert.True(t, err == nil)
   151  
   152  	user.Email = "asdf@ghjk.l"
   153  	_, err = th.App.UpdateUser(user, false)
   154  	assert.False(t, err == nil)
   155  }
   156  
   157  func TestUpdateOAuthUserAttrs(t *testing.T) {
   158  	th := Setup()
   159  	defer th.TearDown()
   160  
   161  	id := model.NewId()
   162  	id2 := model.NewId()
   163  	gitlabProvider := einterfaces.GetOauthProvider("gitlab")
   164  
   165  	username := "user" + id
   166  	username2 := "user" + id2
   167  
   168  	email := "user" + id + "@nowhere.com"
   169  	email2 := "user" + id2 + "@nowhere.com"
   170  
   171  	var user, user2 *model.User
   172  	var gitlabUserObj oauthgitlab.GitLabUser
   173  	user, gitlabUserObj = createGitlabUser(t, th.App, username, email)
   174  	user2, _ = createGitlabUser(t, th.App, username2, email2)
   175  
   176  	t.Run("UpdateUsername", func(t *testing.T) {
   177  		t.Run("NoExistingUserWithSameUsername", func(t *testing.T) {
   178  			gitlabUserObj.Username = "updateduser" + model.NewId()
   179  			gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
   180  			data := bytes.NewReader(gitlabUser)
   181  
   182  			user = getUserFromDB(th.App, user.Id, t)
   183  			th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
   184  			user = getUserFromDB(th.App, user.Id, t)
   185  
   186  			if user.Username != gitlabUserObj.Username {
   187  				t.Fatal("user's username is not updated")
   188  			}
   189  		})
   190  
   191  		t.Run("ExistinguserWithSameUsername", func(t *testing.T) {
   192  			gitlabUserObj.Username = user2.Username
   193  
   194  			gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
   195  			data := bytes.NewReader(gitlabUser)
   196  
   197  			user = getUserFromDB(th.App, user.Id, t)
   198  			th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
   199  			user = getUserFromDB(th.App, user.Id, t)
   200  
   201  			if user.Username == gitlabUserObj.Username {
   202  				t.Fatal("user's username is updated though there already exists another user with the same username")
   203  			}
   204  		})
   205  	})
   206  
   207  	t.Run("UpdateEmail", func(t *testing.T) {
   208  		t.Run("NoExistingUserWithSameEmail", func(t *testing.T) {
   209  			gitlabUserObj.Email = "newuser" + model.NewId() + "@nowhere.com"
   210  			gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
   211  			data := bytes.NewReader(gitlabUser)
   212  
   213  			user = getUserFromDB(th.App, user.Id, t)
   214  			th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
   215  			user = getUserFromDB(th.App, user.Id, t)
   216  
   217  			if user.Email != gitlabUserObj.Email {
   218  				t.Fatal("user's email is not updated")
   219  			}
   220  
   221  			if !user.EmailVerified {
   222  				t.Fatal("user's email should have been verified")
   223  			}
   224  		})
   225  
   226  		t.Run("ExistingUserWithSameEmail", func(t *testing.T) {
   227  			gitlabUserObj.Email = user2.Email
   228  
   229  			gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
   230  			data := bytes.NewReader(gitlabUser)
   231  
   232  			user = getUserFromDB(th.App, user.Id, t)
   233  			th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
   234  			user = getUserFromDB(th.App, user.Id, t)
   235  
   236  			if user.Email == gitlabUserObj.Email {
   237  				t.Fatal("user's email is updated though there already exists another user with the same email")
   238  			}
   239  		})
   240  	})
   241  
   242  	t.Run("UpdateFirstName", func(t *testing.T) {
   243  		gitlabUserObj.Name = "Updated User"
   244  		gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
   245  		data := bytes.NewReader(gitlabUser)
   246  
   247  		user = getUserFromDB(th.App, user.Id, t)
   248  		th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
   249  		user = getUserFromDB(th.App, user.Id, t)
   250  
   251  		if user.FirstName != "Updated" {
   252  			t.Fatal("user's first name is not updated")
   253  		}
   254  	})
   255  
   256  	t.Run("UpdateLastName", func(t *testing.T) {
   257  		gitlabUserObj.Name = "Updated Lastname"
   258  		gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
   259  		data := bytes.NewReader(gitlabUser)
   260  
   261  		user = getUserFromDB(th.App, user.Id, t)
   262  		th.App.UpdateOAuthUserAttrs(data, user, gitlabProvider, "gitlab")
   263  		user = getUserFromDB(th.App, user.Id, t)
   264  
   265  		if user.LastName != "Lastname" {
   266  			t.Fatal("user's last name is not updated")
   267  		}
   268  	})
   269  }
   270  
   271  func getUserFromDB(a *App, id string, t *testing.T) *model.User {
   272  	user, err := a.GetUser(id)
   273  	if err != nil {
   274  		t.Fatal("user is not found", err)
   275  		return nil
   276  	}
   277  	return user
   278  }
   279  
   280  func getGitlabUserPayload(gitlabUser oauthgitlab.GitLabUser, t *testing.T) []byte {
   281  	var payload []byte
   282  	var err error
   283  	if payload, err = json.Marshal(gitlabUser); err != nil {
   284  		t.Fatal("Serialization of gitlab user to json failed", err)
   285  	}
   286  
   287  	return payload
   288  }
   289  
   290  func createGitlabUser(t *testing.T, a *App, username string, email string) (*model.User, oauthgitlab.GitLabUser) {
   291  	r := rand.New(rand.NewSource(time.Now().UnixNano()))
   292  	gitlabUserObj := oauthgitlab.GitLabUser{Id: int64(r.Intn(1000)) + 1, Username: username, Login: "user1", Email: email, Name: "Test User"}
   293  	gitlabUser := getGitlabUserPayload(gitlabUserObj, t)
   294  
   295  	var user *model.User
   296  	var err *model.AppError
   297  
   298  	if user, err = a.CreateOAuthUser("gitlab", bytes.NewReader(gitlabUser), ""); err != nil {
   299  		t.Fatal("unable to create the user", err)
   300  	}
   301  
   302  	return user, gitlabUserObj
   303  }
   304  
   305  func TestGetUsersByStatus(t *testing.T) {
   306  	th := Setup()
   307  	defer th.TearDown()
   308  
   309  	team := th.CreateTeam()
   310  	channel, err := th.App.CreateChannel(&model.Channel{
   311  		DisplayName: "dn_" + model.NewId(),
   312  		Name:        "name_" + model.NewId(),
   313  		Type:        model.CHANNEL_OPEN,
   314  		TeamId:      team.Id,
   315  		CreatorId:   model.NewId(),
   316  	}, false)
   317  	if err != nil {
   318  		t.Fatalf("failed to create channel: %v", err)
   319  	}
   320  
   321  	createUserWithStatus := func(username string, status string) *model.User {
   322  		id := model.NewId()
   323  
   324  		user, err := th.App.CreateUser(&model.User{
   325  			Email:    "success+" + id + "@simulator.amazonses.com",
   326  			Username: "un_" + username + "_" + id,
   327  			Nickname: "nn_" + id,
   328  			Password: "Password1",
   329  		})
   330  		if err != nil {
   331  			t.Fatalf("failed to create user: %v", err)
   332  		}
   333  
   334  		th.LinkUserToTeam(user, team)
   335  		th.AddUserToChannel(user, channel)
   336  
   337  		th.App.SaveAndBroadcastStatus(&model.Status{
   338  			UserId: user.Id,
   339  			Status: status,
   340  			Manual: true,
   341  		})
   342  
   343  		return user
   344  	}
   345  
   346  	// Creating these out of order in case that affects results
   347  	awayUser1 := createUserWithStatus("away1", model.STATUS_AWAY)
   348  	awayUser2 := createUserWithStatus("away2", model.STATUS_AWAY)
   349  	dndUser1 := createUserWithStatus("dnd1", model.STATUS_DND)
   350  	dndUser2 := createUserWithStatus("dnd2", model.STATUS_DND)
   351  	offlineUser1 := createUserWithStatus("offline1", model.STATUS_OFFLINE)
   352  	offlineUser2 := createUserWithStatus("offline2", model.STATUS_OFFLINE)
   353  	onlineUser1 := createUserWithStatus("online1", model.STATUS_ONLINE)
   354  	onlineUser2 := createUserWithStatus("online2", model.STATUS_ONLINE)
   355  
   356  	t.Run("sorting by status then alphabetical", func(t *testing.T) {
   357  		usersByStatus, err := th.App.GetUsersInChannelPageByStatus(channel.Id, 0, 8, true)
   358  		if err != nil {
   359  			t.Fatal(err)
   360  		}
   361  
   362  		expectedUsersByStatus := []*model.User{
   363  			onlineUser1,
   364  			onlineUser2,
   365  			awayUser1,
   366  			awayUser2,
   367  			dndUser1,
   368  			dndUser2,
   369  			offlineUser1,
   370  			offlineUser2,
   371  		}
   372  
   373  		if len(usersByStatus) != len(expectedUsersByStatus) {
   374  			t.Fatalf("received only %v users, expected %v", len(usersByStatus), len(expectedUsersByStatus))
   375  		}
   376  
   377  		for i := range usersByStatus {
   378  			if usersByStatus[i].Id != expectedUsersByStatus[i].Id {
   379  				t.Fatalf("received user %v at index %v, expected %v", usersByStatus[i].Username, i, expectedUsersByStatus[i].Username)
   380  			}
   381  		}
   382  	})
   383  
   384  	t.Run("paging", func(t *testing.T) {
   385  		usersByStatus, err := th.App.GetUsersInChannelPageByStatus(channel.Id, 0, 3, true)
   386  		if err != nil {
   387  			t.Fatal(err)
   388  		}
   389  
   390  		if len(usersByStatus) != 3 {
   391  			t.Fatal("received too many users")
   392  		}
   393  
   394  		if usersByStatus[0].Id != onlineUser1.Id && usersByStatus[1].Id != onlineUser2.Id {
   395  			t.Fatal("expected to receive online users first")
   396  		}
   397  
   398  		if usersByStatus[2].Id != awayUser1.Id {
   399  			t.Fatal("expected to receive away users second")
   400  		}
   401  
   402  		usersByStatus, err = th.App.GetUsersInChannelPageByStatus(channel.Id, 1, 3, true)
   403  		if err != nil {
   404  			t.Fatal(err)
   405  		}
   406  
   407  		if usersByStatus[0].Id != awayUser2.Id {
   408  			t.Fatal("expected to receive away users second")
   409  		}
   410  
   411  		if usersByStatus[1].Id != dndUser1.Id && usersByStatus[2].Id != dndUser2.Id {
   412  			t.Fatal("expected to receive dnd users third")
   413  		}
   414  
   415  		usersByStatus, err = th.App.GetUsersInChannelPageByStatus(channel.Id, 1, 4, true)
   416  		if err != nil {
   417  			t.Fatal(err)
   418  		}
   419  
   420  		if len(usersByStatus) != 4 {
   421  			t.Fatal("received too many users")
   422  		}
   423  
   424  		if usersByStatus[0].Id != dndUser1.Id && usersByStatus[1].Id != dndUser2.Id {
   425  			t.Fatal("expected to receive dnd users third")
   426  		}
   427  
   428  		if usersByStatus[2].Id != offlineUser1.Id && usersByStatus[3].Id != offlineUser2.Id {
   429  			t.Fatal("expected to receive offline users last")
   430  		}
   431  	})
   432  }
   433  
   434  func TestCreateUserWithToken(t *testing.T) {
   435  	th := Setup().InitBasic()
   436  	defer th.TearDown()
   437  
   438  	user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""}
   439  
   440  	t.Run("invalid token", func(t *testing.T) {
   441  		if _, err := th.App.CreateUserWithToken(&user, "123"); err == nil {
   442  			t.Fatal("Should fail on unexisting token")
   443  		}
   444  	})
   445  
   446  	t.Run("invalid token type", func(t *testing.T) {
   447  		token := model.NewToken(
   448  			TOKEN_TYPE_VERIFY_EMAIL,
   449  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   450  		)
   451  		<-th.App.Srv.Store.Token().Save(token)
   452  		defer th.App.DeleteToken(token)
   453  		if _, err := th.App.CreateUserWithToken(&user, token.Token); err == nil {
   454  			t.Fatal("Should fail on bad token type")
   455  		}
   456  	})
   457  
   458  	t.Run("expired token", func(t *testing.T) {
   459  		token := model.NewToken(
   460  			TOKEN_TYPE_TEAM_INVITATION,
   461  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": user.Email}),
   462  		)
   463  		token.CreateAt = model.GetMillis() - TEAM_INVITATION_EXPIRY_TIME - 1
   464  		<-th.App.Srv.Store.Token().Save(token)
   465  		defer th.App.DeleteToken(token)
   466  		if _, err := th.App.CreateUserWithToken(&user, token.Token); err == nil {
   467  			t.Fatal("Should fail on expired token")
   468  		}
   469  	})
   470  
   471  	t.Run("invalid team id", func(t *testing.T) {
   472  		token := model.NewToken(
   473  			TOKEN_TYPE_TEAM_INVITATION,
   474  			model.MapToJson(map[string]string{"teamId": model.NewId(), "email": user.Email}),
   475  		)
   476  		<-th.App.Srv.Store.Token().Save(token)
   477  		defer th.App.DeleteToken(token)
   478  		if _, err := th.App.CreateUserWithToken(&user, token.Token); err == nil {
   479  			t.Fatal("Should fail on bad team id")
   480  		}
   481  	})
   482  
   483  	t.Run("valid request", func(t *testing.T) {
   484  		invitationEmail := model.NewId() + "other-email@test.com"
   485  		token := model.NewToken(
   486  			TOKEN_TYPE_TEAM_INVITATION,
   487  			model.MapToJson(map[string]string{"teamId": th.BasicTeam.Id, "email": invitationEmail}),
   488  		)
   489  		<-th.App.Srv.Store.Token().Save(token)
   490  		newUser, err := th.App.CreateUserWithToken(&user, token.Token)
   491  		if err != nil {
   492  			t.Log(err)
   493  			t.Fatal("Should add user to the team")
   494  		}
   495  		if newUser.Email != invitationEmail {
   496  			t.Fatal("The user email must be the invitation one")
   497  		}
   498  		if result := <-th.App.Srv.Store.Token().GetByToken(token.Token); result.Err == nil {
   499  			t.Fatal("The token must be deleted after be used")
   500  		}
   501  	})
   502  }
   503  
   504  func TestPermanentDeleteUser(t *testing.T) {
   505  	th := Setup().InitBasic()
   506  	defer th.TearDown()
   507  
   508  	b := []byte("testimage")
   509  
   510  	finfo, err := th.App.DoUploadFile(time.Now(), th.BasicTeam.Id, th.BasicChannel.Id, th.BasicUser.Id, "testfile.txt", b)
   511  
   512  	if err != nil {
   513  		t.Log(err)
   514  		t.Fatal("Unable to upload file")
   515  	}
   516  
   517  	err = th.App.PermanentDeleteUser(th.BasicUser)
   518  	if err != nil {
   519  		t.Log(err)
   520  		t.Fatal("Unable to delete user")
   521  	}
   522  
   523  	res, err := th.App.FileExists(finfo.Path)
   524  
   525  	if err != nil {
   526  		t.Log(err)
   527  		t.Fatal("Unable to check whether file exists")
   528  	}
   529  
   530  	if res {
   531  		t.Log(err)
   532  		t.Fatal("File was not deleted on FS")
   533  	}
   534  
   535  	finfo, err = th.App.GetFileInfo(finfo.Id)
   536  
   537  	if finfo != nil {
   538  		t.Log(err)
   539  		t.Fatal("Unable to find finfo")
   540  	}
   541  
   542  	if err == nil {
   543  		t.Log(err)
   544  		t.Fatal("GetFileInfo after DeleteUser is nil")
   545  	}
   546  }
   547  
   548  func TestRecordUserServiceTermsAction(t *testing.T) {
   549  	th := Setup().InitBasic()
   550  	defer th.TearDown()
   551  
   552  	user := &model.User{
   553  		Email:       strings.ToLower(model.NewId()) + "success+test@example.com",
   554  		Nickname:    "Luke Skywalker", // trying to bring balance to the "Force", one test user at a time
   555  		Username:    "luke" + model.NewId(),
   556  		Password:    "passwd1",
   557  		AuthService: "",
   558  	}
   559  	user, err := th.App.CreateUser(user)
   560  	if err != nil {
   561  		t.Fatalf("failed to create user: %v", err)
   562  	}
   563  
   564  	defer th.App.PermanentDeleteUser(user)
   565  
   566  	serviceTerms, err := th.App.CreateServiceTerms("text", user.Id)
   567  	if err != nil {
   568  		t.Fatalf("failed to create service terms: %v", err)
   569  	}
   570  
   571  	err = th.App.RecordUserServiceTermsAction(user.Id, serviceTerms.Id, true)
   572  	if err != nil {
   573  		t.Fatalf("failed to record user action: %v", err)
   574  	}
   575  
   576  	nuser, err := th.App.GetUser(user.Id)
   577  	assert.Equal(t, serviceTerms.Id, nuser.AcceptedServiceTermsId)
   578  
   579  	err = th.App.RecordUserServiceTermsAction(user.Id, serviceTerms.Id, false)
   580  	if err != nil {
   581  		t.Fatalf("failed to record user action: %v", err)
   582  	}
   583  
   584  	nuser, err = th.App.GetUser(user.Id)
   585  	assert.Empty(t, nuser.AcceptedServiceTermsId)
   586  }