forked from hailey.at/cocoon
An atproto PDS written in Go

implement enabling / disabling email auth factor (not currently checked on auth checks though)

Signed-off-by: Will Andrews <did:plc:dadhhalkfcq3gucaq25hjqon>

+3 -2
models/models.go
··· 29 Root []byte 30 Preferences []byte 31 Deactivated bool 32 } 33 34 func (r *Repo) SignFor(ctx context.Context, did string, msg []byte) ([]byte, error) { ··· 121 } 122 123 type ReservedKey struct { 124 - KeyDid string `gorm:"primaryKey"` 125 - Did *string `gorm:"index"` 126 PrivateKey []byte 127 CreatedAt time.Time `gorm:"index"` 128 }
··· 29 Root []byte 30 Preferences []byte 31 Deactivated bool 32 + EmailAuthFactor bool 33 } 34 35 func (r *Repo) SignFor(ctx context.Context, did string, msg []byte) ([]byte, error) { ··· 122 } 123 124 type ReservedKey struct { 125 + KeyDid string `gorm:"primaryKey"` 126 + Did *string `gorm:"index"` 127 PrivateKey []byte 128 CreatedAt time.Time `gorm:"index"` 129 }
+1 -1
server/handle_server_create_session.go
··· 103 Did: repo.Repo.Did, 104 Email: repo.Email, 105 EmailConfirmed: repo.EmailConfirmedAt != nil, 106 - EmailAuthFactor: false, 107 Active: repo.Active(), 108 Status: repo.Status(), 109 })
··· 103 Did: repo.Repo.Did, 104 Email: repo.Email, 105 EmailConfirmed: repo.EmailConfirmedAt != nil, 106 + EmailAuthFactor: repo.EmailAuthFactor, 107 Active: repo.Active(), 108 Status: repo.Status(), 109 })
+1 -1
server/handle_server_get_session.go
··· 23 Did: repo.Repo.Did, 24 Email: repo.Email, 25 EmailConfirmed: repo.EmailConfirmedAt != nil, 26 - EmailAuthFactor: false, // TODO: todo todo 27 Active: repo.Active(), 28 Status: repo.Status(), 29 })
··· 23 Did: repo.Repo.Did, 24 Email: repo.Email, 25 EmailConfirmed: repo.EmailConfirmedAt != nil, 26 + EmailAuthFactor: repo.EmailAuthFactor, 27 Active: repo.Active(), 28 Status: repo.Status(), 29 })
+24 -7
server/handle_server_update_email.go
··· 11 type ComAtprotoServerUpdateEmailRequest struct { 12 Email string `json:"email" validate:"required"` 13 EmailAuthFactor bool `json:"emailAuthFactor"` 14 - Token string `json:"token" validate:"required"` 15 } 16 17 func (s *Server) handleServerUpdateEmail(e echo.Context) error { ··· 29 return helpers.InputError(e, nil) 30 } 31 32 - if urepo.EmailUpdateCode == nil || urepo.EmailUpdateCodeExpiresAt == nil { 33 return helpers.InvalidTokenError(e) 34 } 35 36 - if *urepo.EmailUpdateCode != req.Token { 37 - return helpers.InvalidTokenError(e) 38 } 39 40 - if time.Now().UTC().After(*urepo.EmailUpdateCodeExpiresAt) { 41 - return helpers.ExpiredTokenError(e) 42 } 43 44 - if err := s.db.Exec(ctx, "UPDATE repos SET email_update_code = NULL, email_update_code_expires_at = NULL, email_confirmed_at = NULL, email = ? WHERE did = ?", nil, req.Email, urepo.Repo.Did).Error; err != nil { 45 s.logger.Error("error updating repo", "error", err) 46 return helpers.ServerError(e, nil) 47 }
··· 11 type ComAtprotoServerUpdateEmailRequest struct { 12 Email string `json:"email" validate:"required"` 13 EmailAuthFactor bool `json:"emailAuthFactor"` 14 + Token string `json:"token"` 15 } 16 17 func (s *Server) handleServerUpdateEmail(e echo.Context) error { ··· 29 return helpers.InputError(e, nil) 30 } 31 32 + // To disable email auth factor a token is required. 33 + // To enable email auth factor a token is not required. 34 + // If updating an email address, a token will be sent anyway 35 + if urepo.EmailAuthFactor && req.EmailAuthFactor == false && req.Token == "" { 36 return helpers.InvalidTokenError(e) 37 } 38 39 + if req.Token != "" { 40 + if urepo.EmailUpdateCode == nil || urepo.EmailUpdateCodeExpiresAt == nil { 41 + return helpers.InvalidTokenError(e) 42 + } 43 + 44 + if *urepo.EmailUpdateCode != req.Token { 45 + return helpers.InvalidTokenError(e) 46 + } 47 + 48 + if time.Now().UTC().After(*urepo.EmailUpdateCodeExpiresAt) { 49 + return helpers.ExpiredTokenError(e) 50 + } 51 } 52 53 + query := "UPDATE repos SET email_update_code = NULL, email_update_code_expires_at = NULL, email_auth_factor = ?, email = ?" 54 + 55 + if urepo.Email != req.Email { 56 + query += ",email_confirmed_at = NULL" 57 } 58 59 + query += " WHERE did = ?" 60 + 61 + if err := s.db.Exec(ctx, query, nil, req.EmailAuthFactor, req.Email, urepo.Repo.Did).Error; err != nil { 62 s.logger.Error("error updating repo", "error", err) 63 return helpers.ServerError(e, nil) 64 }