Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(offersubscription): skip optional autosetupprovidercallback if it is not configured #865

Merged
merged 1 commit into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,11 @@ await _offerProviderService
}

return (
new[] {
[
data.IsSingleInstance ?
ProcessStepTypeId.SINGLE_INSTANCE_SUBSCRIPTION_DETAILS_CREATION :
ProcessStepTypeId.START_AUTOSETUP },
ProcessStepTypeId.START_AUTOSETUP
],
triggerProvider ? ProcessStepStatusId.DONE : ProcessStepStatusId.SKIPPED,
true,
null);
Expand All @@ -100,6 +101,15 @@ await _offerProviderService
throw new NotFoundException($"OfferSubscription {offerSubscriptionId} does not exist");
}

if (string.IsNullOrWhiteSpace(data.CallbackUrl))
{
return (
null,
ProcessStepStatusId.SKIPPED,
true,
null);
}

if (data.Status != OfferSubscriptionStatusId.ACTIVE)
{
throw new ConflictException("offer subscription should be active");
Expand All @@ -110,11 +120,6 @@ await _offerProviderService
throw new ConflictException("Client should be set");
}

if (string.IsNullOrWhiteSpace(data.CallbackUrl))
{
throw new ConflictException("Callback Url should be set here");
}

if (data.ServiceAccounts.Count() > 1)
{
throw new ConflictException("There should be not more than one service account for the offer subscription");
Expand All @@ -123,16 +128,22 @@ await _offerProviderService
CallbackTechnicalUserInfoData? technicalUserInfoData = null;
if (data.ServiceAccounts.Count() == 1)
{
var serviceAccount = data.ServiceAccounts.FirstOrDefault();
var serviceAccount = data.ServiceAccounts.First();
if (serviceAccount.TechnicalClientId == null)
{
throw new ConflictException($"ClientId of serviceAccount {serviceAccount.TechnicalUserId} should be set");
}
var internalClientId = await _provisioningManager.GetIdOfCentralClientAsync(serviceAccount.TechnicalClientId).ConfigureAwait(ConfigureAwaitOptions.None);
var authData = await _provisioningManager.GetCentralClientAuthDataAsync(internalClientId).ConfigureAwait(ConfigureAwaitOptions.None);
async Task<string?> GetServiceAccountSecret(string technicalClientId)
{
var internalClientId = await _provisioningManager.GetIdOfCentralClientAsync(technicalClientId).ConfigureAwait(ConfigureAwaitOptions.None);
var authData = await _provisioningManager.GetCentralClientAuthDataAsync(internalClientId).ConfigureAwait(ConfigureAwaitOptions.None);
return authData.Secret;
}
technicalUserInfoData = new CallbackTechnicalUserInfoData(
serviceAccount.TechnicalUserId,
authData.Secret,
serviceAccount.CompanyServiceAccountKindId == CompanyServiceAccountKindId.INTERNAL
? await GetServiceAccountSecret(serviceAccount.TechnicalClientId).ConfigureAwait(ConfigureAwaitOptions.None)
: null,
serviceAccount.TechnicalClientId);
}

Expand All @@ -141,7 +152,7 @@ await _offerProviderService
new CallbackClientInfoData(data.ClientId)
);
await _offerProviderService
.TriggerOfferProviderCallback(callbackData, data.CallbackUrl!, cancellationToken)
.TriggerOfferProviderCallback(callbackData, data.CallbackUrl, cancellationToken)
.ConfigureAwait(ConfigureAwaitOptions.None);

return (
Expand Down
4 changes: 2 additions & 2 deletions src/marketplace/Offers.Library/Service/OfferSetupService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ public async Task TriggerActivateSubscription(Guid offerSubscriptionId)
if (string.IsNullOrWhiteSpace(offerDetails.RequesterEmail))
{
return new ValueTuple<IEnumerable<ProcessStepTypeId>?, ProcessStepStatusId, bool, string?>(
offerDetails.InstanceData.IsSingleInstance ? null : new[] { ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK },
offerDetails.InstanceData.IsSingleInstance || !offerDetails.HasCallbackUrl ? null : [ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK],
ProcessStepStatusId.DONE,
true,
null);
Expand All @@ -687,7 +687,7 @@ public async Task TriggerActivateSubscription(Guid offerSubscriptionId)
SendMail(basePortalAddress, $"{offerDetails.RequesterFirstname} {offerDetails.RequesterLastname}", offerDetails.RequesterEmail, offerDetails.OfferName, offerDetails.OfferTypeId);

return new ValueTuple<IEnumerable<ProcessStepTypeId>?, ProcessStepStatusId, bool, string?>(
offerDetails.InstanceData.IsSingleInstance ? null : new[] { ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK },
offerDetails.InstanceData.IsSingleInstance || !offerDetails.HasCallbackUrl ? null : [ProcessStepTypeId.TRIGGER_PROVIDER_CALLBACK],
ProcessStepStatusId.DONE,
true,
null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ public record SubscriptionActivationData(
Guid? SalesManagerId,
Guid? ProviderCompanyId,
string? ClientClientId,
IEnumerable<string> InternalServiceAccountClientIds
IEnumerable<string> InternalServiceAccountClientIds,
bool HasCallbackUrl
);
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ public interface IOfferSubscriptionsRepository
Task<VerifyProcessData?> GetProcessStepData(Guid offerSubscriptionId, IEnumerable<ProcessStepTypeId> processStepTypeIds);
Task<OfferSubscriptionClientCreationData?> GetClientCreationData(Guid offerSubscriptionId);
Task<OfferSubscriptionTechnicalUserCreationData?> GetTechnicalUserCreationData(Guid offerSubscriptionId);
Task<(IEnumerable<(Guid TechnicalUserId, string? TechnicalClientId)> ServiceAccounts, string? ClientId, string? CallbackUrl, OfferSubscriptionStatusId Status)> GetTriggerProviderCallbackInformation(Guid offerSubscriptionId);
Task<(IEnumerable<(Guid TechnicalUserId, string? TechnicalClientId, CompanyServiceAccountKindId CompanyServiceAccountKindId)> ServiceAccounts, string? ClientId, string? CallbackUrl, OfferSubscriptionStatusId Status)> GetTriggerProviderCallbackInformation(Guid offerSubscriptionId);
OfferSubscriptionProcessData CreateOfferSubscriptionProcessData(Guid offerSubscriptionId, string offerUrl);
void RemoveOfferSubscriptionProcessData(Guid offerSubscriptionProcessDataId);
IAsyncEnumerable<ProcessStepData> GetProcessStepsForSubscription(Guid offerSubscriptionId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,8 @@ public Task<Guid> GetOfferSubscriptionDataForProcessIdAsync(Guid processId) =>
x.Offer.OfferTypeId == OfferTypeId.APP && (x.Offer.AppInstanceSetup == null || !x.Offer.AppInstanceSetup!.IsSingleInstance) ?
x.AppSubscriptionDetail!.AppInstance!.IamClient!.ClientClientId :
null,
x.CompanyServiceAccounts.Where(sa => sa.CompanyServiceAccountKindId == CompanyServiceAccountKindId.INTERNAL && sa.ClientClientId != null).Select(sa => sa.ClientClientId!)
x.CompanyServiceAccounts.Where(sa => sa.CompanyServiceAccountKindId == CompanyServiceAccountKindId.INTERNAL && sa.ClientClientId != null).Select(sa => sa.ClientClientId!),
x.Offer.ProviderCompany!.ProviderCompanyDetail!.AutoSetupCallbackUrl != null
))
.SingleOrDefaultAsync();

Expand Down Expand Up @@ -451,11 +452,11 @@ public Task<Guid> GetOfferSubscriptionDataForProcessIdAsync(Guid processId) =>
.SingleOrDefaultAsync();

/// <inheritdoc />
public Task<(IEnumerable<(Guid TechnicalUserId, string? TechnicalClientId)> ServiceAccounts, string? ClientId, string? CallbackUrl, OfferSubscriptionStatusId Status)> GetTriggerProviderCallbackInformation(Guid offerSubscriptionId) =>
public Task<(IEnumerable<(Guid TechnicalUserId, string? TechnicalClientId, CompanyServiceAccountKindId CompanyServiceAccountKindId)> ServiceAccounts, string? ClientId, string? CallbackUrl, OfferSubscriptionStatusId Status)> GetTriggerProviderCallbackInformation(Guid offerSubscriptionId) =>
_context.OfferSubscriptions
.Where(x => x.Id == offerSubscriptionId)
.Select(x => new ValueTuple<IEnumerable<(Guid, string?)>, string?, string?, OfferSubscriptionStatusId>(
x.CompanyServiceAccounts.Select(sa => new ValueTuple<Guid, string?>(sa.Id, sa.ClientClientId)),
.Select(x => new ValueTuple<IEnumerable<(Guid, string?, CompanyServiceAccountKindId)>, string?, string?, OfferSubscriptionStatusId>(
x.CompanyServiceAccounts.Select(sa => new ValueTuple<Guid, string?, CompanyServiceAccountKindId>(sa.Id, sa.ClientClientId, sa.CompanyServiceAccountKindId)),
x.AppSubscriptionDetail!.AppInstance!.IamClient!.ClientClientId,
x.Offer!.ProviderCompany!.ProviderCompanyDetail!.AutoSetupCallbackUrl,
x.OfferSubscriptionStatusId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public async Task TriggerProviderCallback_InvalidSubscriptionId_Throws()
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns<(IEnumerable<(Guid, string?)>, string?, string?, OfferSubscriptionStatusId)>(default);
.Returns<(IEnumerable<(Guid, string?, CompanyServiceAccountKindId)>, string?, string?, OfferSubscriptionStatusId)>(default);
async Task Act() => await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);

// Act
Expand All @@ -159,7 +159,7 @@ public async Task TriggerProviderCallback_WithPendingSubscription_Throws()
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((Enumerable.Empty<(Guid, string?)>(), string.Empty, null, OfferSubscriptionStatusId.PENDING));
.Returns((Enumerable.Empty<(Guid, string?, CompanyServiceAccountKindId)>(), string.Empty, "callback", OfferSubscriptionStatusId.PENDING));
async Task Act() => await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);

// Act
Expand All @@ -175,7 +175,7 @@ public async Task TriggerProviderCallback_WithClientIdNotSet_Throws()
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((Enumerable.Empty<(Guid, string?)>(), null, null, OfferSubscriptionStatusId.ACTIVE));
.Returns((Enumerable.Empty<(Guid, string?, CompanyServiceAccountKindId)>(), null, "callback", OfferSubscriptionStatusId.ACTIVE));
async Task Act() => await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);

// Act
Expand All @@ -186,19 +186,19 @@ public async Task TriggerProviderCallback_WithClientIdNotSet_Throws()
}

[Fact]
public async Task TriggerProviderCallback_WithCallbackUrlNotSet_Throws()
public async Task TriggerProviderCallback_WithCallbackUrlNotSet_Skips()
{
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((Enumerable.Empty<(Guid, string?)>(), "cl1", null, OfferSubscriptionStatusId.ACTIVE));
async Task Act() => await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);
.Returns((Enumerable.Empty<(Guid, string?, CompanyServiceAccountKindId)>(), "cl1", null, OfferSubscriptionStatusId.ACTIVE));

// Act
var ex = await Assert.ThrowsAsync<ConflictException>(Act);
var result = await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);

// Assert
ex.Message.Should().Be("Callback Url should be set here");
result.nextStepTypeIds.Should().BeNull();
result.stepStatusId.Should().Be(ProcessStepStatusId.SKIPPED);
}

[Fact]
Expand All @@ -207,7 +207,7 @@ public async Task TriggerProviderCallback_WithNoServiceAccountSet_CallsExpected(
// Arrange
var fakeId = Guid.NewGuid();
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((Enumerable.Empty<(Guid, string?)>(), "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));
.Returns((Enumerable.Empty<(Guid, string?, CompanyServiceAccountKindId)>(), "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));

// Act
var result = await _sut.TriggerProviderCallback(fakeId, CancellationToken.None);
Expand All @@ -226,10 +226,10 @@ public async Task TriggerProviderCallback_WithMultipleServiceAccountSet_Throws()
{
// Arrange
var fakeId = Guid.NewGuid();
var serviceAccounts = new (Guid, string?)[]
var serviceAccounts = new (Guid, string?, CompanyServiceAccountKindId)[]
{
new(Guid.NewGuid(), "sa1"),
new(Guid.NewGuid(), "sa2")
new(Guid.NewGuid(), "sa1", CompanyServiceAccountKindId.INTERNAL),
new(Guid.NewGuid(), "sa2", CompanyServiceAccountKindId.INTERNAL)
};
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(fakeId))
.Returns((serviceAccounts, "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));
Expand All @@ -243,15 +243,15 @@ public async Task TriggerProviderCallback_WithMultipleServiceAccountSet_Throws()
}

[Fact]
public async Task TriggerProviderCallback_WithValidData_ReturnsExpected()
public async Task TriggerProviderCallback_WithValidData_InternalSA_ReturnsExpected()
{
// Arrange
var technicalUserId = Guid.NewGuid();
var technicalUserClientId = "sa1";
var technicalUserInternalClientId = Guid.NewGuid().ToString();
var serviceAccounts = new (Guid, string?)[]
var serviceAccounts = new (Guid, string?, CompanyServiceAccountKindId)[]
{
new(technicalUserId, technicalUserClientId)
new(technicalUserId, technicalUserClientId, CompanyServiceAccountKindId.INTERNAL)
};
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(_subscriptionId))
.Returns((serviceAccounts, "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));
Expand All @@ -271,6 +271,34 @@ public async Task TriggerProviderCallback_WithValidData_ReturnsExpected()
.MustHaveHappenedOnceExactly();
}

[Fact]
public async Task TriggerProviderCallback_WithValidData_ExternalSA_ReturnsExpected()
{
// Arrange
var technicalUserId = Guid.NewGuid();
var technicalUserClientId = "sa1";
var serviceAccounts = new (Guid, string?, CompanyServiceAccountKindId)[]
{
new(technicalUserId, technicalUserClientId, CompanyServiceAccountKindId.EXTERNAL)
};
A.CallTo(() => _offerSubscriptionRepository.GetTriggerProviderCallbackInformation(_subscriptionId))
.Returns((serviceAccounts, "cl1", "https://callback.com", OfferSubscriptionStatusId.ACTIVE));

// Act
var result = await _sut.TriggerProviderCallback(_subscriptionId, CancellationToken.None);

// Assert
result.nextStepTypeIds.Should().BeNull();
result.stepStatusId.Should().Be(ProcessStepStatusId.DONE);
result.modified.Should().BeTrue();
A.CallTo(() => _provisioningManager.GetIdOfCentralClientAsync(A<string>._))
.MustNotHaveHappened();
A.CallTo(() => _provisioningManager.GetCentralClientAuthDataAsync(A<string>._))
.MustNotHaveHappened();
A.CallTo(() => _offerProviderService.TriggerOfferProviderCallback(A<OfferProviderCallbackData>.That.Matches(x => x.TechnicalUserInfo!.TechnicalUserSecret == null), A<string>._, A<CancellationToken>._))
.MustHaveHappenedOnceExactly();
}

#endregion

#region Setup
Expand Down
Loading
Loading