Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

user_test.go 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package user_test
  4. import (
  5. "context"
  6. "fmt"
  7. "math/rand"
  8. "strings"
  9. "testing"
  10. "time"
  11. "code.gitea.io/gitea/models/auth"
  12. "code.gitea.io/gitea/models/db"
  13. "code.gitea.io/gitea/models/unittest"
  14. user_model "code.gitea.io/gitea/models/user"
  15. "code.gitea.io/gitea/modules/auth/password/hash"
  16. "code.gitea.io/gitea/modules/container"
  17. "code.gitea.io/gitea/modules/optional"
  18. "code.gitea.io/gitea/modules/setting"
  19. "code.gitea.io/gitea/modules/structs"
  20. "code.gitea.io/gitea/modules/timeutil"
  21. "github.com/stretchr/testify/assert"
  22. )
  23. func TestOAuth2Application_LoadUser(t *testing.T) {
  24. assert.NoError(t, unittest.PrepareTestDatabase())
  25. app := unittest.AssertExistsAndLoadBean(t, &auth.OAuth2Application{ID: 1})
  26. user, err := user_model.GetUserByID(db.DefaultContext, app.UID)
  27. assert.NoError(t, err)
  28. assert.NotNil(t, user)
  29. }
  30. func TestGetUserEmailsByNames(t *testing.T) {
  31. assert.NoError(t, unittest.PrepareTestDatabase())
  32. // ignore none active user email
  33. assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"}))
  34. assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"}))
  35. assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "org7"}))
  36. }
  37. func TestCanCreateOrganization(t *testing.T) {
  38. assert.NoError(t, unittest.PrepareTestDatabase())
  39. admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
  40. assert.True(t, admin.CanCreateOrganization())
  41. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  42. assert.True(t, user.CanCreateOrganization())
  43. // Disable user create organization permission.
  44. user.AllowCreateOrganization = false
  45. assert.False(t, user.CanCreateOrganization())
  46. setting.Admin.DisableRegularOrgCreation = true
  47. user.AllowCreateOrganization = true
  48. assert.True(t, admin.CanCreateOrganization())
  49. assert.False(t, user.CanCreateOrganization())
  50. }
  51. func TestSearchUsers(t *testing.T) {
  52. assert.NoError(t, unittest.PrepareTestDatabase())
  53. testSuccess := func(opts *user_model.SearchUserOptions, expectedUserOrOrgIDs []int64) {
  54. users, _, err := user_model.SearchUsers(db.DefaultContext, opts)
  55. assert.NoError(t, err)
  56. cassText := fmt.Sprintf("ids: %v, opts: %v", expectedUserOrOrgIDs, opts)
  57. if assert.Len(t, users, len(expectedUserOrOrgIDs), "case: %s", cassText) {
  58. for i, expectedID := range expectedUserOrOrgIDs {
  59. assert.EqualValues(t, expectedID, users[i].ID, "case: %s", cassText)
  60. }
  61. }
  62. }
  63. // test orgs
  64. testOrgSuccess := func(opts *user_model.SearchUserOptions, expectedOrgIDs []int64) {
  65. opts.Type = user_model.UserTypeOrganization
  66. testSuccess(opts, expectedOrgIDs)
  67. }
  68. testOrgSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1, PageSize: 2}},
  69. []int64{3, 6})
  70. testOrgSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 2, PageSize: 2}},
  71. []int64{7, 17})
  72. testOrgSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 3, PageSize: 2}},
  73. []int64{19, 25})
  74. testOrgSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 4, PageSize: 2}},
  75. []int64{26, 41})
  76. testOrgSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 5, PageSize: 2}},
  77. []int64{})
  78. // test users
  79. testUserSuccess := func(opts *user_model.SearchUserOptions, expectedUserIDs []int64) {
  80. opts.Type = user_model.UserTypeIndividual
  81. testSuccess(opts, expectedUserIDs)
  82. }
  83. testUserSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}},
  84. []int64{1, 2, 4, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32, 34, 37, 38, 39, 40})
  85. testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsActive: optional.Some(false)},
  86. []int64{9})
  87. testUserSuccess(&user_model.SearchUserOptions{OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: optional.Some(true)},
  88. []int64{1, 2, 4, 5, 8, 10, 11, 12, 13, 14, 15, 16, 18, 20, 21, 24, 27, 28, 29, 30, 32, 34, 37, 38, 39, 40})
  89. testUserSuccess(&user_model.SearchUserOptions{Keyword: "user1", OrderBy: "id ASC", ListOptions: db.ListOptions{Page: 1}, IsActive: optional.Some(true)},
  90. []int64{1, 10, 11, 12, 13, 14, 15, 16, 18})
  91. // order by name asc default
  92. testUserSuccess(&user_model.SearchUserOptions{Keyword: "user1", ListOptions: db.ListOptions{Page: 1}, IsActive: optional.Some(true)},
  93. []int64{1, 10, 11, 12, 13, 14, 15, 16, 18})
  94. testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsAdmin: optional.Some(true)},
  95. []int64{1})
  96. testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsRestricted: optional.Some(true)},
  97. []int64{29})
  98. testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsProhibitLogin: optional.Some(true)},
  99. []int64{37})
  100. testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsTwoFactorEnabled: optional.Some(true)},
  101. []int64{24})
  102. }
  103. func TestEmailNotificationPreferences(t *testing.T) {
  104. assert.NoError(t, unittest.PrepareTestDatabase())
  105. for _, test := range []struct {
  106. expected string
  107. userID int64
  108. }{
  109. {user_model.EmailNotificationsEnabled, 1},
  110. {user_model.EmailNotificationsEnabled, 2},
  111. {user_model.EmailNotificationsOnMention, 3},
  112. {user_model.EmailNotificationsOnMention, 4},
  113. {user_model.EmailNotificationsEnabled, 5},
  114. {user_model.EmailNotificationsEnabled, 6},
  115. {user_model.EmailNotificationsDisabled, 7},
  116. {user_model.EmailNotificationsEnabled, 8},
  117. {user_model.EmailNotificationsOnMention, 9},
  118. } {
  119. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: test.userID})
  120. assert.Equal(t, test.expected, user.EmailNotificationsPreference)
  121. }
  122. }
  123. func TestHashPasswordDeterministic(t *testing.T) {
  124. b := make([]byte, 16)
  125. u := &user_model.User{}
  126. algos := hash.RecommendedHashAlgorithms
  127. for j := 0; j < len(algos); j++ {
  128. u.PasswdHashAlgo = algos[j]
  129. for i := 0; i < 50; i++ {
  130. // generate a random password
  131. rand.Read(b)
  132. pass := string(b)
  133. // save the current password in the user - hash it and store the result
  134. u.SetPassword(pass)
  135. r1 := u.Passwd
  136. // run again
  137. u.SetPassword(pass)
  138. r2 := u.Passwd
  139. assert.NotEqual(t, r1, r2)
  140. assert.True(t, u.ValidatePassword(pass))
  141. }
  142. }
  143. }
  144. func BenchmarkHashPassword(b *testing.B) {
  145. // BenchmarkHashPassword ensures that it takes a reasonable amount of time
  146. // to hash a password - in order to protect from brute-force attacks.
  147. pass := "password1337"
  148. u := &user_model.User{Passwd: pass}
  149. b.ResetTimer()
  150. for i := 0; i < b.N; i++ {
  151. u.SetPassword(pass)
  152. }
  153. }
  154. func TestNewGitSig(t *testing.T) {
  155. users := make([]*user_model.User, 0, 20)
  156. err := db.GetEngine(db.DefaultContext).Find(&users)
  157. assert.NoError(t, err)
  158. for _, user := range users {
  159. sig := user.NewGitSig()
  160. assert.NotContains(t, sig.Name, "<")
  161. assert.NotContains(t, sig.Name, ">")
  162. assert.NotContains(t, sig.Name, "\n")
  163. assert.NotEqual(t, len(strings.TrimSpace(sig.Name)), 0)
  164. }
  165. }
  166. func TestDisplayName(t *testing.T) {
  167. users := make([]*user_model.User, 0, 20)
  168. err := db.GetEngine(db.DefaultContext).Find(&users)
  169. assert.NoError(t, err)
  170. for _, user := range users {
  171. displayName := user.DisplayName()
  172. assert.Equal(t, strings.TrimSpace(displayName), displayName)
  173. if len(strings.TrimSpace(user.FullName)) == 0 {
  174. assert.Equal(t, user.Name, displayName)
  175. }
  176. assert.NotEqual(t, len(strings.TrimSpace(displayName)), 0)
  177. }
  178. }
  179. func TestCreateUserInvalidEmail(t *testing.T) {
  180. user := &user_model.User{
  181. Name: "GiteaBot",
  182. Email: "GiteaBot@gitea.io\r\n",
  183. Passwd: ";p['////..-++']",
  184. IsAdmin: false,
  185. Theme: setting.UI.DefaultTheme,
  186. MustChangePassword: false,
  187. }
  188. err := user_model.CreateUser(db.DefaultContext, user)
  189. assert.Error(t, err)
  190. assert.True(t, user_model.IsErrEmailCharIsNotSupported(err))
  191. }
  192. func TestCreateUserEmailAlreadyUsed(t *testing.T) {
  193. assert.NoError(t, unittest.PrepareTestDatabase())
  194. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  195. // add new user with user2's email
  196. user.Name = "testuser"
  197. user.LowerName = strings.ToLower(user.Name)
  198. user.ID = 0
  199. err := user_model.CreateUser(db.DefaultContext, user)
  200. assert.Error(t, err)
  201. assert.True(t, user_model.IsErrEmailAlreadyUsed(err))
  202. }
  203. func TestCreateUserCustomTimestamps(t *testing.T) {
  204. assert.NoError(t, unittest.PrepareTestDatabase())
  205. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  206. // Add new user with a custom creation timestamp.
  207. var creationTimestamp timeutil.TimeStamp = 12345
  208. user.Name = "testuser"
  209. user.LowerName = strings.ToLower(user.Name)
  210. user.ID = 0
  211. user.Email = "unique@example.com"
  212. user.CreatedUnix = creationTimestamp
  213. err := user_model.CreateUser(db.DefaultContext, user)
  214. assert.NoError(t, err)
  215. fetched, err := user_model.GetUserByID(context.Background(), user.ID)
  216. assert.NoError(t, err)
  217. assert.Equal(t, creationTimestamp, fetched.CreatedUnix)
  218. assert.Equal(t, creationTimestamp, fetched.UpdatedUnix)
  219. }
  220. func TestCreateUserWithoutCustomTimestamps(t *testing.T) {
  221. assert.NoError(t, unittest.PrepareTestDatabase())
  222. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  223. // There is no way to use a mocked time for the XORM auto-time functionality,
  224. // so use the real clock to approximate the expected timestamp.
  225. timestampStart := time.Now().Unix()
  226. // Add new user without a custom creation timestamp.
  227. user.Name = "Testuser"
  228. user.LowerName = strings.ToLower(user.Name)
  229. user.ID = 0
  230. user.Email = "unique@example.com"
  231. user.CreatedUnix = 0
  232. user.UpdatedUnix = 0
  233. err := user_model.CreateUser(db.DefaultContext, user)
  234. assert.NoError(t, err)
  235. timestampEnd := time.Now().Unix()
  236. fetched, err := user_model.GetUserByID(context.Background(), user.ID)
  237. assert.NoError(t, err)
  238. assert.LessOrEqual(t, timestampStart, fetched.CreatedUnix)
  239. assert.LessOrEqual(t, fetched.CreatedUnix, timestampEnd)
  240. assert.LessOrEqual(t, timestampStart, fetched.UpdatedUnix)
  241. assert.LessOrEqual(t, fetched.UpdatedUnix, timestampEnd)
  242. }
  243. func TestGetUserIDsByNames(t *testing.T) {
  244. assert.NoError(t, unittest.PrepareTestDatabase())
  245. // ignore non existing
  246. IDs, err := user_model.GetUserIDsByNames(db.DefaultContext, []string{"user1", "user2", "none_existing_user"}, true)
  247. assert.NoError(t, err)
  248. assert.Equal(t, []int64{1, 2}, IDs)
  249. // ignore non existing
  250. IDs, err = user_model.GetUserIDsByNames(db.DefaultContext, []string{"user1", "do_not_exist"}, false)
  251. assert.Error(t, err)
  252. assert.Equal(t, []int64(nil), IDs)
  253. }
  254. func TestGetMaileableUsersByIDs(t *testing.T) {
  255. assert.NoError(t, unittest.PrepareTestDatabase())
  256. results, err := user_model.GetMaileableUsersByIDs(db.DefaultContext, []int64{1, 4}, false)
  257. assert.NoError(t, err)
  258. assert.Len(t, results, 1)
  259. if len(results) > 1 {
  260. assert.Equal(t, results[0].ID, 1)
  261. }
  262. results, err = user_model.GetMaileableUsersByIDs(db.DefaultContext, []int64{1, 4}, true)
  263. assert.NoError(t, err)
  264. assert.Len(t, results, 2)
  265. if len(results) > 2 {
  266. assert.Equal(t, results[0].ID, 1)
  267. assert.Equal(t, results[1].ID, 4)
  268. }
  269. }
  270. func TestNewUserRedirect(t *testing.T) {
  271. // redirect to a completely new name
  272. assert.NoError(t, unittest.PrepareTestDatabase())
  273. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
  274. assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "newusername"))
  275. unittest.AssertExistsAndLoadBean(t, &user_model.Redirect{
  276. LowerName: user.LowerName,
  277. RedirectUserID: user.ID,
  278. })
  279. unittest.AssertExistsAndLoadBean(t, &user_model.Redirect{
  280. LowerName: "olduser1",
  281. RedirectUserID: user.ID,
  282. })
  283. }
  284. func TestNewUserRedirect2(t *testing.T) {
  285. // redirect to previously used name
  286. assert.NoError(t, unittest.PrepareTestDatabase())
  287. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
  288. assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "olduser1"))
  289. unittest.AssertExistsAndLoadBean(t, &user_model.Redirect{
  290. LowerName: user.LowerName,
  291. RedirectUserID: user.ID,
  292. })
  293. unittest.AssertNotExistsBean(t, &user_model.Redirect{
  294. LowerName: "olduser1",
  295. RedirectUserID: user.ID,
  296. })
  297. }
  298. func TestNewUserRedirect3(t *testing.T) {
  299. // redirect for a previously-unredirected user
  300. assert.NoError(t, unittest.PrepareTestDatabase())
  301. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  302. assert.NoError(t, user_model.NewUserRedirect(db.DefaultContext, user.ID, user.Name, "newusername"))
  303. unittest.AssertExistsAndLoadBean(t, &user_model.Redirect{
  304. LowerName: user.LowerName,
  305. RedirectUserID: user.ID,
  306. })
  307. }
  308. func TestGetUserByOpenID(t *testing.T) {
  309. assert.NoError(t, unittest.PrepareTestDatabase())
  310. _, err := user_model.GetUserByOpenID(db.DefaultContext, "https://unknown")
  311. if assert.Error(t, err) {
  312. assert.True(t, user_model.IsErrUserNotExist(err))
  313. }
  314. user, err := user_model.GetUserByOpenID(db.DefaultContext, "https://user1.domain1.tld")
  315. if assert.NoError(t, err) {
  316. assert.Equal(t, int64(1), user.ID)
  317. }
  318. user, err = user_model.GetUserByOpenID(db.DefaultContext, "https://domain1.tld/user2/")
  319. if assert.NoError(t, err) {
  320. assert.Equal(t, int64(2), user.ID)
  321. }
  322. }
  323. func TestFollowUser(t *testing.T) {
  324. assert.NoError(t, unittest.PrepareTestDatabase())
  325. testSuccess := func(follower, followed *user_model.User) {
  326. assert.NoError(t, user_model.FollowUser(db.DefaultContext, follower, followed))
  327. unittest.AssertExistsAndLoadBean(t, &user_model.Follow{UserID: follower.ID, FollowID: followed.ID})
  328. }
  329. user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  330. user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
  331. user5 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
  332. testSuccess(user4, user2)
  333. testSuccess(user5, user2)
  334. assert.NoError(t, user_model.FollowUser(db.DefaultContext, user2, user2))
  335. unittest.CheckConsistencyFor(t, &user_model.User{})
  336. }
  337. func TestUnfollowUser(t *testing.T) {
  338. assert.NoError(t, unittest.PrepareTestDatabase())
  339. testSuccess := func(followerID, followedID int64) {
  340. assert.NoError(t, user_model.UnfollowUser(db.DefaultContext, followerID, followedID))
  341. unittest.AssertNotExistsBean(t, &user_model.Follow{UserID: followerID, FollowID: followedID})
  342. }
  343. testSuccess(4, 2)
  344. testSuccess(5, 2)
  345. testSuccess(2, 2)
  346. unittest.CheckConsistencyFor(t, &user_model.User{})
  347. }
  348. func TestIsUserVisibleToViewer(t *testing.T) {
  349. assert.NoError(t, unittest.PrepareTestDatabase())
  350. user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) // admin, public
  351. user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) // normal, public
  352. user20 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 20}) // public, same team as user31
  353. user29 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 29}) // public, is restricted
  354. user31 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 31}) // private, same team as user20
  355. user33 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 33}) // limited, follows 31
  356. test := func(u, viewer *user_model.User, expected bool) {
  357. name := func(u *user_model.User) string {
  358. if u == nil {
  359. return "<nil>"
  360. }
  361. return u.Name
  362. }
  363. assert.Equal(t, expected, user_model.IsUserVisibleToViewer(db.DefaultContext, u, viewer), "user %v should be visible to viewer %v: %v", name(u), name(viewer), expected)
  364. }
  365. // admin viewer
  366. test(user1, user1, true)
  367. test(user20, user1, true)
  368. test(user31, user1, true)
  369. test(user33, user1, true)
  370. // non admin viewer
  371. test(user4, user4, true)
  372. test(user20, user4, true)
  373. test(user31, user4, false)
  374. test(user33, user4, true)
  375. test(user4, nil, true)
  376. // public user
  377. test(user4, user20, true)
  378. test(user4, user31, true)
  379. test(user4, user33, true)
  380. // limited user
  381. test(user33, user33, true)
  382. test(user33, user4, true)
  383. test(user33, user29, false)
  384. test(user33, nil, false)
  385. // private user
  386. test(user31, user31, true)
  387. test(user31, user4, false)
  388. test(user31, user20, true)
  389. test(user31, user29, false)
  390. test(user31, user33, true)
  391. test(user31, nil, false)
  392. }
  393. func Test_ValidateUser(t *testing.T) {
  394. oldSetting := setting.Service.AllowedUserVisibilityModesSlice
  395. defer func() {
  396. setting.Service.AllowedUserVisibilityModesSlice = oldSetting
  397. }()
  398. setting.Service.AllowedUserVisibilityModesSlice = []bool{true, false, true}
  399. kases := map[*user_model.User]bool{
  400. {ID: 1, Visibility: structs.VisibleTypePublic}: true,
  401. {ID: 2, Visibility: structs.VisibleTypeLimited}: false,
  402. {ID: 2, Visibility: structs.VisibleTypePrivate}: true,
  403. }
  404. for kase, expected := range kases {
  405. assert.EqualValues(t, expected, nil == user_model.ValidateUser(kase), fmt.Sprintf("case: %+v", kase))
  406. }
  407. }
  408. func Test_NormalizeUserFromEmail(t *testing.T) {
  409. testCases := []struct {
  410. Input string
  411. Expected string
  412. IsNormalizedValid bool
  413. }{
  414. {"name@example.com", "name", true},
  415. {"test'`´name", "testname", true},
  416. {"Sinéad.O'Connor", "Sinead.OConnor", true},
  417. {"Æsir", "AEsir", true},
  418. {"éé", "ee", true}, // \u00e9\u0065\u0301
  419. {"Awareness Hub", "Awareness-Hub", true},
  420. {"double__underscore", "double__underscore", false}, // We should consider squashing double non-alpha characters
  421. {".bad.", ".bad.", false},
  422. {"new😀user", "new😀user", false}, // No plans to support
  423. {`"quoted"`, `"quoted"`, false}, // No plans to support
  424. }
  425. for _, testCase := range testCases {
  426. normalizedName, err := user_model.NormalizeUserName(testCase.Input)
  427. assert.NoError(t, err)
  428. assert.EqualValues(t, testCase.Expected, normalizedName)
  429. if testCase.IsNormalizedValid {
  430. assert.NoError(t, user_model.IsUsableUsername(normalizedName))
  431. } else {
  432. assert.Error(t, user_model.IsUsableUsername(normalizedName))
  433. }
  434. }
  435. }
  436. func TestDisabledUserFeatures(t *testing.T) {
  437. assert.NoError(t, unittest.PrepareTestDatabase())
  438. testValues := container.SetOf(setting.UserFeatureDeletion,
  439. setting.UserFeatureManageSSHKeys,
  440. setting.UserFeatureManageGPGKeys)
  441. oldSetting := setting.Admin.ExternalUserDisableFeatures
  442. defer func() {
  443. setting.Admin.ExternalUserDisableFeatures = oldSetting
  444. }()
  445. setting.Admin.ExternalUserDisableFeatures = testValues
  446. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
  447. assert.Len(t, setting.Admin.UserDisabledFeatures.Values(), 0)
  448. // no features should be disabled with a plain login type
  449. assert.LessOrEqual(t, user.LoginType, auth.Plain)
  450. assert.Len(t, user_model.DisabledFeaturesWithLoginType(user).Values(), 0)
  451. for _, f := range testValues.Values() {
  452. assert.False(t, user_model.IsFeatureDisabledWithLoginType(user, f))
  453. }
  454. // check disabled features with external login type
  455. user.LoginType = auth.OAuth2
  456. // all features should be disabled
  457. assert.NotEmpty(t, user_model.DisabledFeaturesWithLoginType(user).Values())
  458. for _, f := range testValues.Values() {
  459. assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f))
  460. }
  461. }