code.gitea.io/gitea@v1.22.3/tests/integration/user_test.go (about) 1 // Copyright 2017 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "net/http" 8 "testing" 9 10 auth_model "code.gitea.io/gitea/models/auth" 11 issues_model "code.gitea.io/gitea/models/issues" 12 repo_model "code.gitea.io/gitea/models/repo" 13 "code.gitea.io/gitea/models/unittest" 14 user_model "code.gitea.io/gitea/models/user" 15 "code.gitea.io/gitea/modules/setting" 16 api "code.gitea.io/gitea/modules/structs" 17 "code.gitea.io/gitea/modules/test" 18 "code.gitea.io/gitea/modules/translation" 19 "code.gitea.io/gitea/tests" 20 21 "github.com/stretchr/testify/assert" 22 ) 23 24 func TestViewUser(t *testing.T) { 25 defer tests.PrepareTestEnv(t)() 26 27 req := NewRequest(t, "GET", "/user2") 28 MakeRequest(t, req, http.StatusOK) 29 } 30 31 func TestRenameUsername(t *testing.T) { 32 defer tests.PrepareTestEnv(t)() 33 34 session := loginUser(t, "user2") 35 req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ 36 "_csrf": GetCSRF(t, session, "/user/settings"), 37 "name": "newUsername", 38 "email": "user2@example.com", 39 "language": "en-US", 40 }) 41 session.MakeRequest(t, req, http.StatusSeeOther) 42 43 unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "newUsername"}) 44 unittest.AssertNotExistsBean(t, &user_model.User{Name: "user2"}) 45 } 46 47 func TestRenameInvalidUsername(t *testing.T) { 48 defer tests.PrepareTestEnv(t)() 49 50 invalidUsernames := []string{ 51 "%2f*", 52 "%2f.", 53 "%2f..", 54 "%00", 55 "thisHas ASpace", 56 "p<A>tho>lo<gical", 57 ".", 58 "..", 59 ".well-known", 60 ".abc", 61 "abc.", 62 "a..bc", 63 "a...bc", 64 "a.-bc", 65 "a._bc", 66 "a_-bc", 67 "a/bc", 68 "☁️", 69 "-", 70 "--diff", 71 "-im-here", 72 "a space", 73 } 74 75 session := loginUser(t, "user2") 76 for _, invalidUsername := range invalidUsernames { 77 t.Logf("Testing username %s", invalidUsername) 78 79 req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ 80 "_csrf": GetCSRF(t, session, "/user/settings"), 81 "name": invalidUsername, 82 "email": "user2@example.com", 83 }) 84 resp := session.MakeRequest(t, req, http.StatusOK) 85 htmlDoc := NewHTMLParser(t, resp.Body) 86 assert.Contains(t, 87 htmlDoc.doc.Find(".ui.negative.message").Text(), 88 translation.NewLocale("en-US").TrString("form.username_error"), 89 ) 90 91 unittest.AssertNotExistsBean(t, &user_model.User{Name: invalidUsername}) 92 } 93 } 94 95 func TestRenameReservedUsername(t *testing.T) { 96 defer tests.PrepareTestEnv(t)() 97 98 reservedUsernames := []string{ 99 // ".", "..", ".well-known", // The names are not only reserved but also invalid 100 "admin", 101 "api", 102 "assets", 103 "attachments", 104 "avatar", 105 "avatars", 106 "captcha", 107 "commits", 108 "debug", 109 "error", 110 "explore", 111 "favicon.ico", 112 "ghost", 113 "issues", 114 "login", 115 "manifest.json", 116 "metrics", 117 "milestones", 118 "new", 119 "notifications", 120 "org", 121 "pulls", 122 "raw", 123 "repo", 124 "repo-avatars", 125 "robots.txt", 126 "search", 127 "serviceworker.js", 128 "ssh_info", 129 "swagger.v1.json", 130 "user", 131 "v2", 132 } 133 134 session := loginUser(t, "user2") 135 for _, reservedUsername := range reservedUsernames { 136 t.Logf("Testing username %s", reservedUsername) 137 req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ 138 "_csrf": GetCSRF(t, session, "/user/settings"), 139 "name": reservedUsername, 140 "email": "user2@example.com", 141 "language": "en-US", 142 }) 143 resp := session.MakeRequest(t, req, http.StatusSeeOther) 144 145 req = NewRequest(t, "GET", test.RedirectURL(resp)) 146 resp = session.MakeRequest(t, req, http.StatusOK) 147 htmlDoc := NewHTMLParser(t, resp.Body) 148 assert.Contains(t, 149 htmlDoc.doc.Find(".ui.negative.message").Text(), 150 translation.NewLocale("en-US").TrString("user.form.name_reserved", reservedUsername), 151 ) 152 153 unittest.AssertNotExistsBean(t, &user_model.User{Name: reservedUsername}) 154 } 155 } 156 157 func TestExportUserGPGKeys(t *testing.T) { 158 defer tests.PrepareTestEnv(t)() 159 // Export empty key list 160 testExportUserGPGKeys(t, "user1", `-----BEGIN PGP PUBLIC KEY BLOCK----- 161 Note: This user hasn't uploaded any GPG keys. 162 163 164 =twTO 165 -----END PGP PUBLIC KEY BLOCK----- 166 `) 167 // Import key 168 // User1 <user1@example.com> 169 session := loginUser(t, "user1") 170 token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser) 171 testCreateGPGKey(t, session.MakeRequest, token, http.StatusCreated, `-----BEGIN PGP PUBLIC KEY BLOCK----- 172 173 mQENBFyy/VUBCADJ7zbM20Z1RWmFoVgp5WkQfI2rU1Vj9cQHes9i42wVLLtcbPeo 174 QzubgzvMPITDy7nfWxgSf83E23DoHQ1ACFbQh/6eFSRrjsusp3YQ/08NSfPPbcu8 175 0M5G+VGwSfzS5uEcwBVQmHyKdcOZIERTNMtYZx1C3bjLD1XVJHvWz9D72Uq4qeO3 176 8SR+lzp5n6ppUakcmRnxt3nGRBj1+hEGkdgzyPo93iy+WioegY2lwCA9xMEo5dah 177 BmYxWx51zyiXYlReTaxlyb3/nuSUt8IcW3Q8zjdtJj4Nu8U1SpV8EdaA1I9IPbHW 178 510OSLmD3XhqHH5m6mIxL1YoWxk3V7gpDROtABEBAAG0GVVzZXIxIDx1c2VyMUBl 179 eGFtcGxlLmNvbT6JAU4EEwEIADgWIQTQEbrYxmXsp1z3j7z9+v0I6RSEHwUCXLL9 180 VQIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRD9+v0I6RSEH22YCACFqL5+ 181 6M0m18AMC/pumcpnnmvAS1GrrKTF8nOROA1augZwp1WCNuKw2R6uOJIHANrYECSn 182 u7+j6GBP2gbIW8mSAzS6HWCs7GGiPpVtT4wcu8wljUI6BxjpyZtoEkriyBjt6HfK 183 rkegbkuySoJvjq4IcO5D1LB1JWgsUjMYQJj/ZpBIzVtjG9QtFSOiT1Hct4PoZHdC 184 nsdSgyCkwRZXG+u3kT/wP9F663ba4o16vYlz3dCGo66lF2tyoG3qcyZ1OUzUrnuv 185 96ytAzT6XIhrE0nVoBprMxFF5zExotJD3bHjcGBFNLf944bhjKee3U6t9+OsfJVC 186 l7N5xxIawCuTQdbfuQENBFyy/VUBCADe61yGEoTwKfsOKIhxLaNoRmD883O0tiWt 187 soO/HPj9dPQLTOiwXgSgSCd8C+LNxGKct87wgFozpah4tDLC6c0nALuHJ0SLbkfz 188 55aRhLeOOcrAydatDp72GroXzqpZ0xZBk5wjIWdgEol2GmVRM8QGbeuakU/HVz5y 189 lPzxUUocgdbSi3GE3zbzijQzVJdyL/kw/KP7pKT/PPKKJ2C5NQDLy0XGKEHddXGR 190 EWKkVlRalxq/TjfaMR0bi3MpezBsQmp99ATPO/d7trayZUxQHRtXzGFiOXfDHATr 191 qN730sODjqvU+mpc/SHCRwh9qWDjZRHSuKU5YDBjb5jIQJivZsQ/ABEBAAGJATYE 192 GAEIACAWIQTQEbrYxmXsp1z3j7z9+v0I6RSEHwUCXLL9VQIbDAAKCRD9+v0I6RSE 193 H7WoB/4tXl+97rQ6owPCGSVp1Xbwt2521V7COgsOFRVTRTryEWxRW8mm0S7wQvax 194 C0TLXKur6NVYQMn01iyL+FZzRpEWNuYF3f9QeeLJ/+l2DafESNhNTy17+RPmacK6 195 21dccpqchByVw/UMDeHSyjQLiG2lxzt8Gfx2gHmSbrq3aWovTGyz6JTffZvfy/n2 196 0Hm437OBPazO0gZyXhdV2PE5RSUfvAgm44235tcV5EV0d32TJDfv61+Vr2GUbah6 197 7XhJ1v6JYuh8kaYaEz8OpZDeh7f6Ho6PzJrsy/TKTKhGgZNINj1iaPFyOkQgKR5M 198 GrE0MHOxUbc9tbtyk0F1SuzREUBH 199 =DDXw 200 -----END PGP PUBLIC KEY BLOCK----- 201 `) 202 // Export new key 203 testExportUserGPGKeys(t, "user1", `-----BEGIN PGP PUBLIC KEY BLOCK----- 204 205 xsBNBFyy/VUBCADJ7zbM20Z1RWmFoVgp5WkQfI2rU1Vj9cQHes9i42wVLLtcbPeo 206 QzubgzvMPITDy7nfWxgSf83E23DoHQ1ACFbQh/6eFSRrjsusp3YQ/08NSfPPbcu8 207 0M5G+VGwSfzS5uEcwBVQmHyKdcOZIERTNMtYZx1C3bjLD1XVJHvWz9D72Uq4qeO3 208 8SR+lzp5n6ppUakcmRnxt3nGRBj1+hEGkdgzyPo93iy+WioegY2lwCA9xMEo5dah 209 BmYxWx51zyiXYlReTaxlyb3/nuSUt8IcW3Q8zjdtJj4Nu8U1SpV8EdaA1I9IPbHW 210 510OSLmD3XhqHH5m6mIxL1YoWxk3V7gpDROtABEBAAHNGVVzZXIxIDx1c2VyMUBl 211 eGFtcGxlLmNvbT7CwI4EEwEIADgWIQTQEbrYxmXsp1z3j7z9+v0I6RSEHwUCXLL9 212 VQIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRD9+v0I6RSEH22YCACFqL5+ 213 6M0m18AMC/pumcpnnmvAS1GrrKTF8nOROA1augZwp1WCNuKw2R6uOJIHANrYECSn 214 u7+j6GBP2gbIW8mSAzS6HWCs7GGiPpVtT4wcu8wljUI6BxjpyZtoEkriyBjt6HfK 215 rkegbkuySoJvjq4IcO5D1LB1JWgsUjMYQJj/ZpBIzVtjG9QtFSOiT1Hct4PoZHdC 216 nsdSgyCkwRZXG+u3kT/wP9F663ba4o16vYlz3dCGo66lF2tyoG3qcyZ1OUzUrnuv 217 96ytAzT6XIhrE0nVoBprMxFF5zExotJD3bHjcGBFNLf944bhjKee3U6t9+OsfJVC 218 l7N5xxIawCuTQdbfzsBNBFyy/VUBCADe61yGEoTwKfsOKIhxLaNoRmD883O0tiWt 219 soO/HPj9dPQLTOiwXgSgSCd8C+LNxGKct87wgFozpah4tDLC6c0nALuHJ0SLbkfz 220 55aRhLeOOcrAydatDp72GroXzqpZ0xZBk5wjIWdgEol2GmVRM8QGbeuakU/HVz5y 221 lPzxUUocgdbSi3GE3zbzijQzVJdyL/kw/KP7pKT/PPKKJ2C5NQDLy0XGKEHddXGR 222 EWKkVlRalxq/TjfaMR0bi3MpezBsQmp99ATPO/d7trayZUxQHRtXzGFiOXfDHATr 223 qN730sODjqvU+mpc/SHCRwh9qWDjZRHSuKU5YDBjb5jIQJivZsQ/ABEBAAHCwHYE 224 GAEIACAWIQTQEbrYxmXsp1z3j7z9+v0I6RSEHwUCXLL9VQIbDAAKCRD9+v0I6RSE 225 H7WoB/4tXl+97rQ6owPCGSVp1Xbwt2521V7COgsOFRVTRTryEWxRW8mm0S7wQvax 226 C0TLXKur6NVYQMn01iyL+FZzRpEWNuYF3f9QeeLJ/+l2DafESNhNTy17+RPmacK6 227 21dccpqchByVw/UMDeHSyjQLiG2lxzt8Gfx2gHmSbrq3aWovTGyz6JTffZvfy/n2 228 0Hm437OBPazO0gZyXhdV2PE5RSUfvAgm44235tcV5EV0d32TJDfv61+Vr2GUbah6 229 7XhJ1v6JYuh8kaYaEz8OpZDeh7f6Ho6PzJrsy/TKTKhGgZNINj1iaPFyOkQgKR5M 230 GrE0MHOxUbc9tbtyk0F1SuzREUBH 231 =WFf5 232 -----END PGP PUBLIC KEY BLOCK----- 233 `) 234 } 235 236 func testExportUserGPGKeys(t *testing.T, user, expected string) { 237 session := loginUser(t, user) 238 t.Logf("Testing username %s export gpg keys", user) 239 req := NewRequest(t, "GET", "/"+user+".gpg") 240 resp := session.MakeRequest(t, req, http.StatusOK) 241 // t.Log(resp.Body.String()) 242 assert.Equal(t, expected, resp.Body.String()) 243 } 244 245 func TestGetUserRss(t *testing.T) { 246 defer tests.PrepareTestEnv(t)() 247 248 user34 := "the_34-user.with.all.allowedChars" 249 req := NewRequestf(t, "GET", "/%s.rss", user34) 250 resp := MakeRequest(t, req, http.StatusOK) 251 if assert.EqualValues(t, "application/rss+xml;charset=utf-8", resp.Header().Get("Content-Type")) { 252 rssDoc := NewHTMLParser(t, resp.Body).Find("channel") 253 title, _ := rssDoc.ChildrenFiltered("title").Html() 254 assert.EqualValues(t, "Feed of "the_1-user.with.all.allowedChars"", title) 255 description, _ := rssDoc.ChildrenFiltered("description").Html() 256 assert.EqualValues(t, "<p dir="auto">some <a href="https://commonmark.org/" rel="nofollow">commonmark</a>!</p>\n", description) 257 } 258 259 req = NewRequestf(t, "GET", "/non-existent-user.rss") 260 MakeRequest(t, req, http.StatusNotFound) 261 262 session := loginUser(t, "user2") 263 req = NewRequestf(t, "GET", "/non-existent-user.rss") 264 session.MakeRequest(t, req, http.StatusNotFound) 265 } 266 267 func TestListStopWatches(t *testing.T) { 268 defer tests.PrepareTestEnv(t)() 269 270 repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) 271 owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 272 273 session := loginUser(t, owner.Name) 274 req := NewRequest(t, "GET", "/user/stopwatches") 275 resp := session.MakeRequest(t, req, http.StatusOK) 276 var apiWatches []*api.StopWatch 277 DecodeJSON(t, resp, &apiWatches) 278 stopwatch := unittest.AssertExistsAndLoadBean(t, &issues_model.Stopwatch{UserID: owner.ID}) 279 issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: stopwatch.IssueID}) 280 if assert.Len(t, apiWatches, 1) { 281 assert.EqualValues(t, stopwatch.CreatedUnix.AsTime().Unix(), apiWatches[0].Created.Unix()) 282 assert.EqualValues(t, issue.Index, apiWatches[0].IssueIndex) 283 assert.EqualValues(t, issue.Title, apiWatches[0].IssueTitle) 284 assert.EqualValues(t, repo.Name, apiWatches[0].RepoName) 285 assert.EqualValues(t, repo.OwnerName, apiWatches[0].RepoOwnerName) 286 assert.Greater(t, apiWatches[0].Seconds, int64(0)) 287 } 288 } 289 290 func TestUserLocationMapLink(t *testing.T) { 291 setting.Service.UserLocationMapURL = "https://example/foo/" 292 defer tests.PrepareTestEnv(t)() 293 294 session := loginUser(t, "user2") 295 req := NewRequestWithValues(t, "POST", "/user/settings", map[string]string{ 296 "_csrf": GetCSRF(t, session, "/user/settings"), 297 "name": "user2", 298 "email": "user@example.com", 299 "language": "en-US", 300 "location": "A/b", 301 }) 302 session.MakeRequest(t, req, http.StatusSeeOther) 303 304 req = NewRequest(t, "GET", "/user2/") 305 resp := session.MakeRequest(t, req, http.StatusOK) 306 htmlDoc := NewHTMLParser(t, resp.Body) 307 htmlDoc.AssertElement(t, `a[href="https://example/foo/A%2Fb"]`, true) 308 }