From 2943344eaa61cf53ef6e2a6d145dbca9c984d883 Mon Sep 17 00:00:00 2001 From: brookjeynes Date: Wed, 8 Oct 2025 19:10:29 +1000 Subject: [PATCH] feat: add redis Signed-off-by: brookjeynes --- go.mod | 7 ++++--- go.sum | 15 +++++++++++++-- internal/server/app.go | 7 +++++++ internal/server/config/config.go | 23 +++++++++++++++++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index e6a5fd6..e145dc8 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,9 @@ go 1.24.0 toolchain go1.24.4 -replace github.com/bluesky-social/indigo => github.com/oppiliappan/indigo v0.0.0-20250728090836-5f170569da93 - require ( github.com/a-h/templ v0.3.898 - github.com/bluesky-social/indigo v0.0.0-20250728163042-01ae6633b28c + github.com/bluesky-social/indigo v0.0.0-20251003000214-3259b215110e github.com/bluesky-social/jetstream v0.0.0-20250414024304-d17bd81a945e github.com/carlmjohnson/versioninfo v0.22.5 github.com/go-chi/chi/v5 v5.2.1 @@ -17,6 +15,7 @@ require ( github.com/lestrrat-go/jwx/v2 v2.0.12 github.com/mattn/go-sqlite3 v1.14.22 github.com/posthog/posthog-go v1.5.12 + github.com/redis/go-redis/v9 v9.14.0 github.com/sethvargo/go-envconfig v1.3.0 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e golang.org/x/net v0.42.0 @@ -34,6 +33,7 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cli/browser v1.3.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -42,6 +42,7 @@ require ( github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/websocket v1.5.1 // indirect diff --git a/go.sum b/go.sum index dec2fab..314d5ca 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,14 @@ github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer5 github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bluesky-social/indigo v0.0.0-20251003000214-3259b215110e h1:IutKPwmbU0LrYqw03EuwJtMdAe67rDTrL1U8S8dicRU= +github.com/bluesky-social/indigo v0.0.0-20251003000214-3259b215110e/go.mod h1:n6QE1NDPFoi7PRbMUZmc2y7FibCqiVU4ePpsvhHUBR8= github.com/bluesky-social/jetstream v0.0.0-20250414024304-d17bd81a945e h1:P/O6TDHs53gwgV845uDHI+Nri889ixksRrh4bCkCdxo= github.com/bluesky-social/jetstream v0.0.0-20250414024304-d17bd81a945e/go.mod h1:WiYEeyJSdUwqoaZ71KJSpTblemUCpwJfh5oVXplK6T4= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/carlmjohnson/versioninfo v0.22.5 h1:O00sjOLUAFxYQjlN/bzYTuZiS0y6fWDQjMRvwtKgwwc= github.com/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -26,6 +32,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8Yc github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -46,8 +54,11 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -165,8 +176,6 @@ github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0 github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/oppiliappan/indigo v0.0.0-20250728090836-5f170569da93 h1:7HH9daZ4xfUJUlHlH82i1xHyKSqKj/OWO+3aQLZbQWM= -github.com/oppiliappan/indigo v0.0.0-20250728090836-5f170569da93/go.mod h1:0XUyOCRtL4/OiyeqMTmr6RlVHQMDgw3LS7CfibuZR5Q= github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9 h1:1/WtZae0yGtPq+TI6+Tv1WTxkukpXeMlviSxvL7SRgk= github.com/petar/GoLLRB v0.0.0-20210522233825-ae3b015fd3e9/go.mod h1:x3N5drFsm2uilKKuuYo6LdyD8vZAW55sH/9w+pbo1sw= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -185,6 +194,8 @@ github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/redis/go-redis/v9 v9.14.0 h1:u4tNCjXOyzfgeLN+vAZaW1xUooqWDqVEsZN0U01jfAE= +github.com/redis/go-redis/v9 v9.14.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= diff --git a/internal/server/app.go b/internal/server/app.go index d2d8d5a..2f49a21 100644 --- a/internal/server/app.go +++ b/internal/server/app.go @@ -34,6 +34,7 @@ type Server struct { Config *config.Config Posthog posthog.Client IdResolver *atproto.Resolver + Session *session.SessionStore ComputedData ComputedData } @@ -53,6 +54,9 @@ func Make(ctx context.Context, config *config.Config) (*Server, error) { idResolver := atproto.DefaultResolver() + cache := cache.New(config.Redis.Addr) + sess := session.New(cache) + posthog, err := posthog.NewWithConfig(config.Posthog.ApiKey, posthog.Config{Endpoint: config.Posthog.Endpoint}) if err != nil { return nil, fmt.Errorf("failed to create posthog client: %w", err) @@ -88,6 +92,7 @@ func Make(ctx context.Context, config *config.Config) (*Server, error) { return nil, fmt.Errorf("failed to start jetstream watcher: %w", err) } + // -- Computed data sortedLanguages := make([]db.Language, 0, len(db.Languages)) for _, l := range db.Languages { sortedLanguages = append(sortedLanguages, l) @@ -119,6 +124,7 @@ func Make(ctx context.Context, config *config.Config) (*Server, error) { slices.SortFunc(sortedReactions, func(a, b db.Reaction) int { return cmp.Compare(a.ID, b.ID) }) + // -- state := &Server{ Db: d, @@ -126,6 +132,7 @@ func Make(ctx context.Context, config *config.Config) (*Server, error) { Config: config, Posthog: posthog, IdResolver: idResolver, + Session: sess, ComputedData: ComputedData{ SortedLanguages: sortedLanguages, SortedCategories: sortedCategories, diff --git a/internal/server/config/config.go b/internal/server/config/config.go index 89b1751..d1b8c18 100644 --- a/internal/server/config/config.go +++ b/internal/server/config/config.go @@ -2,6 +2,8 @@ package config import ( "context" + "fmt" + "net/url" "github.com/sethvargo/go-envconfig" ) @@ -31,12 +33,33 @@ type GoogleConfig struct { ApiKey string `env:"API_KEY"` } +type RedisConfig struct { + Addr string `env:"ADDR, default=localhost:6379"` + Password string `env:"PASS"` + DB int `env:"DB, default=0"` +} + +func (cfg RedisConfig) ToURL() string { + u := &url.URL{ + Scheme: "redis", + Host: cfg.Addr, + Path: fmt.Sprintf("/%d", cfg.DB), + } + + if cfg.Password != "" { + u.User = url.UserPassword("default", cfg.Password) + } + + return u.String() +} + type Config struct { Core CoreConfig `env:",prefix=YOTEN_"` Jetstream JetstreamConfig `env:",prefix=TANGLED_JETSTREAM_"` OAuth OAuthConfig `env:",prefix=YOTEN_OAUTH_"` Posthog PosthogConfig `env:",prefix=YOTEN_POSTHOG_"` Google GoogleConfig `env:",prefix=YOTEN_GOOGLE_"` + Redis RedisConfig `env:",prefix=YOTEN_REDIS_"` } func LoadConfig(ctx context.Context) (*Config, error) { -- 2.43.0 From ded4764a75112216fbb08bbe485f42cc64b8f6a8 Mon Sep 17 00:00:00 2001 From: brookjeynes Date: Wed, 8 Oct 2025 19:14:57 +1000 Subject: [PATCH] feat: redirect user back to where they were after login redirect Signed-off-by: brookjeynes --- internal/server/middleware/middleware.go | 16 +++++++++++++--- internal/server/views/login.templ | 10 +++++++++- internal/server/views/views.go | 3 ++- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/internal/server/middleware/middleware.go b/internal/server/middleware/middleware.go index 7b37e56..08f0eb9 100644 --- a/internal/server/middleware/middleware.go +++ b/internal/server/middleware/middleware.go @@ -2,8 +2,10 @@ package middleware import ( "context" + "fmt" "log" "net/http" + "net/url" "slices" "strings" @@ -38,13 +40,19 @@ type middlewareFunc func(http.Handler) http.Handler func AuthMiddleware(a *oauth.OAuth) middlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - redirectFunc := func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/login", http.StatusTemporaryRedirect) + returnURL := "/" + if u, err := url.Parse(r.Header.Get("Referer")); err == nil { + returnURL = u.RequestURI() } + loginURL := fmt.Sprintf("/login?return_url=%s", url.QueryEscape(returnURL)) + + redirectFunc := func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect) + } if r.Header.Get("HX-Request") == "true" { redirectFunc = func(w http.ResponseWriter, _ *http.Request) { - w.Header().Set("HX-Redirect", "/login") + w.Header().Set("HX-Redirect", loginURL) w.WriteHeader(http.StatusOK) } } @@ -76,6 +84,8 @@ func (mw Middleware) ResolveIdent() middlewareFunc { return } + didOrHandle = strings.TrimPrefix(didOrHandle, "@") + id, err := mw.idResolver.ResolveIdent(r.Context(), didOrHandle) if err != nil { log.Println("failed to resolve did/handle:", err) diff --git a/internal/server/views/login.templ b/internal/server/views/login.templ index f5e1ea3..234021c 100644 --- a/internal/server/views/login.templ +++ b/internal/server/views/login.templ @@ -28,9 +28,17 @@ templ LoginPage(params LoginPageParams) {
- +

Enter your Bluesky handle (e.g., alice.bsky.social) or full DID

+