github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/pkg/graphql/app_template_validation.go (about) 1 package graphql 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 8 "github.com/go-ozzo/ozzo-validation/v4/is" 9 10 validation "github.com/go-ozzo/ozzo-validation/v4" 11 "github.com/kyma-incubator/compass/components/director/pkg/inputvalidation" 12 "github.com/pkg/errors" 13 ) 14 15 // Validate missing godoc 16 func (i ApplicationTemplateInput) Validate() error { 17 return validation.Errors{ 18 "Rule.ValidPlaceholders": validPlaceholders(i.Placeholders, i.ApplicationInput), 19 "appInput": validation.Validate(i.ApplicationInput), 20 "name": validation.Validate(i.Name, validation.Required, is.PrintableASCII, validation.Length(1, 100)), 21 "description": validation.Validate(i.Description, validation.RuneLength(0, descriptionStringLengthLimit)), 22 "placeholders": validation.Validate(i.Placeholders, validation.Each(validation.Required)), 23 "accessLevel": validation.Validate(i.AccessLevel, validation.Required, validation.In(ApplicationTemplateAccessLevelGlobal)), 24 "webhooks": validation.Validate(i.Webhooks, validation.By(webhooksRuleFunc)), 25 "applicationNamespace": validation.Validate(i.ApplicationNamespace, validation.Length(1, longStringLengthLimit)), 26 }.Filter() 27 } 28 29 // Validate missing godoc 30 func (i ApplicationTemplateUpdateInput) Validate() error { 31 return validation.Errors{ 32 "Rule.ValidPlaceholders": validPlaceholders(i.Placeholders, i.ApplicationInput), 33 "appInput": validation.Validate(i.ApplicationInput), 34 "name": validation.Validate(i.Name, validation.Required, is.PrintableASCII, validation.Length(1, 100)), 35 "description": validation.Validate(i.Description, validation.RuneLength(0, descriptionStringLengthLimit)), 36 "placeholders": validation.Validate(i.Placeholders, validation.Each(validation.Required)), 37 "accessLevel": validation.Validate(i.AccessLevel, validation.Required, validation.In(ApplicationTemplateAccessLevelGlobal)), 38 "webhooks": validation.Validate(i.Webhooks, validation.By(webhooksRuleFunc)), 39 "applicationNamespace": validation.Validate(i.ApplicationNamespace, validation.Length(1, longStringLengthLimit)), 40 }.Filter() 41 } 42 43 // Validate missing godoc 44 func (i PlaceholderDefinitionInput) Validate() error { 45 return validation.ValidateStruct(&i, 46 validation.Field(&i.Name, validation.Required, inputvalidation.DNSName), 47 validation.Field(&i.Description, validation.RuneLength(0, descriptionStringLengthLimit)), 48 validation.Field(&i.JSONPath, validation.RuneLength(0, jsonPathStringLengthLimit)), 49 ) 50 } 51 52 // Validate missing godoc 53 func (i ApplicationFromTemplateInput) Validate() error { 54 return validation.Errors{ 55 "Rule.EitherPlaceholdersOrPlaceholdersPayloadExists": i.ensureEitherPlaceholdersOrPlaceholdersPayloadExists(), 56 "Rule.UniquePlaceholders": i.ensureUniquePlaceholders(), 57 "templateName": validation.Validate(i.TemplateName, validation.Required, is.PrintableASCII, validation.Length(1, 100)), 58 "values": validation.Validate(i.Values, validation.Each(validation.Required)), 59 }.Filter() 60 } 61 62 func (i ApplicationFromTemplateInput) ensureUniquePlaceholders() error { 63 keys := make(map[string]interface{}) 64 for _, item := range i.Values { 65 if item == nil { 66 continue 67 } 68 if _, exist := keys[item.Placeholder]; exist { 69 return errors.Errorf("placeholder [name=%s] not unique", item.Placeholder) 70 } 71 72 keys[item.Placeholder] = struct{}{} 73 } 74 return nil 75 } 76 77 func (i ApplicationFromTemplateInput) ensureEitherPlaceholdersOrPlaceholdersPayloadExists() error { 78 if (i.PlaceholdersPayload != nil) == (len(i.Values) != 0) { 79 return errors.Errorf("one of values or placeholdersPayload should be provided") 80 } 81 return nil 82 } 83 84 // Validate missing godoc 85 func (i TemplateValueInput) Validate() error { 86 return validation.ValidateStruct(&i, 87 validation.Field(&i.Placeholder, validation.Required, inputvalidation.DNSName), 88 validation.Field(&i.Value, validation.RuneLength(0, shortStringLengthLimit)), 89 ) 90 } 91 92 func webhooksRuleFunc(value interface{}) error { 93 webhookInputs, ok := value.([]*WebhookInput) 94 if !ok { 95 return errors.New("value could not be cast to WebhookInput slice") 96 } 97 98 for _, webhookInput := range webhookInputs { 99 if err := webhookInput.Validate(); err != nil { 100 return err 101 } 102 } 103 104 return nil 105 } 106 107 func ensureUniquePlaceholders(placeholders []*PlaceholderDefinitionInput) error { 108 keys := make(map[string]interface{}) 109 for _, item := range placeholders { 110 if item == nil { 111 continue 112 } 113 114 if _, exist := keys[item.Name]; exist { 115 return errors.Errorf("placeholder [name=%s] not unique", item.Name) 116 } 117 118 keys[item.Name] = struct{}{} 119 } 120 return nil 121 } 122 123 func ensurePlaceholdersUsed(placeholders []*PlaceholderDefinitionInput, appInput *ApplicationJSONInput) error { 124 placeholdersMarshalled, err := json.Marshal(appInput) 125 if err != nil { 126 return errors.Wrap(err, "while marshalling placeholders") 127 } 128 129 placeholdersString := string(placeholdersMarshalled) 130 131 for _, value := range placeholders { 132 if value == nil { 133 continue 134 } 135 if !strings.Contains(placeholdersString, fmt.Sprintf("{{%s}}", value.Name)) { 136 return errors.Errorf("application input does not use provided placeholder [name=%s]", value.Name) 137 } 138 } 139 140 return nil 141 } 142 143 func validPlaceholders(placeholders []*PlaceholderDefinitionInput, appInput *ApplicationJSONInput) error { 144 if err := ensureUniquePlaceholders(placeholders); err != nil { 145 return err 146 } 147 if err := ensurePlaceholdersUsed(placeholders, appInput); err != nil { 148 return err 149 } 150 return nil 151 }