code.gitea.io/gitea@v1.21.7/models/user/email_address_test.go (about)

     1  // Copyright 2017 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package user_test
     5  
     6  import (
     7  	"testing"
     8  
     9  	"code.gitea.io/gitea/models/db"
    10  	"code.gitea.io/gitea/models/unittest"
    11  	user_model "code.gitea.io/gitea/models/user"
    12  	"code.gitea.io/gitea/modules/util"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestGetEmailAddresses(t *testing.T) {
    18  	assert.NoError(t, unittest.PrepareTestDatabase())
    19  
    20  	emails, _ := user_model.GetEmailAddresses(db.DefaultContext, int64(1))
    21  	if assert.Len(t, emails, 3) {
    22  		assert.True(t, emails[0].IsPrimary)
    23  		assert.True(t, emails[2].IsActivated)
    24  		assert.False(t, emails[2].IsPrimary)
    25  	}
    26  
    27  	emails, _ = user_model.GetEmailAddresses(db.DefaultContext, int64(2))
    28  	if assert.Len(t, emails, 2) {
    29  		assert.True(t, emails[0].IsPrimary)
    30  		assert.True(t, emails[0].IsActivated)
    31  	}
    32  }
    33  
    34  func TestIsEmailUsed(t *testing.T) {
    35  	assert.NoError(t, unittest.PrepareTestDatabase())
    36  
    37  	isExist, _ := user_model.IsEmailUsed(db.DefaultContext, "")
    38  	assert.True(t, isExist)
    39  	isExist, _ = user_model.IsEmailUsed(db.DefaultContext, "user11@example.com")
    40  	assert.True(t, isExist)
    41  	isExist, _ = user_model.IsEmailUsed(db.DefaultContext, "user1234567890@example.com")
    42  	assert.False(t, isExist)
    43  }
    44  
    45  func TestAddEmailAddress(t *testing.T) {
    46  	assert.NoError(t, unittest.PrepareTestDatabase())
    47  
    48  	assert.NoError(t, user_model.AddEmailAddress(db.DefaultContext, &user_model.EmailAddress{
    49  		Email:       "user1234567890@example.com",
    50  		LowerEmail:  "user1234567890@example.com",
    51  		IsPrimary:   true,
    52  		IsActivated: true,
    53  	}))
    54  
    55  	// ErrEmailAlreadyUsed
    56  	err := user_model.AddEmailAddress(db.DefaultContext, &user_model.EmailAddress{
    57  		Email:      "user1234567890@example.com",
    58  		LowerEmail: "user1234567890@example.com",
    59  	})
    60  	assert.Error(t, err)
    61  	assert.True(t, user_model.IsErrEmailAlreadyUsed(err))
    62  }
    63  
    64  func TestAddEmailAddresses(t *testing.T) {
    65  	assert.NoError(t, unittest.PrepareTestDatabase())
    66  
    67  	// insert multiple email address
    68  	emails := make([]*user_model.EmailAddress, 2)
    69  	emails[0] = &user_model.EmailAddress{
    70  		Email:       "user1234@example.com",
    71  		LowerEmail:  "user1234@example.com",
    72  		IsActivated: true,
    73  	}
    74  	emails[1] = &user_model.EmailAddress{
    75  		Email:       "user5678@example.com",
    76  		LowerEmail:  "user5678@example.com",
    77  		IsActivated: true,
    78  	}
    79  	assert.NoError(t, user_model.AddEmailAddresses(db.DefaultContext, emails))
    80  
    81  	// ErrEmailAlreadyUsed
    82  	err := user_model.AddEmailAddresses(db.DefaultContext, emails)
    83  	assert.Error(t, err)
    84  	assert.True(t, user_model.IsErrEmailAlreadyUsed(err))
    85  }
    86  
    87  func TestDeleteEmailAddress(t *testing.T) {
    88  	assert.NoError(t, unittest.PrepareTestDatabase())
    89  
    90  	assert.NoError(t, user_model.DeleteEmailAddress(db.DefaultContext, &user_model.EmailAddress{
    91  		UID:        int64(1),
    92  		ID:         int64(33),
    93  		Email:      "user1-2@example.com",
    94  		LowerEmail: "user1-2@example.com",
    95  	}))
    96  
    97  	assert.NoError(t, user_model.DeleteEmailAddress(db.DefaultContext, &user_model.EmailAddress{
    98  		UID:        int64(1),
    99  		Email:      "user1-3@example.com",
   100  		LowerEmail: "user1-3@example.com",
   101  	}))
   102  
   103  	// Email address does not exist
   104  	err := user_model.DeleteEmailAddress(db.DefaultContext, &user_model.EmailAddress{
   105  		UID:        int64(1),
   106  		Email:      "user1234567890@example.com",
   107  		LowerEmail: "user1234567890@example.com",
   108  	})
   109  	assert.Error(t, err)
   110  }
   111  
   112  func TestDeleteEmailAddresses(t *testing.T) {
   113  	assert.NoError(t, unittest.PrepareTestDatabase())
   114  
   115  	// delete multiple email address
   116  	emails := make([]*user_model.EmailAddress, 2)
   117  	emails[0] = &user_model.EmailAddress{
   118  		UID:        int64(2),
   119  		ID:         int64(3),
   120  		Email:      "user2@example.com",
   121  		LowerEmail: "user2@example.com",
   122  	}
   123  	emails[1] = &user_model.EmailAddress{
   124  		UID:        int64(2),
   125  		Email:      "user2-2@example.com",
   126  		LowerEmail: "user2-2@example.com",
   127  	}
   128  	assert.NoError(t, user_model.DeleteEmailAddresses(db.DefaultContext, emails))
   129  
   130  	// ErrEmailAlreadyUsed
   131  	err := user_model.DeleteEmailAddresses(db.DefaultContext, emails)
   132  	assert.Error(t, err)
   133  }
   134  
   135  func TestMakeEmailPrimary(t *testing.T) {
   136  	assert.NoError(t, unittest.PrepareTestDatabase())
   137  
   138  	email := &user_model.EmailAddress{
   139  		Email: "user567890@example.com",
   140  	}
   141  	err := user_model.MakeEmailPrimary(db.DefaultContext, email)
   142  	assert.Error(t, err)
   143  	assert.EqualError(t, err, user_model.ErrEmailAddressNotExist{Email: email.Email}.Error())
   144  
   145  	email = &user_model.EmailAddress{
   146  		Email: "user11@example.com",
   147  	}
   148  	err = user_model.MakeEmailPrimary(db.DefaultContext, email)
   149  	assert.Error(t, err)
   150  	assert.EqualError(t, err, user_model.ErrEmailNotActivated.Error())
   151  
   152  	email = &user_model.EmailAddress{
   153  		Email: "user9999999@example.com",
   154  	}
   155  	err = user_model.MakeEmailPrimary(db.DefaultContext, email)
   156  	assert.Error(t, err)
   157  	assert.True(t, user_model.IsErrUserNotExist(err))
   158  
   159  	email = &user_model.EmailAddress{
   160  		Email: "user101@example.com",
   161  	}
   162  	err = user_model.MakeEmailPrimary(db.DefaultContext, email)
   163  	assert.NoError(t, err)
   164  
   165  	user, _ := user_model.GetUserByID(db.DefaultContext, int64(10))
   166  	assert.Equal(t, "user101@example.com", user.Email)
   167  }
   168  
   169  func TestActivate(t *testing.T) {
   170  	assert.NoError(t, unittest.PrepareTestDatabase())
   171  
   172  	email := &user_model.EmailAddress{
   173  		ID:    int64(1),
   174  		UID:   int64(1),
   175  		Email: "user11@example.com",
   176  	}
   177  	assert.NoError(t, user_model.ActivateEmail(db.DefaultContext, email))
   178  
   179  	emails, _ := user_model.GetEmailAddresses(db.DefaultContext, int64(1))
   180  	assert.Len(t, emails, 3)
   181  	assert.True(t, emails[0].IsActivated)
   182  	assert.True(t, emails[0].IsPrimary)
   183  	assert.False(t, emails[1].IsPrimary)
   184  	assert.True(t, emails[2].IsActivated)
   185  	assert.False(t, emails[2].IsPrimary)
   186  }
   187  
   188  func TestListEmails(t *testing.T) {
   189  	assert.NoError(t, unittest.PrepareTestDatabase())
   190  
   191  	// Must find all users and their emails
   192  	opts := &user_model.SearchEmailOptions{
   193  		ListOptions: db.ListOptions{
   194  			PageSize: 10000,
   195  		},
   196  	}
   197  	emails, count, err := user_model.SearchEmails(db.DefaultContext, opts)
   198  	assert.NoError(t, err)
   199  	assert.NotEqual(t, int64(0), count)
   200  	assert.True(t, count > 5)
   201  
   202  	contains := func(match func(s *user_model.SearchEmailResult) bool) bool {
   203  		for _, v := range emails {
   204  			if match(v) {
   205  				return true
   206  			}
   207  		}
   208  		return false
   209  	}
   210  
   211  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 18 }))
   212  	// 'org3' is an organization
   213  	assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 3 }))
   214  
   215  	// Must find no records
   216  	opts = &user_model.SearchEmailOptions{Keyword: "NOTFOUND"}
   217  	emails, count, err = user_model.SearchEmails(db.DefaultContext, opts)
   218  	assert.NoError(t, err)
   219  	assert.Equal(t, int64(0), count)
   220  
   221  	// Must find users 'user2', 'user28', etc.
   222  	opts = &user_model.SearchEmailOptions{Keyword: "user2"}
   223  	emails, count, err = user_model.SearchEmails(db.DefaultContext, opts)
   224  	assert.NoError(t, err)
   225  	assert.NotEqual(t, int64(0), count)
   226  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 2 }))
   227  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 27 }))
   228  
   229  	// Must find only primary addresses (i.e. from the `user` table)
   230  	opts = &user_model.SearchEmailOptions{IsPrimary: util.OptionalBoolTrue}
   231  	emails, _, err = user_model.SearchEmails(db.DefaultContext, opts)
   232  	assert.NoError(t, err)
   233  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsPrimary }))
   234  	assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsPrimary }))
   235  
   236  	// Must find only inactive addresses (i.e. not validated)
   237  	opts = &user_model.SearchEmailOptions{IsActivated: util.OptionalBoolFalse}
   238  	emails, _, err = user_model.SearchEmails(db.DefaultContext, opts)
   239  	assert.NoError(t, err)
   240  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsActivated }))
   241  	assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsActivated }))
   242  
   243  	// Must find more than one page, but retrieve only one
   244  	opts = &user_model.SearchEmailOptions{
   245  		ListOptions: db.ListOptions{
   246  			PageSize: 5,
   247  			Page:     1,
   248  		},
   249  	}
   250  	emails, count, err = user_model.SearchEmails(db.DefaultContext, opts)
   251  	assert.NoError(t, err)
   252  	assert.Len(t, emails, 5)
   253  	assert.Greater(t, count, int64(len(emails)))
   254  }
   255  
   256  func TestEmailAddressValidate(t *testing.T) {
   257  	kases := map[string]error{
   258  		"abc@gmail.com":                  nil,
   259  		"132@hotmail.com":                nil,
   260  		"1-3-2@test.org":                 nil,
   261  		"1.3.2@test.org":                 nil,
   262  		"a_123@test.org.cn":              nil,
   263  		`first.last@iana.org`:            nil,
   264  		`first!last@iana.org`:            nil,
   265  		`first#last@iana.org`:            nil,
   266  		`first$last@iana.org`:            nil,
   267  		`first%last@iana.org`:            nil,
   268  		`first&last@iana.org`:            nil,
   269  		`first'last@iana.org`:            nil,
   270  		`first*last@iana.org`:            nil,
   271  		`first+last@iana.org`:            nil,
   272  		`first/last@iana.org`:            nil,
   273  		`first=last@iana.org`:            nil,
   274  		`first?last@iana.org`:            nil,
   275  		`first^last@iana.org`:            nil,
   276  		"first`last@iana.org":            nil,
   277  		`first{last@iana.org`:            nil,
   278  		`first|last@iana.org`:            nil,
   279  		`first}last@iana.org`:            nil,
   280  		`first~last@iana.org`:            nil,
   281  		`first;last@iana.org`:            user_model.ErrEmailCharIsNotSupported{`first;last@iana.org`},
   282  		".233@qq.com":                    user_model.ErrEmailInvalid{".233@qq.com"},
   283  		"!233@qq.com":                    nil,
   284  		"#233@qq.com":                    nil,
   285  		"$233@qq.com":                    nil,
   286  		"%233@qq.com":                    nil,
   287  		"&233@qq.com":                    nil,
   288  		"'233@qq.com":                    nil,
   289  		"*233@qq.com":                    nil,
   290  		"+233@qq.com":                    nil,
   291  		"-233@qq.com":                    user_model.ErrEmailInvalid{"-233@qq.com"},
   292  		"/233@qq.com":                    nil,
   293  		"=233@qq.com":                    nil,
   294  		"?233@qq.com":                    nil,
   295  		"^233@qq.com":                    nil,
   296  		"_233@qq.com":                    nil,
   297  		"`233@qq.com":                    nil,
   298  		"{233@qq.com":                    nil,
   299  		"|233@qq.com":                    nil,
   300  		"}233@qq.com":                    nil,
   301  		"~233@qq.com":                    nil,
   302  		";233@qq.com":                    user_model.ErrEmailCharIsNotSupported{";233@qq.com"},
   303  		"Foo <foo@bar.com>":              user_model.ErrEmailCharIsNotSupported{"Foo <foo@bar.com>"},
   304  		string([]byte{0xE2, 0x84, 0xAA}): user_model.ErrEmailCharIsNotSupported{string([]byte{0xE2, 0x84, 0xAA})},
   305  	}
   306  	for kase, err := range kases {
   307  		t.Run(kase, func(t *testing.T) {
   308  			assert.EqualValues(t, err, user_model.ValidateEmail(kase))
   309  		})
   310  	}
   311  }