refactor: move computed data code to function to simplify visuals #21

merged
opened by brookjeynes.dev targeting master from push-lokxzmtxxkxo
Changed files
+96 -11
internal
server
+1 -1
internal/server/app.go
···
idResolver := atproto.DefaultResolver()
-
oauth, err := oauth.New(config, posthog, log.SubLogger(logger, "oauth"))
+
oauth, err := oauth.New(config, posthog, idResolver, log.SubLogger(logger, "oauth"))
if err != nil {
return nil, fmt.Errorf("failed to start oauth handler: %w", err)
}
+2 -2
internal/server/handlers/login.go
···
// Basic handle validation
if !strings.Contains(handle, ".") {
l.Error("invalid handle format", "handle", handle)
-
htmx.HxError(w, http.StatusBadGateway, fmt.Sprintf("'%s' is an invalid handle. Did you mean %s.bsky.social?", handle, handle))
+
htmx.HxError(w, http.StatusBadRequest, fmt.Sprintf("'%s' is an invalid handle. Did you mean %s.bsky.social?", handle, handle))
return
}
resolved, err := h.IdResolver.ResolveIdent(context.Background(), handle)
if err != nil {
l.Error("failed to resolve handle", "handle", handle, "err", err)
-
htmx.HxError(w, http.StatusBadGateway, fmt.Sprintf("'%s' is an invalid handle", handle))
+
htmx.HxError(w, http.StatusBadRequest, fmt.Sprintf("'%s' is an invalid handle", handle))
return
} else {
if !h.Config.Core.Dev && resolved.DID.String() != "" {
+1 -1
internal/server/handlers/profile.go
···
})
if err := g.Wait(); err != nil {
-
l.Error("failed to fetch critical profile data for", "did", profileDid, "err", err)
+
l.Error("failed to fetch critical profile data", "did", profileDid, "err", err)
htmx.HxError(w, http.StatusInternalServerError, "Failed to fetch profile data, try again later.")
return
}
+88 -6
internal/server/oauth/handler.go
···
package oauth
import (
+
"context"
"encoding/json"
+
"fmt"
"net/http"
+
"time"
+
comatproto "github.com/bluesky-social/indigo/api/atproto"
+
lexutil "github.com/bluesky-social/indigo/lex/util"
"github.com/go-chi/chi/v5"
"github.com/lestrrat-go/jwx/v2/jwk"
"github.com/posthog/posthog-go"
+
"yoten.app/api/yoten"
ph "yoten.app/internal/clients/posthog"
+
"yoten.app/internal/db"
+
"yoten.app/internal/server/htmx"
)
func (o *OAuth) Router() http.Handler {
···
}
func (o *OAuth) callback(w http.ResponseWriter, r *http.Request) {
+
l := o.Logger.With("handler", "callback")
ctx := r.Context()
sessData, err := o.ClientApp.ProcessCallback(ctx, r.URL.Query())
···
}
if err := o.SaveSession(w, r, sessData); err != nil {
-
o.Logger.Error("failed to save session", "err", err)
+
l.Error("failed to save session", "err", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
-
if !o.Config.Core.Dev {
-
err = o.Posthog.Enqueue(posthog.Capture{
-
DistinctId: sessData.AccountDID.String(),
-
Event: ph.UserSignInSuccessEvent,
+
did := sessData.AccountDID.String()
+
resolved, err := o.IdResolver.ResolveIdent(context.Background(), did)
+
if err != nil {
+
l.Error("failed to resolve handle", "handle", resolved.Handle.String(), "err", err)
+
htmx.HxError(w, http.StatusBadRequest, fmt.Sprintf("'%s' is an invalid handle", resolved.Handle.String()))
+
return
+
}
+
+
client, err := o.AuthorizedClient(r)
+
if err != nil {
+
l.Error("failed to get authorized client", "err", err)
+
http.Error(w, err.Error(), http.StatusInternalServerError)
+
return
+
}
+
+
ex, _ := comatproto.RepoGetRecord(r.Context(), client, "", yoten.ActorProfileNSID, did, "self")
+
var cid *string
+
if ex != nil {
+
cid = ex.Cid
+
}
+
+
// This should only occur once per account
+
if ex == nil {
+
createdAt := time.Now().Format(time.RFC3339)
+
atresp, err := comatproto.RepoPutRecord(r.Context(), client, &comatproto.RepoPutRecord_Input{
+
Collection: yoten.ActorProfileNSID,
+
Repo: did,
+
Rkey: "self",
+
Record: &lexutil.LexiconTypeDecoder{
+
Val: &yoten.ActorProfile{
+
DisplayName: resolved.Handle.String(),
+
Description: db.ToPtr(""),
+
Languages: make([]string, 0),
+
Location: db.ToPtr(""),
+
CreatedAt: createdAt,
+
}},
+
+
SwapRecord: cid,
})
if err != nil {
-
o.Logger.Error("failed to enqueue posthog event", "err", err)
+
l.Error("failed to create profile record", "err", err)
+
htmx.HxError(w, http.StatusInternalServerError, "Failed to announce profile creation, try again later")
+
return
+
}
+
+
l.Debug("created profile record", "uri", atresp.Uri)
+
+
if !o.Config.Core.Dev {
+
err = o.Posthog.Enqueue(posthog.Capture{
+
DistinctId: sessData.AccountDID.String(),
+
Event: ph.UserSignInSuccessEvent,
+
})
+
if err != nil {
+
l.Error("failed to enqueue posthog event", "err", err)
+
}
+
+
properties := posthog.NewProperties().
+
Set("display_name", resolved.Handle.String()).
+
Set("language_count", 0).
+
Set("$set_once", posthog.NewProperties().
+
Set("initial_did", did).
+
Set("initial_handle", resolved.Handle.String()).
+
Set("created_at", createdAt),
+
)
+
+
err = o.Posthog.Enqueue(posthog.Identify{
+
DistinctId: did,
+
Properties: properties,
+
})
+
if err != nil {
+
l.Error("failed to enqueue posthog identify event", "err", err)
+
}
+
+
err = o.Posthog.Enqueue(posthog.Capture{
+
DistinctId: did,
+
Event: ph.ProfileRecordCreatedEvent,
+
})
+
if err != nil {
+
l.Error("failed to enqueue posthog event", "err", err)
+
}
}
}
+4 -1
internal/server/oauth/oauth.go
···
"github.com/gorilla/sessions"
"github.com/posthog/posthog-go"
+
"yoten.app/internal/atproto"
"yoten.app/internal/server/config"
"yoten.app/internal/types"
)
···
JwksUri string
Posthog posthog.Client
Logger *slog.Logger
+
IdResolver *atproto.Resolver
}
-
func New(config *config.Config, ph posthog.Client, logger *slog.Logger) (*OAuth, error) {
+
func New(config *config.Config, ph posthog.Client, idResolver *atproto.Resolver, logger *slog.Logger) (*OAuth, error) {
var oauthConfig oauth.ClientConfig
var clientUri string
···
SessionStore: sessStore,
JwksUri: jwksUri,
Posthog: ph,
+
IdResolver: idResolver,
Logger: logger,
}, nil