github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/model/user_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package model
     5  
     6  import (
     7  	"fmt"
     8  	"math/rand"
     9  	"net/http"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestPasswordHash(t *testing.T) {
    18  	hash := HashPassword("Test")
    19  
    20  	assert.True(t, ComparePassword(hash, "Test"), "Passwords don't match")
    21  	assert.False(t, ComparePassword(hash, "Test2"), "Passwords should not have matched")
    22  }
    23  
    24  func TestUserDeepCopy(t *testing.T) {
    25  	id := NewId()
    26  	authData := "authdata"
    27  	mapKey := "key"
    28  	mapValue := "key"
    29  
    30  	user := &User{Id: id, AuthData: NewString(authData), Props: map[string]string{}, NotifyProps: map[string]string{}, Timezone: map[string]string{}}
    31  	user.Props[mapKey] = mapValue
    32  	user.NotifyProps[mapKey] = mapValue
    33  	user.Timezone[mapKey] = mapValue
    34  
    35  	copyUser := user.DeepCopy()
    36  	copyUser.Id = "someid"
    37  	*copyUser.AuthData = "changed"
    38  	copyUser.Props[mapKey] = "changed"
    39  	copyUser.NotifyProps[mapKey] = "changed"
    40  	copyUser.Timezone[mapKey] = "changed"
    41  
    42  	assert.Equal(t, id, user.Id)
    43  	assert.Equal(t, authData, *user.AuthData)
    44  	assert.Equal(t, mapValue, user.Props[mapKey])
    45  	assert.Equal(t, mapValue, user.NotifyProps[mapKey])
    46  	assert.Equal(t, mapValue, user.Timezone[mapKey])
    47  
    48  	user = &User{Id: id}
    49  	copyUser = user.DeepCopy()
    50  
    51  	assert.Equal(t, id, copyUser.Id)
    52  }
    53  
    54  func TestUserJson(t *testing.T) {
    55  	user := User{Id: NewId(), Username: NewId()}
    56  	json := user.ToJson()
    57  	ruser := UserFromJson(strings.NewReader(json))
    58  
    59  	assert.Equal(t, user.Id, ruser.Id, "Ids do not match")
    60  }
    61  
    62  func TestUserPreSave(t *testing.T) {
    63  	user := User{Password: "test"}
    64  	user.PreSave()
    65  	user.Etag(true, true)
    66  	assert.NotNil(t, user.Timezone, "Timezone is nil")
    67  	assert.Equal(t, user.Timezone["useAutomaticTimezone"], "true", "Timezone is not set to default")
    68  }
    69  
    70  func TestUserPreUpdate(t *testing.T) {
    71  	user := User{Password: "test"}
    72  	user.PreUpdate()
    73  }
    74  
    75  func TestUserUpdateMentionKeysFromUsername(t *testing.T) {
    76  	user := User{Username: "user"}
    77  	user.SetDefaultNotifications()
    78  	assert.Equalf(t, user.NotifyProps["mention_keys"], "", "default mention keys are invalid: %v", user.NotifyProps["mention_keys"])
    79  
    80  	user.Username = "person"
    81  	user.UpdateMentionKeysFromUsername("user")
    82  	assert.Equalf(t, user.NotifyProps["mention_keys"], "", "mention keys are invalid after changing username: %v", user.NotifyProps["mention_keys"])
    83  
    84  	user.NotifyProps["mention_keys"] += ",mention"
    85  	user.UpdateMentionKeysFromUsername("person")
    86  	assert.Equalf(t, user.NotifyProps["mention_keys"], ",mention", "mention keys are invalid after adding extra mention keyword: %v", user.NotifyProps["mention_keys"])
    87  
    88  	user.Username = "user"
    89  	user.UpdateMentionKeysFromUsername("person")
    90  	assert.Equalf(t, user.NotifyProps["mention_keys"], ",mention", "mention keys are invalid after changing username with extra mention keyword: %v", user.NotifyProps["mention_keys"])
    91  }
    92  
    93  func TestUserIsValid(t *testing.T) {
    94  	user := User{}
    95  	err := user.IsValid()
    96  	require.True(t, HasExpectedUserIsValidError(err, "id", ""), "expected user is valid error: %s", err.Error())
    97  
    98  	user.Id = NewId()
    99  	err = user.IsValid()
   100  	require.True(t, HasExpectedUserIsValidError(err, "create_at", user.Id), "expected user is valid error: %s", err.Error())
   101  
   102  	user.CreateAt = GetMillis()
   103  	err = user.IsValid()
   104  	require.True(t, HasExpectedUserIsValidError(err, "update_at", user.Id), "expected user is valid error: %s", err.Error())
   105  
   106  	user.UpdateAt = GetMillis()
   107  	err = user.IsValid()
   108  	require.True(t, HasExpectedUserIsValidError(err, "username", user.Id), "expected user is valid error: %s", err.Error())
   109  
   110  	user.Username = NewId() + "^hello#"
   111  	err = user.IsValid()
   112  	require.True(t, HasExpectedUserIsValidError(err, "username", user.Id), "expected user is valid error: %s", err.Error())
   113  
   114  	user.Username = NewId()
   115  	err = user.IsValid()
   116  	require.True(t, HasExpectedUserIsValidError(err, "email", user.Id), "expected user is valid error: %s", err.Error())
   117  
   118  	user.Email = strings.Repeat("01234567890", 20)
   119  	err = user.IsValid()
   120  	require.True(t, HasExpectedUserIsValidError(err, "email", user.Id), "expected user is valid error: %s", err.Error())
   121  
   122  	user.Email = "user@example.com"
   123  
   124  	user.Nickname = strings.Repeat("a", 65)
   125  	err = user.IsValid()
   126  	require.True(t, HasExpectedUserIsValidError(err, "nickname", user.Id), "expected user is valid error: %s", err.Error())
   127  
   128  	user.Nickname = strings.Repeat("a", 64)
   129  	require.Error(t, user.IsValid())
   130  
   131  	user.FirstName = ""
   132  	user.LastName = ""
   133  	require.Error(t, user.IsValid())
   134  
   135  	user.FirstName = strings.Repeat("a", 65)
   136  	err = user.IsValid()
   137  	require.True(t, HasExpectedUserIsValidError(err, "first_name", user.Id), "expected user is valid error: %s", err.Error())
   138  
   139  	user.FirstName = strings.Repeat("a", 64)
   140  	user.LastName = strings.Repeat("a", 65)
   141  	err = user.IsValid()
   142  	require.True(t, HasExpectedUserIsValidError(err, "last_name", user.Id), "expected user is valid error: %s", err.Error())
   143  
   144  	user.LastName = strings.Repeat("a", 64)
   145  	user.Position = strings.Repeat("a", 128)
   146  	require.Error(t, user.IsValid())
   147  
   148  	user.Position = strings.Repeat("a", 129)
   149  	err = user.IsValid()
   150  	require.True(t, HasExpectedUserIsValidError(err, "position", user.Id), "expected user is valid error: %s", err.Error())
   151  }
   152  
   153  func HasExpectedUserIsValidError(err *AppError, fieldName string, userId string) bool {
   154  	if err == nil {
   155  		return false
   156  	}
   157  
   158  	return err.Where == "User.IsValid" &&
   159  		err.Id == fmt.Sprintf("model.user.is_valid.%s.app_error", fieldName) &&
   160  		err.StatusCode == http.StatusBadRequest &&
   161  		(userId == "" || err.DetailedError == "user_id="+userId)
   162  }
   163  
   164  func TestUserGetFullName(t *testing.T) {
   165  	user := User{}
   166  	assert.Equal(t, user.GetFullName(), "", "Full name should be blank")
   167  
   168  	user.FirstName = "first"
   169  	assert.Equal(t, user.GetFullName(), "first", "Full name should be first name")
   170  
   171  	user.FirstName = ""
   172  	user.LastName = "last"
   173  	assert.Equal(t, user.GetFullName(), "last", "Full name should be last name")
   174  
   175  	user.FirstName = "first"
   176  	assert.Equal(t, user.GetFullName(), "first last", "Full name should be first name and last name")
   177  }
   178  
   179  func TestUserGetDisplayName(t *testing.T) {
   180  	user := User{Username: "username"}
   181  
   182  	assert.Equal(t, user.GetDisplayName(SHOW_FULLNAME), "username", "Display name should be username")
   183  	assert.Equal(t, user.GetDisplayName(SHOW_NICKNAME_FULLNAME), "username", "Display name should be username")
   184  	assert.Equal(t, user.GetDisplayName(SHOW_USERNAME), "username", "Display name should be username")
   185  
   186  	user.FirstName = "first"
   187  	user.LastName = "last"
   188  
   189  	assert.Equal(t, user.GetDisplayName(SHOW_FULLNAME), "first last", "Display name should be full name")
   190  	assert.Equal(t, user.GetDisplayName(SHOW_NICKNAME_FULLNAME), "first last", "Display name should be full name since there is no nickname")
   191  	assert.Equal(t, user.GetDisplayName(SHOW_USERNAME), "username", "Display name should be username")
   192  
   193  	user.Nickname = "nickname"
   194  	assert.Equal(t, user.GetDisplayName(SHOW_NICKNAME_FULLNAME), "nickname", "Display name should be nickname")
   195  }
   196  
   197  func TestUserGetDisplayNameWithPrefix(t *testing.T) {
   198  	user := User{Username: "username"}
   199  
   200  	assert.Equal(t, user.GetDisplayNameWithPrefix(SHOW_FULLNAME, "@"), "@username", "Display name should be username")
   201  	assert.Equal(t, user.GetDisplayNameWithPrefix(SHOW_NICKNAME_FULLNAME, "@"), "@username", "Display name should be username")
   202  	assert.Equal(t, user.GetDisplayNameWithPrefix(SHOW_USERNAME, "@"), "@username", "Display name should be username")
   203  
   204  	user.FirstName = "first"
   205  	user.LastName = "last"
   206  
   207  	assert.Equal(t, user.GetDisplayNameWithPrefix(SHOW_FULLNAME, "@"), "first last", "Display name should be full name")
   208  	assert.Equal(t, user.GetDisplayNameWithPrefix(SHOW_NICKNAME_FULLNAME, "@"), "first last", "Display name should be full name since there is no nickname")
   209  	assert.Equal(t, user.GetDisplayNameWithPrefix(SHOW_USERNAME, "@"), "@username", "Display name should be username")
   210  
   211  	user.Nickname = "nickname"
   212  	assert.Equal(t, user.GetDisplayNameWithPrefix(SHOW_NICKNAME_FULLNAME, "@"), "nickname", "Display name should be nickname")
   213  }
   214  
   215  var usernames = []struct {
   216  	value    string
   217  	expected bool
   218  }{
   219  	{"spin-punch", true},
   220  	{"sp", true},
   221  	{"s", true},
   222  	{"1spin-punch", true},
   223  	{"-spin-punch", true},
   224  	{".spin-punch", true},
   225  	{"Spin-punch", false},
   226  	{"spin punch-", false},
   227  	{"spin_punch", true},
   228  	{"spin", true},
   229  	{"PUNCH", false},
   230  	{"spin.punch", true},
   231  	{"spin'punch", false},
   232  	{"spin*punch", false},
   233  	{"all", false},
   234  	{"system", false},
   235  }
   236  
   237  func TestValidUsername(t *testing.T) {
   238  	for _, v := range usernames {
   239  		if IsValidUsername(v.value) != v.expected {
   240  			t.Errorf("expect %v as %v", v.value, v.expected)
   241  		}
   242  	}
   243  }
   244  
   245  func TestNormalizeUsername(t *testing.T) {
   246  	assert.Equal(t, NormalizeUsername("Spin-punch"), "spin-punch", "didn't normalize username properly")
   247  	assert.Equal(t, NormalizeUsername("PUNCH"), "punch", "didn't normalize username properly")
   248  	assert.Equal(t, NormalizeUsername("spin"), "spin", "didn't normalize username properly")
   249  }
   250  
   251  func TestNormalizeEmail(t *testing.T) {
   252  	assert.Equal(t, NormalizeEmail("TEST@EXAMPLE.COM"), "test@example.com", "didn't normalize email properly")
   253  	assert.Equal(t, NormalizeEmail("TEST2@example.com"), "test2@example.com", "didn't normalize email properly")
   254  	assert.Equal(t, NormalizeEmail("test3@example.com"), "test3@example.com", "didn't normalize email properly")
   255  }
   256  
   257  func TestCleanUsername(t *testing.T) {
   258  	assert.Equal(t, CleanUsername("Spin-punch"), "spin-punch", "didn't clean name properly")
   259  	assert.Equal(t, CleanUsername("PUNCH"), "punch", "didn't clean name properly")
   260  	assert.Equal(t, CleanUsername("spin'punch"), "spin-punch", "didn't clean name properly")
   261  	assert.Equal(t, CleanUsername("spin"), "spin", "didn't clean name properly")
   262  	assert.Equal(t, len(CleanUsername("all")), 27, "didn't clean name properly")
   263  }
   264  
   265  func TestRoles(t *testing.T) {
   266  	require.True(t, IsValidUserRoles("team_user"))
   267  	require.False(t, IsValidUserRoles("system_admin"))
   268  	require.True(t, IsValidUserRoles("system_user system_admin"))
   269  	require.False(t, IsInRole("system_admin junk", "admin"))
   270  	require.True(t, IsInRole("system_admin junk", "system_admin"))
   271  	require.False(t, IsInRole("admin", "system_admin"))
   272  }
   273  
   274  func TestIsValidLocale(t *testing.T) {
   275  	for _, test := range []struct {
   276  		Name     string
   277  		Locale   string
   278  		Expected bool
   279  	}{
   280  		{
   281  			Name:     "empty locale",
   282  			Locale:   "",
   283  			Expected: true,
   284  		},
   285  		{
   286  			Name:     "locale with only language",
   287  			Locale:   "fr",
   288  			Expected: true,
   289  		},
   290  		{
   291  			Name:     "locale with region",
   292  			Locale:   "en-DE", // English, as used in Germany
   293  			Expected: true,
   294  		},
   295  		{
   296  			Name:     "invalid locale",
   297  			Locale:   "'",
   298  			Expected: false,
   299  		},
   300  
   301  		// Note that the following cases are all valid language tags, but they're considered invalid here because of
   302  		// the max length of the User.Locale field.
   303  		{
   304  			Name:     "locale with extended language subtag",
   305  			Locale:   "zh-yue-HK", // Chinese, Cantonese, as used in Hong Kong
   306  			Expected: false,
   307  		},
   308  		{
   309  			Name:     "locale with script",
   310  			Locale:   "hy-Latn-IT-arevela", // Eastern Armenian written in Latin script, as used in Italy
   311  			Expected: false,
   312  		},
   313  		{
   314  			Name:     "locale with variant",
   315  			Locale:   "sl-rozaj-biske", // San Giorgio dialect of Resian dialect of Slovenian
   316  			Expected: false,
   317  		},
   318  		{
   319  			Name:     "locale with extension",
   320  			Locale:   "de-DE-u-co-phonebk", // German, as used in Germany, using German phonebook sort order
   321  			Expected: false,
   322  		},
   323  	} {
   324  		t.Run(test.Name, func(t *testing.T) {
   325  			assert.Equal(t, test.Expected, IsValidLocale(test.Locale))
   326  		})
   327  	}
   328  }
   329  
   330  func TestUserSlice(t *testing.T) {
   331  	t.Run("FilterByActive", func(t *testing.T) {
   332  		user0 := &User{Id: "user0", DeleteAt: 0, IsBot: true}
   333  		user1 := &User{Id: "user1", DeleteAt: 0, IsBot: true}
   334  		user2 := &User{Id: "user2", DeleteAt: 1, IsBot: false}
   335  
   336  		slice := UserSlice([]*User{user0, user1, user2})
   337  
   338  		activeUsers := slice.FilterByActive(true)
   339  		assert.Equal(t, 2, len(activeUsers))
   340  		for _, user := range activeUsers {
   341  			assert.True(t, user.DeleteAt == 0)
   342  		}
   343  
   344  		inactiveUsers := slice.FilterByActive(false)
   345  		assert.Equal(t, 1, len(inactiveUsers))
   346  		for _, user := range inactiveUsers {
   347  			assert.True(t, user.DeleteAt != 0)
   348  		}
   349  
   350  		nonBotUsers := slice.FilterWithoutBots()
   351  		assert.Equal(t, 1, len(nonBotUsers))
   352  	})
   353  }
   354  
   355  func TestGeneratePassword(t *testing.T) {
   356  	passwordRandom = lockedRand{
   357  		rn: rand.New(rand.NewSource(12345)),
   358  	}
   359  
   360  	t.Run("Should be the minimum length or 4, whichever is less", func(t *testing.T) {
   361  		password1 := GeneratePassword(5)
   362  		assert.Len(t, password1, 5)
   363  		password2 := GeneratePassword(10)
   364  		assert.Len(t, password2, 10)
   365  		password3 := GeneratePassword(1)
   366  		assert.Len(t, password3, 4)
   367  	})
   368  
   369  	t.Run("Should contain at least one of symbols, upper case, lower case and numbers", func(t *testing.T) {
   370  		password := GeneratePassword(4)
   371  		require.Len(t, password, 4)
   372  		assert.Contains(t, []rune(passwordUpperCaseLetters), []rune(password)[0])
   373  		assert.Contains(t, []rune(passwordNumbers), []rune(password)[1])
   374  		assert.Contains(t, []rune(passwordLowerCaseLetters), []rune(password)[2])
   375  		assert.Contains(t, []rune(passwordSpecialChars), []rune(password)[3])
   376  	})
   377  
   378  	t.Run("Should not fail on concurrent calls", func(t *testing.T) {
   379  		for i := 0; i < 10; i++ {
   380  			go GeneratePassword(10)
   381  		}
   382  	})
   383  }