code.gitea.io/gitea@v1.22.3/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/optional"
    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 TestMakeEmailPrimary(t *testing.T) {
    46  	assert.NoError(t, unittest.PrepareTestDatabase())
    47  
    48  	err := user_model.MakeActiveEmailPrimary(db.DefaultContext, 9999999)
    49  	assert.Error(t, err)
    50  	assert.ErrorIs(t, err, user_model.ErrEmailAddressNotExist{})
    51  
    52  	email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user11@example.com"})
    53  	err = user_model.MakeActiveEmailPrimary(db.DefaultContext, email.ID)
    54  	assert.Error(t, err)
    55  	assert.ErrorIs(t, err, user_model.ErrEmailAddressNotExist{}) // inactive email is considered as not exist for "MakeActiveEmailPrimary"
    56  
    57  	email = unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user9999999@example.com"})
    58  	err = user_model.MakeActiveEmailPrimary(db.DefaultContext, email.ID)
    59  	assert.Error(t, err)
    60  	assert.True(t, user_model.IsErrUserNotExist(err))
    61  
    62  	email = unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user101@example.com"})
    63  	err = user_model.MakeActiveEmailPrimary(db.DefaultContext, email.ID)
    64  	assert.NoError(t, err)
    65  
    66  	user, _ := user_model.GetUserByID(db.DefaultContext, int64(10))
    67  	assert.Equal(t, "user101@example.com", user.Email)
    68  }
    69  
    70  func TestActivate(t *testing.T) {
    71  	assert.NoError(t, unittest.PrepareTestDatabase())
    72  
    73  	email := &user_model.EmailAddress{
    74  		ID:    int64(1),
    75  		UID:   int64(1),
    76  		Email: "user11@example.com",
    77  	}
    78  	assert.NoError(t, user_model.ActivateEmail(db.DefaultContext, email))
    79  
    80  	emails, _ := user_model.GetEmailAddresses(db.DefaultContext, int64(1))
    81  	assert.Len(t, emails, 3)
    82  	assert.True(t, emails[0].IsActivated)
    83  	assert.True(t, emails[0].IsPrimary)
    84  	assert.False(t, emails[1].IsPrimary)
    85  	assert.True(t, emails[2].IsActivated)
    86  	assert.False(t, emails[2].IsPrimary)
    87  }
    88  
    89  func TestListEmails(t *testing.T) {
    90  	assert.NoError(t, unittest.PrepareTestDatabase())
    91  
    92  	// Must find all users and their emails
    93  	opts := &user_model.SearchEmailOptions{
    94  		ListOptions: db.ListOptions{
    95  			PageSize: 10000,
    96  		},
    97  	}
    98  	emails, count, err := user_model.SearchEmails(db.DefaultContext, opts)
    99  	assert.NoError(t, err)
   100  	assert.NotEqual(t, int64(0), count)
   101  	assert.True(t, count > 5)
   102  
   103  	contains := func(match func(s *user_model.SearchEmailResult) bool) bool {
   104  		for _, v := range emails {
   105  			if match(v) {
   106  				return true
   107  			}
   108  		}
   109  		return false
   110  	}
   111  
   112  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 18 }))
   113  	// 'org3' is an organization
   114  	assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 3 }))
   115  
   116  	// Must find no records
   117  	opts = &user_model.SearchEmailOptions{Keyword: "NOTFOUND"}
   118  	emails, count, err = user_model.SearchEmails(db.DefaultContext, opts)
   119  	assert.NoError(t, err)
   120  	assert.Equal(t, int64(0), count)
   121  
   122  	// Must find users 'user2', 'user28', etc.
   123  	opts = &user_model.SearchEmailOptions{Keyword: "user2"}
   124  	emails, count, err = user_model.SearchEmails(db.DefaultContext, opts)
   125  	assert.NoError(t, err)
   126  	assert.NotEqual(t, int64(0), count)
   127  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 2 }))
   128  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 27 }))
   129  
   130  	// Must find only primary addresses (i.e. from the `user` table)
   131  	opts = &user_model.SearchEmailOptions{IsPrimary: optional.Some(true)}
   132  	emails, _, err = user_model.SearchEmails(db.DefaultContext, opts)
   133  	assert.NoError(t, err)
   134  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsPrimary }))
   135  	assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsPrimary }))
   136  
   137  	// Must find only inactive addresses (i.e. not validated)
   138  	opts = &user_model.SearchEmailOptions{IsActivated: optional.Some(false)}
   139  	emails, _, err = user_model.SearchEmails(db.DefaultContext, opts)
   140  	assert.NoError(t, err)
   141  	assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsActivated }))
   142  	assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsActivated }))
   143  
   144  	// Must find more than one page, but retrieve only one
   145  	opts = &user_model.SearchEmailOptions{
   146  		ListOptions: db.ListOptions{
   147  			PageSize: 5,
   148  			Page:     1,
   149  		},
   150  	}
   151  	emails, count, err = user_model.SearchEmails(db.DefaultContext, opts)
   152  	assert.NoError(t, err)
   153  	assert.Len(t, emails, 5)
   154  	assert.Greater(t, count, int64(len(emails)))
   155  }
   156  
   157  func TestEmailAddressValidate(t *testing.T) {
   158  	kases := map[string]error{
   159  		"abc@gmail.com":                  nil,
   160  		"132@hotmail.com":                nil,
   161  		"1-3-2@test.org":                 nil,
   162  		"1.3.2@test.org":                 nil,
   163  		"a_123@test.org.cn":              nil,
   164  		`first.last@iana.org`:            nil,
   165  		`first!last@iana.org`:            nil,
   166  		`first#last@iana.org`:            nil,
   167  		`first$last@iana.org`:            nil,
   168  		`first%last@iana.org`:            nil,
   169  		`first&last@iana.org`:            nil,
   170  		`first'last@iana.org`:            nil,
   171  		`first*last@iana.org`:            nil,
   172  		`first+last@iana.org`:            nil,
   173  		`first/last@iana.org`:            nil,
   174  		`first=last@iana.org`:            nil,
   175  		`first?last@iana.org`:            nil,
   176  		`first^last@iana.org`:            nil,
   177  		"first`last@iana.org":            nil,
   178  		`first{last@iana.org`:            nil,
   179  		`first|last@iana.org`:            nil,
   180  		`first}last@iana.org`:            nil,
   181  		`first~last@iana.org`:            nil,
   182  		`first;last@iana.org`:            user_model.ErrEmailCharIsNotSupported{`first;last@iana.org`},
   183  		".233@qq.com":                    user_model.ErrEmailInvalid{".233@qq.com"},
   184  		"!233@qq.com":                    nil,
   185  		"#233@qq.com":                    nil,
   186  		"$233@qq.com":                    nil,
   187  		"%233@qq.com":                    nil,
   188  		"&233@qq.com":                    nil,
   189  		"'233@qq.com":                    nil,
   190  		"*233@qq.com":                    nil,
   191  		"+233@qq.com":                    nil,
   192  		"-233@qq.com":                    user_model.ErrEmailInvalid{"-233@qq.com"},
   193  		"/233@qq.com":                    nil,
   194  		"=233@qq.com":                    nil,
   195  		"?233@qq.com":                    nil,
   196  		"^233@qq.com":                    nil,
   197  		"_233@qq.com":                    nil,
   198  		"`233@qq.com":                    nil,
   199  		"{233@qq.com":                    nil,
   200  		"|233@qq.com":                    nil,
   201  		"}233@qq.com":                    nil,
   202  		"~233@qq.com":                    nil,
   203  		";233@qq.com":                    user_model.ErrEmailCharIsNotSupported{";233@qq.com"},
   204  		"Foo <foo@bar.com>":              user_model.ErrEmailCharIsNotSupported{"Foo <foo@bar.com>"},
   205  		string([]byte{0xE2, 0x84, 0xAA}): user_model.ErrEmailCharIsNotSupported{string([]byte{0xE2, 0x84, 0xAA})},
   206  	}
   207  	for kase, err := range kases {
   208  		t.Run(kase, func(t *testing.T) {
   209  			assert.EqualValues(t, err, user_model.ValidateEmail(kase))
   210  		})
   211  	}
   212  }