gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package user_test
  4. import (
  5. "slices"
  6. "testing"
  7. "code.gitea.io/gitea/models/db"
  8. "code.gitea.io/gitea/models/unittest"
  9. user_model "code.gitea.io/gitea/models/user"
  10. "code.gitea.io/gitea/modules/optional"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. func TestGetEmailAddresses(t *testing.T) {
  14. assert.NoError(t, unittest.PrepareTestDatabase())
  15. emails, _ := user_model.GetEmailAddresses(t.Context(), int64(1))
  16. if assert.Len(t, emails, 3) {
  17. assert.True(t, emails[0].IsPrimary)
  18. assert.True(t, emails[2].IsActivated)
  19. assert.False(t, emails[2].IsPrimary)
  20. }
  21. emails, _ = user_model.GetEmailAddresses(t.Context(), int64(2))
  22. if assert.Len(t, emails, 2) {
  23. assert.True(t, emails[0].IsPrimary)
  24. assert.True(t, emails[0].IsActivated)
  25. }
  26. }
  27. func TestIsEmailUsed(t *testing.T) {
  28. assert.NoError(t, unittest.PrepareTestDatabase())
  29. isExist, _ := user_model.IsEmailUsed(t.Context(), "")
  30. assert.True(t, isExist)
  31. isExist, _ = user_model.IsEmailUsed(t.Context(), "user11@example.com")
  32. assert.True(t, isExist)
  33. isExist, _ = user_model.IsEmailUsed(t.Context(), "user1234567890@example.com")
  34. assert.False(t, isExist)
  35. }
  36. func TestMakeEmailPrimary(t *testing.T) {
  37. assert.NoError(t, unittest.PrepareTestDatabase())
  38. err := user_model.MakeActiveEmailPrimary(t.Context(), 9999999)
  39. assert.Error(t, err)
  40. assert.ErrorIs(t, err, user_model.ErrEmailAddressNotExist{})
  41. email := unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user11@example.com"})
  42. err = user_model.MakeActiveEmailPrimary(t.Context(), email.ID)
  43. assert.Error(t, err)
  44. assert.ErrorIs(t, err, user_model.ErrEmailAddressNotExist{}) // inactive email is considered as not exist for "MakeActiveEmailPrimary"
  45. email = unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user9999999@example.com"})
  46. err = user_model.MakeActiveEmailPrimary(t.Context(), email.ID)
  47. assert.Error(t, err)
  48. assert.True(t, user_model.IsErrUserNotExist(err))
  49. email = unittest.AssertExistsAndLoadBean(t, &user_model.EmailAddress{Email: "user101@example.com"})
  50. err = user_model.MakeActiveEmailPrimary(t.Context(), email.ID)
  51. assert.NoError(t, err)
  52. user, _ := user_model.GetUserByID(t.Context(), int64(10))
  53. assert.Equal(t, "user101@example.com", user.Email)
  54. }
  55. func TestActivate(t *testing.T) {
  56. assert.NoError(t, unittest.PrepareTestDatabase())
  57. email := &user_model.EmailAddress{
  58. ID: int64(1),
  59. UID: int64(1),
  60. Email: "user11@example.com",
  61. }
  62. assert.NoError(t, user_model.ActivateEmail(t.Context(), email))
  63. emails, _ := user_model.GetEmailAddresses(t.Context(), int64(1))
  64. assert.Len(t, emails, 3)
  65. assert.True(t, emails[0].IsActivated)
  66. assert.True(t, emails[0].IsPrimary)
  67. assert.False(t, emails[1].IsPrimary)
  68. assert.True(t, emails[2].IsActivated)
  69. assert.False(t, emails[2].IsPrimary)
  70. }
  71. func TestListEmails(t *testing.T) {
  72. assert.NoError(t, unittest.PrepareTestDatabase())
  73. // Must find all users and their emails
  74. opts := &user_model.SearchEmailOptions{
  75. ListOptions: db.ListOptions{
  76. PageSize: 10000,
  77. },
  78. }
  79. emails, count, err := user_model.SearchEmails(t.Context(), opts)
  80. assert.NoError(t, err)
  81. assert.Greater(t, count, int64(5))
  82. contains := func(match func(s *user_model.SearchEmailResult) bool) bool {
  83. return slices.ContainsFunc(emails, match)
  84. }
  85. assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 18 }))
  86. // 'org3' is an organization
  87. assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 3 }))
  88. // Must find no records
  89. opts = &user_model.SearchEmailOptions{Keyword: "NOTFOUND"}
  90. emails, count, err = user_model.SearchEmails(t.Context(), opts)
  91. assert.NoError(t, err)
  92. assert.Equal(t, int64(0), count)
  93. // Must find users 'user2', 'user28', etc.
  94. opts = &user_model.SearchEmailOptions{Keyword: "user2"}
  95. emails, count, err = user_model.SearchEmails(t.Context(), opts)
  96. assert.NoError(t, err)
  97. assert.NotEqual(t, int64(0), count)
  98. assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 2 }))
  99. assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.UID == 27 }))
  100. // Must find only primary addresses (i.e. from the `user` table)
  101. opts = &user_model.SearchEmailOptions{IsPrimary: optional.Some(true)}
  102. emails, _, err = user_model.SearchEmails(t.Context(), opts)
  103. assert.NoError(t, err)
  104. assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsPrimary }))
  105. assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsPrimary }))
  106. // Must find only inactive addresses (i.e. not validated)
  107. opts = &user_model.SearchEmailOptions{IsActivated: optional.Some(false)}
  108. emails, _, err = user_model.SearchEmails(t.Context(), opts)
  109. assert.NoError(t, err)
  110. assert.True(t, contains(func(s *user_model.SearchEmailResult) bool { return !s.IsActivated }))
  111. assert.False(t, contains(func(s *user_model.SearchEmailResult) bool { return s.IsActivated }))
  112. // Must find more than one page, but retrieve only one
  113. opts = &user_model.SearchEmailOptions{
  114. ListOptions: db.ListOptions{
  115. PageSize: 5,
  116. Page: 1,
  117. },
  118. }
  119. emails, count, err = user_model.SearchEmails(t.Context(), opts)
  120. assert.NoError(t, err)
  121. assert.Len(t, emails, 5)
  122. assert.Greater(t, count, int64(len(emails)))
  123. }
  124. func TestEmailAddressValidate(t *testing.T) {
  125. kases := map[string]error{
  126. "abc@gmail.com": nil,
  127. "132@hotmail.com": nil,
  128. "1-3-2@test.org": nil,
  129. "1.3.2@test.org": nil,
  130. "a_123@test.org.cn": nil,
  131. `first.last@iana.org`: nil,
  132. `first!last@iana.org`: nil,
  133. `first#last@iana.org`: nil,
  134. `first$last@iana.org`: nil,
  135. `first%last@iana.org`: nil,
  136. `first&last@iana.org`: nil,
  137. `first'last@iana.org`: nil,
  138. `first*last@iana.org`: nil,
  139. `first+last@iana.org`: nil,
  140. `first/last@iana.org`: nil,
  141. `first=last@iana.org`: nil,
  142. `first?last@iana.org`: nil,
  143. `first^last@iana.org`: nil,
  144. "first`last@iana.org": nil,
  145. `first{last@iana.org`: nil,
  146. `first|last@iana.org`: nil,
  147. `first}last@iana.org`: nil,
  148. `first~last@iana.org`: nil,
  149. `first;last@iana.org`: user_model.ErrEmailCharIsNotSupported{`first;last@iana.org`},
  150. ".233@qq.com": user_model.ErrEmailInvalid{".233@qq.com"},
  151. "!233@qq.com": nil,
  152. "#233@qq.com": nil,
  153. "$233@qq.com": nil,
  154. "%233@qq.com": nil,
  155. "&233@qq.com": nil,
  156. "'233@qq.com": nil,
  157. "*233@qq.com": nil,
  158. "+233@qq.com": nil,
  159. "-233@qq.com": user_model.ErrEmailInvalid{"-233@qq.com"},
  160. "/233@qq.com": nil,
  161. "=233@qq.com": nil,
  162. "?233@qq.com": nil,
  163. "^233@qq.com": nil,
  164. "_233@qq.com": nil,
  165. "`233@qq.com": nil,
  166. "{233@qq.com": nil,
  167. "|233@qq.com": nil,
  168. "}233@qq.com": nil,
  169. "~233@qq.com": nil,
  170. ";233@qq.com": user_model.ErrEmailCharIsNotSupported{";233@qq.com"},
  171. "Foo <foo@bar.com>": user_model.ErrEmailCharIsNotSupported{"Foo <foo@bar.com>"},
  172. string([]byte{0xE2, 0x84, 0xAA}): user_model.ErrEmailCharIsNotSupported{string([]byte{0xE2, 0x84, 0xAA})},
  173. }
  174. for kase, err := range kases {
  175. t.Run(kase, func(t *testing.T) {
  176. assert.Equal(t, err, user_model.ValidateEmail(kase))
  177. })
  178. }
  179. }