github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/bundleinstanceauth/service.go (about) 1 package bundleinstanceauth 2 3 import ( 4 "context" 5 6 "github.com/kyma-incubator/compass/components/director/pkg/consumer" 7 "github.com/kyma-incubator/compass/components/director/pkg/log" 8 9 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 10 11 "github.com/kyma-incubator/compass/components/director/internal/domain/tenant" 12 "github.com/kyma-incubator/compass/components/director/internal/model" 13 "github.com/kyma-incubator/compass/components/director/internal/timestamp" 14 "github.com/kyma-incubator/compass/components/director/pkg/jsonschema" 15 "github.com/pkg/errors" 16 ) 17 18 // Repository missing godoc 19 //go:generate mockery --name=Repository --output=automock --outpkg=automock --case=underscore --disable-version-string 20 type Repository interface { 21 Create(ctx context.Context, item *model.BundleInstanceAuth) error 22 GetByID(ctx context.Context, tenantID string, id string) (*model.BundleInstanceAuth, error) 23 GetForBundle(ctx context.Context, tenant string, id string, bundleID string) (*model.BundleInstanceAuth, error) 24 ListByBundleID(ctx context.Context, tenantID string, bundleID string) ([]*model.BundleInstanceAuth, error) 25 ListByRuntimeID(ctx context.Context, tenantID string, runtimeID string) ([]*model.BundleInstanceAuth, error) 26 Update(ctx context.Context, tenant string, item *model.BundleInstanceAuth) error 27 Delete(ctx context.Context, tenantID string, id string) error 28 } 29 30 // UIDService missing godoc 31 //go:generate mockery --name=UIDService --output=automock --outpkg=automock --case=underscore --disable-version-string 32 type UIDService interface { 33 Generate() string 34 } 35 36 type service struct { 37 repo Repository 38 uidService UIDService 39 timestampGen timestamp.Generator 40 } 41 42 // NewService missing godoc 43 func NewService(repo Repository, uidService UIDService) *service { 44 return &service{ 45 repo: repo, 46 uidService: uidService, 47 timestampGen: timestamp.DefaultGenerator, 48 } 49 } 50 51 // Create missing godoc 52 func (s *service) Create(ctx context.Context, bundleID string, in model.BundleInstanceAuthRequestInput, defaultAuth *model.Auth, requestInputSchema *string) (string, error) { 53 tnt, err := tenant.LoadFromContext(ctx) 54 if err != nil { 55 return "", err 56 } 57 58 log.C(ctx).Debugf("Validating BundleInstanceAuth request input for Bundle with id %s", bundleID) 59 if err = validateInputParamsAgainstSchema(in.InputParams, requestInputSchema); err != nil { 60 return "", errors.Wrapf(err, "while validating BundleInstanceAuth request input for Bundle with id %s", bundleID) 61 } 62 63 con, err := consumer.LoadFromContext(ctx) 64 if err != nil { 65 return "", err 66 } 67 68 var runtimeID *string 69 if con.ConsumerType == consumer.Runtime || con.ConsumerType == consumer.ExternalCertificate { 70 runtimeID = &con.ConsumerID 71 } 72 73 id := s.uidService.Generate() 74 log.C(ctx).Debugf("ID %s generated for BundleInstanceAuth for Bundle with id %s", id, bundleID) 75 bndlInstAuth := in.ToBundleInstanceAuth(id, bundleID, tnt, defaultAuth, nil, runtimeID, nil) 76 77 err = s.setCreationStatusFromAuth(ctx, &bndlInstAuth, defaultAuth) 78 if err != nil { 79 return "", errors.Wrapf(err, "while setting creation status for BundleInstanceAuth with id %s", id) 80 } 81 82 err = s.repo.Create(ctx, &bndlInstAuth) 83 if err != nil { 84 return "", errors.Wrapf(err, "while creating BundleInstanceAuth with id %s for Bundle with id %s", id, bundleID) 85 } 86 87 return id, nil 88 } 89 90 // CreateBundleInstanceAuth creates a BundleInstanceAuth for a Bundle with id - bundleID from a given input 91 func (s *service) CreateBundleInstanceAuth(ctx context.Context, bundleID string, in model.BundleInstanceAuthCreateInput, requestInputSchema *string) (string, error) { 92 tnt, err := tenant.LoadFromContext(ctx) 93 if err != nil { 94 return "", err 95 } 96 97 log.C(ctx).Debugf("Validating BundleInstanceAuth request input for Bundle with id %q", bundleID) 98 if err = validateInputParamsAgainstSchema(in.InputParams, requestInputSchema); err != nil { 99 return "", errors.Wrapf(err, "while validating BundleInstanceAuth request input for Bundle with id %q", bundleID) 100 } 101 102 id := s.uidService.Generate() 103 log.C(ctx).Debugf("ID %q generated for BundleInstanceAuth for Bundle with id %q", id, bundleID) 104 bndlInstAuth := in.ToBundleInstanceAuth(id, bundleID, tnt, nil) 105 106 // Always create bundle instance auth with status SUCCEEDED 107 if err = bndlInstAuth.SetDefaultStatus(model.BundleInstanceAuthStatusConditionSucceeded, s.timestampGen()); err != nil { 108 return "", err 109 } 110 111 if err = s.repo.Create(ctx, &bndlInstAuth); err != nil { 112 return "", errors.Wrapf(err, "while creating BundleInstanceAuth with id %s for Bundle with id %s", id, bundleID) 113 } 114 115 return id, nil 116 } 117 118 // Get missing godoc 119 func (s *service) Get(ctx context.Context, id string) (*model.BundleInstanceAuth, error) { 120 tnt, err := tenant.LoadFromContext(ctx) 121 if err != nil { 122 return nil, err 123 } 124 125 instanceAuth, err := s.repo.GetByID(ctx, tnt, id) 126 if err != nil { 127 return nil, errors.Wrapf(err, "while getting BundleInstanceAuth with id %s", id) 128 } 129 130 return instanceAuth, nil 131 } 132 133 // GetForBundle missing godoc 134 func (s *service) GetForBundle(ctx context.Context, id string, bundleID string) (*model.BundleInstanceAuth, error) { 135 tnt, err := tenant.LoadFromContext(ctx) 136 if err != nil { 137 return nil, err 138 } 139 140 bndl, err := s.repo.GetForBundle(ctx, tnt, id, bundleID) 141 if err != nil { 142 return nil, errors.Wrapf(err, "while getting Bundle Instance Auth with ID: [%s]", id) 143 } 144 145 return bndl, nil 146 } 147 148 // List missing godoc 149 func (s *service) List(ctx context.Context, bundleID string) ([]*model.BundleInstanceAuth, error) { 150 tnt, err := tenant.LoadFromContext(ctx) 151 if err != nil { 152 return nil, err 153 } 154 155 bndlInstanceAuths, err := s.repo.ListByBundleID(ctx, tnt, bundleID) 156 if err != nil { 157 return nil, errors.Wrap(err, "while listing Bundle Instance Auths") 158 } 159 160 return bndlInstanceAuths, nil 161 } 162 163 // ListByRuntimeID missing godoc 164 func (s *service) ListByRuntimeID(ctx context.Context, runtimeID string) ([]*model.BundleInstanceAuth, error) { 165 tnt, err := tenant.LoadFromContext(ctx) 166 if err != nil { 167 return nil, err 168 } 169 170 bndlInstanceAuths, err := s.repo.ListByRuntimeID(ctx, tnt, runtimeID) 171 if err != nil { 172 return nil, errors.Wrap(err, "while listing Bundle Instance Auths") 173 } 174 175 return bndlInstanceAuths, nil 176 } 177 178 // Update missing godoc 179 func (s *service) Update(ctx context.Context, instanceAuth *model.BundleInstanceAuth) error { 180 tnt, err := tenant.LoadFromContext(ctx) 181 if err != nil { 182 return err 183 } 184 185 if err = s.repo.Update(ctx, tnt, instanceAuth); err != nil { 186 return errors.Wrap(err, "while updating Bundle Instance Auths") 187 } 188 189 return nil 190 } 191 192 // SetAuth missing godoc 193 func (s *service) SetAuth(ctx context.Context, id string, in model.BundleInstanceAuthSetInput) error { 194 tnt, err := tenant.LoadFromContext(ctx) 195 if err != nil { 196 return err 197 } 198 199 instanceAuth, err := s.repo.GetByID(ctx, tnt, id) 200 if err != nil { 201 return errors.Wrapf(err, "while getting BundleInstanceAuth with id %s", id) 202 } 203 if instanceAuth == nil { 204 return errors.Errorf("BundleInstanceAuth with id %s not found", id) 205 } 206 207 if instanceAuth.Status == nil || instanceAuth.Status.Condition != model.BundleInstanceAuthStatusConditionPending { 208 return apperrors.NewInvalidOperationError("auth can be set only on BundleInstanceAuths in PENDING state") 209 } 210 211 err = s.setUpdateAuthAndStatus(ctx, instanceAuth, in) 212 if err != nil { 213 return err 214 } 215 216 if err = s.repo.Update(ctx, tnt, instanceAuth); err != nil { 217 return errors.Wrapf(err, "while updating BundleInstanceAuth with ID %s", id) 218 } 219 return nil 220 } 221 222 // RequestDeletion missing godoc 223 func (s *service) RequestDeletion(ctx context.Context, instanceAuth *model.BundleInstanceAuth, defaultBundleInstanceAuth *model.Auth) (bool, error) { 224 tnt, err := tenant.LoadFromContext(ctx) 225 if err != nil { 226 return false, err 227 } 228 if instanceAuth == nil { 229 return false, apperrors.NewInternalError("BundleInstanceAuth is required to request its deletion") 230 } 231 232 if defaultBundleInstanceAuth == nil { 233 log.C(ctx).Debugf("Default credentials for BundleInstanceAuth with id %s are not provided.", instanceAuth.ID) 234 235 err := instanceAuth.SetDefaultStatus(model.BundleInstanceAuthStatusConditionUnused, s.timestampGen()) 236 if err != nil { 237 return false, errors.Wrapf(err, "while setting status of BundleInstanceAuth with id %s to '%s'", instanceAuth.ID, model.BundleInstanceAuthStatusConditionUnused) 238 } 239 log.C(ctx).Infof("Status for BundleInstanceAuth with id %s set to '%s'. Credentials are ready for being deleted by Application or Integration System.", instanceAuth.ID, model.BundleInstanceAuthStatusConditionUnused) 240 241 if err = s.repo.Update(ctx, tnt, instanceAuth); err != nil { 242 return false, errors.Wrapf(err, "while updating BundleInstanceAuth with id %s", instanceAuth.ID) 243 } 244 245 return false, nil 246 } 247 248 log.C(ctx).Debugf("Default credentials for BundleInstanceAuth with id %s are provided.", instanceAuth.ID) 249 if err = s.Delete(ctx, instanceAuth.ID); err != nil { 250 return false, err 251 } 252 253 return true, nil 254 } 255 256 // Delete missing godoc 257 func (s *service) Delete(ctx context.Context, id string) error { 258 tnt, err := tenant.LoadFromContext(ctx) 259 if err != nil { 260 return err 261 } 262 263 log.C(ctx).Debugf("Deleting BundleInstanceAuth entity with id %s in db", id) 264 err = s.repo.Delete(ctx, tnt, id) 265 266 return errors.Wrapf(err, "while deleting BundleInstanceAuth with id %s", id) 267 } 268 269 func (s *service) setUpdateAuthAndStatus(ctx context.Context, instanceAuth *model.BundleInstanceAuth, in model.BundleInstanceAuthSetInput) error { 270 if instanceAuth == nil { 271 return nil 272 } 273 274 ts := s.timestampGen() 275 276 instanceAuth.Auth = in.Auth.ToAuth() 277 instanceAuth.Status = in.Status.ToBundleInstanceAuthStatus(ts) 278 279 // Input validation ensures that status can be nil only when auth was provided, so we can assume SUCCEEDED status 280 if instanceAuth.Status == nil { 281 log.C(ctx).Infof("Updating the status of BundleInstanceAuth with id %s to '%s'", instanceAuth.ID, model.BundleInstanceAuthStatusConditionSucceeded) 282 err := instanceAuth.SetDefaultStatus(model.BundleInstanceAuthStatusConditionSucceeded, ts) 283 if err != nil { 284 return errors.Wrapf(err, "while setting status '%s' to BundleInstanceAuth with id %s", model.BundleInstanceAuthStatusConditionSucceeded, instanceAuth.ID) 285 } 286 } 287 288 return nil 289 } 290 291 func (s *service) setCreationStatusFromAuth(ctx context.Context, instanceAuth *model.BundleInstanceAuth, defaultAuth *model.Auth) error { 292 if instanceAuth == nil { 293 return nil 294 } 295 296 var condition model.BundleInstanceAuthStatusCondition 297 if defaultAuth != nil { 298 log.C(ctx).Infof("Default credentials for BundleInstanceAuth with id %s from Bundle with id %s are provided. Setting creation status to '%s'", instanceAuth.ID, instanceAuth.BundleID, model.BundleInstanceAuthStatusConditionSucceeded) 299 condition = model.BundleInstanceAuthStatusConditionSucceeded 300 } else { 301 log.C(ctx).Infof("Default credentials for BundleInstanceAuth with id %s from Bundle with id %s are not provided. Setting creation status to '%s'", instanceAuth.ID, instanceAuth.BundleID, model.BundleInstanceAuthStatusConditionPending) 302 condition = model.BundleInstanceAuthStatusConditionPending 303 } 304 305 err := instanceAuth.SetDefaultStatus(condition, s.timestampGen()) 306 return errors.Wrapf(err, "while setting default status for BundleInstanceAuth with id %s", instanceAuth.ID) 307 } 308 309 func validateInputParamsAgainstSchema(inputParams *string, schema *string) error { 310 if schema == nil { 311 return nil 312 } 313 if inputParams == nil { 314 return apperrors.NewInvalidDataError("json schema for input parameters was defined for the bundle but no input parameters were provided") 315 } 316 317 validator, err := jsonschema.NewValidatorFromStringSchema(*schema) 318 if err != nil { 319 return errors.Wrapf(err, "while creating JSON Schema validator for schema %+s", *schema) 320 } 321 322 result, err := validator.ValidateString(*inputParams) 323 if err != nil { 324 return errors.Wrapf(err, "while validating value %s against JSON Schema: %s", *inputParams, *schema) 325 } 326 if !result.Valid { 327 return errors.Wrapf(result.Error, "while validating value %s against JSON Schema: %s", *inputParams, *schema) 328 } 329 330 return nil 331 }