From a68f31e6a603b10243ece9b479e1ad5659a633fe Mon Sep 17 00:00:00 2001 From: Drewry Pope Date: Fri, 1 Mar 2024 14:33:19 -0600 Subject: [PATCH] update deps --- sources/identity/cmd/cmd.go | 185 ++++++++++++++++-- .../identity/configuration/configuration.go | 8 + sources/identity/go.mod | 27 ++- sources/identity/go.sum | 59 +++++- sources/identity/stream/stream.go | 103 +++++----- 5 files changed, 305 insertions(+), 77 deletions(-) diff --git a/sources/identity/cmd/cmd.go b/sources/identity/cmd/cmd.go index 29c502b1..8ec4e680 100644 --- a/sources/identity/cmd/cmd.go +++ b/sources/identity/cmd/cmd.go @@ -40,6 +40,10 @@ import ( "github.com/knadh/koanf" "github.com/muesli/reflow/wordwrap" "github.com/muesli/reflow/wrap" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/samber/do/v2" "github.com/spf13/cobra" gossh "golang.org/x/crypto/ssh" ) @@ -54,12 +58,12 @@ remote config ( s3 -> db -> - nats -> + nats/centrifuge -> etc) ( dont do all this, just this is the direction eventually as things become available if) */ -// todo: put these into configuration +// todo: put these into configuration but also as flat defaults in configuration var Separator = "." var ConfigurationFilePath = "config.kdl" var EmbeddedConfigurationFilePath = "embed/config.kdl" @@ -77,7 +81,7 @@ func NewConfiguration() *configuration.IdentityServerConfiguration { // run these against ? binary dir ? pwd of execution ? appdata ? .config ? .local ??? // then check for further locations/env-prefixes/etc from first pass, rerun on top with second pass // (maybe config.kdl next to binary sets a new set of configurationPaths, finish out loading from defaults, then load from new paths) - // this pattern continues, after hard-code default env/file search, then custom file/env search, then eventually maybe nats/s3 or other remote or db config + // this pattern continues, after hard-code default env/file search, then custom file/env search, then eventually maybe nats/centrifuge/s3 or other remote or db config }, EmbeddedConfigurationFilePaths: []string{ EmbeddedConfigurationFilePath, @@ -88,6 +92,12 @@ func NewConfiguration() *configuration.IdentityServerConfiguration { } func WrappedCharmFromContext(ctx context.Context, config *configuration.IdentityServerConfiguration) *cobra.Command { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } cmd := charmcmd.RootCmd go func() { @@ -107,10 +117,22 @@ func WrappedCharmFromContext(ctx context.Context, config *configuration.Identity } func CharmCmd(ctx context.Context, config *configuration.IdentityServerConfiguration) *cobra.Command { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } return WrappedCharmFromContext(ctx, config) } func StartCharmCmd(ctx context.Context, config *configuration.IdentityServerConfiguration) *cobra.Command { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } result := WrappedCharmFromContext(ctx, config) result.Use = "charm" result.Aliases = []string{"ch", "c"} @@ -136,10 +158,19 @@ func DefaultRootCmd() *cobra.Command { } func DefaultRootCmdWithContext(ctx context.Context) *cobra.Command { + if ctx == nil { + ctx = context.Background() + } return RootCmd(ctx, LoadDefaultConfiguration()) } func RootCmd(ctx context.Context, config *configuration.IdentityServerConfiguration) *cobra.Command { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } result := &cobra.Command{ Use: "identity", Short: "publish your identity", @@ -150,6 +181,12 @@ func RootCmd(ctx context.Context, config *configuration.IdentityServerConfigurat } func StartAllCmd(ctx context.Context, config *configuration.IdentityServerConfiguration) *cobra.Command { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } result := &cobra.Command{ Use: "start", Short: "Starts the identity and charm servers", @@ -162,6 +199,12 @@ func StartAllCmd(ctx context.Context, config *configuration.IdentityServerConfig } func StartIdentityCmd(ctx context.Context, config *configuration.IdentityServerConfiguration) *cobra.Command { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } return &cobra.Command{ Use: "identity", Short: "Starts only the identity server", @@ -171,6 +214,12 @@ func StartIdentityCmd(ctx context.Context, config *configuration.IdentityServerC } func StartStreamCmd(ctx context.Context, config *configuration.IdentityServerConfiguration) *cobra.Command { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } return &cobra.Command{ Use: "stream", Short: "Starts only the stream server", @@ -180,6 +229,12 @@ func StartStreamCmd(ctx context.Context, config *configuration.IdentityServerCon } func GetTasks(ctx context.Context, config *configuration.IdentityServerConfiguration) []func(context.Context, *sync.WaitGroup) func(*cobra.Command, []string) { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } return []func(ictx context.Context, wg *sync.WaitGroup) func(*cobra.Command, []string){ StartStream(config), StartCharm(config), @@ -188,15 +243,50 @@ func GetTasks(ctx context.Context, config *configuration.IdentityServerConfigura } func StartAllTasks(ctx context.Context, config *configuration.IdentityServerConfiguration) func(*cobra.Command, []string) { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } return func(cmd *cobra.Command, args []string) { if ctx == nil { ctx = context.Background() } - StartAll(ctx, GetTasks(ctx, config)...)(cmd, args) + StartTasks(ctx, GetTasks(ctx, config)...)(cmd, args) } } -func StartAll(ctx context.Context, tasks ...func(context.Context, *sync.WaitGroup) func(*cobra.Command, []string)) func(*cobra.Command, []string) { +// type Application struct { +// MustInvoke []*Application +// Name *string +// Service interface{} +// tasks []func(context.Context, *sync.WaitGroup) func(*cobra.Command, []string) +// } +// +// type Application[T any] struct { +// Service T +// Compile func(*cobra.Command, []string) +// } +type Application[T any] interface { + Service() T + Compile(*cobra.Command, []string) func(*cobra.Command, []string) +} +type Service[T any] interface { + Provide(injector *do.Injector) error + Invoke(injector *do.Injector) T +} + +type JwtVerifierService struct { +} +type JwtVerifierApp struct { + Application[JwtVerifierService] +} + +func StartTasks(ctx context.Context, tasks ...func(context.Context, *sync.WaitGroup) func(*cobra.Command, []string)) func(*cobra.Command, []string) { + if ctx == nil { + ctx = context.Background() + } return func(cmd *cobra.Command, args []string) { if ctx == nil { ctx = context.Background() @@ -216,8 +306,8 @@ func StartAll(ctx context.Context, tasks ...func(context.Context, *sync.WaitGrou } c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT, os.Interrupt, os.Kill) - defer signal.Stop(c) + // signal.Notify(c, os.Interrupt) // , syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT // , os.Kill // todo: this needs to let me force kill it, maybe take out os.kill or something? + // defer signal.Stop(c) select { case <-c: @@ -234,16 +324,28 @@ func StartAll(ctx context.Context, tasks ...func(context.Context, *sync.WaitGrou } func CleanupAndShutdown(cancel context.CancelFunc, done chan struct{}) { + log.Info("Cleaning up and shutting down.") cancel() + log.Info("Cancelled context. waiting for tasks to complete.") <-done + log.Info("All tasks done. Shutting down.") } func FinalShutdown(ctx context.Context, cmd *cobra.Command, args []string, tasks ...func(context.Context, *sync.WaitGroup) func(*cobra.Command, []string)) { + if ctx == nil { + ctx = context.Background() + } + if cmd == nil { + panic("cmd is nil") + } log.Info("All tasks cleaned up. Shutting down.", "len(tasks)", len(tasks), "command", cmd.Name(), "args", args) log.Info("Bye!", "time", time.Now()) } func RunTask(ctx context.Context, wg *sync.WaitGroup, taskFunc func(context.Context, *cobra.Command, []string)) func(*cobra.Command, []string) { + if ctx == nil { + ctx = context.Background() + } return func(cmd *cobra.Command, args []string) { if ctx == nil { ctx = context.Background() @@ -254,18 +356,23 @@ func RunTask(ctx context.Context, wg *sync.WaitGroup, taskFunc func(context.Cont } func StartStreamFromContext(ctx context.Context, config *configuration.IdentityServerConfiguration) func(*cobra.Command, []string) { + if ctx == nil { + ctx = context.Background() + } + if config == nil { + panic("config is nil") + } return func(cmd *cobra.Command, args []string) { - if ctx == nil { - ctx = context.Background() - } StartStream(config)(ctx, nil)(cmd, args) } } func StartStream(config *configuration.IdentityServerConfiguration) func(context.Context, *sync.WaitGroup) func(*cobra.Command, []string) { + if config == nil { + panic("config is nil") + } return func(ctx context.Context, wg *sync.WaitGroup) func(*cobra.Command, []string) { return func(cmd *cobra.Command, args []string) { - // todo: do something with the wait group ! don't increment for stream itself, but for the tasks it runs !! todo: is this the wrong way around? fuck log.Info("Starting stream server") if ctx == nil { ctx = context.Background() @@ -278,15 +385,20 @@ func StartCharmFromContext(ctx context.Context, config *configuration.IdentitySe if ctx == nil { ctx = context.Background() } + if config == nil { + panic("config is nil") + } return func(cmd *cobra.Command, args []string) { StartCharm(config)(ctx, nil)(cmd, args) } } func StartCharm(config *configuration.IdentityServerConfiguration) func(context.Context, *sync.WaitGroup) func(*cobra.Command, []string) { + if config == nil { + panic("config is nil") + } return func(ctx context.Context, wg *sync.WaitGroup) func(*cobra.Command, []string) { return func(cmd *cobra.Command, args []string) { - // todo: do something with the wait group ! don't increment for stream itself, but for the tasks it runs !! todo: is this the wrong way around? fuck log.Info("Starting charm server") if err := charmcmd.ServeCmdRunEWithContext(ctx, cmd, args); err != nil { log.Error("Error running charm server command", "error", err) @@ -299,14 +411,25 @@ func StartIdentityFromContext(ctx context.Context, config *configuration.Identit if ctx == nil { ctx = context.Background() } + if config == nil { + panic("config is nil") + } return func(cmd *cobra.Command, args []string) { StartIdentity(config)(ctx, nil)(cmd, args) } } + +var keyTypeCounter = promauto.NewCounterVec(prometheus.CounterOpts{ + Name: "wish_auth_by_type_total", + Help: "The total number of authentications by type", +}, []string{"type"}) + func StartIdentity(config *configuration.IdentityServerConfiguration) func(context.Context, *sync.WaitGroup) func(*cobra.Command, []string) { + if config == nil { + panic("config is nil") + } return func(goctx context.Context, wg *sync.WaitGroup) func(*cobra.Command, []string) { return func(cmd *cobra.Command, args []string) { - // todo: do something with the wait group ! don't increment for stream itself, but for the tasks it runs !! todo: is this the wrong way around? fuck log.Info("Starting identity server") if goctx == nil { goctx = context.Background() @@ -314,13 +437,21 @@ func StartIdentity(config *configuration.IdentityServerConfiguration) func(conte connections := auth.NewSafeConnectionMap() web.GoRunWebServer(goctx, connections, config) handler := scp.NewFileSystemHandler(ScpFileSystemDirPath) + registry := prometheus.NewRegistry() + s, err := wish.NewServer( wish.WithMiddleware( scp.Middleware(handler, handler), bubbletea.Middleware(TeaHandler), comment.Middleware("Thanks, have a nice day!"), elapsed.Middleware(), - promwish.MiddlewareWithContext(goctx, "0.0.0.0:9222", "identity", promwish.SkipDefaultDoneSignals(), promwish.WithWaitGroup(wg)), + promwish.MiddlewareRegistry( + registry, + prometheus.Labels{ + "app": "identity", + }, + promwish.DefaultCommandFn, + ), logging.Middleware(), observability.Middleware(connections), ), @@ -345,15 +476,28 @@ func StartIdentity(config *configuration.IdentityServerConfiguration) func(conte return } + metrics := promwish.NewServer( + "localhost:9222", + promhttp.InstrumentMetricHandler( + registry, promhttp.HandlerFor(registry, promhttp.HandlerOpts{}), + ), + ) + done := make(chan os.Signal, 1) - signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) - log.Info("Starting ssh server", "identity.server.host", config.Configuration.String("identity.server.host"), "identity.server.ssh.port", config.Configuration.Int("identity.server.ssh.port"), "address", fmt.Sprintf("%s:%d", config.Configuration.String("identity.server.host"), config.Configuration.Int("identity.server.ssh.port"))) go func() { + log.Info("Starting ssh server", "identity.server.host", config.Configuration.String("identity.server.host"), "identity.server.ssh.port", config.Configuration.Int("identity.server.ssh.port"), "address", fmt.Sprintf("%s:%d", config.Configuration.String("identity.server.host"), config.Configuration.Int("identity.server.ssh.port"))) if err := s.ListenAndServe(); err != nil && !errors.Is(err, ssh.ErrServerClosed) { log.Error("could not start server", "error", err) done <- os.Interrupt } }() + go func() { + log.Info("Starting metrics server", "address", "localhost:9222") + if err = metrics.ListenAndServe(); err != nil { + log.Fatal("Fail to start metrics server", "error", err) + done <- os.Interrupt + } + }() go func() { select { @@ -363,13 +507,20 @@ func StartIdentity(config *configuration.IdentityServerConfiguration) func(conte } }() + signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) <-done + log.Info("Done signal received, shutting down ssh server and metrics server.") ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() + log.Info("Shutting down ssh server", "identity.server.host", config.Configuration.String("identity.server.host"), "identity.server.ssh.port", config.Configuration.Int("identity.server.ssh.port"), "address", fmt.Sprintf("%s:%d", config.Configuration.String("identity.server.host"), config.Configuration.Int("identity.server.ssh.port"))) if err := s.Shutdown(ctx); err != nil && !errors.Is(err, ssh.ErrServerClosed) { log.Error("could not stop server", "error", err) } - log.Info("Stopping ssh server", "identity.server.host", config.Configuration.String("identity.server.host"), "identity.server.ssh.port", config.Configuration.Int("identity.server.ssh.port"), "address", fmt.Sprintf("%s:%d", config.Configuration.String("identity.server.host"), config.Configuration.Int("identity.server.ssh.port"))) + log.Info("Stopping metrics server", "address", "localhost:9222") + if err := metrics.Shutdown(ctx); err != nil && !errors.Is(err, ssh.ErrServerClosed) { + log.Error("could not stop metrics server", "error", err) + } + log.Info("Stopped ssh and metrics servers", "time", time.Now()) } } } diff --git a/sources/identity/configuration/configuration.go b/sources/identity/configuration/configuration.go index 4520af53..d810b544 100644 --- a/sources/identity/configuration/configuration.go +++ b/sources/identity/configuration/configuration.go @@ -107,6 +107,14 @@ func (c *IdentityServerConfiguration) LoadConfiguration() { c.Configuration.Set("identity.server.port", 1) c.Configuration.Set("identity.server.web.port", 7000) + c.Configuration.Set("identity.server.nats.host", "localhost") + c.Configuration.Set("identity.server.nats.port", 4222) + c.Configuration.Set("identity.server.tls.cert.server", "./data/tls/cert.pem") + c.Configuration.Set("identity.server.tls.cert.client", "./data/tls/client-cert.pem") + c.Configuration.Set("identity.server.tls.key.server", "./data/tls/key.pem") + c.Configuration.Set("identity.server.tls.key.client", "./data/tls/client-key.pem") + c.Configuration.Set("identity.server.tls.ca", "./data/tls/ca.pem") + log.Info("Loaded default configuration", "config", c.Configuration.Sprint()) log.Info("Loading embedded file configuration", "config", c.ConfigurationLocations.EmbeddedConfigurationFilePaths) diff --git a/sources/identity/go.mod b/sources/identity/go.mod index 916ad89e..1cbf5eb4 100644 --- a/sources/identity/go.mod +++ b/sources/identity/go.mod @@ -6,13 +6,14 @@ require ( github.com/a-h/templ v0.2.543 github.com/angelofallars/htmx-go v0.5.0 github.com/auth0/go-jwt-middleware/v2 v2.2.1 + github.com/centrifugal/centrifuge v0.30.6 github.com/charmbracelet/bubbles v0.18.0 github.com/charmbracelet/bubbletea v0.25.0 github.com/charmbracelet/charm v0.12.6 github.com/charmbracelet/lipgloss v0.9.1 github.com/charmbracelet/log v0.3.1 github.com/charmbracelet/melt v0.6.0 - github.com/charmbracelet/promwish v0.7.1-0.20240207115211-16eca892c72a + github.com/charmbracelet/promwish v0.7.1-0.20240301193744-83a66da07faa github.com/charmbracelet/ssh v0.0.0-20240202115812-f4ab1009799a github.com/charmbracelet/wish v1.3.1 github.com/go-chi/chi v1.5.5 @@ -22,17 +23,20 @@ require ( github.com/knadh/koanf/parsers/kdl v0.1.1 github.com/muesli/reflow v0.3.0 github.com/nrednav/cuid2 v1.0.0 + github.com/prometheus/client_golang v1.19.0 + github.com/samber/do/v2 v2.0.0-beta.5 github.com/spf13/cobra v1.8.0 github.com/tursodatabase/libsql-client-go v0.0.0-20240208053015-5d6aa1e2196d - golang.org/x/crypto v0.19.0 + golang.org/x/crypto v0.20.0 gopkg.in/go-jose/go-jose.v2 v2.6.2 ) replace github.com/charmbracelet/charm => github.com/developing-today-forks/charm v0.12.7-0.20240225103047-e4778561c8b2 -replace github.com/charmbracelet/promwish => github.com/developing-today-forks/promwish v0.7.1-0.20240225132336-cfc604974e84 +replace github.com/charmbracelet/ssh => github.com/developing-today-forks/ssh v0.0.0-20240301201110-744c36bdb9f9 require ( + github.com/FZambia/eagle v0.1.0 // indirect github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 // indirect github.com/atotto/clipboard v0.1.4 // indirect @@ -40,11 +44,12 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/caarlos0/env/v6 v6.10.1 // indirect github.com/calmh/randomart v1.1.0 // indirect + github.com/centrifugal/protocol v0.11.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/charmbracelet/keygen v0.5.0 // indirect - github.com/charmbracelet/x/errors v0.0.0-20240222131549-03ee51df8bea // indirect - github.com/charmbracelet/x/exp/term v0.0.0-20240222131549-03ee51df8bea // indirect + github.com/charmbracelet/x/errors v0.0.0-20240229115032-4b79243a3516 // indirect + github.com/charmbracelet/x/exp/term v0.0.0-20240229115032-4b79243a3516 // indirect github.com/containerd/console v1.0.4 // indirect github.com/creack/pty v1.1.21 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect @@ -61,12 +66,16 @@ require ( github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v23.5.26+incompatible // indirect github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/igm/sockjs-go/v3 v3.0.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jacobsa/crypto v0.0.0-20190317225127-9f44e2d11115 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.17.7 // indirect github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect @@ -88,15 +97,19 @@ require ( github.com/ncruces/go-strftime v0.1.9 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect - github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.6.0 // indirect - github.com/prometheus/common v0.48.0 // indirect + github.com/prometheus/common v0.49.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/redis/rueidis v1.0.22 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/samber/go-type-to-string v1.2.0 // indirect github.com/sblinch/kdl-go v0.0.0-20240108033718-e453df3dbf65 // indirect + github.com/segmentio/asm v1.2.0 // indirect + github.com/segmentio/encoding v0.3.6 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect go.opencensus.io v0.24.0 // indirect goji.io v2.0.2+incompatible // indirect diff --git a/sources/identity/go.sum b/sources/identity/go.sum index ea258fbc..1226c508 100644 --- a/sources/identity/go.sum +++ b/sources/identity/go.sum @@ -1,6 +1,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/FZambia/eagle v0.1.0 h1:9gyX6x+xjoIfglgyPTcYm7dvY7FJ93us1QY5De4CyXA= +github.com/FZambia/eagle v0.1.0/go.mod h1:YjGSPVkQTNcVLfzEUQJNgW9ScPR0K4u/Ky0yeFa4oDA= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/a-h/templ v0.2.543 h1:8YyLvyUtf0/IE2nIwZ62Z/m2o2NqwhnMynzOL78Lzbk= @@ -48,6 +50,10 @@ github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5 github.com/calmh/randomart v1.1.0 h1:evl+iwc10LXtHdMZhzLxmsCQVmWnkXs44SbC6Uk0Il8= github.com/calmh/randomart v1.1.0/go.mod h1:DQUbPVyP+7PAs21w/AnfMKG5NioxS3TbZ2F9MSK/jFM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/centrifugal/centrifuge v0.30.6 h1:dofN2c8bbgSz9AIC3Odh4bqS0gQKMDjcqabN50Idx/c= +github.com/centrifugal/centrifuge v0.30.6/go.mod h1:MnS7xcblZYWieK6hCGJuKKAcE6kAte34KPPBK1rybUk= +github.com/centrifugal/protocol v0.11.0 h1:pQKfVT4c3/uiRNszaOenE4NqJqL4VBlzBku8skI739w= +github.com/centrifugal/protocol v0.11.0/go.mod h1:33nZhrA2iRoR6jT+oVzu1ARx+iWIgxOgYuZMhWMWVM4= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -66,14 +72,18 @@ github.com/charmbracelet/log v0.3.1 h1:TjuY4OBNbxmHWSwO3tosgqs5I3biyY8sQPny/eCMT github.com/charmbracelet/log v0.3.1/go.mod h1:OR4E1hutLsax3ZKpXbgUqPtTjQfrh1pG3zwHGWuuq8g= github.com/charmbracelet/melt v0.6.0 h1:3OqxzeY5wDqCokoD8syE+CC9J2xjwF68HfJhScW8f64= github.com/charmbracelet/melt v0.6.0/go.mod h1:9sMWYbPCIKI4C3tjB7PXsI7TthZ5DMDGMcnd9r7q9NM= -github.com/charmbracelet/ssh v0.0.0-20240202115812-f4ab1009799a h1:ryXQeBfu7DN77RFiKLa/VA9VRkMsinpkv4qYparR//k= -github.com/charmbracelet/ssh v0.0.0-20240202115812-f4ab1009799a/go.mod h1:GPT/bjXsVDf5TKq2P1n4zl79ZnGwt2lWr19DomWm7zw= +github.com/charmbracelet/promwish v0.7.1-0.20240207115211-16eca892c72a h1:Lss/6xmgH0KCV/mHWLN6PexepAulh2e7GMygPJaB9qA= +github.com/charmbracelet/promwish v0.7.1-0.20240207115211-16eca892c72a/go.mod h1:goUZLOznBTC1mNdzR159pS9alz/quEjMkQwO9L7VrMc= +github.com/charmbracelet/promwish v0.7.1-0.20240301193744-83a66da07faa h1:LPj4YGVb2ibvUcc3Rsna7nEniKLPd+4+TwiifvRUbP4= +github.com/charmbracelet/promwish v0.7.1-0.20240301193744-83a66da07faa/go.mod h1:uBUtuH96hSDko9+oVmlWyMHzBaKQ7SVkVTsIIcgTz6E= github.com/charmbracelet/wish v1.3.1 h1:HXrHadxu6qbZOfwjEuu2OWpGWuhpKVd26Ecpv+QEc58= github.com/charmbracelet/wish v1.3.1/go.mod h1:4GbN5YK/Qmip0k/nT+dOuYVpdKgj3oZBnsOeEJlG9fE= github.com/charmbracelet/x/errors v0.0.0-20240222131549-03ee51df8bea h1:yhfWma0tKEAgKKyevfOJej8wsiPXgaAiFEpDQ9miBEA= github.com/charmbracelet/x/errors v0.0.0-20240222131549-03ee51df8bea/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0= -github.com/charmbracelet/x/exp/term v0.0.0-20240222131549-03ee51df8bea h1:yR3myZbStObDdwXEXVUbo6mlWrofBSrUxjc/J9sircA= -github.com/charmbracelet/x/exp/term v0.0.0-20240222131549-03ee51df8bea/go.mod h1:ntNL6rRIDmBHKUmo6ZKt344wCTcrPsSrfVj72qT8A5U= +github.com/charmbracelet/x/errors v0.0.0-20240229115032-4b79243a3516 h1:t6MBEAWHeZRMFEIHm5F9I1tzEB69ocEajtgR1SsAWUk= +github.com/charmbracelet/x/errors v0.0.0-20240229115032-4b79243a3516/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0= +github.com/charmbracelet/x/exp/term v0.0.0-20240229115032-4b79243a3516 h1:wL/PiybPudKHv/LDgAUqS9eoPQr3pOAmzShMPG99cXA= +github.com/charmbracelet/x/exp/term v0.0.0-20240229115032-4b79243a3516/go.mod h1:ntNL6rRIDmBHKUmo6ZKt344wCTcrPsSrfVj72qT8A5U= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -94,8 +104,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/developing-today-forks/charm v0.12.7-0.20240225103047-e4778561c8b2 h1:V9VSrMU1Z0yT12ZCkzbZRajTbI7UqfcJ2Q1KfJe9SmM= github.com/developing-today-forks/charm v0.12.7-0.20240225103047-e4778561c8b2/go.mod h1:AFyEKBZDsnfTvNIg0B3Lxvx8U3uvwk+yzLq8W4VMvug= -github.com/developing-today-forks/promwish v0.7.1-0.20240225132336-cfc604974e84 h1:2vOZu2XLbJYnPFySRZ16LTFFJD9GkGzYmQkBucb1K2k= -github.com/developing-today-forks/promwish v0.7.1-0.20240225132336-cfc604974e84/go.mod h1:goUZLOznBTC1mNdzR159pS9alz/quEjMkQwO9L7VrMc= +github.com/developing-today-forks/ssh v0.0.0-20240301201110-744c36bdb9f9 h1:HsiulzK87n1K2yrG58alhrwv4meR62J9xRmN9EHZLmo= +github.com/developing-today-forks/ssh v0.0.0-20240301201110-744c36bdb9f9/go.mod h1:wUZ0VTrLI5ixIbYOSRHrqrZnfj8EXgLZOOvQYAQ2f18= github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= @@ -184,11 +194,14 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= -github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gowebly/helpers v0.3.0 h1:hif8JqkknOIuApoADbDopIAVzQlWjNPG1o8ZdGOPmDg= github.com/gowebly/helpers v0.3.0/go.mod h1:gGHGcRTEBdoeySZPh+5GqcVrMLgkP1CaqZD28u0srAM= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= @@ -231,6 +244,8 @@ github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKe github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hjson/hjson-go/v4 v4.0.0 h1:wlm6IYYqHjOdXH1gHev4VoXCaW20HdQAGCxdOEEg2cs= github.com/hjson/hjson-go/v4 v4.0.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E= +github.com/igm/sockjs-go/v3 v3.0.2 h1:2m0k53w0DBiGozeQUIEPR6snZFmpFpYvVsGnfLPNXbE= +github.com/igm/sockjs-go/v3 v3.0.2/go.mod h1:UqchsOjeagIBFHvd+RZpLaVRbCwGilEC08EDHsD1jYE= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= @@ -248,6 +263,8 @@ github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHW github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -275,6 +292,8 @@ github.com/libsql/sqlite-antlr4-parser v0.0.0-20230802215326-5cb5bb604475/go.mod github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -353,6 +372,8 @@ github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnu github.com/nrednav/cuid2 v1.0.0 h1:27dn1oGiG+23Wa8XJ2DHeMoMa18Zs9u1+UHI9IlcGKM= github.com/nrednav/cuid2 v1.0.0/go.mod h1:pdRH5Zrjwnv8DZ74XvHR3jX+bzJNfQjwLQ3JgSI2EmI= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= +github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -374,6 +395,8 @@ github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= +github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -385,12 +408,16 @@ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB8 github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.49.0 h1:ToNTdK4zSnPVJmh698mGFkDor9wBI/iGaJy5dbH1EgI= +github.com/prometheus/common v0.49.0/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/redis/rueidis v1.0.22 h1:PhsokG7wqQlIf63g72jSqNk0iRqvfOjSKbL9JVRu79s= +github.com/redis/rueidis v1.0.22/go.mod h1:8EOzvsg3o5dUDitRj4vpsolUKkSIvFz88PeQnqwTVk0= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= @@ -404,9 +431,18 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/samber/do/v2 v2.0.0-beta.5 h1:KpQhVkkzDlsLSDC5WXgyCL8Q3SqOYoInFJIbvntPazM= +github.com/samber/do/v2 v2.0.0-beta.5/go.mod h1:FNMy1RSKMX11Ag8v4KW95n9k+ZkCXn8GuvDKufVKN9E= +github.com/samber/go-type-to-string v1.2.0 h1:Pvdqx3r/EHn9/DTKoW6RoHz/850s5yV1vA6MqKKG5Ys= +github.com/samber/go-type-to-string v1.2.0/go.mod h1:jpU77vIDoIxkahknKDoEx9C8bQ1ADnh2sotZ8I4QqBU= github.com/sblinch/kdl-go v0.0.0-20240108033718-e453df3dbf65 h1:N8SBepByh/KfKXr5lFetT5FcNEU14/ftiXyVU6697J0= github.com/sblinch/kdl-go v0.0.0-20240108033718-e453df3dbf65/go.mod h1:b3oNGuAKOQzhsCKmuLc/urEOPzgHj6fB8vl8bwTBh28= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg= +github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= +github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= +github.com/segmentio/encoding v0.3.6 h1:E6lVLyDPseWEulBmCmAKPanDd3jiyGDo5gMcugCRwZQ= +github.com/segmentio/encoding v0.3.6/go.mod h1:n0JeuIqEQrQoPDGsjo8UNd1iA0U8d8+oHAA4E3G3OxM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -442,6 +478,8 @@ github.com/tursodatabase/libsql-client-go v0.0.0-20240208053015-5d6aa1e2196d/go. github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI= @@ -456,6 +494,8 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= goji.io v2.0.2+incompatible h1:uIssv/elbKRLznFUy3Xj4+2Mz/qKhek/9aZQDUMae7c= @@ -469,6 +509,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= +golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= @@ -551,6 +593,7 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/sources/identity/stream/stream.go b/sources/identity/stream/stream.go index 5273c333..a7dac968 100644 --- a/sources/identity/stream/stream.go +++ b/sources/identity/stream/stream.go @@ -2,8 +2,10 @@ package stream import ( "context" + "net/http" "time" + "github.com/centrifugal/centrifuge" "github.com/charmbracelet/log" "github.com/developing-today/code/src/identity/configuration" "github.com/spf13/cobra" @@ -11,56 +13,67 @@ import ( func RunStreamServer(ctx context.Context, config *configuration.IdentityServerConfiguration, cmd *cobra.Command, args []string) { log.Info("Starting stream server") - time.Sleep(5 * time.Second) + node, err := centrifuge.New(centrifuge.Config{}) + if err != nil { + log.Fatal(err) + } - // TODO: Implement NATS server, when this shuts down it crashes the rest of the server. uncomment and fix + SetupNodeHandlers(node) - // // Extract TLS configuration from IdentityServerConfiguration - // certFile := config.Configuration.String("tls.cert.server") - // keyFile := config.Configuration.String("tls.key.server") - // caFile := config.Configuration.String("tls.ca") - // host := config.Configuration.String("nats.host") - // port := config.Configuration.Int("nats.port") + srv := &http.Server{Addr: ":8000", Handler: nil} - // serverTlsConfig, err := server.GenTLSConfig(&server.TLSConfigOpts{ - // CertFile: certFile, - // KeyFile: keyFile, - // CaFile: caFile, - // Verify: true, - // }) - // if err != nil { - // log.Fatalf("TLS config error: %v", err) - // } + wsHandler := centrifuge.NewWebsocketHandler(node, centrifuge.WebsocketConfig{}) + http.Handle("/connection/websocket", Auth(wsHandler)) + http.Handle("/", http.FileServer(http.Dir("./"))) - // // Setup the embedded server options. - // opts := server.Options{ - // Host: host, - // Port: port, - // TLSConfig: serverTlsConfig, - // } + go func() { + <-ctx.Done() - // // Initialize and start the NATS server - // ns, err := server.NewServer(&opts) - // if err != nil { - // log.Fatalf("Server initialization error: %v", err) - // } + shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() - // go func() { - // log.Info("NATS server starting") - // ns.Start() - // if ns.ReadyForConnections(10 * time.Second) { - // log.Info("NATS server ready for connections") - // } - // }() - // defer func() { - // log.Info("NATS server shutting down") - // ns.Shutdown() - // log.Info("Stopping stream server") - // }() + log.Info("Shutting down server") + if err := srv.Shutdown(shutdownCtx); err != nil { + log.Error("Shutdown error", "error", err) + } + }() - // select { - // case <-ctx.Done(): - // log.Info("Stream server cancelled") - // return - // } + log.Info("Starting server", "url", "http://localhost:8000") + if err := srv.ListenAndServe(); err != http.ErrServerClosed { + log.Fatal("ListenAndServe error", "error", err) + } +} + +func SetupNodeHandlers(node *centrifuge.Node) { + node.OnConnect(func(client *centrifuge.Client) { + transportName := client.Transport().Name() + transportProto := client.Transport().Protocol() + log.Info("Client connected", "transportName", transportName, "transportProto", transportProto) + + client.OnSubscribe(func(e centrifuge.SubscribeEvent, cb centrifuge.SubscribeCallback) { + log.Info("Client subscribes on channel", "channel", e.Channel) + cb(centrifuge.SubscribeReply{}, nil) + }) + + client.OnPublish(func(e centrifuge.PublishEvent, cb centrifuge.PublishCallback) { + log.Info("Client publishes into channel", "channel", e.Channel, "data", string(e.Data)) + cb(centrifuge.PublishReply{}, nil) + }) + + client.OnDisconnect(func(e centrifuge.DisconnectEvent) { + log.Info("Client disconnected") + }) + }) +} + +func Auth(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + cred := ¢rifuge.Credentials{ + UserID: "", + } + newCtx := centrifuge.SetCredentials(ctx, cred) + r = r.WithContext(newCtx) + h.ServeHTTP(w, r) + }) }