An atproto PDS written in Go
103
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 11920453a6fb7d1e1fe614ce3331916638c5af96 105 lines 2.9 kB view raw
1package server 2 3import ( 4 "context" 5 "strings" 6 "time" 7 8 "github.com/Azure/go-autorest/autorest/to" 9 "github.com/bluesky-social/indigo/api/atproto" 10 "github.com/bluesky-social/indigo/atproto/atcrypto" 11 "github.com/bluesky-social/indigo/events" 12 "github.com/bluesky-social/indigo/util" 13 "github.com/haileyok/cocoon/identity" 14 "github.com/haileyok/cocoon/internal/helpers" 15 "github.com/haileyok/cocoon/models" 16 "github.com/haileyok/cocoon/plc" 17 "github.com/labstack/echo/v4" 18) 19 20type ComAtprotoIdentityUpdateHandleRequest struct { 21 Handle string `json:"handle" validate:"atproto-handle"` 22} 23 24func (s *Server) handleIdentityUpdateHandle(e echo.Context) error { 25 logger := s.logger.With("name", "handleIdentityUpdateHandle") 26 27 repo := e.Get("repo").(*models.RepoActor) 28 29 var req ComAtprotoIdentityUpdateHandleRequest 30 if err := e.Bind(&req); err != nil { 31 logger.Error("error binding", "error", err) 32 return helpers.ServerError(e, nil) 33 } 34 35 req.Handle = strings.ToLower(req.Handle) 36 37 if err := e.Validate(req); err != nil { 38 return helpers.InputError(e, nil) 39 } 40 41 ctx := context.WithValue(e.Request().Context(), "skip-cache", true) 42 43 if strings.HasPrefix(repo.Repo.Did, "did:plc:") { 44 log, err := identity.FetchDidAuditLog(ctx, nil, repo.Repo.Did) 45 if err != nil { 46 logger.Error("error fetching doc", "error", err) 47 return helpers.ServerError(e, nil) 48 } 49 50 latest := log[len(log)-1] 51 52 var newAka []string 53 for _, aka := range latest.Operation.AlsoKnownAs { 54 if aka == "at://"+repo.Handle { 55 continue 56 } 57 newAka = append(newAka, aka) 58 } 59 60 newAka = append(newAka, "at://"+req.Handle) 61 62 op := plc.Operation{ 63 Type: "plc_operation", 64 VerificationMethods: latest.Operation.VerificationMethods, 65 RotationKeys: latest.Operation.RotationKeys, 66 AlsoKnownAs: newAka, 67 Services: latest.Operation.Services, 68 Prev: &latest.Cid, 69 } 70 71 k, err := atcrypto.ParsePrivateBytesK256(repo.SigningKey) 72 if err != nil { 73 logger.Error("error parsing signing key", "error", err) 74 return helpers.ServerError(e, nil) 75 } 76 77 if err := s.plcClient.SignOp(k, &op); err != nil { 78 return err 79 } 80 81 if err := s.plcClient.SendOperation(e.Request().Context(), repo.Repo.Did, &op); err != nil { 82 return err 83 } 84 } 85 86 if err := s.passport.BustDoc(context.TODO(), repo.Repo.Did); err != nil { 87 logger.Warn("error busting did doc", "error", err) 88 } 89 90 s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{ 91 RepoIdentity: &atproto.SyncSubscribeRepos_Identity{ 92 Did: repo.Repo.Did, 93 Handle: to.StringPtr(req.Handle), 94 Seq: time.Now().UnixMicro(), // TODO: no 95 Time: time.Now().Format(util.ISO8601), 96 }, 97 }) 98 99 if err := s.db.Exec(ctx, "UPDATE actors SET handle = ? WHERE did = ?", nil, req.Handle, repo.Repo.Did).Error; err != nil { 100 logger.Error("error updating handle in db", "error", err) 101 return helpers.ServerError(e, nil) 102 } 103 104 return nil 105}