An atproto PDS written in Go
103
fork

Configure Feed

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

at 5100abe77e6b3017ef8155191937e2a59510b105 103 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/crypto" 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 repo := e.Get("repo").(*models.RepoActor) 26 27 var req ComAtprotoIdentityUpdateHandleRequest 28 if err := e.Bind(&req); err != nil { 29 s.logger.Error("error binding", "error", err) 30 return helpers.ServerError(e, nil) 31 } 32 33 req.Handle = strings.ToLower(req.Handle) 34 35 if err := e.Validate(req); err != nil { 36 return helpers.InputError(e, nil) 37 } 38 39 ctx := context.WithValue(e.Request().Context(), "skip-cache", true) 40 41 if strings.HasPrefix(repo.Repo.Did, "did:plc:") { 42 log, err := identity.FetchDidAuditLog(ctx, nil, repo.Repo.Did) 43 if err != nil { 44 s.logger.Error("error fetching doc", "error", err) 45 return helpers.ServerError(e, nil) 46 } 47 48 latest := log[len(log)-1] 49 50 var newAka []string 51 for _, aka := range latest.Operation.AlsoKnownAs { 52 if aka == "at://"+repo.Handle { 53 continue 54 } 55 newAka = append(newAka, aka) 56 } 57 58 newAka = append(newAka, "at://"+req.Handle) 59 60 op := plc.Operation{ 61 Type: "plc_operation", 62 VerificationMethods: latest.Operation.VerificationMethods, 63 RotationKeys: latest.Operation.RotationKeys, 64 AlsoKnownAs: newAka, 65 Services: latest.Operation.Services, 66 Prev: &latest.Cid, 67 } 68 69 k, err := crypto.ParsePrivateBytesK256(repo.SigningKey) 70 if err != nil { 71 s.logger.Error("error parsing signing key", "error", err) 72 return helpers.ServerError(e, nil) 73 } 74 75 if err := s.plcClient.SignOp(k, &op); err != nil { 76 return err 77 } 78 79 if err := s.plcClient.SendOperation(e.Request().Context(), repo.Repo.Did, &op); err != nil { 80 return err 81 } 82 } 83 84 if err := s.passport.BustDoc(context.TODO(), repo.Repo.Did); err != nil { 85 s.logger.Warn("error busting did doc", "error", err) 86 } 87 88 s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{ 89 RepoIdentity: &atproto.SyncSubscribeRepos_Identity{ 90 Did: repo.Repo.Did, 91 Handle: to.StringPtr(req.Handle), 92 Seq: time.Now().UnixMicro(), // TODO: no 93 Time: time.Now().Format(util.ISO8601), 94 }, 95 }) 96 97 if err := s.db.Exec("UPDATE actors SET handle = ? WHERE did = ?", nil, req.Handle, repo.Repo.Did).Error; err != nil { 98 s.logger.Error("error updating handle in db", "error", err) 99 return helpers.ServerError(e, nil) 100 } 101 102 return nil 103}