Skip to content

Commit

Permalink
Fix NullReferenceException when using a gateway before instance is cr…
Browse files Browse the repository at this point in the history
…eated (#848)
  • Loading branch information
chrrust authored Oct 18, 2024
1 parent ffda2c4 commit 531a4f3
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 15 deletions.
43 changes: 29 additions & 14 deletions src/Altinn.App.Core/Internal/Data/CachedInstanceDataAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ namespace Altinn.App.Core.Internal.Data;
internal sealed class CachedInstanceDataAccessor : IInstanceDataMutator
{
// DataClient needs a few arguments to fetch data
private readonly string _org;
private readonly string _app;
private readonly Guid _instanceGuid;
private readonly int _instanceOwnerPartyId;

Expand Down Expand Up @@ -60,12 +58,13 @@ public CachedInstanceDataAccessor(
ModelSerializationService modelSerializationService
)
{
var splitApp = instance.AppId.Split("/");
_org = splitApp[0];
_app = splitApp[1];
var splitId = instance.Id.Split("/");
_instanceOwnerPartyId = int.Parse(splitId[0], CultureInfo.InvariantCulture);
_instanceGuid = Guid.Parse(splitId[1]);
if (instance.Id is not null)
{
var splitId = instance.Id.Split("/");
_instanceOwnerPartyId = int.Parse(splitId[0], CultureInfo.InvariantCulture);
_instanceGuid = Guid.Parse(splitId[1]);
}

Instance = instance;
_dataClient = dataClient;
_appMetadata = appMetadata;
Expand Down Expand Up @@ -93,18 +92,27 @@ public async Task<object> GetFormData(DataElementIdentifier dataElementIdentifie
}

/// <inheritdoc />
public async Task<ReadOnlyMemory<byte>> GetBinaryData(DataElementIdentifier dataElementIdentifier) =>
await _binaryCache.GetOrCreate(
public async Task<ReadOnlyMemory<byte>> GetBinaryData(DataElementIdentifier dataElementIdentifier)
{
if (_instanceOwnerPartyId == 0 || _instanceGuid == Guid.Empty)
{
throw new InvalidOperationException("Cannot access instance data before it has been created");
}

var appMetadata = await _appMetadata.GetApplicationMetadata();

return await _binaryCache.GetOrCreate(
dataElementIdentifier,
async () =>
await _dataClient.GetDataBytes(
_org,
_app,
appMetadata.AppIdentifier.Org,
appMetadata.AppIdentifier.App,
_instanceOwnerPartyId,
_instanceGuid,
dataElementIdentifier.Guid
)
);
}

/// <inheritdoc />
public DataElement GetDataElement(DataElementIdentifier dataElementIdentifier)
Expand Down Expand Up @@ -230,6 +238,11 @@ public List<DataElementChange> GetDataElementChanges(bool initializeAltinnRowId)

internal async Task UpdateInstanceData(List<DataElementChange> changes)
{
if (_instanceOwnerPartyId == 0 || _instanceGuid == Guid.Empty)
{
throw new InvalidOperationException("Cannot access instance data before it has been created");
}

var tasks = new List<Task>();
ConcurrentBag<DataElement> createdDataElements = new();
// We need to create data elements here, so that we can set them correctly on the instance
Expand Down Expand Up @@ -258,14 +271,16 @@ async Task InsertBinaryData()
tasks.Add(InsertBinaryData());
}

var appMetadata = await _appMetadata.GetApplicationMetadata();

// Delete data elements
foreach (var dataElementId in _dataElementsToDelete)
{
async Task DeleteData()
{
await _dataClient.DeleteData(
_org,
_app,
appMetadata.AppIdentifier.Org,
appMetadata.AppIdentifier.App,
_instanceOwnerPartyId,
_instanceGuid,
dataElementId.Guid,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Altinn.App.Core.Internal.Process.Elements;
using Altinn.App.Core.Internal.Process.ProcessTasks;
using Altinn.App.Core.Internal.Profile;
using Altinn.App.Core.Models;
using Altinn.App.Core.Models.Process;
using Altinn.App.Core.Models.UserAction;
using Altinn.Platform.Profile.Models;
Expand Down Expand Up @@ -457,6 +458,7 @@ public async Task Next_returns_unsuccessful_unauthorized_when_action_handler_ret
[Fact]
public async Task Next_moves_instance_to_next_task_and_produces_instanceevents()
{
_appMetadataMock.Setup(x => x.GetApplicationMetadata()).ReturnsAsync(new ApplicationMetadata("org/app"));
var expectedInstance = new Instance()
{
Id = _instanceId,
Expand Down Expand Up @@ -604,6 +606,7 @@ public async Task Next_moves_instance_to_next_task_and_produces_instanceevents()
[Fact]
public async Task Next_moves_instance_to_next_task_and_produces_abandon_instanceevent_when_action_reject()
{
_appMetadataMock.Setup(x => x.GetApplicationMetadata()).ReturnsAsync(new ApplicationMetadata("org/app"));
var expectedInstance = new Instance()
{
Id = _instanceId,
Expand Down Expand Up @@ -752,6 +755,7 @@ public async Task Next_moves_instance_to_next_task_and_produces_abandon_instance
[Fact]
public async Task Next_moves_instance_to_end_event_and_ends_proces()
{
_appMetadataMock.Setup(x => x.GetApplicationMetadata()).ReturnsAsync(new ApplicationMetadata("org/app"));
var expectedInstance = new Instance()
{
Id = _instanceId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public async Task Finalize_WithValidInputs_ShouldCallCorrectMethods()
await _processTaskFinalizer.Finalize(instance.Process.CurrentTask.ElementId, instance);

// Assert
_appMetadataMock.Verify(x => x.GetApplicationMetadata(), Times.Once);
// Called once in Finalize and once in CachedInstanceDataAccessor.UpdateInstanceData
_appMetadataMock.Verify(x => x.GetApplicationMetadata(), Times.Exactly(2));
}
}

0 comments on commit 531a4f3

Please sign in to comment.