test: start integration improvement

This commit is contained in:
Frederic Jahn
2023-03-31 09:00:16 +02:00
parent 0faeb24fc9
commit afdfa4ad7d
12 changed files with 259 additions and 158 deletions

View File

@ -24,7 +24,7 @@ type DefaultManager struct {
persister persistence.JwkPersister
}
//Returns a DefaultManager that reads and persists the jwks to database and generates jwks if a new secret gets added to the config.
// Returns a DefaultManager that reads and persists the jwks to database and generates jwks if a new secret gets added to the config.
func NewDefaultManager(keys []string, persister persistence.JwkPersister) (*DefaultManager, error) {
encrypter, err := aes_gcm.NewAESGCM(keys)
if err != nil {

View File

@ -1,4 +1,4 @@
package server
package handler
import (
"github.com/labstack/echo-contrib/prometheus"
@ -6,9 +6,8 @@ import (
"github.com/labstack/echo/v4/middleware"
"github.com/teamhanko/hanko/backend/config"
"github.com/teamhanko/hanko/backend/dto"
"github.com/teamhanko/hanko/backend/handler"
hankoMiddleware "github.com/teamhanko/hanko/backend/middleware"
"github.com/teamhanko/hanko/backend/persistence"
hankoMiddleware "github.com/teamhanko/hanko/backend/server/middleware"
)
func NewAdminRouter(cfg *config.Config, persister persistence.Persister, prometheus *prometheus.Prometheus) *echo.Echo {
@ -30,20 +29,20 @@ func NewAdminRouter(cfg *config.Config, persister persistence.Persister, prometh
prometheus.SetMetricsPath(e)
}
healthHandler := handler.NewHealthHandler()
healthHandler := NewHealthHandler()
health := e.Group("/health")
health.GET("/alive", healthHandler.Alive)
health.GET("/ready", healthHandler.Ready)
userHandler := handler.NewUserHandlerAdmin(persister)
userHandler := NewUserHandlerAdmin(persister)
user := g.Group("/users")
user.GET("", userHandler.List)
user.GET("/:id", userHandler.Get)
user.DELETE("/:id", userHandler.Delete)
auditLogHandler := handler.NewAuditLogHandler(persister)
auditLogHandler := NewAuditLogHandler(persister)
auditLogs := g.Group("/audit_logs")
auditLogs.GET("", auditLogHandler.List)

View File

@ -1,4 +1,4 @@
package server
package handler
import (
"fmt"
@ -9,10 +9,9 @@ import (
"github.com/teamhanko/hanko/backend/config"
"github.com/teamhanko/hanko/backend/crypto/jwk"
"github.com/teamhanko/hanko/backend/dto"
"github.com/teamhanko/hanko/backend/handler"
"github.com/teamhanko/hanko/backend/mail"
middleware2 "github.com/teamhanko/hanko/backend/middleware"
"github.com/teamhanko/hanko/backend/persistence"
hankoMiddleware "github.com/teamhanko/hanko/backend/server/middleware"
"github.com/teamhanko/hanko/backend/session"
)
@ -22,7 +21,7 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
e.HTTPErrorHandler = dto.NewHTTPErrorHandler(dto.HTTPErrorHandlerConfig{Debug: false, Logger: e.Logger})
e.Use(middleware.RequestID())
e.Use(hankoMiddleware.GetLoggerMiddleware())
e.Use(middleware2.GetLoggerMiddleware())
if cfg.Server.Public.Cors.Enabled {
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
@ -58,34 +57,34 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
auditLogger := auditlog.NewLogger(persister, cfg.AuditLog)
if cfg.Password.Enabled {
passwordHandler := handler.NewPasswordHandler(persister, sessionManager, cfg, auditLogger)
passwordHandler := NewPasswordHandler(persister, sessionManager, cfg, auditLogger)
password := e.Group("/password")
password.PUT("", passwordHandler.Set, hankoMiddleware.Session(sessionManager))
password.PUT("", passwordHandler.Set, middleware2.Session(sessionManager))
password.POST("/login", passwordHandler.Login)
}
userHandler := handler.NewUserHandler(cfg, persister, sessionManager, auditLogger)
userHandler := NewUserHandler(cfg, persister, sessionManager, auditLogger)
e.GET("/me", userHandler.Me, hankoMiddleware.Session(sessionManager))
e.GET("/me", userHandler.Me, middleware2.Session(sessionManager))
user := e.Group("/users")
user.POST("", userHandler.Create)
user.GET("/:id", userHandler.Get, hankoMiddleware.Session(sessionManager))
user.GET("/:id", userHandler.Get, middleware2.Session(sessionManager))
e.POST("/user", userHandler.GetUserIdByEmail)
e.POST("/logout", userHandler.Logout, hankoMiddleware.Session(sessionManager))
e.POST("/logout", userHandler.Logout, middleware2.Session(sessionManager))
if cfg.Account.AllowDeletion {
e.DELETE("/user", userHandler.Delete, hankoMiddleware.Session(sessionManager))
e.DELETE("/user", userHandler.Delete, middleware2.Session(sessionManager))
}
healthHandler := handler.NewHealthHandler()
webauthnHandler, err := handler.NewWebauthnHandler(cfg, persister, sessionManager, auditLogger)
healthHandler := NewHealthHandler()
webauthnHandler, err := NewWebauthnHandler(cfg, persister, sessionManager, auditLogger)
if err != nil {
panic(fmt.Errorf("failed to create public webauthn handler: %w", err))
}
passcodeHandler, err := handler.NewPasscodeHandler(cfg, persister, sessionManager, mailer, auditLogger)
passcodeHandler, err := NewPasscodeHandler(cfg, persister, sessionManager, mailer, auditLogger)
if err != nil {
panic(fmt.Errorf("failed to create public passcode handler: %w", err))
}
@ -94,7 +93,7 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
health.GET("/alive", healthHandler.Alive)
health.GET("/ready", healthHandler.Ready)
wellKnownHandler, err := handler.NewWellKnownHandler(*cfg, jwkManager)
wellKnownHandler, err := NewWellKnownHandler(*cfg, jwkManager)
if err != nil {
panic(fmt.Errorf("failed to create well-known handler: %w", err))
}
@ -102,13 +101,13 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
wellKnown.GET("/jwks.json", wellKnownHandler.GetPublicKeys)
wellKnown.GET("/config", wellKnownHandler.GetConfig)
emailHandler, err := handler.NewEmailHandler(cfg, persister, sessionManager, auditLogger)
emailHandler, err := NewEmailHandler(cfg, persister, sessionManager, auditLogger)
if err != nil {
panic(fmt.Errorf("failed to create public email handler: %w", err))
}
webauthn := e.Group("/webauthn")
webauthnRegistration := webauthn.Group("/registration", hankoMiddleware.Session(sessionManager))
webauthnRegistration := webauthn.Group("/registration", middleware2.Session(sessionManager))
webauthnRegistration.POST("/initialize", webauthnHandler.BeginRegistration)
webauthnRegistration.POST("/finalize", webauthnHandler.FinishRegistration)
@ -116,7 +115,7 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
webauthnLogin.POST("/initialize", webauthnHandler.BeginAuthentication)
webauthnLogin.POST("/finalize", webauthnHandler.FinishAuthentication)
webauthnCredentials := webauthn.Group("/credentials", hankoMiddleware.Session(sessionManager))
webauthnCredentials := webauthn.Group("/credentials", middleware2.Session(sessionManager))
webauthnCredentials.GET("", webauthnHandler.ListCredentials)
webauthnCredentials.PATCH("/:id", webauthnHandler.UpdateCredential)
webauthnCredentials.DELETE("/:id", webauthnHandler.DeleteCredential)
@ -126,13 +125,13 @@ func NewPublicRouter(cfg *config.Config, persister persistence.Persister, promet
passcodeLogin.POST("/initialize", passcodeHandler.Init)
passcodeLogin.POST("/finalize", passcodeHandler.Finish)
email := e.Group("/emails", hankoMiddleware.Session(sessionManager))
email := e.Group("/emails", middleware2.Session(sessionManager))
email.GET("", emailHandler.List)
email.POST("", emailHandler.Create)
email.DELETE("/:id", emailHandler.Delete)
email.POST("/:id/set_primary", emailHandler.SetPrimaryEmail)
thirdPartyHandler := handler.NewThirdPartyHandler(cfg, persister, sessionManager, auditLogger, jwkManager)
thirdPartyHandler := NewThirdPartyHandler(cfg, persister, sessionManager, auditLogger, jwkManager)
thirdparty := e.Group("thirdparty")
thirdparty.GET("/auth", thirdPartyHandler.Auth)
thirdparty.GET("/callback", thirdPartyHandler.Callback)

View File

@ -3,15 +3,16 @@ package handler
import (
"bytes"
"encoding/json"
"fmt"
"github.com/gofrs/uuid"
"github.com/labstack/echo/v4"
"github.com/lestrrat-go/jwx/v2/jwt"
_ "github.com/lib/pq"
"github.com/stretchr/testify/suite"
"github.com/teamhanko/hanko/backend/config"
"github.com/teamhanko/hanko/backend/crypto/jwk"
"github.com/teamhanko/hanko/backend/dto"
"github.com/teamhanko/hanko/backend/persistence"
"github.com/teamhanko/hanko/backend/persistence/models"
"github.com/teamhanko/hanko/backend/session"
"github.com/teamhanko/hanko/backend/test"
"net/http"
"net/http/httptest"
@ -24,75 +25,36 @@ func TestUserSuite(t *testing.T) {
}
type userSuite struct {
suite.Suite
storage persistence.Storage
db *test.TestDB
}
func (s *userSuite) SetupSuite() {
if testing.Short() {
return
}
dialect := "postgres"
db, err := test.StartDB("user_test", dialect)
s.NoError(err)
storage, err := persistence.New(config.Database{
Url: db.DatabaseUrl,
})
s.NoError(err)
s.storage = storage
s.db = db
}
func (s *userSuite) SetupTest() {
if s.db != nil {
err := s.storage.MigrateUp()
s.NoError(err)
}
}
func (s *userSuite) TearDownTest() {
if s.db != nil {
err := s.storage.MigrateDown(-1)
s.NoError(err)
}
}
func (s *userSuite) TearDownSuite() {
if s.db != nil {
s.NoError(test.PurgeDB(s.db))
}
test.Suite
}
func (s *userSuite) TestUserHandler_Create() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
e := echo.New()
e.Validator = dto.NewCustomValidator()
e := NewPublicRouter(&test.DefaultConfig, s.Storage, nil)
body := UserCreateBody{Email: "jane.doe@example.com"}
bodyJson, err := json.Marshal(body)
s.NoError(err)
req := httptest.NewRequest(http.MethodPost, "/users", bytes.NewReader(bodyJson))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
e.ServeHTTP(rec, req)
if s.NoError(handler.Create(c)) {
if s.Equal(http.StatusOK, rec.Result().StatusCode) {
user := models.User{}
err := json.Unmarshal(rec.Body.Bytes(), &user)
s.NoError(err)
s.False(user.ID.IsNil())
count, err := s.storage.GetUserPersister().Count(uuid.Nil, "")
count, err := s.Storage.GetUserPersister().Count(uuid.Nil, "")
s.NoError(err)
s.Equal(1, count)
email, err := s.storage.GetEmailPersister().FindByAddress(body.Email)
email, err := s.Storage.GetEmailPersister().FindByAddress(body.Email)
s.NoError(err)
s.NotNil(email)
}
@ -102,30 +64,29 @@ func (s *userSuite) TestUserHandler_Create_CaseInsensitive() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
e := echo.New()
e.Validator = dto.NewCustomValidator()
e := NewPublicRouter(&test.DefaultConfig, s.Storage, nil)
body := UserCreateBody{Email: "JANE.DOE@EXAMPLE.COM"}
bodyJson, err := json.Marshal(body)
s.NoError(err)
req := httptest.NewRequest(http.MethodPost, "/users", bytes.NewReader(bodyJson))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
e.ServeHTTP(rec, req)
if s.NoError(handler.Create(c)) {
if s.Equal(http.StatusOK, rec.Result().StatusCode) {
user := models.User{}
err := json.Unmarshal(rec.Body.Bytes(), &user)
s.NoError(err)
s.False(user.ID.IsNil())
count, err := s.storage.GetUserPersister().Count(uuid.Nil, "")
count, err := s.Storage.GetUserPersister().Count(uuid.Nil, "")
s.NoError(err)
s.Equal(1, count)
email, err := s.storage.GetEmailPersister().FindByAddress(strings.ToLower(body.Email))
email, err := s.Storage.GetEmailPersister().FindByAddress(strings.ToLower(body.Email))
s.NoError(err)
s.NotNil(email)
}
@ -135,24 +96,25 @@ func (s *userSuite) TestUserHandler_Create_UserExists() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
err := test.LoadFixtures(s.db.DbCon, s.db.Dialect, "../test/fixtures/user")
err := s.LoadFixtures("../test/fixtures/user")
s.Require().NoError(err)
e := echo.New()
e.Validator = dto.NewCustomValidator()
e := NewPublicRouter(&test.DefaultConfig, s.Storage, nil)
body := UserCreateBody{Email: "john.doe@example.com"}
bodyJson, err := json.Marshal(body)
s.NoError(err)
req := httptest.NewRequest(http.MethodPost, "/users", bytes.NewReader(bodyJson))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
e.ServeHTTP(rec, req)
err = handler.Create(c)
if s.Error(err) {
httpError := dto.ToHttpError(err)
if s.Equal(http.StatusConflict, rec.Result().StatusCode) {
httpError := dto.HTTPError{}
err := json.Unmarshal(rec.Body.Bytes(), &httpError)
s.NoError(err)
s.Equal(http.StatusConflict, httpError.Code)
}
}
@ -161,60 +123,65 @@ func (s *userSuite) TestUserHandler_Create_UserExists_CaseInsensitive() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
err := test.LoadFixtures(s.db.DbCon, s.db.Dialect, "../test/fixtures/user")
err := s.LoadFixtures("../test/fixtures/user")
s.Require().NoError(err)
e := echo.New()
e.Validator = dto.NewCustomValidator()
e := NewPublicRouter(&test.DefaultConfig, s.Storage, nil)
body := UserCreateBody{Email: "JOHN.DOE@EXAMPLE.COM"}
bodyJson, err := json.Marshal(body)
s.NoError(err)
req := httptest.NewRequest(http.MethodPost, "/users", bytes.NewReader(bodyJson))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
e.ServeHTTP(rec, req)
err = handler.Create(c)
if s.Error(err) {
httpError := dto.ToHttpError(err)
if s.Equal(http.StatusConflict, rec.Result().StatusCode) {
httpError := dto.HTTPError{}
err := json.Unmarshal(rec.Body.Bytes(), &httpError)
s.NoError(err)
s.Equal(http.StatusConflict, httpError.Code)
}
}
func (s *userSuite) TestUserHandler_Create_InvalidEmail() {
e := echo.New()
e.Validator = dto.NewCustomValidator()
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
e := NewPublicRouter(&test.DefaultConfig, s.Storage, nil)
req := httptest.NewRequest(http.MethodPost, "/users", strings.NewReader(`{"email": 123"}`))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, nil, nil, nil)
e.ServeHTTP(rec, req)
err := handler.Create(c)
if s.Error(err) {
httpError := dto.ToHttpError(err)
if s.Equal(http.StatusBadRequest, rec.Result().StatusCode) {
httpError := dto.HTTPError{}
err := json.Unmarshal(rec.Body.Bytes(), &httpError)
s.NoError(err)
s.Equal(http.StatusBadRequest, httpError.Code)
}
}
func (s *userSuite) TestUserHandler_Create_EmailMissing() {
e := echo.New()
e.Validator = dto.NewCustomValidator()
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
e := NewPublicRouter(&test.DefaultConfig, s.Storage, nil)
req := httptest.NewRequest(http.MethodPost, "/users", strings.NewReader(`{"bogus": 123}`))
req.Header.Set("Content-Type", "application/json")
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, nil, nil, nil)
e.ServeHTTP(rec, req)
err := handler.Create(c)
if s.Error(err) {
httpError := dto.ToHttpError(err)
if s.Equal(http.StatusBadRequest, rec.Result().StatusCode) {
httpError := dto.HTTPError{}
err := json.Unmarshal(rec.Body.Bytes(), &httpError)
s.NoError(err)
s.Equal(http.StatusBadRequest, httpError.Code)
}
}
@ -223,27 +190,33 @@ func (s *userSuite) TestUserHandler_Get() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
err := test.LoadFixtures(s.db.DbCon, s.db.Dialect, "../test/fixtures/user")
err := s.LoadFixtures("../test/fixtures/user")
s.Require().NoError(err)
userId := "b5dd5267-b462-48be-b70d-bcd6f1bbe7a5"
e := echo.New()
req := httptest.NewRequest(http.MethodGet, "/", nil)
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
c.SetPath("/users/:id")
c.SetParamNames("id")
c.SetParamValues(userId)
e := NewPublicRouter(&test.DefaultConfig, s.Storage, nil)
token := jwt.New()
err = token.Set(jwt.SubjectKey, userId)
jwkManager, err := jwk.NewDefaultManager(test.DefaultConfig.Secrets.Keys, s.Storage.GetJwkPersister())
if err != nil {
panic(fmt.Errorf("failed to create jwk manager: %w", err))
}
sessionManager, err := session.NewManager(jwkManager, test.DefaultConfig.Session)
if err != nil {
panic(fmt.Errorf("failed to create session generator: %w", err))
}
token, err := sessionManager.GenerateJWT(uuid.FromStringOrNil(userId))
s.Require().NoError(err)
cookie, err := sessionManager.GenerateCookie(token)
s.Require().NoError(err)
c.Set("session", token)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
req := httptest.NewRequest(http.MethodGet, fmt.Sprintf("/users/%s", userId), nil)
req.AddCookie(cookie)
rec := httptest.NewRecorder()
if s.NoError(handler.Get(c)) {
e.ServeHTTP(rec, req)
if s.Equal(http.StatusOK, rec.Result().StatusCode) {
s.Equal(rec.Code, http.StatusOK)
user := models.User{}
err := json.Unmarshal(rec.Body.Bytes(), &user)
@ -257,7 +230,7 @@ func (s *userSuite) TestUserHandler_GetUserWithWebAuthnCredential() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
err := test.LoadFixtures(s.db.DbCon, s.db.Dialect, "../test/fixtures/user_with_webauthn_credential")
err := s.LoadFixtures("../test/fixtures/user_with_webauthn_credential")
s.Require().NoError(err)
userId := "b5dd5267-b462-48be-b70d-bcd6f1bbe7a5"
@ -275,7 +248,7 @@ func (s *userSuite) TestUserHandler_GetUserWithWebAuthnCredential() {
s.Require().NoError(err)
c.Set("session", token)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
handler := NewUserHandler(&defaultConfig, s.Storage, sessionManager{}, test.NewAuditLogger())
if s.NoError(handler.Get(c)) {
s.Equal(rec.Code, http.StatusOK)
@ -348,7 +321,7 @@ func (s *userSuite) TestUserHandler_GetUserIdByEmail_UserNotFound() {
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
handler := NewUserHandler(&defaultConfig, s.Storage, sessionManager{}, test.NewAuditLogger())
err := handler.GetUserIdByEmail(c)
if s.Error(err) {
@ -361,7 +334,7 @@ func (s *userSuite) TestUserHandler_GetUserIdByEmail() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
err := test.LoadFixtures(s.db.DbCon, s.db.Dialect, "../test/fixtures/user_with_webauthn_credential")
err := s.LoadFixtures("../test/fixtures/user_with_webauthn_credential")
s.Require().NoError(err)
userId := "b5dd5267-b462-48be-b70d-bcd6f1bbe7a5"
@ -373,7 +346,7 @@ func (s *userSuite) TestUserHandler_GetUserIdByEmail() {
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
handler := NewUserHandler(&defaultConfig, s.Storage, sessionManager{}, test.NewAuditLogger())
if s.NoError(handler.GetUserIdByEmail(c)) {
s.Equal(http.StatusOK, rec.Code)
@ -392,7 +365,7 @@ func (s *userSuite) TestUserHandler_GetUserIdByEmail_CaseInsensitive() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
err := test.LoadFixtures(s.db.DbCon, s.db.Dialect, "../test/fixtures/user_with_webauthn_credential")
err := s.LoadFixtures("../test/fixtures/user_with_webauthn_credential")
s.Require().NoError(err)
userId := "b5dd5267-b462-48be-b70d-bcd6f1bbe7a5"
@ -404,7 +377,7 @@ func (s *userSuite) TestUserHandler_GetUserIdByEmail_CaseInsensitive() {
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
handler := NewUserHandler(&defaultConfig, s.Storage, sessionManager{}, test.NewAuditLogger())
if s.NoError(handler.GetUserIdByEmail(c)) {
s.Equal(http.StatusOK, rec.Code)
@ -423,7 +396,7 @@ func (s *userSuite) TestUserHandler_Me() {
if testing.Short() {
s.T().Skip("skipping test in short mode.")
}
err := test.LoadFixtures(s.db.DbCon, s.db.Dialect, "../test/fixtures/user_with_webauthn_credential")
err := s.LoadFixtures("../test/fixtures/user_with_webauthn_credential")
s.Require().NoError(err)
userId := "b5dd5267-b462-48be-b70d-bcd6f1bbe7a5"
@ -439,7 +412,7 @@ func (s *userSuite) TestUserHandler_Me() {
s.Require().NoError(err)
c.Set("session", token)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
handler := NewUserHandler(&defaultConfig, s.Storage, sessionManager{}, test.NewAuditLogger())
if s.NoError(handler.Me(c)) {
s.Equal(http.StatusOK, rec.Code)
@ -466,7 +439,7 @@ func (s *userSuite) TestUserHandler_Logout() {
s.NoError(err)
c.Set("session", token)
handler := NewUserHandler(&defaultConfig, s.storage, sessionManager{}, test.NewAuditLogger())
handler := NewUserHandler(&defaultConfig, s.Storage, sessionManager{}, test.NewAuditLogger())
if s.NoError(handler.Logout(c)) {
s.Equal(http.StatusNoContent, rec.Code)

View File

@ -176,6 +176,13 @@ var defaultConfig = config.Config{
},
Timeout: 60000,
},
Secrets: config.Secrets{
Keys: []string{"abcdefghijklmnop"},
},
Passcode: config.Passcode{Smtp: config.SMTP{
Host: "localhost",
Port: "2500",
}},
}
type sessionManager struct {

View File

@ -3,18 +3,19 @@ package server
import (
"github.com/labstack/echo-contrib/prometheus"
"github.com/teamhanko/hanko/backend/config"
"github.com/teamhanko/hanko/backend/handler"
"github.com/teamhanko/hanko/backend/persistence"
"sync"
)
func StartPublic(cfg *config.Config, wg *sync.WaitGroup, persister persistence.Persister, prometheus *prometheus.Prometheus) {
defer wg.Done()
router := NewPublicRouter(cfg, persister, prometheus)
router := handler.NewPublicRouter(cfg, persister, prometheus)
router.Logger.Fatal(router.Start(cfg.Server.Public.Address))
}
func StartAdmin(cfg *config.Config, wg *sync.WaitGroup, persister persistence.Persister, prometheus *prometheus.Prometheus) {
defer wg.Done()
router := NewAdminRouter(cfg, persister, prometheus)
router := handler.NewAdminRouter(cfg, persister, prometheus)
router.Logger.Fatal(router.Start(cfg.Server.Admin.Address))
}

22
backend/test/config.go Normal file
View File

@ -0,0 +1,22 @@
package test
import "github.com/teamhanko/hanko/backend/config"
var DefaultConfig = config.Config{
Webauthn: config.WebauthnSettings{
RelyingParty: config.RelyingParty{
Id: "localhost",
DisplayName: "Test Relying Party",
Icon: "",
Origin: "http://localhost:8080",
},
Timeout: 60000,
},
Secrets: config.Secrets{
Keys: []string{"abcdefghijklmnop"},
},
Passcode: config.Passcode{Smtp: config.SMTP{
Host: "localhost",
Port: "2500",
}},
}

View File

@ -4,7 +4,6 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/go-testfixtures/testfixtures/v3"
_ "github.com/lib/pq"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
@ -101,7 +100,7 @@ func getContainerOptions(dialect string) (*dockertest.RunOptions, error) {
case "postgres":
return &dockertest.RunOptions{
Repository: "postgres",
Tag: "11",
Tag: "12-alpine",
Env: []string{
fmt.Sprintf("POSTGRES_PASSWORD=%s", database_password),
fmt.Sprintf("POSTGRES_USER=%s", database_user),
@ -137,22 +136,3 @@ func getPortID(dialect string) string {
return ""
}
}
// LoadFixtures loads predefined data from the path in the database.
func LoadFixtures(db *sql.DB, dialect string, path string) error {
fixtures, err := testfixtures.New(
testfixtures.Database(db),
testfixtures.Dialect(dialect),
testfixtures.Directory(path),
)
if err != nil {
return fmt.Errorf("could not create testfixtures: %w", err)
}
err = fixtures.Load()
if err != nil {
return fmt.Errorf("could not load fixtures: %w", err)
}
return nil
}

31
backend/test/random.go Normal file
View File

@ -0,0 +1,31 @@
package test
import (
"crypto/rand"
"encoding/base64"
)
// GenerateRandomBytes returns securely generated random bytes.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomBytes(n int) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
// Note that err == nil only if we read len(b) bytes.
if err != nil {
return nil, err
}
return b, nil
}
// GenerateRandomStringURLSafe returns a URL-safe, base64 encoded
// securely generated random string.
// It will return an error if the system's secure random
// number generator fails to function correctly, in which
// case the caller should not continue.
func GenerateRandomStringURLSafe(n int) (string, error) {
b, err := GenerateRandomBytes(n)
return base64.URLEncoding.EncodeToString(b), err
}

89
backend/test/suite.go Normal file
View File

@ -0,0 +1,89 @@
package test
import (
"fmt"
"github.com/go-testfixtures/testfixtures/v3"
"github.com/gobuffalo/pop/v6"
"github.com/gobuffalo/pop/v6/logging"
"github.com/stretchr/testify/suite"
"github.com/teamhanko/hanko/backend/config"
"github.com/teamhanko/hanko/backend/persistence"
"strings"
"testing"
)
type Suite struct {
suite.Suite
Storage persistence.Storage
DB *TestDB
Name string // used for database docker container name, so that tests can run in parallel
}
func (s *Suite) SetupSuite() {
if testing.Short() {
return
}
//pop.SetLogger(testLogger)
pop.Debug = true
if s.Name == "" {
var err error
s.Name, err = GenerateRandomStringURLSafe(5)
s.Name = strings.ReplaceAll(s.Name, "=", "")
if err != nil {
s.Fail("failed to generate database container name")
}
}
dialect := "postgres"
db, err := StartDB(s.Name, dialect)
s.NoError(err)
storage, err := persistence.New(config.Database{
Url: db.DatabaseUrl,
})
s.NoError(err)
s.Storage = storage
s.DB = db
}
func (s *Suite) SetupTest() {
if s.DB != nil {
err := s.Storage.MigrateUp()
s.NoError(err)
}
}
func (s *Suite) TearDownTest() {
if s.DB != nil {
err := s.Storage.MigrateDown(-1)
s.NoError(err)
}
}
func (s *Suite) TearDownSuite() {
if s.DB != nil {
s.NoError(PurgeDB(s.DB))
}
}
// LoadFixtures loads predefined data from the path in the database.
func (s *Suite) LoadFixtures(path string) error {
fixtures, err := testfixtures.New(
testfixtures.Database(s.DB.DbCon),
testfixtures.Dialect(s.DB.Dialect),
testfixtures.Directory(path),
)
if err != nil {
return fmt.Errorf("could not create testfixtures: %w", err)
}
err = fixtures.Load()
if err != nil {
return fmt.Errorf("could not load fixtures: %w", err)
}
return nil
}
func testLogger(level logging.Level, s string, args ...interface{}) {
}