Skip to content

Commit

Permalink
Lagt til dynamiske felter for manifestfil (#575)
Browse files Browse the repository at this point in the history
* Lagt til dynamiske felter for manifestfil

* Ny collection og håndtering av UseManifestFileShim

* Lagt til forslag fra code rabbit

* Første utkast endringer

* Feilmelding fiks

* Oppdatert logikk for exception

* Lagt til validering i resourceExt

* Lagt til sjekk for nullverdi

---------

Co-authored-by: Martin Todorov <>
  • Loading branch information
mSunberg authored Nov 7, 2024
1 parent e070ea0 commit 5d41543
Show file tree
Hide file tree
Showing 15 changed files with 125 additions and 17 deletions.
4 changes: 2 additions & 2 deletions altinn-broker-postman-collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -860,7 +860,7 @@
],
"body": {
"mode": "raw",
"raw": "{\r\n \"resourceId\": \"{{resourceId}}\",\r\n \"maxFileTransferSize\": \"1073741824\",\r\n \"fileTransferTimeToLive\": \"PT2H\",\r\n \"purgeFileTransferAfterAllRecipientsConfirmed\" : false,\r\n \"purgeFileTransferGracePeriod\": \"PT14H\",\r\n \"useManifestFileShim\": false\r\n}",
"raw": "{\r\n \"resourceId\": \"{{resourceId}}\",\r\n \"maxFileTransferSize\": \"1112391230\",\r\n \"fileTransferTimeToLive\": \"PT2H\",\r\n \"PurgeFileTransferAfterAllRecipientsConfirmed\" : false,\r\n \"purgeFileTransferGracePeriod\": \"PT14H\",\r\n \"ExternalServiceCodeLegacy\": \"\",\r\n \"ExternalServiceEditionCodeLegacy\": \"\",\r\n \"UseManifestFileShim\": false\r\n}",
"options": {
"raw": {
"language": "json"
Expand Down Expand Up @@ -1333,7 +1333,7 @@
}
}
],
"variable": [
"variable": [
{
"key": "serviceowner_orgnumber",
"value": "Organization number of service owner / \"tjeneste-eier\". Nine digits, no prefix.",
Expand Down
4 changes: 3 additions & 1 deletion src/Altinn.Broker.API/Controllers/ResourceController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ public async Task<ActionResult> ConfigureResource(string resourceId, [FromBody]
FileTransferTimeToLive = resourceExt.FileTransferTimeToLive,
PurgeFileTransferAfterAllRecipientsConfirmed = resourceExt.PurgeFileTransferAfterAllRecipientsConfirmed,
PurgeFileTransferGracePeriod = resourceExt.PurgeFileTransferGracePeriod,
UseManifestFileShim = resourceExt.UseManifestFileShim
UseManifestFileShim = resourceExt.UseManifestFileShim,
ExternalServiceCodeLegacy = resourceExt.ExternalServiceCodeLegacy,
ExternalServiceEditionCodeLegacy = resourceExt.ExternalServiceEditionCodeLegacy
}, cancellationToken);

return result.Match(
Expand Down
32 changes: 32 additions & 0 deletions src/Altinn.Broker.API/Helpers/ValidateUseManifestFileShim.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.ComponentModel.DataAnnotations;

namespace Altinn.Broker.Helpers
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class ValidateUseManifestFileShim : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var useManifestFileShimProperty = validationContext.ObjectType.GetProperty("UseManifestFileShim");
var externalServiceCodeLegacyProperty = validationContext.ObjectType.GetProperty("ExternalServiceCodeLegacy");
var externalServiceEditionCodeLegacyProperty = validationContext.ObjectType.GetProperty("ExternalServiceEditionCodeLegacy");
var useManifestFileShimValue = (bool?)useManifestFileShimProperty.GetValue(validationContext.ObjectInstance, null);
var externalServiceCodeLegacyValue = externalServiceCodeLegacyProperty.GetValue(validationContext.ObjectInstance, null);
var externalServiceEditionCodeLegacyValue = externalServiceEditionCodeLegacyProperty.GetValue(validationContext.ObjectInstance, null);

if (useManifestFileShimValue == true)
{
if (externalServiceCodeLegacyValue == null || (externalServiceCodeLegacyValue is string strValue && string.IsNullOrEmpty(strValue)))
{
return new ValidationResult("ExternalServiceCodeLegacy must be set and not be an empty string.");
}

if (externalServiceEditionCodeLegacyValue == null || (externalServiceEditionCodeLegacyValue is int intValue && intValue == 0))
{
return new ValidationResult("ExternalServiceEditionCodeLegacy must be set and not be zero.");
}
}
return ValidationResult.Success;
}
}
}
10 changes: 10 additions & 0 deletions src/Altinn.Broker.API/Models/ResourceExt.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using System.Text.Json.Serialization;

using Altinn.Broker.Helpers;

namespace Altinn.Broker.Models;

/// <summary>
/// API input model for file initialization.
/// </summary>
[ValidateUseManifestFileShim]

public class ResourceExt
{

Expand Down Expand Up @@ -37,4 +41,10 @@ public class ResourceExt
/// </summary>
[JsonPropertyName("useManifestFileShim")]
public bool? UseManifestFileShim { get; set; }

[JsonPropertyName("externalServiceCodeLegacy")]
public string? ExternalServiceCodeLegacy { get; set; }

[JsonPropertyName("externalServiceEditionCodeLegacy")]
public int? ExternalServiceEditionCodeLegacy { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ public async Task<OneOf<Task, Error>> Process(ConfigureResourceRequest request,
if (request.UseManifestFileShim is not null)
{
var updateManifestFileShimResult = await UpdateUseManifestFileShim(resource, request.UseManifestFileShim.Value, cancellationToken);
await resourceRepository.UpdateExternalServiceCodeLegacy(resource.Id, request.ExternalServiceCodeLegacy, cancellationToken);
await resourceRepository.UpdateExternalServiceEditionCodeLegacy(resource.Id, request.ExternalServiceEditionCodeLegacy, cancellationToken);

if (updateManifestFileShimResult.IsT1)
{
return updateManifestFileShimResult.AsT1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public class ConfigureResourceRequest
public bool? PurgeFileTransferAfterAllRecipientsConfirmed { get; set; } = true;
public string? PurgeFileTransferGracePeriod { get; set; }
public bool? UseManifestFileShim { get; set; }
public string? ExternalServiceCodeLegacy { get; set; }
public int? ExternalServiceEditionCodeLegacy { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public async Task<OneOf<DownloadFileResponse, Error>> Process(DownloadFileReques
var fileBuffer = new byte[downloadStream.Length];
downloadStream.Read(fileBuffer, 0, fileBuffer.Length);
downloadStream = new ManifestDownloadStream(fileBuffer);
(downloadStream as ManifestDownloadStream)?.AddManifestFile(fileTransfer);
(downloadStream as ManifestDownloadStream)?.AddManifestFile(fileTransfer, resource);
}
await actorFileTransferStatusRepository.InsertActorFileTransferStatus(request.FileTransferId, ActorFileTransferStatus.DownloadStarted, request.Token.Consumer, cancellationToken);
return new DownloadFileResponse()
Expand Down
2 changes: 2 additions & 0 deletions src/Altinn.Broker.Core/Domain/ResourceEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ public class ResourceEntity
public bool PurgeFileTransferAfterAllRecipientsConfirmed { get; set; } = true;
public TimeSpan? PurgeFileTransferGracePeriod { get; set; }
public bool? UseManifestFileShim { get; set; }
public string? ExternalServiceCodeLegacy { get; set; }
public int? ExternalServiceEditionCodeLegacy { get; set; }
}
9 changes: 5 additions & 4 deletions src/Altinn.Broker.Core/Helpers/BrokerServiceManifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public BrokerServiceManifest()
public string ExternalServiceCode { get; set; }

[XmlElement("ExternalServiceEditionCode")]
public string ExternalServiceEditionCode { get; set; }
public int? ExternalServiceEditionCode { get; set; }

[XmlElement("SendersReference")]
public string SendersReference { get; set; }
Expand Down Expand Up @@ -54,12 +54,13 @@ public class PropertyEntry

public static class BrokerServiceManifestExtensions
{
public static BrokerServiceManifest CreateManifest(this FileTransferEntity entity)
public static BrokerServiceManifest CreateManifest(this FileTransferEntity entity, ResourceEntity resource)
{
var manifest = new BrokerServiceManifest
{
ExternalServiceCode = entity.ResourceId,
ExternalServiceEditionCode = "Altinn3",

ExternalServiceCode = resource.UseManifestFileShim == true ? resource.ExternalServiceCodeLegacy : null,

Check warning on line 62 in src/Altinn.Broker.Core/Helpers/BrokerServiceManifest.cs

View workflow job for this annotation

GitHub Actions / QA / Test application

Possible null reference assignment.
ExternalServiceEditionCode = resource.UseManifestFileShim == true ? resource.ExternalServiceEditionCodeLegacy : null,
SendersReference = entity.SendersFileTransferReference,

Check warning on line 64 in src/Altinn.Broker.Core/Helpers/BrokerServiceManifest.cs

View workflow job for this annotation

GitHub Actions / QA / Test application

Possible null reference assignment.
Reportee = entity.RecipientCurrentStatuses.First().Actor.ActorExternalId,
SentDate = DateTime.UtcNow,
Expand Down
2 changes: 1 addition & 1 deletion src/Altinn.Broker.Core/Helpers/IManifestDownloadStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
namespace Altinn.Broker.Core.Helpers;
internal interface IManifestDownloadStream
{
Task AddManifestFile(FileTransferEntity fileTransferEntity);
Task AddManifestFile(FileTransferEntity fileTransferEntity, ResourceEntity resource);
}
4 changes: 2 additions & 2 deletions src/Altinn.Broker.Core/Helpers/ManifestDownloadStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ protected override void Dispose(bool disposing)
}


public async Task AddManifestFile(FileTransferEntity fileTransferEntity)
public async Task AddManifestFile(FileTransferEntity fileTransferEntity, ResourceEntity resource)
{
ValidateNotClosed();

Expand Down Expand Up @@ -226,7 +226,7 @@ public async Task AddManifestFile(FileTransferEntity fileTransferEntity)
var newManifestEntry = archive.CreateEntry("Manifest.xml");
using (var manifestStream = newManifestEntry.Open())
{
var manifest = fileTransferEntity.CreateManifest();
var manifest = fileTransferEntity.CreateManifest(resource);
WriteSerializeManifestToZip(manifest, manifestStream);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/Altinn.Broker.Core/Repositories/IResourceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ public interface IResourceRepository
Task UpdatePurgeFileTransferAfterAllRecipientsConfirmed(string resourceId, bool PurgeFileTransferAfterAllRecipientsConfirmed, CancellationToken cancellationToken = default);
Task UpdatePurgeFileTransferGracePeriod(string resourceId, TimeSpan PurgeFileTransferGracePeriod, CancellationToken cancellationToken = default);
Task UpdateUseManifestFileShim(string resourceId, bool useManifestFileShim, CancellationToken cancellationToken = default);
Task UpdateExternalServiceCodeLegacy(string resourceId, string externalServiceCodeLegacy, CancellationToken cancellationToken = default);
Task UpdateExternalServiceEditionCodeLegacy(string resourceId, int? externalServiceEditionCodeLegacy, CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ALTER TABLE broker.altinn_resource
ADD external_service_code_legacy varchar(7);
COMMENT ON COLUMN broker.altinn_resource.external_service_code_legacy IS 'Part of legacy solution';

ALTER TABLE broker.altinn_resource
ADD external_service_edition_code_legacy int;
COMMENT ON COLUMN broker.altinn_resource.external_service_edition_code_legacy IS 'Part of legacy solution';
26 changes: 24 additions & 2 deletions src/Altinn.Broker.Persistence/Repositories/ResourceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ResourceRepository(NpgsqlDataSource dataSource, IAltinnResourceRepo
public async Task<ResourceEntity?> GetResource(string resourceId, CancellationToken cancellationToken)
{
await using var command = dataSource.CreateCommand(
"SELECT resource_id_pk, organization_number, max_file_transfer_size, file_transfer_time_to_live, created, service_owner_id_fk, purge_file_transfer_after_all_recipients_confirmed, purge_file_transfer_grace_period, use_manifest_file_shim " +
"SELECT resource_id_pk, organization_number, max_file_transfer_size, file_transfer_time_to_live, created, service_owner_id_fk, purge_file_transfer_after_all_recipients_confirmed, purge_file_transfer_grace_period, use_manifest_file_shim, external_service_code_legacy, external_service_edition_code_legacy " +
"FROM broker.altinn_resource " +
"WHERE resource_id_pk = @resourceId " +
"ORDER BY created desc");
Expand All @@ -29,7 +29,9 @@ public class ResourceRepository(NpgsqlDataSource dataSource, IAltinnResourceRepo
ServiceOwnerId = reader.GetString(reader.GetOrdinal("service_owner_id_fk")),
PurgeFileTransferAfterAllRecipientsConfirmed = reader.GetBoolean(reader.GetOrdinal("purge_file_transfer_after_all_recipients_confirmed")),
PurgeFileTransferGracePeriod = reader.IsDBNull(reader.GetOrdinal("purge_file_transfer_grace_period")) ? null : reader.GetTimeSpan(reader.GetOrdinal("purge_file_transfer_grace_period")),
UseManifestFileShim = reader.IsDBNull(reader.GetOrdinal("use_manifest_file_shim")) ? null : reader.GetBoolean(reader.GetOrdinal("use_manifest_file_shim"))
UseManifestFileShim = reader.IsDBNull(reader.GetOrdinal("use_manifest_file_shim")) ? null : reader.GetBoolean(reader.GetOrdinal("use_manifest_file_shim")),
ExternalServiceCodeLegacy = reader.IsDBNull(reader.GetOrdinal("external_service_code_legacy")) ? null : reader.GetString(reader.GetOrdinal("external_service_code_legacy")),
ExternalServiceEditionCodeLegacy = reader.IsDBNull(reader.GetOrdinal("external_service_edition_code_legacy")) ? null : reader.GetInt32(reader.GetOrdinal("external_service_edition_code_legacy"))
};
}
if (resource is null)
Expand Down Expand Up @@ -107,4 +109,24 @@ public async Task UpdateUseManifestFileShim(string resourceId, bool useManifestF
command.Parameters.AddWithValue("@UseManifestFileShim", useManifestFileShim);
command.ExecuteNonQuery();
}
public async Task UpdateExternalServiceCodeLegacy(string resourceId, string externalServiceCodeLegacy, CancellationToken cancellationToken = default)
{
await using var command = dataSource.CreateCommand(
"UPDATE broker.altinn_resource " +
"SET external_service_code_legacy = @externalServiceCodeLegacy " +
"WHERE resource_id_pk = @resourceId");
command.Parameters.AddWithValue("@resourceId", resourceId);
command.Parameters.AddWithValue("@externalServiceCodeLegacy", externalServiceCodeLegacy);
command.ExecuteNonQuery();
}
public async Task UpdateExternalServiceEditionCodeLegacy(string resourceId, int? externalServiceEditionCodeLegacy, CancellationToken cancellationToken = default)
{
await using var command = dataSource.CreateCommand(
"UPDATE broker.altinn_resource " +
"SET external_service_edition_code_legacy = @externalServiceEditionCodeLegacy " +
"WHERE resource_id_pk = @resourceId");
command.Parameters.AddWithValue("@resourceId", resourceId);
command.Parameters.AddWithValue("@externalServiceEditionCodeLegacy", (object?)externalServiceEditionCodeLegacy ?? DBNull.Value);
command.ExecuteNonQuery();
}
}
33 changes: 29 additions & 4 deletions tests/Altinn.Broker.Tests/ManifestDownloadStreamTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Altinn.Broker.Core.Helpers;
using Altinn.Broker.Core.Domain;
using Altinn.Broker.Core.Helpers;
using Altinn.Broker.Tests.Factories;
using Altinn.Broker.Tests.Helpers;

Expand All @@ -11,10 +12,18 @@ public class ManifestDownloadStreamTests
[Fact]
public async Task StreamWithoutManifest_AddManifest_ManifestIsAddedAsync()
{
var resource = new ResourceEntity
{
Id = "manifest-shim-resource",
ServiceOwnerId = "someServiceOwnerId",
UseManifestFileShim = true,
ExternalServiceCodeLegacy = "someExternalServiceCode",
ExternalServiceEditionCodeLegacy = 123
};
var stream = ReadFile("Data/ManifestFileTests/Payload.zip");
var originalFileLength = stream.Length;
var file = FileTransferEntityFactory.BasicFileTransfer();
await stream.AddManifestFile(file);
await stream.AddManifestFile(file, resource);
Assert.True(stream.Length > originalFileLength);
var brokerManifest = stream.GetBrokerManifest();
Assert.Equal(brokerManifest.Reportee, file.RecipientCurrentStatuses.First().Actor.ActorExternalId);
Expand All @@ -24,11 +33,19 @@ public async Task StreamWithoutManifest_AddManifest_ManifestIsAddedAsync()
[Fact]
public async Task StreamWithManifest_AddManifest_ExistingManifestIsReplacedAsync()
{
var resource = new ResourceEntity
{
Id = "manifest-shim-resource",
ServiceOwnerId = "someServiceOwnerId",
UseManifestFileShim = true,
ExternalServiceCodeLegacy = "someExternalServiceCode",
ExternalServiceEditionCodeLegacy = 123
};
var stream = ReadFile("Data/ManifestFileTests/PayloadWithExistingManifest.zip");
var originalBrokerManifest = stream.GetBrokerManifest();
var originalFileLength = stream.Length;
var file = FileTransferEntityFactory.BasicFileTransfer();
await stream.AddManifestFile(file);
await stream.AddManifestFile(file, resource);
var newBrokerManifest = stream.GetBrokerManifest();
Assert.NotEqual(stream.Length, originalFileLength);
Assert.NotEqual(originalBrokerManifest.Reportee, newBrokerManifest.Reportee);
Expand All @@ -41,9 +58,17 @@ public async Task StreamWithManifest_AddManifest_ExistingManifestIsReplacedAsync
[Fact]
public async Task StreamThatIsNotZip_AddManifest_FailsAsync()
{
var resource = new ResourceEntity
{
Id = "manifest-shim-resource",
ServiceOwnerId = "someServiceOwnerId",
UseManifestFileShim = true,
ExternalServiceCodeLegacy = "someExternalServiceCode",
ExternalServiceEditionCodeLegacy = 123
};
var stream = ReadFile("Data/ManifestFileTests/payload.txt");
var file = FileTransferEntityFactory.BasicFileTransfer();
await Assert.ThrowsAsync<InvalidOperationException>(() => stream.AddManifestFile(file));
await Assert.ThrowsAsync<InvalidOperationException>(() => stream.AddManifestFile(file, resource));
}

private ManifestDownloadStream ReadFile(string path)
Expand Down

0 comments on commit 5d41543

Please sign in to comment.