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  }