diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -33,13 +33,13 @@ - [ ] `com.atproto.repo.listMissingBlobs` ### Server -- [ ] `com.atproto.server.activateAccount` +- [x] `com.atproto.server.activateAccount` - [x] `com.atproto.server.checkAccountStatus` - [x] `com.atproto.server.confirmEmail` - [x] `com.atproto.server.createAccount` - [x] `com.atproto.server.createInviteCode` - [x] `com.atproto.server.createInviteCodes` -- [ ] `com.atproto.server.deactivateAccount` +- [x] `com.atproto.server.deactivateAccount` - [ ] `com.atproto.server.deleteAccount` - [x] `com.atproto.server.deleteSession` - [x] `com.atproto.server.describeServer` diff --git a/models/models.go b/models/models.go --- a/models/models.go +++ b/models/models.go @@ -4,6 +4,7 @@ import ( "context" "time" + "github.com/Azure/go-autorest/autorest/to" "github.com/bluesky-social/indigo/atproto/crypto" ) @@ -23,6 +24,7 @@ SigningKey []byte Rev string Root []byte Preferences []byte + Deactivated bool } func (r *Repo) SignFor(ctx context.Context, did string, msg []byte) ([]byte, error) { @@ -37,6 +39,18 @@ return nil, err } return sig, nil +} + +func (r *Repo) Status() *string { + var status *string + if r.Deactivated { + status = to.StringPtr("deactivated") + } + return status +} + +func (r *Repo) Active() bool { + return r.Status() == nil } type Actor struct { diff --git a/server/handle_repo_list_repos.go b/server/handle_repo_list_repos.go --- a/server/handle_repo_list_repos.go +++ b/server/handle_repo_list_repos.go @@ -37,8 +37,8 @@ items = append(items, ComAtprotoSyncListReposRepoItem{ Did: r.Did, Head: c.String(), Rev: r.Rev, - Active: true, - Status: nil, + Active: r.Active(), + Status: r.Status(), }) } diff --git a/server/handle_server_activate_account.go b/server/handle_server_activate_account.go new file mode 100644 --- /dev/null +++ b/server/handle_server_activate_account.go @@ -0,0 +1,45 @@ +package server + +import ( + "context" + "time" + + "github.com/bluesky-social/indigo/api/atproto" + "github.com/bluesky-social/indigo/events" + "github.com/bluesky-social/indigo/util" + "github.com/haileyok/cocoon/internal/helpers" + "github.com/haileyok/cocoon/models" + "github.com/labstack/echo/v4" +) + +type ComAtprotoServerActivateAccountRequest struct { + // NOTE: this implementation will not pay attention to this value + DeleteAfter time.Time `json:"deleteAfter"` +} + +func (s *Server) handleServerActivateAccount(e echo.Context) error { + var req ComAtprotoServerDeactivateAccountRequest + if err := e.Bind(&req); err != nil { + s.logger.Error("error binding", "error", err) + return helpers.ServerError(e, nil) + } + + urepo := e.Get("repo").(*models.RepoActor) + + if err := s.db.Exec("UPDATE repos SET deactivated = ? WHERE did = ?", nil, false, urepo.Repo.Did).Error; err != nil { + s.logger.Error("error updating account status to deactivated", "error", err) + return helpers.ServerError(e, nil) + } + + s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{ + RepoAccount: &atproto.SyncSubscribeRepos_Account{ + Active: true, + Did: urepo.Repo.Did, + Status: nil, + Seq: time.Now().UnixMicro(), // TODO: bad puppy + Time: time.Now().Format(util.ISO8601), + }, + }) + + return e.NoContent(200) +} diff --git a/server/handle_server_create_session.go b/server/handle_server_create_session.go --- a/server/handle_server_create_session.go +++ b/server/handle_server_create_session.go @@ -102,7 +102,7 @@ Did: repo.Repo.Did, Email: repo.Email, EmailConfirmed: repo.EmailConfirmedAt != nil, EmailAuthFactor: false, - Active: true, // TODO: eventually do takedowns - Status: nil, // TODO eventually do takedowns + Active: repo.Active(), + Status: repo.Status(), }) } diff --git a/server/handle_server_deactivate_account.go b/server/handle_server_deactivate_account.go new file mode 100644 --- /dev/null +++ b/server/handle_server_deactivate_account.go @@ -0,0 +1,46 @@ +package server + +import ( + "context" + "time" + + "github.com/Azure/go-autorest/autorest/to" + "github.com/bluesky-social/indigo/api/atproto" + "github.com/bluesky-social/indigo/events" + "github.com/bluesky-social/indigo/util" + "github.com/haileyok/cocoon/internal/helpers" + "github.com/haileyok/cocoon/models" + "github.com/labstack/echo/v4" +) + +type ComAtprotoServerDeactivateAccountRequest struct { + // NOTE: this implementation will not pay attention to this value + DeleteAfter time.Time `json:"deleteAfter"` +} + +func (s *Server) handleServerDeactivateAccount(e echo.Context) error { + var req ComAtprotoServerDeactivateAccountRequest + if err := e.Bind(&req); err != nil { + s.logger.Error("error binding", "error", err) + return helpers.ServerError(e, nil) + } + + urepo := e.Get("repo").(*models.RepoActor) + + if err := s.db.Exec("UPDATE repos SET deactivated = ? WHERE did = ?", nil, true, urepo.Repo.Did).Error; err != nil { + s.logger.Error("error updating account status to deactivated", "error", err) + return helpers.ServerError(e, nil) + } + + s.evtman.AddEvent(context.TODO(), &events.XRPCStreamEvent{ + RepoAccount: &atproto.SyncSubscribeRepos_Account{ + Active: false, + Did: urepo.Repo.Did, + Status: to.StringPtr("deactivated"), + Seq: time.Now().UnixMicro(), // TODO: bad puppy + Time: time.Now().Format(util.ISO8601), + }, + }) + + return e.NoContent(200) +} diff --git a/server/handle_server_get_session.go b/server/handle_server_get_session.go --- a/server/handle_server_get_session.go +++ b/server/handle_server_get_session.go @@ -24,7 +24,7 @@ Did: repo.Repo.Did, Email: repo.Email, EmailConfirmed: repo.EmailConfirmedAt != nil, EmailAuthFactor: false, // TODO: todo todo - Active: true, - Status: nil, + Active: repo.Active(), + Status: repo.Status(), }) } diff --git a/server/handle_server_refresh_session.go b/server/handle_server_refresh_session.go --- a/server/handle_server_refresh_session.go +++ b/server/handle_server_refresh_session.go @@ -40,7 +40,7 @@ AccessJwt: sess.AccessToken, RefreshJwt: sess.RefreshToken, Handle: repo.Handle, Did: repo.Repo.Did, - Active: true, - Status: nil, + Active: repo.Active(), + Status: repo.Status(), }) } diff --git a/server/handle_sync_get_repo_status.go b/server/handle_sync_get_repo_status.go --- a/server/handle_sync_get_repo_status.go +++ b/server/handle_sync_get_repo_status.go @@ -26,8 +26,8 @@ } return e.JSON(200, ComAtprotoSyncGetRepoStatusResponse{ Did: urepo.Repo.Did, - Active: true, - Status: nil, + Active: urepo.Active(), + Status: urepo.Status(), Rev: &urepo.Rev, }) } diff --git a/server/server.go b/server/server.go --- a/server/server.go +++ b/server/server.go @@ -461,6 +461,8 @@ s.echo.POST("/xrpc/com.atproto.server.resetPassword", s.handleServerResetPassword, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) s.echo.POST("/xrpc/com.atproto.server.updateEmail", s.handleServerUpdateEmail, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) s.echo.GET("/xrpc/com.atproto.server.getServiceAuth", s.handleServerGetServiceAuth, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) s.echo.GET("/xrpc/com.atproto.server.checkAccountStatus", s.handleServerCheckAccountStatus, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) + s.echo.POST("/xrpc/com.atproto.server.deactivateAccount", s.handleServerDeactivateAccount, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) + s.echo.POST("/xrpc/com.atproto.server.activateAccount", s.handleServerActivateAccount, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware) // repo s.echo.POST("/xrpc/com.atproto.repo.createRecord", s.handleCreateRecord, s.handleLegacySessionMiddleware, s.handleOauthSessionMiddleware)