github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/scopes_sync/service.go (about) 1 package scopes 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/kyma-incubator/compass/components/director/pkg/model" 8 9 "github.com/kyma-incubator/compass/components/director/internal/domain/oauth20" 10 "github.com/kyma-incubator/compass/components/director/internal/repo" 11 "github.com/kyma-incubator/compass/components/director/pkg/log" 12 "github.com/kyma-incubator/compass/components/director/pkg/persistence" 13 "github.com/kyma-incubator/compass/components/director/pkg/str" 14 "github.com/ory/hydra-client-go/models" 15 "github.com/pkg/errors" 16 ) 17 18 // SyncService missing godoc 19 type SyncService interface { 20 SynchronizeClientScopes(context.Context) error 21 } 22 23 // SystemAuthRepo missing godoc 24 //go:generate mockery --name=SystemAuthRepo --output=automock --outpkg=automock --case=underscore --disable-version-string 25 type SystemAuthRepo interface { 26 ListGlobalWithConditions(ctx context.Context, conditions repo.Conditions) ([]model.SystemAuth, error) 27 } 28 29 // OAuthService missing godoc 30 //go:generate mockery --name=OAuthService --output=automock --outpkg=automock --case=underscore --disable-version-string 31 type OAuthService interface { 32 ListClients() ([]*models.OAuth2Client, error) 33 UpdateClient(ctx context.Context, clientID string, objectType model.SystemAuthReferenceObjectType) error 34 GetClientDetails(objType model.SystemAuthReferenceObjectType) (*oauth20.ClientDetails, error) 35 } 36 37 type service struct { 38 oAuth20Svc OAuthService 39 transact persistence.Transactioner 40 repo SystemAuthRepo 41 } 42 43 // NewService missing godoc 44 func NewService(oAuth20Svc OAuthService, transact persistence.Transactioner, repo SystemAuthRepo) SyncService { 45 return &service{ 46 oAuth20Svc: oAuth20Svc, 47 transact: transact, 48 repo: repo, 49 } 50 } 51 52 // SynchronizeClientScopes missing godoc 53 func (s *service) SynchronizeClientScopes(ctx context.Context) error { 54 hydraClients, err := s.listHydraClients() 55 if err != nil { 56 return err 57 } 58 59 auths, err := s.systemAuthsWithOAuth(ctx) 60 if err != nil { 61 return err 62 } 63 64 areAllClientsUpdated := true 65 for _, auth := range auths { 66 log.C(ctx).Infof("Synchronizing oauth client of system auth with ID %s", auth.ID) 67 if auth.Value == nil || auth.Value.Credential.Oauth == nil { 68 log.C(ctx).Infof("System auth with ID %s does not have oauth client for update", auth.ID) 69 continue 70 } 71 72 clientID := auth.Value.Credential.Oauth.ClientID 73 74 objType, err := auth.GetReferenceObjectType() 75 if err != nil { 76 areAllClientsUpdated = false 77 log.C(ctx).WithError(err).Errorf("Error while getting obj type of client with ID %s: %v", clientID, err) 78 continue 79 } 80 81 requiredClientDetails, err := s.oAuth20Svc.GetClientDetails(objType) 82 if err != nil { 83 areAllClientsUpdated = false 84 log.C(ctx).WithError(err).Errorf("Error while getting client credentials scopes for client with ID %s: %v", clientID, err) 85 continue 86 } 87 88 clientDetails, ok := hydraClients[clientID] 89 if !ok { 90 log.C(ctx).Errorf("Client with ID %s is not present in Hydra", clientID) 91 continue 92 } 93 if str.Matches(clientDetails.Scopes, requiredClientDetails.Scopes) && str.Matches(clientDetails.GrantTypes, requiredClientDetails.GrantTypes) { 94 log.C(ctx).Infof("Scopes and grant types for client with ID %s and type %s are in sync", clientID, objType) 95 continue 96 } 97 98 if err = s.oAuth20Svc.UpdateClient(ctx, clientID, objType); err != nil { 99 areAllClientsUpdated = false 100 log.C(ctx).WithError(err).Errorf("Error while updating scopes of client with ID %s: %v", clientID, err) 101 } 102 } 103 if !areAllClientsUpdated { 104 return errors.New("Not all clients were updated successfully") 105 } 106 107 log.C(ctx).Info("Finished synchronization of Hydra scopes") 108 return nil 109 } 110 111 func (s *service) listHydraClients() (map[string]*oauth20.ClientDetails, error) { 112 clients, err := s.oAuth20Svc.ListClients() 113 if err != nil { 114 return nil, errors.Wrap(err, "while listing clients from hydra") 115 } 116 117 clientsMap := make(map[string]*oauth20.ClientDetails) 118 for _, c := range clients { 119 clientsMap[c.ClientID] = &oauth20.ClientDetails{ 120 Scopes: strings.Split(c.Scope, " "), 121 GrantTypes: c.GrantTypes, 122 } 123 } 124 return clientsMap, nil 125 } 126 127 func (s *service) systemAuthsWithOAuth(ctx context.Context) ([]model.SystemAuth, error) { 128 tx, err := s.transact.Begin() 129 if err != nil { 130 return nil, errors.Wrap(err, "while opening database transaction") 131 } 132 defer s.transact.RollbackUnlessCommitted(ctx, tx) 133 ctx = persistence.SaveToContext(ctx, tx) 134 135 conditions := repo.Conditions{ 136 repo.NewNotEqualCondition("(value -> 'Credential' -> 'Oauth')", "null"), 137 } 138 auths, err := s.repo.ListGlobalWithConditions(ctx, conditions) 139 if err != nil { 140 return nil, err 141 } 142 143 if err := tx.Commit(); err != nil { 144 return nil, errors.Wrap(err, "while database transaction commit") 145 } 146 147 return auths, nil 148 }