package cart import ( "errors" "log" messages "git.k6n.net/mats/go-cart-actor/proto/cart" ) // SetRecoveryContact replaces the entire recovery-contact bundle on a cart in // a single event. PUT-style semantics — empty email and an empty token list // both persist as "no contact attached"; callers wanting to clear should send // an empty bundle. // // Trivial whitespace-only normalization is intentionally NOT done here: the // notifier layer owns validation (and the LoggingNotifier just logs). A future // real notifier does its own normalization before sending, so we don't want // to lose the original input. func SetRecoveryContact(grain *CartGrain, req *messages.SetRecoveryContact) error { if req == nil { return errors.New("SetRecoveryContact: nil payload") } grain.Email = req.Email if len(req.PushTokens) == 0 { grain.PushTokens = nil return nil } tokens := make([]PushToken, 0, len(req.PushTokens)) dropped := 0 for _, t := range req.PushTokens { if t == nil { // Defensive: a malformed wire request left a nil slot in the // repeated field. Skip rather than crash and surface at debug // level so a misbehaving client is visible without spamming. dropped++ continue } tokens = append(tokens, PushToken{ Platform: t.Platform, Token: t.Token, }) } if dropped > 0 { log.Printf("SetRecoveryContact: dropped %d nil push-token entries (malformed wire)", dropped) } if len(tokens) == 0 { grain.PushTokens = nil return nil } grain.PushTokens = tokens return nil }