Signed-off-by: brookjeynes me@brookjeynes.dev
+4
-3
go.mod
+4
-3
go.mod
···-replace github.com/bluesky-social/indigo => github.com/oppiliappan/indigo v0.0.0-20250728090836-5f170569da93·········
+13
-2
go.sum
+13
-2
go.sum
···+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/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8=···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/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/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+23
internal/server/config/config.go
+23
internal/server/config/config.go
······
+9
-1
internal/server/views/login.templ
+9
-1
internal/server/views/login.templ
···-<input type="text" id="handle" name="handle" placeholder="username.bsky.social" class="input" autocomplete="username"/><p class="text-xs text-text-muted">Enter your Bluesky handle (e.g., alice.bsky.social) or full DID</p>
+2
-1
internal/server/views/views.go
+2
-1
internal/server/views/views.go
-55
internal/atproto/xrpc.go
-55
internal/atproto/xrpc.go
···-func (c *Client) RepoPutRecord(ctx context.Context, input *atproto.RepoPutRecord_Input) (*atproto.RepoPutRecord_Output, error) {-if err := c.Do(ctx, c.authArgs, xrpc.Procedure, "application/json", "com.atproto.repo.putRecord", nil, input, &out); err != nil {-func (c *Client) RepoGetRecord(ctx context.Context, cid string, collection string, repo string, rkey string) (*atproto.RepoGetRecord_Output, error) {-if err := c.Do(ctx, c.authArgs, xrpc.Query, "", "com.atproto.repo.getRecord", params, nil, &out); err != nil {-func (c *Client) RepoDeleteRecord(ctx context.Context, input *atproto.RepoDeleteRecord_Input) (*atproto.RepoDeleteRecord_Output, error) {-if err := c.Do(ctx, c.authArgs, xrpc.Procedure, "application/json", "com.atproto.repo.deleteRecord", nil, input, &out); err != nil {
+14
internal/cache/cache.go
+14
internal/cache/cache.go
+172
internal/cache/session/store.go
+172
internal/cache/session/store.go
···+func (s *SessionStore) GetRequestByState(ctx context.Context, state string) (*OAuthRequest, error) {+func (s *SessionStore) RefreshSession(ctx context.Context, did, access, refresh, expiry string) error {+func (s *SessionStore) getRequestKeyFromState(ctx context.Context, state string) (string, error) {
+18
-10
internal/db/db.go
+18
-10
internal/db/db.go
······
+7
-7
internal/server/handlers/activity.go
+7
-7
internal/server/handlers/activity.go
··················-ex, _ := client.RepoGetRecord(r.Context(), "", yoten.ActivityDefNSID, user.Did, updatedActivity.Rkey)+ex, _ := comatproto.RepoGetRecord(r.Context(), client, "", yoten.ActivityDefNSID, user.Did, updatedActivity.Rkey)···
+7
-7
internal/server/handlers/comment.go
+7
-7
internal/server/handlers/comment.go
··················-ex, _ := client.RepoGetRecord(r.Context(), "", yoten.FeedCommentNSID, user.Did, updatedComment.Rkey)+ex, _ := comatproto.RepoGetRecord(r.Context(), client, "", yoten.FeedCommentNSID, user.Did, updatedComment.Rkey)
+3
-3
internal/server/handlers/follow.go
+3
-3
internal/server/handlers/follow.go
·········
+112
internal/server/handlers/login.go
+112
internal/server/handlers/login.go
···+htmx.HxError(w, http.StatusBadGateway, fmt.Sprintf("'%s' is an invalid handle. Did you mean %s.bsky.social?", handle, handle))
+4
-4
internal/server/handlers/pending-ops.go
+4
-4
internal/server/handlers/pending-ops.go
···func ApplyPendingChanges[T Rkeyer](h *Handler, w http.ResponseWriter, r *http.Request, items []T, createKey, updateKey, deleteKey string) ([]T, error) {···func SavePendingCreate[T any](h *Handler, w http.ResponseWriter, r *http.Request, sessionKey string, item T) error {···func SavePendingUpdate[T Rkeyer](h *Handler, w http.ResponseWriter, r *http.Request, sessionKey string, item T) error {···func SavePendingDelete[T Rkeyer](h *Handler, w http.ResponseWriter, r *http.Request, sessionKey string, item T) error {
+5
-5
internal/server/handlers/profile.go
+5
-5
internal/server/handlers/profile.go
·········+ex, _ := comatproto.RepoGetRecord(r.Context(), client, "", yoten.ActorProfileNSID, user.Did, "self")······
+3
-3
internal/server/handlers/reaction.go
+3
-3
internal/server/handlers/reaction.go
·········
+7
-7
internal/server/handlers/resource.go
+7
-7
internal/server/handlers/resource.go
··················-ex, _ := client.RepoGetRecord(r.Context(), "", yoten.FeedResourceNSID, user.Did, resource.Rkey)+ex, _ := comatproto.RepoGetRecord(r.Context(), client, "", yoten.FeedResourceNSID, user.Did, resource.Rkey)
+9
-12
internal/server/handlers/router.go
+9
-12
internal/server/handlers/router.go
············
+7
-7
internal/server/handlers/study-session.go
+7
-7
internal/server/handlers/study-session.go
······-ex, _ := client.RepoGetRecord(r.Context(), "", yoten.FeedSessionNSID, user.Did, updatedStudySession.Rkey)+ex, _ := comatproto.RepoGetRecord(r.Context(), client, "", yoten.FeedSessionNSID, user.Did, updatedStudySession.Rkey)·········htmx.HxError(w, http.StatusUnauthorized, "Failed to delete study session, try again later.")···
+5
-1
internal/server/oauth/consts.go
+5
-1
internal/server/oauth/consts.go
···
+78
internal/server/oauth/handler.go
+78
internal/server/oauth/handler.go
···
-415
internal/server/oauth/handler/handler.go
-415
internal/server/oauth/handler/handler.go
···-htmx.HxError(w, http.StatusBadGateway, fmt.Sprintf("Failed to resolve identity - '%s' is an invalid handle.", handle))-parResp, err := oauthClient.SendParAuthRequest(r.Context(), authServer, authMeta, handle, oauthScope, dpopKey)-ex, _ := xrpcClient.RepoGetRecord(r.Context(), "", yoten.ActorProfileNSID, oauthRequest.Did, "self")-htmx.HxError(w, http.StatusInternalServerError, "Failed to announce profile creation, try again later")
+150
-217
internal/server/oauth/oauth.go
+150
-217
internal/server/oauth/oauth.go
···+oauthConfig = oauth.NewPublicConfig(clientId, callbackUri, []string{"atproto", "transition:generic"})-func (o *OAuth) SaveSession(w http.ResponseWriter, r *http.Request, oreq db.OAuthRequest, oresp *oauth.TokenResponse) (*sessions.Session, error) {+func (o *OAuth) SaveSession(w http.ResponseWriter, r *http.Request, sessionData *oauth.ClientSessionData) error {-func (o *OAuth) CheckSessionAuth(userSession sessions.Session, r *http.Request) (*db.OAuthSession, bool, error) {-resp, err := oauthClient.RefreshTokenRequest(r.Context(), session.RefreshJwt, session.AuthServerIss, session.DpopAuthserverNonce, privateJwk)-func (o *OAuth) AuthorizedClientFromSession(userSession sessions.Session, r *http.Request, w http.ResponseWriter) (*xrpc.Client, error) {-func (o *OAuth) AuthorizedClient(r *http.Request, w http.ResponseWriter) (*xrpc.Client, error) {+func (o *OAuth) ServiceClient(r *http.Request, os ...ServiceClientOpt) (*xrpc.Client, error) {+resp, err := comatproto.ServerGetServiceAuth(r.Context(), client, opts.Audience(), opts.exp, opts.lxm)
+148
internal/server/oauth/store.go
+148
internal/server/oauth/store.go
···+func (r *RedisStore) GetSession(ctx context.Context, did syntax.DID, sessionID string) (*oauth.ClientSessionData, error) {+func (r *RedisStore) DeleteSession(ctx context.Context, did syntax.DID, sessionID string) error {+func (r *RedisStore) GetAuthRequestInfo(ctx context.Context, state string) (*oauth.AuthRequestData, error) {+func (r *RedisStore) SaveAuthRequestInfo(ctx context.Context, info oauth.AuthRequestData) error {
+1
-1
internal/server/views/partials/header.templ
+1
-1
internal/server/views/partials/header.templ
···class="absolute flex flex-col right-0 mt-2 p-1 gap-1 rounded w-48 bg-bg-light border border-bg-dark"