feat: use postgres
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"galaxy/authsession/internal/adapters/local"
|
||||
"galaxy/authsession/internal/adapters/mail"
|
||||
redisadapter "galaxy/authsession/internal/adapters/redis"
|
||||
"galaxy/authsession/internal/adapters/redis/challengestore"
|
||||
"galaxy/authsession/internal/adapters/redis/configprovider"
|
||||
"galaxy/authsession/internal/adapters/redis/projectionpublisher"
|
||||
@@ -26,17 +27,10 @@ import (
|
||||
"galaxy/authsession/internal/service/sendemailcode"
|
||||
"galaxy/authsession/internal/telemetry"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type pinger interface {
|
||||
Ping(context.Context) error
|
||||
}
|
||||
|
||||
type closer interface {
|
||||
Close() error
|
||||
}
|
||||
|
||||
// Runtime owns the runnable authsession application plus the adapter cleanup
|
||||
// functions that must run after the process stops.
|
||||
type Runtime struct {
|
||||
@@ -65,91 +59,64 @@ func NewRuntime(ctx context.Context, cfg config.Config, logger *zap.Logger, tele
|
||||
return nil, errors.Join(err, runtime.Close())
|
||||
}
|
||||
|
||||
challengeStore, err := challengestore.New(challengestore.Config{
|
||||
Addr: cfg.Redis.Addr,
|
||||
Username: cfg.Redis.Username,
|
||||
Password: cfg.Redis.Password,
|
||||
DB: cfg.Redis.DB,
|
||||
TLSEnabled: cfg.Redis.TLSEnabled,
|
||||
redisClient := redisadapter.NewClient(cfg.Redis)
|
||||
if err := redisadapter.InstrumentClient(redisClient, telemetryRuntime); err != nil {
|
||||
return cleanupOnError(fmt.Errorf("new authsession runtime: %w", err))
|
||||
}
|
||||
runtime.cleanupFns = append(runtime.cleanupFns, func() error {
|
||||
err := redisClient.Close()
|
||||
if errors.Is(err, redis.ErrClosed) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
})
|
||||
if err := redisadapter.Ping(ctx, cfg.Redis, redisClient); err != nil {
|
||||
return cleanupOnError(fmt.Errorf("new authsession runtime: %w", err))
|
||||
}
|
||||
|
||||
challengeStore, err := challengestore.New(redisClient, challengestore.Config{
|
||||
KeyPrefix: cfg.Redis.ChallengeKeyPrefix,
|
||||
OperationTimeout: cfg.Redis.OperationTimeout,
|
||||
OperationTimeout: cfg.Redis.Conn.OperationTimeout,
|
||||
})
|
||||
if err != nil {
|
||||
return cleanupOnError(fmt.Errorf("new authsession runtime: challenge store: %w", err))
|
||||
}
|
||||
runtime.cleanupFns = append(runtime.cleanupFns, challengeStore.Close)
|
||||
|
||||
sessionStore, err := sessionstore.New(sessionstore.Config{
|
||||
Addr: cfg.Redis.Addr,
|
||||
Username: cfg.Redis.Username,
|
||||
Password: cfg.Redis.Password,
|
||||
DB: cfg.Redis.DB,
|
||||
TLSEnabled: cfg.Redis.TLSEnabled,
|
||||
sessionStore, err := sessionstore.New(redisClient, sessionstore.Config{
|
||||
SessionKeyPrefix: cfg.Redis.SessionKeyPrefix,
|
||||
UserSessionsKeyPrefix: cfg.Redis.UserSessionsKeyPrefix,
|
||||
UserActiveSessionsKeyPrefix: cfg.Redis.UserActiveSessionsKeyPrefix,
|
||||
OperationTimeout: cfg.Redis.OperationTimeout,
|
||||
OperationTimeout: cfg.Redis.Conn.OperationTimeout,
|
||||
})
|
||||
if err != nil {
|
||||
return cleanupOnError(fmt.Errorf("new authsession runtime: session store: %w", err))
|
||||
}
|
||||
runtime.cleanupFns = append(runtime.cleanupFns, sessionStore.Close)
|
||||
|
||||
configStore, err := configprovider.New(configprovider.Config{
|
||||
Addr: cfg.Redis.Addr,
|
||||
Username: cfg.Redis.Username,
|
||||
Password: cfg.Redis.Password,
|
||||
DB: cfg.Redis.DB,
|
||||
TLSEnabled: cfg.Redis.TLSEnabled,
|
||||
configStore, err := configprovider.New(redisClient, configprovider.Config{
|
||||
SessionLimitKey: cfg.Redis.SessionLimitKey,
|
||||
OperationTimeout: cfg.Redis.OperationTimeout,
|
||||
OperationTimeout: cfg.Redis.Conn.OperationTimeout,
|
||||
})
|
||||
if err != nil {
|
||||
return cleanupOnError(fmt.Errorf("new authsession runtime: config provider: %w", err))
|
||||
}
|
||||
runtime.cleanupFns = append(runtime.cleanupFns, configStore.Close)
|
||||
|
||||
publisher, err := projectionpublisher.New(projectionpublisher.Config{
|
||||
Addr: cfg.Redis.Addr,
|
||||
Username: cfg.Redis.Username,
|
||||
Password: cfg.Redis.Password,
|
||||
DB: cfg.Redis.DB,
|
||||
TLSEnabled: cfg.Redis.TLSEnabled,
|
||||
publisher, err := projectionpublisher.New(redisClient, projectionpublisher.Config{
|
||||
SessionCacheKeyPrefix: cfg.Redis.GatewaySessionCacheKeyPrefix,
|
||||
SessionEventsStream: cfg.Redis.GatewaySessionEventsStream,
|
||||
StreamMaxLen: cfg.Redis.GatewaySessionEventsStreamMaxLen,
|
||||
OperationTimeout: cfg.Redis.OperationTimeout,
|
||||
OperationTimeout: cfg.Redis.Conn.OperationTimeout,
|
||||
})
|
||||
if err != nil {
|
||||
return cleanupOnError(fmt.Errorf("new authsession runtime: projection publisher: %w", err))
|
||||
}
|
||||
runtime.cleanupFns = append(runtime.cleanupFns, publisher.Close)
|
||||
|
||||
abuseProtector, err := sendemailcodeabuse.New(sendemailcodeabuse.Config{
|
||||
Addr: cfg.Redis.Addr,
|
||||
Username: cfg.Redis.Username,
|
||||
Password: cfg.Redis.Password,
|
||||
DB: cfg.Redis.DB,
|
||||
TLSEnabled: cfg.Redis.TLSEnabled,
|
||||
abuseProtector, err := sendemailcodeabuse.New(redisClient, sendemailcodeabuse.Config{
|
||||
KeyPrefix: cfg.Redis.SendEmailCodeThrottleKeyPrefix,
|
||||
OperationTimeout: cfg.Redis.OperationTimeout,
|
||||
OperationTimeout: cfg.Redis.Conn.OperationTimeout,
|
||||
})
|
||||
if err != nil {
|
||||
return cleanupOnError(fmt.Errorf("new authsession runtime: send email code abuse protector: %w", err))
|
||||
}
|
||||
runtime.cleanupFns = append(runtime.cleanupFns, abuseProtector.Close)
|
||||
|
||||
for name, dependency := range map[string]pinger{
|
||||
"challenge store": challengeStore,
|
||||
"session store": sessionStore,
|
||||
"config provider": configStore,
|
||||
"projection publisher": publisher,
|
||||
"send email code abuse protector": abuseProtector,
|
||||
} {
|
||||
if err := dependency.Ping(ctx); err != nil {
|
||||
return cleanupOnError(fmt.Errorf("new authsession runtime: ping %s: %w", name, err))
|
||||
}
|
||||
}
|
||||
|
||||
clock := local.Clock{}
|
||||
idGenerator := local.IDGenerator{}
|
||||
|
||||
@@ -26,7 +26,8 @@ func TestNewRuntimeStartsAndStopsHTTPServers(t *testing.T) {
|
||||
redisServer := miniredis.RunT(t)
|
||||
|
||||
cfg := config.DefaultConfig()
|
||||
cfg.Redis.Addr = redisServer.Addr()
|
||||
cfg.Redis.Conn.MasterAddr = redisServer.Addr()
|
||||
cfg.Redis.Conn.Password = "integration"
|
||||
cfg.PublicHTTP.Addr = mustFreeAddr(t)
|
||||
cfg.InternalHTTP.Addr = mustFreeAddr(t)
|
||||
cfg.ShutdownTimeout = 10 * time.Second
|
||||
@@ -69,7 +70,8 @@ func TestNewRuntimeUsesRESTUserDirectoryWhenConfigured(t *testing.T) {
|
||||
defer userService.Close()
|
||||
|
||||
cfg := config.DefaultConfig()
|
||||
cfg.Redis.Addr = redisServer.Addr()
|
||||
cfg.Redis.Conn.MasterAddr = redisServer.Addr()
|
||||
cfg.Redis.Conn.Password = "integration"
|
||||
cfg.PublicHTTP.Addr = mustFreeAddr(t)
|
||||
cfg.InternalHTTP.Addr = mustFreeAddr(t)
|
||||
cfg.UserService.Mode = "rest"
|
||||
@@ -116,7 +118,8 @@ func TestNewRuntimeUsesRESTMailSenderWhenConfigured(t *testing.T) {
|
||||
defer mailService.Close()
|
||||
|
||||
cfg := config.DefaultConfig()
|
||||
cfg.Redis.Addr = redisServer.Addr()
|
||||
cfg.Redis.Conn.MasterAddr = redisServer.Addr()
|
||||
cfg.Redis.Conn.Password = "integration"
|
||||
cfg.PublicHTTP.Addr = mustFreeAddr(t)
|
||||
cfg.InternalHTTP.Addr = mustFreeAddr(t)
|
||||
cfg.MailService.Mode = "rest"
|
||||
@@ -152,12 +155,13 @@ func TestNewRuntimeFailsFastWhenRedisPingChecksFail(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := config.DefaultConfig()
|
||||
cfg.Redis.Addr = mustFreeAddr(t)
|
||||
cfg.Redis.Conn.MasterAddr = mustFreeAddr(t)
|
||||
cfg.Redis.Conn.Password = "integration"
|
||||
|
||||
runtime, err := NewRuntime(context.Background(), cfg, zap.NewNop(), nil)
|
||||
require.Nil(t, runtime)
|
||||
require.Error(t, err)
|
||||
assert.ErrorContains(t, err, "new authsession runtime: ping")
|
||||
assert.ErrorContains(t, err, "ping redis")
|
||||
}
|
||||
|
||||
func mustFreeAddr(t *testing.T) string {
|
||||
|
||||
Reference in New Issue
Block a user