github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/webhook/converter.go (about)

     1  package webhook
     2  
     3  import (
     4  	"database/sql"
     5  	"encoding/json"
     6  	"fmt"
     7  	"time"
     8  
     9  	"github.com/kyma-incubator/compass/components/director/pkg/auth"
    10  
    11  	"github.com/kyma-incubator/compass/components/director/internal/repo"
    12  
    13  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    14  
    15  	"github.com/kyma-incubator/compass/components/director/internal/model"
    16  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  // AuthConverter missing godoc
    21  //
    22  //go:generate mockery --name=AuthConverter --output=automock --outpkg=automock --case=underscore --disable-version-string
    23  type AuthConverter interface {
    24  	ToGraphQL(in *model.Auth) (*graphql.Auth, error)
    25  	InputFromGraphQL(in *graphql.AuthInput) (*model.AuthInput, error)
    26  }
    27  
    28  type converter struct {
    29  	authConverter AuthConverter
    30  }
    31  
    32  // NewConverter missing godoc
    33  func NewConverter(authConverter AuthConverter) *converter {
    34  	return &converter{authConverter: authConverter}
    35  }
    36  
    37  // ToGraphQL missing godoc
    38  func (c *converter) ToGraphQL(in *model.Webhook) (*graphql.Webhook, error) {
    39  	if in == nil {
    40  		return nil, nil
    41  	}
    42  
    43  	auth, err := c.authConverter.ToGraphQL(in.Auth)
    44  	if err != nil {
    45  		return nil, errors.Wrap(err, "while converting Auth input")
    46  	}
    47  
    48  	var webhookMode *graphql.WebhookMode
    49  	if in.Mode != nil {
    50  		mode := graphql.WebhookMode(*in.Mode)
    51  		webhookMode = &mode
    52  	}
    53  
    54  	var appID *string
    55  	var runtimeID *string
    56  	var appTemplateID *string
    57  	var intSystemID *string
    58  	var formationTemplateID *string
    59  	switch in.ObjectType {
    60  	case model.ApplicationWebhookReference:
    61  		appID = &in.ObjectID
    62  	case model.RuntimeWebhookReference:
    63  		runtimeID = &in.ObjectID
    64  	case model.ApplicationTemplateWebhookReference:
    65  		appTemplateID = &in.ObjectID
    66  	case model.IntegrationSystemWebhookReference:
    67  		intSystemID = &in.ObjectID
    68  	case model.FormationTemplateWebhookReference:
    69  		formationTemplateID = &in.ObjectID
    70  	}
    71  
    72  	return &graphql.Webhook{
    73  		ID:                    in.ID,
    74  		ApplicationID:         appID,
    75  		ApplicationTemplateID: appTemplateID,
    76  		RuntimeID:             runtimeID,
    77  		IntegrationSystemID:   intSystemID,
    78  		FormationTemplateID:   formationTemplateID,
    79  		Type:                  graphql.WebhookType(in.Type),
    80  		Mode:                  webhookMode,
    81  		URL:                   in.URL,
    82  		Auth:                  auth,
    83  		CorrelationIDKey:      in.CorrelationIDKey,
    84  		RetryInterval:         in.RetryInterval,
    85  		Timeout:               in.Timeout,
    86  		URLTemplate:           in.URLTemplate,
    87  		InputTemplate:         in.InputTemplate,
    88  		HeaderTemplate:        in.HeaderTemplate,
    89  		OutputTemplate:        in.OutputTemplate,
    90  		StatusTemplate:        in.StatusTemplate,
    91  		CreatedAt:             timePtrToTimestampPtr(in.CreatedAt),
    92  	}, nil
    93  }
    94  
    95  // ToModel converts graphql.Webhook to model.Webhook
    96  func (c *converter) ToModel(in *graphql.Webhook) (*model.Webhook, error) {
    97  	if in == nil {
    98  		return nil, nil
    99  	}
   100  
   101  	authModel, err := auth.ToModel(in.Auth)
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  
   106  	var objectID string
   107  	var objectType model.WebhookReferenceObjectType
   108  	if in.ApplicationID != nil {
   109  		objectID = *in.ApplicationID
   110  		objectType = model.ApplicationWebhookReference
   111  	} else if in.RuntimeID != nil {
   112  		objectID = *in.RuntimeID
   113  		objectType = model.RuntimeWebhookReference
   114  	} else if in.ApplicationTemplateID != nil {
   115  		objectID = *in.ApplicationTemplateID
   116  		objectType = model.ApplicationTemplateWebhookReference
   117  	} else if in.IntegrationSystemID != nil {
   118  		objectID = *in.IntegrationSystemID
   119  		objectType = model.IntegrationSystemWebhookReference
   120  	} else if in.FormationTemplateID != nil {
   121  		objectID = *in.FormationTemplateID
   122  		objectType = model.FormationTemplateWebhookReference
   123  	} else {
   124  		objectType = model.UnknownWebhookReference
   125  	}
   126  
   127  	var webhookMode *model.WebhookMode
   128  	if in.Mode != nil {
   129  		mode := model.WebhookMode(*in.Mode)
   130  		webhookMode = &mode
   131  	}
   132  
   133  	var createdAt *time.Time = nil
   134  	if in.CreatedAt != nil {
   135  		t := time.Time(*(in.CreatedAt))
   136  		createdAt = &t
   137  	}
   138  
   139  	return &model.Webhook{
   140  		ID:               in.ID,
   141  		ObjectID:         objectID,
   142  		ObjectType:       objectType,
   143  		CorrelationIDKey: in.CorrelationIDKey,
   144  		Type:             model.WebhookType(in.Type),
   145  		URL:              in.URL,
   146  		Auth:             authModel,
   147  		Mode:             webhookMode,
   148  		RetryInterval:    in.RetryInterval,
   149  		Timeout:          in.Timeout,
   150  		URLTemplate:      in.URLTemplate,
   151  		InputTemplate:    in.InputTemplate,
   152  		HeaderTemplate:   in.HeaderTemplate,
   153  		OutputTemplate:   in.OutputTemplate,
   154  		StatusTemplate:   in.StatusTemplate,
   155  		CreatedAt:        createdAt,
   156  	}, nil
   157  }
   158  
   159  // MultipleToGraphQL missing godoc
   160  func (c *converter) MultipleToGraphQL(in []*model.Webhook) ([]*graphql.Webhook, error) {
   161  	webhooks := make([]*graphql.Webhook, 0, len(in))
   162  	for _, r := range in {
   163  		if r == nil {
   164  			continue
   165  		}
   166  
   167  		webhook, err := c.ToGraphQL(r)
   168  		if err != nil {
   169  			return nil, err
   170  		}
   171  
   172  		webhooks = append(webhooks, webhook)
   173  	}
   174  
   175  	return webhooks, nil
   176  }
   177  
   178  // InputFromGraphQL missing godoc
   179  func (c *converter) InputFromGraphQL(in *graphql.WebhookInput) (*model.WebhookInput, error) {
   180  	if in == nil {
   181  		return nil, nil
   182  	}
   183  
   184  	auth, err := c.authConverter.InputFromGraphQL(in.Auth)
   185  	if err != nil {
   186  		return nil, errors.Wrap(err, "while converting Auth input")
   187  	}
   188  
   189  	var webhookMode *model.WebhookMode
   190  	if in.Mode != nil {
   191  		mode := model.WebhookMode(*in.Mode)
   192  		webhookMode = &mode
   193  	}
   194  
   195  	return &model.WebhookInput{
   196  		Type:             model.WebhookType(in.Type),
   197  		URL:              in.URL,
   198  		Auth:             auth,
   199  		Mode:             webhookMode,
   200  		CorrelationIDKey: in.CorrelationIDKey,
   201  		RetryInterval:    in.RetryInterval,
   202  		Timeout:          in.Timeout,
   203  		URLTemplate:      in.URLTemplate,
   204  		InputTemplate:    in.InputTemplate,
   205  		HeaderTemplate:   in.HeaderTemplate,
   206  		OutputTemplate:   in.OutputTemplate,
   207  		StatusTemplate:   in.StatusTemplate,
   208  	}, nil
   209  }
   210  
   211  // MultipleInputFromGraphQL missing godoc
   212  func (c *converter) MultipleInputFromGraphQL(in []*graphql.WebhookInput) ([]*model.WebhookInput, error) {
   213  	inputs := make([]*model.WebhookInput, 0, len(in))
   214  	for _, r := range in {
   215  		if r == nil {
   216  			continue
   217  		}
   218  		webhookIn, err := c.InputFromGraphQL(r)
   219  		if err != nil {
   220  			return nil, err
   221  		}
   222  
   223  		inputs = append(inputs, webhookIn)
   224  	}
   225  
   226  	return inputs, nil
   227  }
   228  
   229  // ToEntity missing godoc
   230  func (c *converter) ToEntity(in *model.Webhook) (*Entity, error) {
   231  	optionalAuth, err := c.toAuthEntity(*in)
   232  	if err != nil {
   233  		return nil, err
   234  	}
   235  
   236  	var webhookMode sql.NullString
   237  	if in.Mode != nil {
   238  		webhookMode.String = string(*in.Mode)
   239  		webhookMode.Valid = true
   240  	}
   241  
   242  	var appID sql.NullString
   243  	var runtimeID sql.NullString
   244  	var appTemplateID sql.NullString
   245  	var intSystemID sql.NullString
   246  	var formationTemplateID sql.NullString
   247  	switch in.ObjectType {
   248  	case model.ApplicationWebhookReference:
   249  		appID = repo.NewValidNullableString(in.ObjectID)
   250  	case model.RuntimeWebhookReference:
   251  		runtimeID = repo.NewValidNullableString(in.ObjectID)
   252  	case model.ApplicationTemplateWebhookReference:
   253  		appTemplateID = repo.NewValidNullableString(in.ObjectID)
   254  	case model.IntegrationSystemWebhookReference:
   255  		intSystemID = repo.NewValidNullableString(in.ObjectID)
   256  	case model.FormationTemplateWebhookReference:
   257  		formationTemplateID = repo.NewValidNullableString(in.ObjectID)
   258  	}
   259  
   260  	return &Entity{
   261  		ID:                    in.ID,
   262  		ApplicationID:         appID,
   263  		ApplicationTemplateID: appTemplateID,
   264  		RuntimeID:             runtimeID,
   265  		IntegrationSystemID:   intSystemID,
   266  		FormationTemplateID:   formationTemplateID,
   267  		CollectionIDKey:       repo.NewNullableString(in.CorrelationIDKey),
   268  		Type:                  string(in.Type),
   269  		URL:                   repo.NewNullableString(in.URL),
   270  		Auth:                  optionalAuth,
   271  		Mode:                  webhookMode,
   272  		RetryInterval:         repo.NewNullableInt(in.RetryInterval),
   273  		Timeout:               repo.NewNullableInt(in.Timeout),
   274  		URLTemplate:           repo.NewNullableString(in.URLTemplate),
   275  		InputTemplate:         repo.NewNullableString(in.InputTemplate),
   276  		HeaderTemplate:        repo.NewNullableString(in.HeaderTemplate),
   277  		OutputTemplate:        repo.NewNullableString(in.OutputTemplate),
   278  		StatusTemplate:        repo.NewNullableString(in.StatusTemplate),
   279  		CreatedAt:             in.CreatedAt,
   280  	}, nil
   281  }
   282  
   283  func (c *converter) toAuthEntity(in model.Webhook) (sql.NullString, error) {
   284  	var optionalAuth sql.NullString
   285  	if in.Auth == nil {
   286  		return optionalAuth, nil
   287  	}
   288  
   289  	b, err := json.Marshal(in.Auth)
   290  	if err != nil {
   291  		return sql.NullString{}, errors.Wrap(err, "while marshalling Auth")
   292  	}
   293  
   294  	if err := optionalAuth.Scan(b); err != nil {
   295  		return sql.NullString{}, errors.Wrap(err, "while scanning optional Auth")
   296  	}
   297  	return optionalAuth, nil
   298  }
   299  
   300  // FromEntity missing godoc
   301  func (c *converter) FromEntity(in *Entity) (*model.Webhook, error) {
   302  	auth, err := c.fromEntityAuth(*in)
   303  	if err != nil {
   304  		return nil, err
   305  	}
   306  
   307  	var webhookMode *model.WebhookMode
   308  	if in.Mode.Valid {
   309  		webhookModeStr := model.WebhookMode(in.Mode.String)
   310  		webhookMode = &webhookModeStr
   311  	}
   312  
   313  	objID, objType, err := c.objectReferenceFromEntity(*in)
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  
   318  	return &model.Webhook{
   319  		ID:               in.ID,
   320  		ObjectID:         objID,
   321  		ObjectType:       objType,
   322  		CorrelationIDKey: repo.StringPtrFromNullableString(in.CollectionIDKey),
   323  		Type:             model.WebhookType(in.Type),
   324  		URL:              repo.StringPtrFromNullableString(in.URL),
   325  		Auth:             auth,
   326  		Mode:             webhookMode,
   327  		RetryInterval:    repo.IntPtrFromNullableInt(in.RetryInterval),
   328  		Timeout:          repo.IntPtrFromNullableInt(in.Timeout),
   329  		URLTemplate:      repo.StringPtrFromNullableString(in.URLTemplate),
   330  		InputTemplate:    repo.StringPtrFromNullableString(in.InputTemplate),
   331  		HeaderTemplate:   repo.StringPtrFromNullableString(in.HeaderTemplate),
   332  		OutputTemplate:   repo.StringPtrFromNullableString(in.OutputTemplate),
   333  		StatusTemplate:   repo.StringPtrFromNullableString(in.StatusTemplate),
   334  		CreatedAt:        in.CreatedAt,
   335  	}, nil
   336  }
   337  
   338  func (c *converter) fromEntityAuth(in Entity) (*model.Auth, error) {
   339  	if !in.Auth.Valid {
   340  		return nil, nil
   341  	}
   342  
   343  	auth := &model.Auth{}
   344  	val, err := in.Auth.Value()
   345  	if err != nil {
   346  		return nil, errors.Wrap(err, "while reading Auth from Entity")
   347  	}
   348  
   349  	b, ok := val.(string)
   350  	if !ok {
   351  		return nil, apperrors.NewInternalError("Auth should be slice of bytes")
   352  	}
   353  	if err := json.Unmarshal([]byte(b), auth); err != nil {
   354  		return nil, errors.Wrap(err, "while unmarshaling Auth")
   355  	}
   356  
   357  	return auth, nil
   358  }
   359  
   360  func (c *converter) objectReferenceFromEntity(in Entity) (string, model.WebhookReferenceObjectType, error) {
   361  	if in.ApplicationID.Valid {
   362  		return in.ApplicationID.String, model.ApplicationWebhookReference, nil
   363  	}
   364  
   365  	if in.RuntimeID.Valid {
   366  		return in.RuntimeID.String, model.RuntimeWebhookReference, nil
   367  	}
   368  
   369  	if in.ApplicationTemplateID.Valid {
   370  		return in.ApplicationTemplateID.String, model.ApplicationTemplateWebhookReference, nil
   371  	}
   372  
   373  	if in.IntegrationSystemID.Valid {
   374  		return in.IntegrationSystemID.String, model.IntegrationSystemWebhookReference, nil
   375  	}
   376  
   377  	if in.FormationTemplateID.Valid {
   378  		return in.FormationTemplateID.String, model.FormationTemplateWebhookReference, nil
   379  	}
   380  
   381  	return "", "", fmt.Errorf("incorrect Object Reference ID and its type for Entity with ID '%s'", in.ID)
   382  }
   383  
   384  func timePtrToTimestampPtr(time *time.Time) *graphql.Timestamp {
   385  	if time == nil {
   386  		return nil
   387  	}
   388  
   389  	t := graphql.Timestamp(*time)
   390  	return &t
   391  }