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

     1  package oauth20
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/kyma-incubator/compass/components/director/internal/model"
     8  
     9  	pkgmodel "github.com/kyma-incubator/compass/components/director/pkg/model"
    10  
    11  	"github.com/kyma-incubator/compass/components/director/pkg/log"
    12  
    13  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    14  
    15  	"github.com/hashicorp/go-multierror"
    16  
    17  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
    18  	"github.com/kyma-incubator/compass/components/director/pkg/persistence"
    19  	"github.com/pkg/errors"
    20  )
    21  
    22  // SystemAuthService missing godoc
    23  //go:generate mockery --name=SystemAuthService --output=automock --outpkg=automock --case=underscore --disable-version-string
    24  type SystemAuthService interface {
    25  	CreateWithCustomID(ctx context.Context, id string, objectType pkgmodel.SystemAuthReferenceObjectType, objectID string, authInput *model.AuthInput) (string, error)
    26  	GetByIDForObject(ctx context.Context, objectType pkgmodel.SystemAuthReferenceObjectType, authID string) (*pkgmodel.SystemAuth, error)
    27  }
    28  
    29  // ApplicationService missing godoc
    30  //go:generate mockery --name=ApplicationService --output=automock --outpkg=automock --case=underscore --disable-version-string
    31  type ApplicationService interface {
    32  	Exist(ctx context.Context, id string) (bool, error)
    33  }
    34  
    35  // RuntimeService missing godoc
    36  //go:generate mockery --name=RuntimeService --output=automock --outpkg=automock --case=underscore --disable-version-string
    37  type RuntimeService interface {
    38  	Exist(ctx context.Context, id string) (bool, error)
    39  }
    40  
    41  // IntegrationSystemService missing godoc
    42  //go:generate mockery --name=IntegrationSystemService --output=automock --outpkg=automock --case=underscore --disable-version-string
    43  type IntegrationSystemService interface {
    44  	Exists(ctx context.Context, id string) (bool, error)
    45  }
    46  
    47  // SystemAuthConverter missing godoc
    48  //go:generate mockery --name=SystemAuthConverter --output=automock --outpkg=automock --case=underscore --disable-version-string
    49  type SystemAuthConverter interface {
    50  	ToGraphQL(model *pkgmodel.SystemAuth) (graphql.SystemAuth, error)
    51  }
    52  
    53  // Service missing godoc
    54  //go:generate mockery --name=Service --output=automock --outpkg=automock --case=underscore --disable-version-string
    55  type Service interface {
    56  	CreateClientCredentials(ctx context.Context, objectType pkgmodel.SystemAuthReferenceObjectType) (*model.OAuthCredentialDataInput, error)
    57  	DeleteClientCredentials(ctx context.Context, clientID string) error
    58  }
    59  
    60  // Resolver missing godoc
    61  type Resolver struct {
    62  	transact       persistence.Transactioner
    63  	svc            Service
    64  	systemAuthSvc  SystemAuthService
    65  	systemAuthConv SystemAuthConverter
    66  	appSvc         ApplicationService
    67  	rtmSvc         RuntimeService
    68  	isSvc          IntegrationSystemService
    69  }
    70  
    71  // NewResolver missing godoc
    72  func NewResolver(transactioner persistence.Transactioner, svc Service, appSvc ApplicationService, rtmSvc RuntimeService, isSvc IntegrationSystemService, systemAuthSvc SystemAuthService, systemAuthConv SystemAuthConverter) *Resolver {
    73  	return &Resolver{transact: transactioner, svc: svc, appSvc: appSvc, rtmSvc: rtmSvc, systemAuthSvc: systemAuthSvc, isSvc: isSvc, systemAuthConv: systemAuthConv}
    74  }
    75  
    76  // RequestClientCredentialsForRuntime missing godoc
    77  func (r *Resolver) RequestClientCredentialsForRuntime(ctx context.Context, id string) (graphql.SystemAuth, error) {
    78  	return r.generateClientCredentials(ctx, pkgmodel.RuntimeReference, id)
    79  }
    80  
    81  // RequestClientCredentialsForApplication missing godoc
    82  func (r *Resolver) RequestClientCredentialsForApplication(ctx context.Context, id string) (graphql.SystemAuth, error) {
    83  	return r.generateClientCredentials(ctx, pkgmodel.ApplicationReference, id)
    84  }
    85  
    86  // RequestClientCredentialsForIntegrationSystem missing godoc
    87  func (r *Resolver) RequestClientCredentialsForIntegrationSystem(ctx context.Context, id string) (graphql.SystemAuth, error) {
    88  	return r.generateClientCredentials(ctx, pkgmodel.IntegrationSystemReference, id)
    89  }
    90  
    91  func (r *Resolver) generateClientCredentials(ctx context.Context, objType pkgmodel.SystemAuthReferenceObjectType, objID string) (graphql.SystemAuth, error) {
    92  	tx, err := r.transact.Begin()
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	defer r.transact.RollbackUnlessCommitted(ctx, tx)
    97  
    98  	log.C(ctx).Infof("Requesting creation of client credentials for %s with id %s", objType, objID)
    99  	ctx = persistence.SaveToContext(ctx, tx)
   100  
   101  	exists, err := r.checkObjectExist(ctx, objType, objID)
   102  	if err != nil {
   103  		return nil, errors.Wrapf(err, "while checking if %s with ID '%s' exists", objType, objID)
   104  	}
   105  	if !exists {
   106  		return nil, fmt.Errorf("%s with ID '%s' not found", objType, objID)
   107  	}
   108  
   109  	log.C(ctx).Debugf("Generating client credentials for %s with id %s by Director", objType, objID)
   110  	clientCreds, err := r.svc.CreateClientCredentials(ctx, objType)
   111  	if err != nil {
   112  		return nil, errors.Wrapf(err, "while creating client credentials for %s with id %s", objType, objID)
   113  	}
   114  	if clientCreds == nil {
   115  		return nil, apperrors.NewInvalidDataError("client credentials cannot be empty")
   116  	}
   117  	log.C(ctx).Debugf("Client credentials for %s with id %s are successfully generated by Director", objType, objID)
   118  	cleanupOnError := func(originalErr error) error {
   119  		cleanupErr := r.svc.DeleteClientCredentials(ctx, clientCreds.ClientID)
   120  		if cleanupErr != nil {
   121  			return multierror.Append(err, cleanupErr)
   122  		}
   123  
   124  		return originalErr
   125  	}
   126  
   127  	id := clientCreds.ClientID
   128  	log.C(ctx).Debugf("Creating SystemAuth for the client credentials for %s with id %s", objType, objID)
   129  	_, err = r.systemAuthSvc.CreateWithCustomID(ctx, id, objType, objID, &model.AuthInput{
   130  		Credential: &model.CredentialDataInput{
   131  			Oauth: clientCreds,
   132  		},
   133  	})
   134  	if err != nil {
   135  		finalErr := cleanupOnError(err)
   136  		return nil, errors.Wrapf(finalErr, "error occurred while creating SystemAuth for %s with id %s", objType, objID)
   137  	}
   138  	log.C(ctx).Debugf("Successfully created SystemAuth for the client credentials for %s with id %s", objType, objID)
   139  
   140  	sysAuth, err := r.systemAuthSvc.GetByIDForObject(ctx, objType, id)
   141  	if err != nil {
   142  		finalErr := cleanupOnError(err)
   143  		return nil, finalErr
   144  	}
   145  
   146  	err = tx.Commit()
   147  	if err != nil {
   148  		finalErr := cleanupOnError(err)
   149  		return nil, finalErr
   150  	}
   151  
   152  	log.C(ctx).Infof("Successfully created client credentials with client_id %s for %s with id %s", id, objType, objID)
   153  	return r.systemAuthConv.ToGraphQL(sysAuth)
   154  }
   155  
   156  func (r *Resolver) checkObjectExist(ctx context.Context, objType pkgmodel.SystemAuthReferenceObjectType, objID string) (bool, error) {
   157  	switch objType {
   158  	case pkgmodel.RuntimeReference:
   159  		return r.rtmSvc.Exist(ctx, objID)
   160  	case pkgmodel.ApplicationReference:
   161  		return r.appSvc.Exist(ctx, objID)
   162  	case pkgmodel.IntegrationSystemReference:
   163  		return r.isSvc.Exists(ctx, objID)
   164  	}
   165  
   166  	return false, fmt.Errorf("invalid object type %s", objType)
   167  }