Update team invitation email link (#26550)
Co-authored-by: Kyle D <kdumontnu@gmail.com> Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
This commit is contained in:
		
							parent
							
								
									3cae50e841
								
							
						
					
					
						commit
						c0ab7070e5
					
				
					 5 changed files with 346 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -398,6 +398,11 @@ func SignUp(ctx *context.Context) {
 | 
			
		|||
	// Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true
 | 
			
		||||
	ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration
 | 
			
		||||
 | 
			
		||||
	redirectTo := ctx.FormString("redirect_to")
 | 
			
		||||
	if len(redirectTo) > 0 {
 | 
			
		||||
		middleware.SetRedirectToCookie(ctx.Resp, redirectTo)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.HTML(http.StatusOK, tplSignUp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -729,6 +734,12 @@ func handleAccountActivation(ctx *context.Context, user *user_model.User) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Flash.Success(ctx.Tr("auth.account_activated"))
 | 
			
		||||
	if redirectTo := ctx.GetSiteCookie("redirect_to"); len(redirectTo) > 0 {
 | 
			
		||||
		middleware.DeleteRedirectToCookie(ctx.Resp)
 | 
			
		||||
		ctx.RedirectToFirst(redirectTo)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Redirect(setting.AppSubURL + "/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,9 +120,9 @@ func VerifyAuthWithOptions(options *VerifyOptions) func(ctx *context.Context) {
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Redirect to dashboard if user tries to visit any non-login page.
 | 
			
		||||
		// Redirect to dashboard (or alternate location) if user tries to visit any non-login page.
 | 
			
		||||
		if options.SignOutRequired && ctx.IsSigned && ctx.Req.URL.RequestURI() != "/" {
 | 
			
		||||
			ctx.Redirect(setting.AppSubURL + "/")
 | 
			
		||||
			ctx.RedirectToFirst(ctx.FormString("redirect_to"))
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,8 @@ package mailer
 | 
			
		|||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
 | 
			
		||||
	org_model "code.gitea.io/gitea/models/organization"
 | 
			
		||||
	user_model "code.gitea.io/gitea/models/user"
 | 
			
		||||
| 
						 | 
				
			
			@ -33,6 +35,22 @@ func MailTeamInvite(ctx context.Context, inviter *user_model.User, team *org_mod
 | 
			
		|||
 | 
			
		||||
	locale := translation.NewLocale(inviter.Language)
 | 
			
		||||
 | 
			
		||||
	// check if a user with this email already exists
 | 
			
		||||
	user, err := user_model.GetUserByEmail(ctx, invite.Email)
 | 
			
		||||
	if err != nil && !user_model.IsErrUserNotExist(err) {
 | 
			
		||||
		return err
 | 
			
		||||
	} else if user != nil && user.ProhibitLogin {
 | 
			
		||||
		return fmt.Errorf("login is prohibited for the invited user")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inviteRedirect := url.QueryEscape(fmt.Sprintf("/org/invite/%s", invite.Token))
 | 
			
		||||
	inviteURL := fmt.Sprintf("%suser/sign_up?redirect_to=%s", setting.AppURL, inviteRedirect)
 | 
			
		||||
 | 
			
		||||
	if err == nil && user != nil {
 | 
			
		||||
		// user account exists
 | 
			
		||||
		inviteURL = fmt.Sprintf("%suser/login?redirect_to=%s", setting.AppURL, inviteRedirect)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	subject := locale.Tr("mail.team_invite.subject", inviter.DisplayName(), org.DisplayName())
 | 
			
		||||
	mailMeta := map[string]any{
 | 
			
		||||
		"Inviter":      inviter,
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +58,7 @@ func MailTeamInvite(ctx context.Context, inviter *user_model.User, team *org_mod
 | 
			
		|||
		"Team":         team,
 | 
			
		||||
		"Invite":       invite,
 | 
			
		||||
		"Subject":      subject,
 | 
			
		||||
		"InviteURL":    inviteURL,
 | 
			
		||||
		// helper
 | 
			
		||||
		"locale":    locale,
 | 
			
		||||
		"Str2html":  templates.Str2html,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,10 +4,9 @@
 | 
			
		|||
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 | 
			
		||||
	<meta name="format-detection" content="telephone=no,date=no,address=no,email=no,url=no">
 | 
			
		||||
</head>
 | 
			
		||||
{{$invite_url := printf "%sorg/invite/%s" AppUrl (QueryEscape .Invite.Token)}}
 | 
			
		||||
<body>
 | 
			
		||||
	<p>{{.locale.Tr "mail.team_invite.text_1" (DotEscape .Inviter.DisplayName) (DotEscape .Team.Name) (DotEscape .Organization.DisplayName) | Str2html}}</p>
 | 
			
		||||
	<p>{{.locale.Tr "mail.team_invite.text_2"}}</p><p><a href="{{$invite_url}}">{{$invite_url}}</a></p>
 | 
			
		||||
	<p>{{.locale.Tr "mail.team_invite.text_2"}}</p><p><a href="{{.InviteURL}}">{{.InviteURL}}</a></p>
 | 
			
		||||
	<p>{{.locale.Tr "mail.link_not_working_do_paste"}}</p>
 | 
			
		||||
	<p>{{.locale.Tr "mail.team_invite.text_3" .Invite.Email}}</p>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,8 @@ package integration
 | 
			
		|||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
| 
						 | 
				
			
			@ -37,9 +39,9 @@ func TestOrgTeamEmailInvite(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	session := loginUser(t, "user1")
 | 
			
		||||
 | 
			
		||||
	url := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
 | 
			
		||||
	csrf := GetCSRF(t, session, url)
 | 
			
		||||
	req := NewRequestWithValues(t, "POST", url+"/action/add", map[string]string{
 | 
			
		||||
	teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
 | 
			
		||||
	csrf := GetCSRF(t, session, teamURL)
 | 
			
		||||
	req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
 | 
			
		||||
		"_csrf": csrf,
 | 
			
		||||
		"uid":   "1",
 | 
			
		||||
		"uname": user.Email,
 | 
			
		||||
| 
						 | 
				
			
			@ -56,9 +58,9 @@ func TestOrgTeamEmailInvite(t *testing.T) {
 | 
			
		|||
	session = loginUser(t, user.Name)
 | 
			
		||||
 | 
			
		||||
	// join the team
 | 
			
		||||
	url = fmt.Sprintf("/org/invite/%s", invites[0].Token)
 | 
			
		||||
	csrf = GetCSRF(t, session, url)
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", url, map[string]string{
 | 
			
		||||
	inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
 | 
			
		||||
	csrf = GetCSRF(t, session, inviteURL)
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", inviteURL, map[string]string{
 | 
			
		||||
		"_csrf": csrf,
 | 
			
		||||
	})
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
| 
						 | 
				
			
			@ -69,3 +71,308 @@ func TestOrgTeamEmailInvite(t *testing.T) {
 | 
			
		|||
	assert.NoError(t, err)
 | 
			
		||||
	assert.True(t, isMember)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check that users are redirected to accept the invitation correctly after login
 | 
			
		||||
func TestOrgTeamEmailInviteRedirectsExistingUser(t *testing.T) {
 | 
			
		||||
	if setting.MailService == nil {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer tests.PrepareTestEnv(t)()
 | 
			
		||||
 | 
			
		||||
	org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
 | 
			
		||||
	team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
 | 
			
		||||
	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
 | 
			
		||||
 | 
			
		||||
	isMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.False(t, isMember)
 | 
			
		||||
 | 
			
		||||
	// create the invite
 | 
			
		||||
	session := loginUser(t, "user1")
 | 
			
		||||
 | 
			
		||||
	teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
 | 
			
		||||
	req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
 | 
			
		||||
		"_csrf": GetCSRF(t, session, teamURL),
 | 
			
		||||
		"uid":   "1",
 | 
			
		||||
		"uname": user.Email,
 | 
			
		||||
	})
 | 
			
		||||
	resp := session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	req = NewRequest(t, "GET", test.RedirectURL(resp))
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	// get the invite token
 | 
			
		||||
	invites, err := organization.GetInvitesByTeamID(db.DefaultContext, team.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Len(t, invites, 1)
 | 
			
		||||
 | 
			
		||||
	// accept the invite
 | 
			
		||||
	inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
 | 
			
		||||
	req = NewRequest(t, "GET", fmt.Sprintf("/user/login?redirect_to=%s", url.QueryEscape(inviteURL)))
 | 
			
		||||
	resp = MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	doc := NewHTMLParser(t, resp.Body)
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", "/user/login", map[string]string{
 | 
			
		||||
		"_csrf":     doc.GetCSRF(),
 | 
			
		||||
		"user_name": "user5",
 | 
			
		||||
		"password":  "password",
 | 
			
		||||
	})
 | 
			
		||||
	for _, c := range resp.Result().Cookies() {
 | 
			
		||||
		req.AddCookie(c)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp = MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	assert.Equal(t, inviteURL, test.RedirectURL(resp))
 | 
			
		||||
 | 
			
		||||
	// complete the login process
 | 
			
		||||
	ch := http.Header{}
 | 
			
		||||
	ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
 | 
			
		||||
	cr := http.Request{Header: ch}
 | 
			
		||||
 | 
			
		||||
	session = emptyTestSession(t)
 | 
			
		||||
	baseURL, err := url.Parse(setting.AppURL)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	session.jar.SetCookies(baseURL, cr.Cookies())
 | 
			
		||||
 | 
			
		||||
	// make the request
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
 | 
			
		||||
		"_csrf": GetCSRF(t, session, test.RedirectURL(resp)),
 | 
			
		||||
	})
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	req = NewRequest(t, "GET", test.RedirectURL(resp))
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	isMember, err = organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.True(t, isMember)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check that newly signed up users are redirected to accept the invitation correctly
 | 
			
		||||
func TestOrgTeamEmailInviteRedirectsNewUser(t *testing.T) {
 | 
			
		||||
	if setting.MailService == nil {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer tests.PrepareTestEnv(t)()
 | 
			
		||||
 | 
			
		||||
	org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
 | 
			
		||||
	team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
 | 
			
		||||
 | 
			
		||||
	// create the invite
 | 
			
		||||
	session := loginUser(t, "user1")
 | 
			
		||||
 | 
			
		||||
	teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
 | 
			
		||||
	req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
 | 
			
		||||
		"_csrf": GetCSRF(t, session, teamURL),
 | 
			
		||||
		"uid":   "1",
 | 
			
		||||
		"uname": "doesnotexist@example.com",
 | 
			
		||||
	})
 | 
			
		||||
	resp := session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	req = NewRequest(t, "GET", test.RedirectURL(resp))
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	// get the invite token
 | 
			
		||||
	invites, err := organization.GetInvitesByTeamID(db.DefaultContext, team.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Len(t, invites, 1)
 | 
			
		||||
 | 
			
		||||
	// accept the invite
 | 
			
		||||
	inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
 | 
			
		||||
	req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
 | 
			
		||||
	resp = MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	doc := NewHTMLParser(t, resp.Body)
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
 | 
			
		||||
		"_csrf":     doc.GetCSRF(),
 | 
			
		||||
		"user_name": "doesnotexist",
 | 
			
		||||
		"email":     "doesnotexist@example.com",
 | 
			
		||||
		"password":  "examplePassword!1",
 | 
			
		||||
		"retype":    "examplePassword!1",
 | 
			
		||||
	})
 | 
			
		||||
	for _, c := range resp.Result().Cookies() {
 | 
			
		||||
		req.AddCookie(c)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp = MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	assert.Equal(t, inviteURL, test.RedirectURL(resp))
 | 
			
		||||
 | 
			
		||||
	// complete the signup process
 | 
			
		||||
	ch := http.Header{}
 | 
			
		||||
	ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
 | 
			
		||||
	cr := http.Request{Header: ch}
 | 
			
		||||
 | 
			
		||||
	session = emptyTestSession(t)
 | 
			
		||||
	baseURL, err := url.Parse(setting.AppURL)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	session.jar.SetCookies(baseURL, cr.Cookies())
 | 
			
		||||
 | 
			
		||||
	// make the redirected request
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
 | 
			
		||||
		"_csrf": GetCSRF(t, session, test.RedirectURL(resp)),
 | 
			
		||||
	})
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	req = NewRequest(t, "GET", test.RedirectURL(resp))
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	// get the new user
 | 
			
		||||
	newUser, err := user_model.GetUserByName(db.DefaultContext, "doesnotexist")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	isMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, newUser.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.True(t, isMember)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check that users are redirected correctly after confirming their email
 | 
			
		||||
func TestOrgTeamEmailInviteRedirectsNewUserWithActivation(t *testing.T) {
 | 
			
		||||
	if setting.MailService == nil {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// enable email confirmation temporarily
 | 
			
		||||
	defer func(prevVal bool) {
 | 
			
		||||
		setting.Service.RegisterEmailConfirm = prevVal
 | 
			
		||||
	}(setting.Service.RegisterEmailConfirm)
 | 
			
		||||
	setting.Service.RegisterEmailConfirm = true
 | 
			
		||||
 | 
			
		||||
	defer tests.PrepareTestEnv(t)()
 | 
			
		||||
 | 
			
		||||
	org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
 | 
			
		||||
	team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
 | 
			
		||||
 | 
			
		||||
	// create the invite
 | 
			
		||||
	session := loginUser(t, "user1")
 | 
			
		||||
 | 
			
		||||
	teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
 | 
			
		||||
	req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
 | 
			
		||||
		"_csrf": GetCSRF(t, session, teamURL),
 | 
			
		||||
		"uid":   "1",
 | 
			
		||||
		"uname": "doesnotexist@example.com",
 | 
			
		||||
	})
 | 
			
		||||
	resp := session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	req = NewRequest(t, "GET", test.RedirectURL(resp))
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	// get the invite token
 | 
			
		||||
	invites, err := organization.GetInvitesByTeamID(db.DefaultContext, team.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Len(t, invites, 1)
 | 
			
		||||
 | 
			
		||||
	// accept the invite
 | 
			
		||||
	inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
 | 
			
		||||
	req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
 | 
			
		||||
	inviteResp := MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	doc := NewHTMLParser(t, resp.Body)
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{
 | 
			
		||||
		"_csrf":     doc.GetCSRF(),
 | 
			
		||||
		"user_name": "doesnotexist",
 | 
			
		||||
		"email":     "doesnotexist@example.com",
 | 
			
		||||
		"password":  "examplePassword!1",
 | 
			
		||||
		"retype":    "examplePassword!1",
 | 
			
		||||
	})
 | 
			
		||||
	for _, c := range inviteResp.Result().Cookies() {
 | 
			
		||||
		req.AddCookie(c)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp = MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	user, err := user_model.GetUserByName(db.DefaultContext, "doesnotexist")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	ch := http.Header{}
 | 
			
		||||
	ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";"))
 | 
			
		||||
	cr := http.Request{Header: ch}
 | 
			
		||||
 | 
			
		||||
	session = emptyTestSession(t)
 | 
			
		||||
	baseURL, err := url.Parse(setting.AppURL)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	session.jar.SetCookies(baseURL, cr.Cookies())
 | 
			
		||||
 | 
			
		||||
	activateURL := fmt.Sprintf("/user/activate?code=%s", user.GenerateEmailActivateCode("doesnotexist@example.com"))
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", activateURL, map[string]string{
 | 
			
		||||
		"password": "examplePassword!1",
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	// use the cookies set by the signup request
 | 
			
		||||
	for _, c := range inviteResp.Result().Cookies() {
 | 
			
		||||
		req.AddCookie(c)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	// should be redirected to accept the invite
 | 
			
		||||
	assert.Equal(t, inviteURL, test.RedirectURL(resp))
 | 
			
		||||
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
 | 
			
		||||
		"_csrf": GetCSRF(t, session, test.RedirectURL(resp)),
 | 
			
		||||
	})
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	req = NewRequest(t, "GET", test.RedirectURL(resp))
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	isMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.True(t, isMember)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test that a logged-in user who navigates to the sign-up link is then redirected using redirect_to
 | 
			
		||||
// For example: an invite may have been created before the user account was created, but they may be
 | 
			
		||||
// accepting the invite after having created an account separately
 | 
			
		||||
func TestOrgTeamEmailInviteRedirectsExistingUserWithLogin(t *testing.T) {
 | 
			
		||||
	if setting.MailService == nil {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer tests.PrepareTestEnv(t)()
 | 
			
		||||
 | 
			
		||||
	org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
 | 
			
		||||
	team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2})
 | 
			
		||||
	user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
 | 
			
		||||
 | 
			
		||||
	isMember, err := organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.False(t, isMember)
 | 
			
		||||
 | 
			
		||||
	// create the invite
 | 
			
		||||
	session := loginUser(t, "user1")
 | 
			
		||||
 | 
			
		||||
	teamURL := fmt.Sprintf("/org/%s/teams/%s", org.Name, team.Name)
 | 
			
		||||
	req := NewRequestWithValues(t, "POST", teamURL+"/action/add", map[string]string{
 | 
			
		||||
		"_csrf": GetCSRF(t, session, teamURL),
 | 
			
		||||
		"uid":   "1",
 | 
			
		||||
		"uname": user.Email,
 | 
			
		||||
	})
 | 
			
		||||
	resp := session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	req = NewRequest(t, "GET", test.RedirectURL(resp))
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	// get the invite token
 | 
			
		||||
	invites, err := organization.GetInvitesByTeamID(db.DefaultContext, team.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Len(t, invites, 1)
 | 
			
		||||
 | 
			
		||||
	// note: the invited user has logged in
 | 
			
		||||
	session = loginUser(t, "user5")
 | 
			
		||||
 | 
			
		||||
	// accept the invite (note: this uses the sign_up url)
 | 
			
		||||
	inviteURL := fmt.Sprintf("/org/invite/%s", invites[0].Token)
 | 
			
		||||
	req = NewRequest(t, "GET", fmt.Sprintf("/user/sign_up?redirect_to=%s", url.QueryEscape(inviteURL)))
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	assert.Equal(t, inviteURL, test.RedirectURL(resp))
 | 
			
		||||
 | 
			
		||||
	// make the request
 | 
			
		||||
	req = NewRequestWithValues(t, "POST", test.RedirectURL(resp), map[string]string{
 | 
			
		||||
		"_csrf": GetCSRF(t, session, test.RedirectURL(resp)),
 | 
			
		||||
	})
 | 
			
		||||
	resp = session.MakeRequest(t, req, http.StatusSeeOther)
 | 
			
		||||
	req = NewRequest(t, "GET", test.RedirectURL(resp))
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
 | 
			
		||||
	isMember, err = organization.IsTeamMember(db.DefaultContext, team.OrgID, team.ID, user.ID)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.True(t, isMember)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue