From a2b2e3066bee46ca15ce66d0deb7ef3e89915248 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Tue, 27 Jun 2023 11:50:09 +0200 Subject: [PATCH] [TESTS] auth LinkAccount test coverage (squash) --- models/auth/source.go | 12 +++ tests/integration/integration_test.go | 42 +++++++++ tests/integration/linkaccount_test.go | 118 +++++++++++++++++++++----- 3 files changed, 152 insertions(+), 20 deletions(-) diff --git a/models/auth/source.go b/models/auth/source.go index 0a904b7772..8dd1cd4759 100644 --- a/models/auth/source.go +++ b/models/auth/source.go @@ -5,6 +5,7 @@ package auth import ( + "context" "fmt" "reflect" @@ -306,6 +307,17 @@ func GetSourceByID(id int64) (*Source, error) { return source, nil } +func GetSourceByName(ctx context.Context, name string) (*Source, error) { + source := &Source{} + has, err := db.GetEngine(ctx).Where("name = ?", name).Get(source) + if err != nil { + return nil, err + } else if !has { + return nil, ErrSourceNotExist{} + } + return source, nil +} + // UpdateSource updates a Source record in DB. func UpdateSource(source *Source) error { var originalSource *Source diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 025325e31d..ce70eac733 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -35,10 +35,12 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers" + "code.gitea.io/gitea/services/auth/source/oauth2" user_service "code.gitea.io/gitea/services/user" "code.gitea.io/gitea/tests" "github.com/PuerkitoBio/goquery" + goth_gitlab "github.com/markbates/goth/providers/gitlab" "github.com/stretchr/testify/assert" "github.com/xeipuuv/gojsonschema" ) @@ -242,6 +244,46 @@ func getUserToken(t testing.TB, userName string, scope ...auth.AccessTokenScope) return getTokenForLoggedInUser(t, loginUser(t, userName), scope...) } +func addAuthSource(t *testing.T, payload map[string]string) *auth.Source { + session := loginUser(t, "user1") + payload["_csrf"] = GetCSRF(t, session, "/admin/auths/new") + req := NewRequestWithValues(t, "POST", "/admin/auths/new", payload) + session.MakeRequest(t, req, http.StatusSeeOther) + source, err := auth.GetSourceByName(context.Background(), payload["name"]) + assert.NoError(t, err) + return source +} + +func authSourcePayloadOAuth2(name string) map[string]string { + return map[string]string{ + "type": fmt.Sprintf("%d", auth.OAuth2), + "name": name, + "is_active": "on", + } +} + +func authSourcePayloadGitLab(name string) map[string]string { + payload := authSourcePayloadOAuth2(name) + payload["oauth2_provider"] = "gitlab" + return payload +} + +func authSourcePayloadGitLabCustom(name string) map[string]string { + payload := authSourcePayloadGitLab(name) + payload["oauth2_use_custom_url"] = "on" + payload["oauth2_auth_url"] = goth_gitlab.AuthURL + payload["oauth2_token_url"] = goth_gitlab.TokenURL + payload["oauth2_profile_url"] = goth_gitlab.ProfileURL + return payload +} + +func authSourcePayloadOIDC(name string) map[string]string { + payload := authSourcePayloadOAuth2(name) + payload["oauth2_provider"] = (&oauth2.OpenIDProvider{}).Name() + payload["open_id_connect_auto_discovery_url"] = codebergURL + "/.well-known/openid-configuration" + return payload +} + func createUser(ctx context.Context, t testing.TB, user *user_model.User) func() { user.MustChangePassword = false user.LowerName = strings.ToLower(user.Name) diff --git a/tests/integration/linkaccount_test.go b/tests/integration/linkaccount_test.go index e7b9f9c261..a951d79a60 100644 --- a/tests/integration/linkaccount_test.go +++ b/tests/integration/linkaccount_test.go @@ -1,12 +1,15 @@ -// Copyright 2023 The Forgejo Authors. All rights reserved. +// SPDX-FileCopyrightText: Copyright the Forgejo contributors // SPDX-License-Identifier: MIT package integration import ( + "context" "net/http" "testing" + auth_model "code.gitea.io/gitea/models/auth" + user_model "code.gitea.io/gitea/models/user" gitea_context "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/tests" @@ -14,50 +17,125 @@ import ( "github.com/stretchr/testify/assert" ) +const codebergURL = "https://codeberg.org" + func TestLinkAccountChoose(t *testing.T) { defer tests.PrepareTestEnv(t)() - username := "linkaccountuser" - email := "linkaccountuser@example.com" - password := "linkaccountuser" - defer createUser(t, username, email, password)() + ctx := context.Background() + + // Create a OIDC source and a known OAuth2 source + codebergName := "codeberg" + codeberg := addAuthSource(t, authSourcePayloadOIDC(codebergName)) + gitlabName := "gitlab" + gitlab := addAuthSource(t, authSourcePayloadGitLabCustom(gitlabName)) + + // + // A local user + // + localUser := &user_model.User{ + Name: "linkaccountuser", + Email: "linkaccountuser@example.com", + Passwd: "linkaccountuser", + Type: user_model.UserTypeIndividual, + } + defer createUser(ctx, t, localUser)() + + // + // A Codeberg user via OIDC + // + userCodebergUserID := "1234" + userCodeberg := &user_model.User{ + Name: "linkaccountcodeberguser", + Email: "linkaccountcodeberguser@example.com", + Passwd: "linkaccountcodeberguser", + Type: user_model.UserTypeIndividual, + LoginType: auth_model.OAuth2, + LoginSource: codeberg.ID, + LoginName: userCodebergUserID, + } + defer createUser(ctx, t, userCodeberg)() + + // + // A Gitlab user + // + userGitLabUserID := "5678" + userGitLab := &user_model.User{ + Name: "linkaccountgitlabuser", + Email: "linkaccountgitlabuser@example.com", + Passwd: "linkaccountgitlabuser", + Type: user_model.UserTypeIndividual, + LoginType: auth_model.OAuth2, + LoginSource: gitlab.ID, + LoginName: userGitLabUserID, + } + defer createUser(ctx, t, userGitLab)() defer func() { testMiddlewareHook = nil }() for _, testCase := range []struct { + title string gothUser goth.User signupTab string signinTab string }{ { - gothUser: goth.User{}, + title: "No existing user", + gothUser: goth.User{ + Provider: codebergName, + }, signupTab: "item active", signinTab: "item ", }, { + title: "Matched local user", gothUser: goth.User{ - Email: email, + Provider: codebergName, + Email: localUser.Email, + }, + signupTab: "item ", + signinTab: "item active", + }, + { + title: "Matched Codeberg local user", + gothUser: goth.User{ + Provider: codebergName, + UserID: userCodebergUserID, + Email: userCodeberg.Email, + }, + signupTab: "item ", + signinTab: "item active", + }, + { + title: "Matched GitLab local user", + gothUser: goth.User{ + Provider: gitlabName, + UserID: userGitLabUserID, + Email: userGitLab.Email, }, signupTab: "item ", signinTab: "item active", }, } { - testMiddlewareHook = func(ctx *gitea_context.Context) { - ctx.Session.Set("linkAccountGothUser", testCase.gothUser) - } + t.Run(testCase.title, func(t *testing.T) { + testMiddlewareHook = func(ctx *gitea_context.Context) { + ctx.Session.Set("linkAccountGothUser", testCase.gothUser) + } - req := NewRequest(t, "GET", "/user/link_account") - resp := MakeRequest(t, req, http.StatusOK) - assert.Equal(t, resp.Code, http.StatusOK, resp.Body) - doc := NewHTMLParser(t, resp.Body) + req := NewRequest(t, "GET", "/user/link_account") + resp := MakeRequest(t, req, http.StatusOK) + if assert.Equal(t, resp.Code, http.StatusOK, resp.Body) { + doc := NewHTMLParser(t, resp.Body) - class, exists := doc.Find(`.new-menu-inner .item[data-tab="auth-link-signup-tab"]`).Attr("class") - assert.True(t, exists, resp.Body) - assert.Equal(t, testCase.signupTab, class) + class, exists := doc.Find(`.new-menu-inner .item[data-tab="auth-link-signup-tab"]`).Attr("class") + assert.True(t, exists, resp.Body) + assert.Equal(t, testCase.signupTab, class) - class, exists = doc.Find(`.new-menu-inner .item[data-tab="auth-link-signin-tab"]`).Attr("class") - assert.True(t, exists) - assert.Equal(t, testCase.signinTab, class) + class, exists = doc.Find(`.new-menu-inner .item[data-tab="auth-link-signin-tab"]`).Attr("class") + assert.True(t, exists) + assert.Equal(t, testCase.signinTab, class) + } + }) } }