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
··· 104 Did: repo.Repo.Did, 105 Email: repo.Email, 106 EmailConfirmed: repo.EmailConfirmedAt != nil, 107 - EmailAuthFactor: false, 108 Active: repo.Active(), 109 Status: repo.Status(), 110 })
··· 104 Did: repo.Repo.Did, 105 Email: repo.Email, 106 EmailConfirmed: repo.EmailConfirmedAt != nil, 107 + EmailAuthFactor: repo.EmailAuthFactor, 108 Active: repo.Active(), 109 Status: repo.Status(), 110 })
+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 { ··· 30 return helpers.InputError(e, nil) 31 } 32 33 - if urepo.EmailUpdateCode == nil || urepo.EmailUpdateCodeExpiresAt == nil { 34 return helpers.InvalidTokenError(e) 35 } 36 37 - if *urepo.EmailUpdateCode != req.Token { 38 - return helpers.InvalidTokenError(e) 39 } 40 41 - if time.Now().UTC().After(*urepo.EmailUpdateCodeExpiresAt) { 42 - return helpers.ExpiredTokenError(e) 43 } 44 45 - 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 { 46 logger.Error("error updating repo", "error", err) 47 return helpers.ServerError(e, nil) 48 }
··· 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 { ··· 30 return helpers.InputError(e, nil) 31 } 32 33 + // To disable email auth factor a token is required. 34 + // To enable email auth factor a token is not required. 35 + // If updating an email address, a token will be sent anyway 36 + if urepo.EmailAuthFactor && req.EmailAuthFactor == false && req.Token == "" { 37 return helpers.InvalidTokenError(e) 38 } 39 40 + if req.Token != "" { 41 + if urepo.EmailUpdateCode == nil || urepo.EmailUpdateCodeExpiresAt == nil { 42 + return helpers.InvalidTokenError(e) 43 + } 44 + 45 + if *urepo.EmailUpdateCode != req.Token { 46 + return helpers.InvalidTokenError(e) 47 + } 48 + 49 + if time.Now().UTC().After(*urepo.EmailUpdateCodeExpiresAt) { 50 + return helpers.ExpiredTokenError(e) 51 + } 52 } 53 54 + query := "UPDATE repos SET email_update_code = NULL, email_update_code_expires_at = NULL, email_auth_factor = ?, email = ?" 55 + 56 + if urepo.Email != req.Email { 57 + query += ",email_confirmed_at = NULL" 58 } 59 60 + query += " WHERE did = ?" 61 + 62 + if err := s.db.Exec(ctx, query, nil, req.EmailAuthFactor, req.Email, urepo.Repo.Did).Error; err != nil { 63 logger.Error("error updating repo", "error", err) 64 return helpers.ServerError(e, nil) 65 }