Auth: Use authn.Service for all tests (#72921)

* Dashboards: Fix tests when authn broker is enabled.
StarService was not configured for tests, the call was guarded by !c.IsSignedIn

* Change default to be anon user to match expectations from tests

* OAuth: rewrite tests to work with authn.Service

* Setup template renderer by default

* Extract cookie options from cfg instead of relying on global variables

* Fix test to work with authn service

* Middleware: rewrite auth tests

* Remvoe session cookie if we cannot refresh access token
This commit is contained in:
Karl Persson
2023-08-09 08:54:52 +02:00
committed by GitHub
parent 5eef8291e2
commit 144e4887ee
19 changed files with 431 additions and 1722 deletions
+7 -1
View File
@@ -72,6 +72,7 @@ func loggedInUserScenarioWithRole(t *testing.T, desc string, method string, url
sc.context.OrgID = testOrgID
sc.context.Login = testUserLogin
sc.context.OrgRole = role
sc.context.IsAnonymous = false
if sc.handlerFunc != nil {
return sc.handlerFunc(sc.context)
}
@@ -212,7 +213,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHa
remoteCacheSvc, renderSvc, sqlStore, tracer, authProxy, loginService, nil,
authenticator, usertest.NewUserServiceFake(), orgtest.NewOrgServiceFake(),
nil, featuremgmt.WithFeatures(), &authntest.FakeService{
ExpectedIdentity: &authn.Identity{OrgID: 1, ID: "user:1", SessionToken: &usertoken.UserToken{}}}, &anontest.FakeAnonymousSessionService{})
ExpectedIdentity: &authn.Identity{IsAnonymous: true, SessionToken: &usertoken.UserToken{}}}, &anontest.FakeAnonymousSessionService{})
return ctxHdlr
}
@@ -310,6 +311,11 @@ func SetupAPITestServer(t *testing.T, opts ...APITestServerOption) *webtest.Serv
hs.registerRoutes()
s := webtest.NewServer(t, hs.RouteRegister)
viewsPath, err := filepath.Abs("../../public/views")
require.NoError(t, err)
s.Mux.UseMiddleware(web.Renderer(viewsPath, "[[", "]]"))
return s
}
+4
View File
@@ -52,6 +52,7 @@ import (
"github.com/grafana/grafana/pkg/services/publicdashboards"
"github.com/grafana/grafana/pkg/services/publicdashboards/api"
"github.com/grafana/grafana/pkg/services/quota/quotatest"
"github.com/grafana/grafana/pkg/services/star/startest"
"github.com/grafana/grafana/pkg/services/tag/tagimpl"
"github.com/grafana/grafana/pkg/services/team/teamtest"
"github.com/grafana/grafana/pkg/services/user"
@@ -160,6 +161,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
dashboardVersionService: fakeDashboardVersionService,
Kinds: corekind.NewBase(nil),
QuotaService: quotatest.New(false, nil),
starService: startest.NewStarServiceFake(),
userService: &usertest.FakeUserService{
ExpectedUser: &user.User{ID: 1, Login: "test-user"},
},
@@ -933,6 +935,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
DashboardService: dashboardService,
Features: featuremgmt.WithFeatures(),
Kinds: corekind.NewBase(nil),
starService: startest.NewStarServiceFake(),
}
hs.callGetDashboard(sc)
@@ -1121,6 +1124,7 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr
DashboardService: dashboardService,
Features: featuremgmt.WithFeatures(),
Kinds: corekind.NewBase(nil),
starService: startest.NewStarServiceFake(),
}
hs.callGetDashboard(sc)
+3 -2
View File
@@ -92,19 +92,20 @@ func (hs *HTTPServer) OAuthLogin(reqCtx *contextmodel.ReqContext) {
return
}
cookies.WriteCookie(reqCtx.Resp, OauthStateCookieName, redirect.Extra[authn.KeyOAuthState], hs.Cfg.OAuthCookieMaxAge, hs.CookieOptionsFromCfg)
if pkce := redirect.Extra[authn.KeyOAuthPKCE]; pkce != "" {
cookies.WriteCookie(reqCtx.Resp, OauthPKCECookieName, pkce, hs.Cfg.OAuthCookieMaxAge, hs.CookieOptionsFromCfg)
}
cookies.WriteCookie(reqCtx.Resp, OauthStateCookieName, redirect.Extra[authn.KeyOAuthState], hs.Cfg.OAuthCookieMaxAge, hs.CookieOptionsFromCfg)
reqCtx.Redirect(redirect.URL)
return
}
identity, err := hs.authnService.Login(reqCtx.Req.Context(), authn.ClientWithPrefix(name), req)
// NOTE: always delete these cookies, even if login failed
cookies.DeleteCookie(reqCtx.Resp, OauthPKCECookieName, hs.CookieOptionsFromCfg)
cookies.DeleteCookie(reqCtx.Resp, OauthStateCookieName, hs.CookieOptionsFromCfg)
cookies.DeleteCookie(reqCtx.Resp, OauthPKCECookieName, hs.CookieOptionsFromCfg)
if err != nil {
reqCtx.Redirect(hs.redirectURLWithErrorCookie(reqCtx, err))
+194 -219
View File
@@ -1,237 +1,212 @@
package api
import (
"crypto/sha256"
"encoding/base64"
"errors"
"net/http"
"net/http/httptest"
"net/url"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/grafana/grafana/pkg/infra/db"
"github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/models/roletype"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/hooks"
"github.com/grafana/grafana/pkg/services/licensing"
"github.com/grafana/grafana/pkg/services/org"
"github.com/grafana/grafana/pkg/models/usertoken"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/services/authn/authntest"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
"github.com/grafana/grafana/pkg/services/supportbundles/supportbundlestest"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/web"
)
func setupSocialHTTPServerWithConfig(t *testing.T, cfg *setting.Cfg) *HTTPServer {
sqlStore := db.InitTestDB(t)
features := featuremgmt.WithFeatures()
return &HTTPServer{
Cfg: cfg,
License: &licensing.OSSLicensingService{Cfg: cfg},
SQLStore: sqlStore,
SocialService: social.ProvideService(cfg, features, &usagestats.UsageStatsMock{}, supportbundlestest.NewFakeBundleService(), remotecache.NewFakeCacheStorage()),
HooksService: hooks.ProvideService(),
SecretsService: fakes.NewFakeSecretsService(),
Features: features,
}
}
func setupOAuthTest(t *testing.T, cfg *setting.Cfg) *web.Mux {
func setClientWithoutRedirectFollow(t *testing.T) {
t.Helper()
if cfg == nil {
cfg = setting.NewCfg()
}
cfg.ErrTemplateName = "error-template"
hs := setupSocialHTTPServerWithConfig(t, cfg)
m := web.New()
m.Use(getContextHandler(t, cfg).Middleware)
viewPath, err := filepath.Abs("../../public/views")
require.NoError(t, err)
m.UseMiddleware(web.Renderer(viewPath, "[[", "]]"))
m.Get("/login/:name", hs.OAuthLogin)
return m
}
func TestOAuthLogin_UnknownProvider(t *testing.T) {
m := setupOAuthTest(t, nil)
req := httptest.NewRequest(http.MethodGet, "/login/notaprovider", nil)
recorder := httptest.NewRecorder()
m.ServeHTTP(recorder, req)
// expect to be redirected to /login
assert.Equal(t, http.StatusFound, recorder.Code)
assert.Equal(t, "/login", recorder.Header().Get("Location"))
}
func TestOAuthLogin_Base(t *testing.T) {
cfg := setting.NewCfg()
sec := cfg.Raw.Section("auth.generic_oauth")
_, err := sec.NewKey("enabled", "true")
require.NoError(t, err)
m := setupOAuthTest(t, cfg)
req := httptest.NewRequest(http.MethodGet, "/login/generic_oauth", nil)
recorder := httptest.NewRecorder()
m.ServeHTTP(recorder, req)
assert.Equal(t, http.StatusFound, recorder.Code)
location := recorder.Header().Get("Location")
assert.NotEmpty(t, location)
u, err := url.Parse(location)
require.NoError(t, err)
assert.False(t, u.Query().Has("code_challenge"))
assert.False(t, u.Query().Has("code_challenge_method"))
resp := recorder.Result()
require.NoError(t, resp.Body.Close())
cookies := resp.Cookies()
var stateCookie *http.Cookie
for _, c := range cookies {
if c.Name == OauthStateCookieName {
stateCookie = c
}
}
require.NotNil(t, stateCookie)
req = httptest.NewRequest(
http.MethodGet,
(&url.URL{
Path: "/login/generic_oauth",
RawQuery: url.Values{
"code": []string{"helloworld"},
"state": []string{u.Query().Get("state")},
}.Encode(),
}).String(),
nil,
)
req.AddCookie(stateCookie)
recorder = httptest.NewRecorder()
m.ServeHTTP(recorder, req)
// TODO: validate that 'creating a token works'
assert.Equal(t, http.StatusInternalServerError, recorder.Code)
assert.Contains(t, recorder.Body.String(), "login.OAuthLogin(NewTransportWithCode)")
}
func TestOAuthLogin_UsePKCE(t *testing.T) {
cfg := setting.NewCfg()
sec := cfg.Raw.Section("auth.generic_oauth")
_, err := sec.NewKey("enabled", "true")
require.NoError(t, err)
_, err = sec.NewKey("use_pkce", "true")
require.NoError(t, err)
m := setupOAuthTest(t, cfg)
req := httptest.NewRequest(http.MethodGet, "/login/generic_oauth", nil)
recorder := httptest.NewRecorder()
m.ServeHTTP(recorder, req)
assert.Equal(t, http.StatusFound, recorder.Code)
location := recorder.Header().Get("Location")
assert.NotEmpty(t, location)
u, err := url.Parse(location)
require.NoError(t, err)
assert.True(t, u.Query().Has("code_challenge"))
assert.Equal(t, "S256", u.Query().Get("code_challenge_method"))
resp := recorder.Result()
require.NoError(t, resp.Body.Close())
var oauthCookie *http.Cookie
for _, cookie := range resp.Cookies() {
if cookie.Name == OauthPKCECookieName {
oauthCookie = cookie
}
}
require.NotNil(t, oauthCookie)
shasum := sha256.Sum256([]byte(oauthCookie.Value))
assert.Equal(
t,
u.Query().Get("code_challenge"),
base64.RawURLEncoding.EncodeToString(shasum[:]),
)
}
func TestOAuthLogin_BuildExternalUserInfo(t *testing.T) {
t.Helper()
cfgOAuthSkipRoleSync := setting.NewCfg()
authOAuthSec := cfgOAuthSkipRoleSync.Raw.Section("auth")
_, err := authOAuthSec.NewKey("oauth_skip_org_role_update_sync", "true")
require.NoError(t, err)
cfgOAuthSkipRoleSync.ErrTemplateName = "error-template"
cfgOAuthOrgRoleSync := setting.NewCfg()
authOAutoWithoutSec := cfgOAuthOrgRoleSync.Raw.Section("auth")
_, err = authOAutoWithoutSec.NewKey("oauth_skip_org_role_update_sync", "false")
require.NoError(t, err)
cfgOAuthOrgRoleSync.ErrTemplateName = "error-template"
testcases := []struct {
name string
cfg *setting.Cfg
basicUser *social.BasicUserInfo
expectedOrgRoles map[int64]org.RoleType
}{
{
name: "should return empty map of org role mapping if the role for the basic info is empty",
cfg: cfgOAuthOrgRoleSync,
basicUser: &social.BasicUserInfo{
Id: "1",
Name: "first lastname",
Email: "example@github.com",
Login: "example",
Role: "",
},
expectedOrgRoles: map[int64]org.RoleType{},
},
{
name: "should set internal role if role exists and we are skipping org role sync",
cfg: cfgOAuthSkipRoleSync,
basicUser: &social.BasicUserInfo{
Id: "1",
Name: "first lastname",
Email: "example@github.com",
Login: "example",
Role: roletype.RoleAdmin,
},
expectedOrgRoles: map[int64]org.RoleType{1: roletype.RoleAdmin},
},
{
name: "should return empty external role, if the role for the basic info is empty",
cfg: cfgOAuthSkipRoleSync,
basicUser: &social.BasicUserInfo{
Id: "1",
Name: "first lastname",
Email: "example@github.com",
Login: "example",
Role: "",
},
expectedOrgRoles: map[int64]org.RoleType{},
old := http.DefaultClient
http.DefaultClient = &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
for _, tc := range testcases {
t.Logf("%s", tc.name)
cfg := tc.cfg
hs := setupSocialHTTPServerWithConfig(t, cfg)
externalUser := hs.buildExternalUserInfo(nil, tc.basicUser, "")
require.Equal(t, tc.expectedOrgRoles, externalUser.OrgRoles)
t.Cleanup(func() {
http.DefaultClient = old
})
}
func TestOAuthLogin_Redirect(t *testing.T) {
type testCase struct {
desc string
expectedErr error
expectedCode int
expectedRedirect *authn.Redirect
}
tests := []testCase{
{
desc: "should be redirected to /login when passing un-configured provider",
expectedErr: authn.ErrClientNotConfigured,
expectedCode: http.StatusFound,
},
{
desc: "should be redirected to provider",
expectedCode: http.StatusFound,
expectedRedirect: &authn.Redirect{
URL: "https://some-provider.com",
Extra: map[string]string{
authn.KeyOAuthState: "some-state",
},
},
},
{
desc: "should set pkce cookie",
expectedCode: http.StatusFound,
expectedRedirect: &authn.Redirect{
URL: "https://some-provider.com",
Extra: map[string]string{
authn.KeyOAuthState: "some-state",
authn.KeyOAuthPKCE: "pkce-",
},
},
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
server := SetupAPITestServer(t, func(hs *HTTPServer) {
hs.Cfg = setting.NewCfg()
hs.SecretsService = fakes.NewFakeSecretsService()
hs.authnService = &authntest.FakeService{
ExpectedErr: tt.expectedErr,
ExpectedRedirect: tt.expectedRedirect,
}
})
// we need to prevent the http.Client from following redirects
setClientWithoutRedirectFollow(t)
res, err := server.Send(server.NewGetRequest("/login/generic_oauth"))
require.NoError(t, err)
assert.Equal(t, http.StatusFound, res.StatusCode)
// on every error we should get redirected to /login
if tt.expectedErr != nil {
assert.Equal(t, "/login", res.Header.Get("Location"))
} else {
// check that we get correct redirect url
assert.Equal(t, tt.expectedRedirect.URL, res.Header.Get("Location"))
require.GreaterOrEqual(t, len(res.Cookies()), 1)
if tt.expectedRedirect.Extra[authn.KeyOAuthPKCE] != "" {
require.Len(t, res.Cookies(), 2)
} else {
require.Len(t, res.Cookies(), 1)
}
require.GreaterOrEqual(t, len(res.Cookies()), 1)
stateCookie := res.Cookies()[0]
assert.Equal(t, OauthStateCookieName, stateCookie.Name)
assert.Equal(t, tt.expectedRedirect.Extra[authn.KeyOAuthState], stateCookie.Value)
if tt.expectedRedirect.Extra[authn.KeyOAuthPKCE] != "" {
require.Len(t, res.Cookies(), 2)
pkceCookie := res.Cookies()[1]
assert.Equal(t, OauthPKCECookieName, pkceCookie.Name)
assert.Equal(t, tt.expectedRedirect.Extra[authn.KeyOAuthPKCE], pkceCookie.Value)
} else {
require.Len(t, res.Cookies(), 1)
}
require.NoError(t, res.Body.Close())
}
})
}
}
func TestOAuthLogin_AuthorizationCode(t *testing.T) {
type testCase struct {
desc string
expectedErr error
expectedIdentity *authn.Identity
}
tests := []testCase{
{
desc: "should redirect to /login on error",
expectedErr: errors.New("some error"),
},
{
desc: "should redirect to / and set session cookie on successful authentication",
expectedIdentity: &authn.Identity{
SessionToken: &usertoken.UserToken{UnhashedToken: "some-token"},
},
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
var cfg *setting.Cfg
server := SetupAPITestServer(t, func(hs *HTTPServer) {
cfg = setting.NewCfg()
hs.Cfg = cfg
hs.Cfg.LoginCookieName = "some_name"
hs.SecretsService = fakes.NewFakeSecretsService()
hs.authnService = &authntest.FakeService{
ExpectedErr: tt.expectedErr,
ExpectedIdentity: tt.expectedIdentity,
}
})
// we need to prevent the http.Client from following redirects
setClientWithoutRedirectFollow(t)
res, err := server.Send(server.NewGetRequest("/login/generic_oauth?code=code"))
require.NoError(t, err)
require.GreaterOrEqual(t, len(res.Cookies()), 3)
// make sure oauth state cookie is deleted
assert.Equal(t, OauthStateCookieName, res.Cookies()[0].Name)
assert.Equal(t, "", res.Cookies()[0].Value)
assert.Equal(t, -1, res.Cookies()[0].MaxAge)
// make sure oauth pkce cookie is deleted
assert.Equal(t, OauthPKCECookieName, res.Cookies()[1].Name)
assert.Equal(t, "", res.Cookies()[1].Value)
assert.Equal(t, -1, res.Cookies()[1].MaxAge)
if tt.expectedErr != nil {
require.Len(t, res.Cookies(), 3)
assert.Equal(t, http.StatusFound, res.StatusCode)
assert.Equal(t, "/login", res.Header.Get("Location"))
assert.Equal(t, loginErrorCookieName, res.Cookies()[2].Name)
} else {
require.Len(t, res.Cookies(), 4)
assert.Equal(t, http.StatusFound, res.StatusCode)
assert.Equal(t, "/", res.Header.Get("Location"))
// verify session expiry cookie is set
assert.Equal(t, cfg.LoginCookieName, res.Cookies()[2].Name)
assert.Equal(t, "grafana_session_expiry", res.Cookies()[3].Name)
}
require.NoError(t, res.Body.Close())
})
}
}
func TestOAuthLogin_Error(t *testing.T) {
server := SetupAPITestServer(t, func(hs *HTTPServer) {
hs.Cfg = setting.NewCfg()
hs.SecretsService = fakes.NewFakeSecretsService()
})
setClientWithoutRedirectFollow(t)
res, err := server.Send(server.NewGetRequest("/login/azuread?error=someerror"))
require.NoError(t, err)
assert.Equal(t, http.StatusFound, res.StatusCode)
assert.Equal(t, "/login", res.Header.Get("Location"))
require.Len(t, res.Cookies(), 1)
errCookie := res.Cookies()[0]
assert.Equal(t, loginErrorCookieName, errCookie.Name)
require.NoError(t, res.Body.Close())
}
+14 -131
View File
@@ -20,14 +20,15 @@ import (
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/login"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/models/usertoken"
"github.com/grafana/grafana/pkg/services/auth/authtest"
"github.com/grafana/grafana/pkg/services/authn"
"github.com/grafana/grafana/pkg/services/authn/authntest"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/hooks"
"github.com/grafana/grafana/pkg/services/licensing"
loginservice "github.com/grafana/grafana/pkg/services/login"
"github.com/grafana/grafana/pkg/services/navtree"
"github.com/grafana/grafana/pkg/services/secrets"
"github.com/grafana/grafana/pkg/services/secrets/fakes"
@@ -317,11 +318,15 @@ func TestLoginPostRedirect(t *testing.T) {
fakeViewIndex(t)
sc := setupScenarioContext(t, "/login")
hs := &HTTPServer{
log: log.NewNopLogger(),
Cfg: setting.NewCfg(),
HooksService: &hooks.HooksService{},
License: &licensing.OSSLicensingService{},
log: log.NewNopLogger(),
Cfg: setting.NewCfg(),
HooksService: &hooks.HooksService{},
License: &licensing.OSSLicensingService{},
authnService: &authntest.FakeService{
ExpectedIdentity: &authn.Identity{ID: "user:42", SessionToken: &usertoken.UserToken{}},
},
AuthTokenService: authtest.NewFakeUserAuthTokenService(),
Features: featuremgmt.WithFeatures(),
}
@@ -333,13 +338,6 @@ func TestLoginPostRedirect(t *testing.T) {
return hs.LoginPost(c)
})
user := &user.User{
ID: 42,
Email: "",
}
hs.authenticator = &fakeAuthenticator{user, "", nil}
redirectCases := []redirectCase{
{
desc: "grafana relative url without subpath",
@@ -429,6 +427,9 @@ func TestLoginPostRedirect(t *testing.T) {
hs.Cfg.AppSubURL = c.appSubURL
t.Run(c.desc, func(t *testing.T) {
if c.desc == "grafana invalid relative url starting with subpath" {
fmt.Println()
}
expCookiePath := "/"
if len(hs.Cfg.AppSubURL) > 0 {
expCookiePath = hs.Cfg.AppSubURL
@@ -640,112 +641,6 @@ func setupAuthProxyLoginTest(t *testing.T, enableLoginToken bool) *scenarioConte
return sc
}
type loginHookTest struct {
info *loginservice.LoginInfo
}
func (r *loginHookTest) LoginHook(loginInfo *loginservice.LoginInfo, req *contextmodel.ReqContext) {
r.info = loginInfo
}
// TOREMOVE: remove with context handler auth
func TestLoginPostRunLokingHook(t *testing.T) {
sc := setupScenarioContext(t, "/login")
hookService := &hooks.HooksService{}
hs := &HTTPServer{
log: log.New("test"),
Cfg: sc.cfg,
License: &licensing.OSSLicensingService{},
AuthTokenService: authtest.NewFakeUserAuthTokenService(),
Features: featuremgmt.WithFeatures(),
HooksService: hookService,
authnService: sc.ctxHdlr.AuthnService,
}
sc.cfg.AuthBrokerEnabled = false
sc.defaultHandler = routing.Wrap(func(c *contextmodel.ReqContext) response.Response {
c.Req.Header.Set("Content-Type", "application/json")
c.Req.Body = io.NopCloser(bytes.NewBufferString(`{"user":"admin","password":"admin"}`))
x := hs.LoginPost(c)
return x
})
testHook := loginHookTest{}
hookService.AddLoginHook(testHook.LoginHook)
testUser := &user.User{
ID: 42,
Email: "",
}
testCases := []struct {
desc string
authUser *user.User
authModule string
authErr error
info loginservice.LoginInfo
}{
{
desc: "invalid credentials",
authErr: login.ErrInvalidCredentials,
info: loginservice.LoginInfo{
AuthModule: "",
HTTPStatus: 401,
Error: login.ErrInvalidCredentials,
},
},
{
desc: "user disabled",
authErr: login.ErrUserDisabled,
info: loginservice.LoginInfo{
AuthModule: "",
HTTPStatus: 401,
Error: login.ErrUserDisabled,
},
},
{
desc: "valid Grafana user",
authUser: testUser,
authModule: "grafana",
info: loginservice.LoginInfo{
AuthModule: "grafana",
User: testUser,
HTTPStatus: 200,
},
},
{
desc: "valid LDAP user",
authUser: testUser,
authModule: loginservice.LDAPAuthModule,
info: loginservice.LoginInfo{
AuthModule: loginservice.LDAPAuthModule,
User: testUser,
HTTPStatus: 200,
},
},
}
for _, c := range testCases {
t.Run(c.desc, func(t *testing.T) {
hs.authenticator = &fakeAuthenticator{c.authUser, c.authModule, c.authErr}
sc.m.Post(sc.url, sc.defaultHandler)
sc.fakeReqNoAssertions("POST", sc.url).exec()
info := testHook.info
assert.Equal(t, c.info.AuthModule, info.AuthModule)
assert.Equal(t, "admin", info.LoginUsername)
assert.Equal(t, c.info.HTTPStatus, info.HTTPStatus)
assert.Equal(t, c.info.Error, info.Error)
if c.info.User != nil {
require.NotEmpty(t, info.User)
assert.Equal(t, c.info.User.ID, info.User.ID)
}
})
}
}
type mockSocialService struct {
oAuthInfo *social.OAuthInfo
oAuthInfos map[string]*social.OAuthInfo
@@ -774,15 +669,3 @@ func (m *mockSocialService) GetOAuthHttpClient(name string) (*http.Client, error
func (m *mockSocialService) GetConnector(string) (social.SocialConnector, error) {
return m.socialConnector, m.err
}
type fakeAuthenticator struct {
ExpectedUser *user.User
ExpectedAuthModule string
ExpectedError error
}
func (fa *fakeAuthenticator) AuthenticateUser(c context.Context, query *loginservice.LoginUserQuery) error {
query.User = fa.ExpectedUser
query.AuthModule = fa.ExpectedAuthModule
return fa.ExpectedError
}