gitea源码

org_team_invite_test.go 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "strings"
  9. "testing"
  10. "code.gitea.io/gitea/models/organization"
  11. "code.gitea.io/gitea/models/unittest"
  12. user_model "code.gitea.io/gitea/models/user"
  13. "code.gitea.io/gitea/modules/setting"
  14. "code.gitea.io/gitea/modules/test"
  15. "code.gitea.io/gitea/tests"
  16. "github.com/stretchr/testify/assert"
  17. )
  18. func TestOrgTeamEmailInvite(t *testing.T) {
  19. if setting.MailService == nil {
  20. t.Skip()
  21. return
  22. }
  23. defer tests.PrepareTestEnv(t)()
  24. org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
  25. team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
  26. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
  27. isMember, err := organization.IsTeamMember(t.Context(), team.OrgID, team.ID, user.ID)
  28. assert.NoError(t, err)
  29. assert.False(t, isMember)
  30. session := loginUser(t, "user1")
  31. teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
  32. csrf := GetUserCSRFToken(t, session)
  33. req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
  34. "_csrf": csrf,
  35. "uid": "1",
  36. "uname": user.Email,
  37. })
  38. resp := session.MakeRequest(t, req, http.StatusSeeOther)
  39. req = NewRequest(t, "GET", test.RedirectURL(resp))
  40. session.MakeRequest(t, req, http.StatusOK)
  41. // get the invite token
  42. invites, err := organization.GetInvitesByTeamID(t.Context(), team.ID)
  43. assert.NoError(t, err)
  44. assert.Len(t, invites, 1)
  45. session = loginUser(t, user.Name)
  46. // join the team
  47. inviteURL := "/org/invite/" + invites[0].Token
  48. csrf = GetUserCSRFToken(t, session)
  49. req = NewRequestWithValues(t, "POST", inviteURL, map[string]string{
  50. "_csrf": csrf,
  51. })
  52. resp = session.MakeRequest(t, req, http.StatusSeeOther)
  53. req = NewRequest(t, "GET", test.RedirectURL(resp))
  54. session.MakeRequest(t, req, http.StatusOK)
  55. isMember, err = organization.IsTeamMember(t.Context(), team.OrgID, team.ID, user.ID)
  56. assert.NoError(t, err)
  57. assert.True(t, isMember)
  58. }
  59. // Check that users are redirected to accept the invitation correctly after login
  60. func TestOrgTeamEmailInviteRedirectsExistingUser(t *testing.T) {
  61. if setting.MailService == nil {
  62. t.Skip()
  63. return
  64. }
  65. defer tests.PrepareTestEnv(t)()
  66. org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
  67. team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
  68. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
  69. isMember, err := organization.IsTeamMember(t.Context(), team.OrgID, team.ID, user.ID)
  70. assert.NoError(t, err)
  71. assert.False(t, isMember)
  72. // create the invite
  73. session := loginUser(t, "user1")
  74. teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
  75. req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
  76. "_csrf": GetUserCSRFToken(t, session),
  77. "uid": "1",
  78. "uname": user.Email,
  79. })
  80. resp := session.MakeRequest(t, req, http.StatusSeeOther)
  81. req = NewRequest(t, "GET", test.RedirectURL(resp))
  82. session.MakeRequest(t, req, http.StatusOK)
  83. // get the invite token
  84. invites, err := organization.GetInvitesByTeamID(t.Context(), team.ID)
  85. assert.NoError(t, err)
  86. assert.Len(t, invites, 1)
  87. // accept the invite
  88. inviteURL := "/org/invite/" + invites[0].Token
  89. req = NewRequest(t, "GET", "/user/login?redirect_to="+url.QueryEscape(inviteURL))
  90. resp = MakeRequest(t, req, http.StatusOK)
  91. doc := NewHTMLParser(t, resp.Body)
  92. req = NewRequestWithValues(t, "POST", "/user/login", map[string]string{
  93. "_csrf": doc.GetCSRF(),
  94. "user_name": "user5",
  95. "password": "password",
  96. })
  97. for _, c := range resp.Result().Cookies() {
  98. req.AddCookie(c)
  99. }
  100. resp = MakeRequest(t, req, http.StatusSeeOther)
  101. assert.Equal(t, inviteURL, test.RedirectURL(resp))
  102. // complete the login process
  103. ch := http.Header{}
  104. ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
  105. cr := http.Request{Header: ch}
  106. session = emptyTestSession(t)
  107. baseURL, err := url.Parse(setting.AppURL)
  108. assert.NoError(t, err)
  109. session.jar.SetCookies(baseURL, cr.Cookies())
  110. // make the request
  111. req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
  112. "_csrf": GetUserCSRFToken(t, session),
  113. })
  114. resp = session.MakeRequest(t, req, http.StatusSeeOther)
  115. req = NewRequest(t, "GET", test.RedirectURL(resp))
  116. session.MakeRequest(t, req, http.StatusOK)
  117. isMember, err = organization.IsTeamMember(t.Context(), team.OrgID, team.ID, user.ID)
  118. assert.NoError(t, err)
  119. assert.True(t, isMember)
  120. }
  121. // Check that newly signed up users are redirected to accept the invitation correctly
  122. func TestOrgTeamEmailInviteRedirectsNewUser(t *testing.T) {
  123. if setting.MailService == nil {
  124. t.Skip()
  125. return
  126. }
  127. defer tests.PrepareTestEnv(t)()
  128. org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
  129. team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
  130. // create the invite
  131. session := loginUser(t, "user1")
  132. teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
  133. req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
  134. "_csrf": GetUserCSRFToken(t, session),
  135. "uid": "1",
  136. "uname": "doesnotexist@example.com",
  137. })
  138. resp := session.MakeRequest(t, req, http.StatusSeeOther)
  139. req = NewRequest(t, "GET", test.RedirectURL(resp))
  140. session.MakeRequest(t, req, http.StatusOK)
  141. // get the invite token
  142. invites, err := organization.GetInvitesByTeamID(t.Context(), team.ID)
  143. assert.NoError(t, err)
  144. assert.Len(t, invites, 1)
  145. // accept the invite
  146. inviteURL := "/org/invite/" + invites[0].Token
  147. req = NewRequest(t, "GET", "/user/sign_up?redirect_to="+url.QueryEscape(inviteURL))
  148. resp = MakeRequest(t, req, http.StatusOK)
  149. doc := NewHTMLParser(t, resp.Body)
  150. req = NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
  151. "_csrf": doc.GetCSRF(),
  152. "user_name": "doesnotexist",
  153. "email": "doesnotexist@example.com",
  154. "password": "examplePassword!1",
  155. "retype": "examplePassword!1",
  156. })
  157. for _, c := range resp.Result().Cookies() {
  158. req.AddCookie(c)
  159. }
  160. resp = MakeRequest(t, req, http.StatusSeeOther)
  161. assert.Equal(t, inviteURL, test.RedirectURL(resp))
  162. // complete the signup process
  163. ch := http.Header{}
  164. ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
  165. cr := http.Request{Header: ch}
  166. session = emptyTestSession(t)
  167. baseURL, err := url.Parse(setting.AppURL)
  168. assert.NoError(t, err)
  169. session.jar.SetCookies(baseURL, cr.Cookies())
  170. // make the redirected request
  171. req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
  172. "_csrf": GetUserCSRFToken(t, session),
  173. })
  174. resp = session.MakeRequest(t, req, http.StatusSeeOther)
  175. req = NewRequest(t, "GET", test.RedirectURL(resp))
  176. session.MakeRequest(t, req, http.StatusOK)
  177. // get the new user
  178. newUser, err := user_model.GetUserByName(t.Context(), "doesnotexist")
  179. assert.NoError(t, err)
  180. isMember, err := organization.IsTeamMember(t.Context(), team.OrgID, team.ID, newUser.ID)
  181. assert.NoError(t, err)
  182. assert.True(t, isMember)
  183. }
  184. // Check that users are redirected correctly after confirming their email
  185. func TestOrgTeamEmailInviteRedirectsNewUserWithActivation(t *testing.T) {
  186. if setting.MailService == nil {
  187. t.Skip()
  188. return
  189. }
  190. // enable email confirmation temporarily
  191. defer test.MockVariableValue(&setting.Service.RegisterEmailConfirm, true)()
  192. defer tests.PrepareTestEnv(t)()
  193. org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
  194. team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
  195. // user1: create the invite
  196. session := loginUser(t, "user1")
  197. teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
  198. req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
  199. "_csrf": GetUserCSRFToken(t, session),
  200. "uid": "1",
  201. "uname": "doesnotexist@example.com",
  202. })
  203. resp := session.MakeRequest(t, req, http.StatusSeeOther)
  204. req = NewRequest(t, "GET", test.RedirectURL(resp))
  205. session.MakeRequest(t, req, http.StatusOK)
  206. // get the invite token
  207. invites, err := organization.GetInvitesByTeamID(t.Context(), team.ID)
  208. assert.NoError(t, err)
  209. assert.Len(t, invites, 1)
  210. // new user: accept the invite
  211. session = emptyTestSession(t)
  212. inviteURL := "/org/invite/" + invites[0].Token
  213. req = NewRequest(t, "GET", "/user/sign_up?redirect_to="+url.QueryEscape(inviteURL))
  214. session.MakeRequest(t, req, http.StatusOK)
  215. req = NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
  216. "user_name": "doesnotexist",
  217. "email": "doesnotexist@example.com",
  218. "password": "examplePassword!1",
  219. "retype": "examplePassword!1",
  220. })
  221. session.MakeRequest(t, req, http.StatusOK)
  222. user, err := user_model.GetUserByName(t.Context(), "doesnotexist")
  223. assert.NoError(t, err)
  224. activationCode := user_model.GenerateUserTimeLimitCode(&user_model.TimeLimitCodeOptions{Purpose: user_model.TimeLimitCodeActivateAccount}, user)
  225. activateURL := "/user/activate?code=" + activationCode
  226. req = NewRequestWithValues(t, "POST", activateURL, map[string]string{
  227. "password": "examplePassword!1",
  228. })
  229. resp = session.MakeRequest(t, req, http.StatusSeeOther)
  230. // should be redirected to accept the invite
  231. assert.Equal(t, inviteURL, test.RedirectURL(resp))
  232. req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
  233. "_csrf": GetUserCSRFToken(t, session),
  234. })
  235. resp = session.MakeRequest(t, req, http.StatusSeeOther)
  236. req = NewRequest(t, "GET", test.RedirectURL(resp))
  237. session.MakeRequest(t, req, http.StatusOK)
  238. isMember, err := organization.IsTeamMember(t.Context(), team.OrgID, team.ID, user.ID)
  239. assert.NoError(t, err)
  240. assert.True(t, isMember)
  241. }
  242. // Test that a logged-in user who navigates to the sign-up link is then redirected using redirect_to
  243. // For example: an invite may have been created before the user account was created, but they may be
  244. // accepting the invite after having created an account separately
  245. func TestOrgTeamEmailInviteRedirectsExistingUserWithLogin(t *testing.T) {
  246. if setting.MailService == nil {
  247. t.Skip()
  248. return
  249. }
  250. defer tests.PrepareTestEnv(t)()
  251. org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
  252. team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
  253. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
  254. isMember, err := organization.IsTeamMember(t.Context(), team.OrgID, team.ID, user.ID)
  255. assert.NoError(t, err)
  256. assert.False(t, isMember)
  257. // create the invite
  258. session := loginUser(t, "user1")
  259. teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
  260. req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
  261. "_csrf": GetUserCSRFToken(t, session),
  262. "uid": "1",
  263. "uname": user.Email,
  264. })
  265. resp := session.MakeRequest(t, req, http.StatusSeeOther)
  266. req = NewRequest(t, "GET", test.RedirectURL(resp))
  267. session.MakeRequest(t, req, http.StatusOK)
  268. // get the invite token
  269. invites, err := organization.GetInvitesByTeamID(t.Context(), team.ID)
  270. assert.NoError(t, err)
  271. assert.Len(t, invites, 1)
  272. // note: the invited user has logged in
  273. session = loginUser(t, "user5")
  274. // accept the invite (note: this uses the sign_up url)
  275. inviteURL := "/org/invite/" + invites[0].Token
  276. req = NewRequest(t, "GET", "/user/sign_up?redirect_to="+url.QueryEscape(inviteURL))
  277. resp = session.MakeRequest(t, req, http.StatusSeeOther)
  278. assert.Equal(t, inviteURL, test.RedirectURL(resp))
  279. // make the request
  280. req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
  281. "_csrf": GetUserCSRFToken(t, session),
  282. })
  283. resp = session.MakeRequest(t, req, http.StatusSeeOther)
  284. req = NewRequest(t, "GET", test.RedirectURL(resp))
  285. session.MakeRequest(t, req, http.StatusOK)
  286. isMember, err = organization.IsTeamMember(t.Context(), team.OrgID, team.ID, user.ID)
  287. assert.NoError(t, err)
  288. assert.True(t, isMember)
  289. }