An atproto PDS written in Go

Add account deactivation (#25)

authored by hailey.at and committed by GitHub eff7934d dda2dc4c

+2 -2
README.md
··· 33 33 34 34 ### Server 35 35 36 - - [ ] `com.atproto.server.activateAccount` 36 + - [x] `com.atproto.server.activateAccount` 37 37 - [x] `com.atproto.server.checkAccountStatus` 38 38 - [x] `com.atproto.server.confirmEmail` 39 39 - [x] `com.atproto.server.createAccount` 40 40 - [x] `com.atproto.server.createInviteCode` 41 41 - [x] `com.atproto.server.createInviteCodes` 42 - - [ ] `com.atproto.server.deactivateAccount` 42 + - [x] `com.atproto.server.deactivateAccount` 43 43 - [ ] `com.atproto.server.deleteAccount` 44 44 - [x] `com.atproto.server.deleteSession` 45 45 - [x] `com.atproto.server.describeServer`
+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)