A fork of the Cocoon PDS but being made more distributed.
11

Configure Feed

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

add account deactivation

Hailey (Sep 14, 2025, 12:37 AM -0700) 64e6cd58 dda2dc4c

+117 -10
+14
models/models.go
··· 4 4 "context" 5 5 "time" 6 6 7 + "github.com/Azure/go-autorest/autorest/to" 7 8 "github.com/bluesky-social/indigo/atproto/crypto" 8 9 ) 9 10 ··· 23 24 Rev string 24 25 Root []byte 25 26 Preferences []byte 27 + Deactivated bool 26 28 } 27 29 28 30 func (r *Repo) SignFor(ctx context.Context, did string, msg []byte) ([]byte, error) { ··· 37 39 } 38 40 39 41 return sig, nil 42 + } 43 + 44 + func (r *Repo) Status() *string { 45 + var status *string 46 + if r.Deactivated { 47 + status = to.StringPtr("deactivated") 48 + } 49 + return status 50 + } 51 + 52 + func (r *Repo) Active() bool { 53 + return r.Status() == nil 40 54 } 41 55 42 56 type Actor struct {
+2 -2
server/handle_repo_list_repos.go
··· 37 37 Did: r.Did, 38 38 Head: c.String(), 39 39 Rev: r.Rev, 40 - Active: true, 41 - Status: nil, 40 + Active: r.Active(), 41 + Status: r.Status(), 42 42 }) 43 43 } 44 44
+45
server/handle_server_activate_account.go
··· 1 + package server 2 + 3 + import ( 4 + "context" 5 + "time" 6 + 7 + "github.com/bluesky-social/indigo/api/atproto" 8 + "github.com/bluesky-social/indigo/events" 9 + "github.com/bluesky-social/indigo/util" 10 + "github.com/haileyok/cocoon/internal/helpers" 11 + "github.com/haileyok/cocoon/models" 12 + "github.com/labstack/echo/v4" 13 + ) 14 + 15 + type ComAtprotoServerActivateAccountRequest struct { 16 + // NOTE: this implementation will not pay attention to this value 17 + DeleteAfter time.Time `json:"deleteAfter"` 18 + } 19 + 20 + func (s *Server) handleServerActivateAccount(e echo.Context) error { 21 + var req ComAtprotoServerDeactivateAccountRequest 22 + if err := e.Bind(&req); err != nil { 23 + s.logger.Error("error binding", "error", err) 24 + return helpers.ServerError(e, nil) 25 + } 26 + 27 + urepo := e.Get("repo").(*models.RepoActor) 28 + 29 + if err := s.db.Exec("UPDATE repos SET deactivated = ? WHERE did = ?", nil, false, urepo.Repo.Did).Error; err != nil { 30 + s.logger.Error("error updating account status to deactivated", "error", err) 31 + return helpers.ServerError(e, nil) 32 + } 33 + 34 + s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{ 35 + RepoAccount: &atproto.SyncSubscribeRepos_Account{ 36 + Active: true, 37 + Did: urepo.Repo.Did, 38 + Status: nil, 39 + Seq: time.Now().UnixMicro(), // TODO: bad puppy 40 + Time: time.Now().Format(util.ISO8601), 41 + }, 42 + }) 43 + 44 + return e.NoContent(200) 45 + }
+2 -2
server/handle_server_create_session.go
··· 102 102 Email: repo.Email, 103 103 EmailConfirmed: repo.EmailConfirmedAt != nil, 104 104 EmailAuthFactor: false, 105 - Active: true, // TODO: eventually do takedowns 106 - Status: nil, // TODO eventually do takedowns 105 + Active: repo.Active(), 106 + Status: repo.Status(), 107 107 }) 108 108 }
+46
server/handle_server_deactivate_account.go
··· 1 + package server 2 + 3 + import ( 4 + "context" 5 + "time" 6 + 7 + "github.com/Azure/go-autorest/autorest/to" 8 + "github.com/bluesky-social/indigo/api/atproto" 9 + "github.com/bluesky-social/indigo/events" 10 + "github.com/bluesky-social/indigo/util" 11 + "github.com/haileyok/cocoon/internal/helpers" 12 + "github.com/haileyok/cocoon/models" 13 + "github.com/labstack/echo/v4" 14 + ) 15 + 16 + type ComAtprotoServerDeactivateAccountRequest struct { 17 + // NOTE: this implementation will not pay attention to this value 18 + DeleteAfter time.Time `json:"deleteAfter"` 19 + } 20 + 21 + func (s *Server) handleServerDeactivateAccount(e echo.Context) error { 22 + var req ComAtprotoServerDeactivateAccountRequest 23 + if err := e.Bind(&req); err != nil { 24 + s.logger.Error("error binding", "error", err) 25 + return helpers.ServerError(e, nil) 26 + } 27 + 28 + urepo := e.Get("repo").(*models.RepoActor) 29 + 30 + if err := s.db.Exec("UPDATE repos SET deactivated = ? WHERE did = ?", nil, true, urepo.Repo.Did).Error; err != nil { 31 + s.logger.Error("error updating account status to deactivated", "error", err) 32 + return helpers.ServerError(e, nil) 33 + } 34 + 35 + s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{ 36 + RepoAccount: &atproto.SyncSubscribeRepos_Account{ 37 + Active: false, 38 + Did: urepo.Repo.Did, 39 + Status: to.StringPtr("deactivated"), 40 + Seq: time.Now().UnixMicro(), // TODO: bad puppy 41 + Time: time.Now().Format(util.ISO8601), 42 + }, 43 + }) 44 + 45 + return e.NoContent(200) 46 + }
+2 -2
server/handle_server_get_session.go
··· 24 24 Email: repo.Email, 25 25 EmailConfirmed: repo.EmailConfirmedAt != nil, 26 26 EmailAuthFactor: false, // TODO: todo todo 27 - Active: true, 28 - Status: nil, 27 + Active: repo.Active(), 28 + Status: repo.Status(), 29 29 }) 30 30 }
+2 -2
server/handle_server_refresh_session.go
··· 40 40 RefreshJwt: sess.RefreshToken, 41 41 Handle: repo.Handle, 42 42 Did: repo.Repo.Did, 43 - Active: true, 44 - Status: nil, 43 + Active: repo.Active(), 44 + Status: repo.Status(), 45 45 }) 46 46 }
+2 -2
server/handle_sync_get_repo_status.go
··· 26 26 27 27 return e.JSON(200, ComAtprotoSyncGetRepoStatusResponse{ 28 28 Did: urepo.Repo.Did, 29 - Active: true, 30 - Status: nil, 29 + Active: urepo.Active(), 30 + Status: urepo.Status(), 31 31 Rev: &urepo.Rev, 32 32 }) 33 33 }
+2
server/server.go
··· 461 461 s.echo.POST("/xrpc/com.atproto.server.updateEmail", s.handleServerUpdateEmail, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) 462 462 s.echo.GET("/xrpc/com.atproto.server.getServiceAuth", s.handleServerGetServiceAuth, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) 463 463 s.echo.GET("/xrpc/com.atproto.server.checkAccountStatus", s.handleServerCheckAccountStatus, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) 464 + s.echo.POST("/xrpc/com.atproto.server.deactivateAccount", s.handleServerDeactivateAccount, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) 465 + s.echo.POST("/xrpc/com.atproto.server.activateAccount", s.handleServerActivateAccount, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) 464 466 465 467 // repo 466 468 s.echo.POST("/xrpc/com.atproto.repo.createRecord", s.handleCreateRecord, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware)