package domain import ( "errors" "net/url" "strings" "git.cin.su/m/Assistant/contracts/capability" ) var ErrInvalidBinding = errors.New("invalid capability binding") func ValidateBinding(binding capability.Binding) error { if binding.ID == "" || binding.CapabilityID == "" || binding.OwnerPrincipalID == "" || binding.Revision < 1 || binding.Protocol != capability.ProtocolIdempotentReceiptV1 || binding.SecretRef == "" || binding.VerifiedAtUnixMillis <= 0 { return ErrInvalidBinding } if binding.State != capability.BindingActive && binding.State != capability.BindingRetired { return ErrInvalidBinding } if binding.Health != capability.HealthAvailable && binding.Health != capability.HealthDegraded && binding.Health != capability.HealthUnavailable { return ErrInvalidBinding } origin, err := url.Parse(binding.HTTPSOrigin) if err != nil || origin.Scheme != "https" || origin.Host == "" || origin.User != nil || origin.RawQuery != "" || origin.Fragment != "" || (origin.Path != "" && origin.Path != "/") { return ErrInvalidBinding } if !fixedPath(binding.DeliveryPath) || !fixedPath(binding.ReceiptPath) || binding.DeliveryPath == binding.ReceiptPath { return ErrInvalidBinding } return nil } func UsableBinding(binding capability.Binding) error { if err := ValidateBinding(binding); err != nil || binding.State != capability.BindingActive || binding.Health != capability.HealthAvailable { return ErrInvalidBinding } return nil } func RetireBinding(binding capability.Binding) (capability.Binding, error) { if err := ValidateBinding(binding); err != nil || binding.State != capability.BindingActive { return capability.Binding{}, ErrInvalidBinding } binding.State = capability.BindingRetired binding.Revision++ return binding, nil } func fixedPath(value string) bool { return strings.HasPrefix(value, "/") && value != "/" && !strings.HasSuffix(value, "/") && !strings.Contains(value, "//") && !strings.ContainsAny(value, "?#\\") && !strings.Contains(value, "..") }