Skip to content

Commit 8a37b98

Browse files
authored
Feat/service task (#745) Add support for service tasks, and add new service tasks for pdf generation and eFormidling.
1 parent 90dad61 commit 8a37b98

File tree

83 files changed

+3996
-655
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+3996
-655
lines changed

src/Altinn.App.Api/Controllers/ProcessController.cs

Lines changed: 96 additions & 202 deletions
Large diffs are not rendered by default.

src/Altinn.App.Core/EFormidling/Extensions/ServiceCollectionExtensions.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public static void AddEFormidlingServices<TM, TR>(this IServiceCollection servic
4040
{
4141
services.AddTransient(typeof(IEFormidlingReceivers), typeof(TR));
4242
services.AddHttpClient<IEFormidlingClient, Common.EFormidlingClient.EFormidlingClient>();
43+
services.AddTransient<IEFormidlingLegacyConfigurationProvider, EFormidlingLegacyConfigurationProvider>();
4344
services.AddTransient<IEFormidlingService, DefaultEFormidlingService>();
4445
services.Configure<Common.EFormidlingClient.Configuration.EFormidlingClientSettings>(
4546
configuration.GetSection("EFormidlingClientSettings")
@@ -63,6 +64,7 @@ public static void AddEFormidlingServices2<TM, TR>(this IServiceCollection servi
6364
{
6465
services.AddTransient(typeof(IEFormidlingReceivers), typeof(TR));
6566
services.AddHttpClient<IEFormidlingClient, Common.EFormidlingClient.EFormidlingClient>();
67+
services.AddTransient<IEFormidlingLegacyConfigurationProvider, EFormidlingLegacyConfigurationProvider>();
6668
services.AddTransient<IEFormidlingService, DefaultEFormidlingService>();
6769
services.Configure<Common.EFormidlingClient.Configuration.EFormidlingClientSettings>(
6870
configuration.GetSection("EFormidlingClientSettings")

src/Altinn.App.Core/EFormidling/Implementation/DefaultEFormidlingReceivers.cs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Altinn.App.Core.EFormidling.Interface;
22
using Altinn.App.Core.Internal.App;
3+
using Altinn.App.Core.Models;
34
using Altinn.Common.EFormidlingClient.Models.SBD;
45
using Altinn.Platform.Storage.Interface.Models;
56

@@ -24,17 +25,44 @@ public DefaultEFormidlingReceivers(IAppMetadata appMetadata)
2425
/// <inheritdoc />
2526
public async Task<List<Receiver>> GetEFormidlingReceivers(Instance instance)
2627
{
27-
await Task.CompletedTask;
28+
ArgumentNullException.ThrowIfNull(instance);
2829

29-
Identifier identifier = new Identifier
30+
ApplicationMetadata appMetadata = await _appMetadata.GetApplicationMetadata();
31+
32+
if (string.IsNullOrWhiteSpace(appMetadata.EFormidling?.Receiver))
33+
{
34+
return new List<Receiver>();
35+
}
36+
37+
string receiver = appMetadata.EFormidling.Receiver.Trim();
38+
39+
return CreateReceiverList(receiver);
40+
}
41+
42+
/// <inheritdoc />
43+
public Task<List<Receiver>> GetEFormidlingReceivers(Instance instance, string? receiverFromConfig)
44+
{
45+
ArgumentNullException.ThrowIfNull(instance);
46+
47+
if (string.IsNullOrWhiteSpace(receiverFromConfig))
48+
{
49+
return Task.FromResult(new List<Receiver>());
50+
}
51+
52+
string receiver = receiverFromConfig.Trim();
53+
54+
return Task.FromResult(CreateReceiverList(receiver));
55+
}
56+
57+
private static List<Receiver> CreateReceiverList(string receiver)
58+
{
59+
var identifier = new Identifier
3060
{
3161
// 0192 prefix for all Norwegian organisations.
32-
Value = $"0192:{(await _appMetadata.GetApplicationMetadata()).EFormidling.Receiver.Trim()}",
62+
Value = $"0192:{receiver}",
3363
Authority = "iso6523-actorid-upis",
3464
};
3565

36-
Receiver receiver = new Receiver { Identifier = identifier };
37-
38-
return new List<Receiver> { receiver };
66+
return [new Receiver { Identifier = identifier }];
3967
}
4068
}

src/Altinn.App.Core/EFormidling/Implementation/DefaultEFormidlingService.cs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using Altinn.App.Core.Internal.Auth;
99
using Altinn.App.Core.Internal.Data;
1010
using Altinn.App.Core.Internal.Events;
11+
using Altinn.App.Core.Internal.Process.Elements.AltinnExtensionProperties;
1112
using Altinn.App.Core.Models;
1213
using Altinn.Common.AccessTokenClient.Services;
1314
using Altinn.Common.EFormidlingClient;
@@ -34,6 +35,7 @@ public class DefaultEFormidlingService : IEFormidlingService
3435
private readonly IDataClient _dataClient;
3536
private readonly IEventsClient _eventClient;
3637
private readonly AppImplementationFactory _appImplementationFactory;
38+
private readonly IEFormidlingLegacyConfigurationProvider _configurationProvider;
3739

3840
/// <summary>
3941
/// Initializes a new instance of the <see cref="DefaultEFormidlingService"/> class.
@@ -45,6 +47,7 @@ public DefaultEFormidlingService(
4547
IDataClient dataClient,
4648
IEventsClient eventClient,
4749
IServiceProvider sp,
50+
IEFormidlingLegacyConfigurationProvider configurationProvider,
4851
IOptions<AppSettings>? appSettings = null,
4952
IOptions<PlatformSettings>? platformSettings = null,
5053
IEFormidlingClient? eFormidlingClient = null,
@@ -61,10 +64,22 @@ public DefaultEFormidlingService(
6164
_dataClient = dataClient;
6265
_eventClient = eventClient;
6366
_appImplementationFactory = sp.GetRequiredService<AppImplementationFactory>();
67+
_configurationProvider = configurationProvider;
6468
}
6569

6670
/// <inheritdoc />
6771
public async Task SendEFormidlingShipment(Instance instance)
72+
{
73+
await SendEFormidlingShipmentInternal(instance, await _configurationProvider.GetLegacyConfiguration());
74+
}
75+
76+
/// <inheritdoc />
77+
public async Task SendEFormidlingShipment(Instance instance, ValidAltinnEFormidlingConfiguration configuration)
78+
{
79+
await SendEFormidlingShipmentInternal(instance, configuration);
80+
}
81+
82+
private async Task SendEFormidlingShipmentInternal(Instance instance, ValidAltinnEFormidlingConfiguration config)
6883
{
6984
var metadata = _appImplementationFactory.Get<IEFormidlingMetadata>();
7085
if (
@@ -83,32 +98,32 @@ public async Task SendEFormidlingShipment(Instance instance)
8398

8499
ApplicationMetadata applicationMetadata = await _appMetadata.GetApplicationMetadata();
85100

86-
string accessToken = _tokenGenerator.GenerateAccessToken(
101+
string userToken = _userTokenProvider.GetUserToken();
102+
string platformAccessToken = _tokenGenerator.GenerateAccessToken(
87103
applicationMetadata.Org,
88104
applicationMetadata.AppIdentifier.App
89105
);
90-
string authzToken = _userTokenProvider.GetUserToken();
91106

92107
var requestHeaders = new Dictionary<string, string>
93108
{
94-
{ "Authorization", $"{AuthorizationSchemes.Bearer} {authzToken}" },
95-
{ General.EFormidlingAccessTokenHeaderName, accessToken },
109+
{ "Authorization", $"{AuthorizationSchemes.Bearer} {userToken}" },
110+
{ General.EFormidlingAccessTokenHeaderName, platformAccessToken },
96111
{ General.SubscriptionKeyHeaderName, _platformSettings.SubscriptionKey },
97112
};
98113

99114
string instanceGuid = instance.Id.Split("/")[1];
100115

101-
StandardBusinessDocument sbd = await ConstructStandardBusinessDocument(instanceGuid, instance);
116+
StandardBusinessDocument sbd = await ConstructStandardBusinessDocument(instanceGuid, instance, config);
102117
await _eFormidlingClient.CreateMessage(sbd, requestHeaders);
103118

104119
(string metadataFilename, Stream stream) = await metadata.GenerateEFormidlingMetadata(instance);
105120

106-
using (stream)
121+
await using (stream)
107122
{
108123
await _eFormidlingClient.UploadAttachment(stream, instanceGuid, metadataFilename, requestHeaders);
109124
}
110125

111-
await SendInstanceData(instance, requestHeaders, metadataFilename);
126+
await SendInstanceData(instance, requestHeaders, metadataFilename, config);
112127

113128
try
114129
{
@@ -124,7 +139,8 @@ public async Task SendEFormidlingShipment(Instance instance)
124139

125140
private async Task<StandardBusinessDocument> ConstructStandardBusinessDocument(
126141
string instanceGuid,
127-
Instance instance
142+
Instance instance,
143+
ValidAltinnEFormidlingConfiguration config
128144
)
129145
{
130146
if (_appSettings is null)
@@ -145,12 +161,11 @@ Instance instance
145161
};
146162

147163
var eFormidlingReceivers = _appImplementationFactory.GetRequired<IEFormidlingReceivers>();
148-
List<Receiver> receivers = await eFormidlingReceivers.GetEFormidlingReceivers(instance);
149-
ApplicationMetadata appMetadata = await _appMetadata.GetApplicationMetadata();
164+
List<Receiver> receivers = await eFormidlingReceivers.GetEFormidlingReceivers(instance, config.Receiver);
150165

151166
Scope scope = new Scope
152167
{
153-
Identifier = appMetadata.EFormidling.Process,
168+
Identifier = config.Process,
154169
InstanceIdentifier = Guid.NewGuid().ToString(),
155170
Type = "ConversationId",
156171
ScopeInformation = new List<ScopeInformation>
@@ -164,10 +179,10 @@ Instance instance
164179
DocumentIdentification documentIdentification = new DocumentIdentification
165180
{
166181
InstanceIdentifier = instanceGuid,
167-
Standard = appMetadata.EFormidling.Standard,
168-
TypeVersion = appMetadata.EFormidling.TypeVersion,
182+
Standard = config.Standard,
183+
TypeVersion = config.TypeVersion,
169184
CreationDateAndTime = completedTime,
170-
Type = appMetadata.EFormidling.Type,
185+
Type = config.Type,
171186
};
172187

173188
StandardBusinessDocumentHeader sbdHeader = new StandardBusinessDocumentHeader
@@ -182,12 +197,12 @@ Instance instance
182197
StandardBusinessDocument sbd = new StandardBusinessDocument
183198
{
184199
StandardBusinessDocumentHeader = sbdHeader,
185-
Arkivmelding = new Arkivmelding { Sikkerhetsnivaa = appMetadata.EFormidling.SecurityLevel },
200+
Arkivmelding = new Arkivmelding { Sikkerhetsnivaa = config.SecurityLevel },
186201
};
187202

188-
if (!string.IsNullOrEmpty(appMetadata.EFormidling.DPFShipmentType))
203+
if (!string.IsNullOrEmpty(config.DpfShipmentType))
189204
{
190-
sbd.Arkivmelding.DPF = new() { ForsendelsesType = appMetadata.EFormidling.DPFShipmentType };
205+
sbd.Arkivmelding.DPF = new() { ForsendelsesType = config.DpfShipmentType };
191206
}
192207

193208
return sbd;
@@ -196,7 +211,8 @@ Instance instance
196211
private async Task SendInstanceData(
197212
Instance instance,
198213
Dictionary<string, string> requestHeaders,
199-
string eformidlingMetadataFilename
214+
string eformidlingMetadataFilename,
215+
ValidAltinnEFormidlingConfiguration config
200216
)
201217
{
202218
ApplicationMetadata applicationMetadata = await _appMetadata.GetApplicationMetadata();
@@ -211,7 +227,7 @@ string eformidlingMetadataFilename
211227

212228
foreach (DataElement dataElement in instance.Data.OrderBy(x => x.Created))
213229
{
214-
if (!applicationMetadata.EFormidling.DataTypes.Contains(dataElement.DataType))
230+
if (!config.DataTypes.Contains(dataElement.DataType))
215231
{
216232
continue;
217233
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
using Altinn.App.Core.Internal.App;
2+
using Altinn.App.Core.Internal.Process.Elements.AltinnExtensionProperties;
3+
using Altinn.App.Core.Internal.Process.ProcessTasks.ServiceTasks.Legacy;
4+
using Altinn.App.Core.Models;
5+
using Altinn.Platform.Storage.Interface.Models;
6+
7+
namespace Altinn.App.Core.EFormidling.Implementation;
8+
9+
/// <summary>
10+
/// A small wrapper around loading legacy eFormidling configuration from ApplicationMetadata, to be able to use the same configuration as the new eFormidling service task.
11+
/// </summary>
12+
/// <remarks>Should be deleted when <see cref="EformidlingServiceTaskLegacy" /> is removed.</remarks>
13+
public interface IEFormidlingLegacyConfigurationProvider
14+
{
15+
/// <summary>
16+
/// Gets validated eFormidling configuration from ApplicationMetadata (legacy).
17+
/// </summary>
18+
/// <returns>Validated eFormidling configuration.</returns>
19+
Task<ValidAltinnEFormidlingConfiguration> GetLegacyConfiguration();
20+
}
21+
22+
/// <inheritdoc />
23+
internal sealed class EFormidlingLegacyConfigurationProvider : IEFormidlingLegacyConfigurationProvider
24+
{
25+
private readonly IAppMetadata _appMetadata;
26+
27+
public EFormidlingLegacyConfigurationProvider(IAppMetadata appMetadata)
28+
{
29+
_appMetadata = appMetadata;
30+
}
31+
32+
public async Task<ValidAltinnEFormidlingConfiguration> GetLegacyConfiguration()
33+
{
34+
ApplicationMetadata applicationMetadata = await _appMetadata.GetApplicationMetadata();
35+
EFormidlingContract? eFormidling = applicationMetadata.EFormidling;
36+
37+
if (eFormidling is null)
38+
{
39+
throw new ApplicationConfigException($"No legacy eFormidling configuration found in application metadata.");
40+
}
41+
42+
return new ValidAltinnEFormidlingConfiguration(
43+
true, // Enabled prop is not used in legacy mode, as whether eFormidling is enabled or not is determined in the legacy service task.
44+
eFormidling.Receiver,
45+
eFormidling.Process,
46+
eFormidling.Standard,
47+
eFormidling.TypeVersion,
48+
eFormidling.Type,
49+
eFormidling.SecurityLevel,
50+
eFormidling.DPFShipmentType,
51+
eFormidling.DataTypes?.ToList() ?? []
52+
);
53+
}
54+
}

src/Altinn.App.Core/EFormidling/Interface/IEFormidlingReceivers.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,30 @@ namespace Altinn.App.Core.EFormidling.Interface;
1111
public interface IEFormidlingReceivers
1212
{
1313
/// <summary>
14-
/// Gets a list of eFormidling shipment receivers
14+
/// Gets a list of eFormidling shipment receivers.
1515
/// </summary>
1616
/// <remarks>
17+
/// <para>
1718
/// Note that the identifier value property on the receiver objects should be prefixed with `0192:` for Norwegian organisations.
19+
/// </para>
1820
/// </remarks>
1921
/// <param name="instance">Instance data</param>
2022
/// <returns>List of eFormidling receivers</returns>
23+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="instance"/> is null</exception>
2124
public Task<List<Receiver>> GetEFormidlingReceivers(Instance instance);
25+
26+
/// <summary>
27+
/// Gets a list of eFormidling shipment receivers.
28+
/// </summary>
29+
/// <remarks>
30+
/// <para>
31+
/// Note that the identifier value property on the receiver objects should be prefixed with `0192:` for Norwegian organisations.
32+
/// </para>
33+
/// </remarks>
34+
/// <param name="instance">Instance data</param>
35+
/// <param name="receiverFromConfig">Receiver organization number from static configuration (BPMN or ApplicationMetadata, depending on if service task is used or not).</param>
36+
/// <returns>List of eFormidling receivers</returns>
37+
/// <exception cref="ArgumentNullException">Thrown when <paramref name="instance"/> is null</exception>
38+
public Task<List<Receiver>> GetEFormidlingReceivers(Instance instance, string? receiverFromConfig) =>
39+
GetEFormidlingReceivers(instance);
2240
}

src/Altinn.App.Core/EFormidling/Interface/IEFormidlingService.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Altinn.App.Core.Internal.Process.Elements.AltinnExtensionProperties;
12
using Altinn.Platform.Storage.Interface.Models;
23

34
namespace Altinn.App.Core.EFormidling.Interface;
@@ -13,4 +14,16 @@ public interface IEFormidlingService
1314
/// <param name="instance">Instance data</param>
1415
/// <returns></returns>
1516
public Task SendEFormidlingShipment(Instance instance);
17+
18+
/// <summary>
19+
/// Send the eFormidling shipment with explicit configuration context.
20+
/// </summary>
21+
/// <param name="instance">Instance data</param>
22+
/// <param name="configuration">A valid config for eFormidling.</param>
23+
/// <returns></returns>
24+
public Task SendEFormidlingShipment(Instance instance, ValidAltinnEFormidlingConfiguration configuration)
25+
{
26+
// Default implementation for backward compatibility - calls legacy method. Only meant to avoid forcing implementers to implement the new method.
27+
return SendEFormidlingShipment(instance);
28+
}
1629
}

src/Altinn.App.Core/Extensions/ServiceCollectionExtensions.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
using Altinn.App.Core.Internal.Process.EventHandlers;
4848
using Altinn.App.Core.Internal.Process.EventHandlers.ProcessTask;
4949
using Altinn.App.Core.Internal.Process.ProcessTasks;
50-
using Altinn.App.Core.Internal.Process.ServiceTasks;
50+
using Altinn.App.Core.Internal.Process.ProcessTasks.ServiceTasks;
51+
using Altinn.App.Core.Internal.Process.ProcessTasks.ServiceTasks.Legacy;
5152
using Altinn.App.Core.Internal.Registers;
5253
using Altinn.App.Core.Internal.Secrets;
5354
using Altinn.App.Core.Internal.Sign;
@@ -371,8 +372,11 @@ private static void AddProcessServices(IServiceCollection services)
371372
services.AddTransient<IProcessTask, NullTypeProcessTask>();
372373

373374
// Service tasks
375+
services.AddTransient<IPdfServiceTaskLegacy, PdfServiceTaskLegacy>();
376+
services.AddTransient<IEFormidlingServiceTaskLegacy, EformidlingServiceTaskLegacy>();
377+
374378
services.AddTransient<IServiceTask, PdfServiceTask>();
375-
services.AddTransient<IServiceTask, EformidlingServiceTask>();
379+
services.AddTransient<IServiceTask, EFormidlingServiceTask>();
376380
}
377381

378382
private static void AddActionServices(IServiceCollection services)

src/Altinn.App.Core/Features/Telemetry/Telemetry.Processes.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ internal void ProcessEnded(ProcessStateChange processChange)
6262
return activity;
6363
}
6464

65+
internal Activity? StartProcessExecuteServiceTaskActivity(Instance instance, string serviceTaskType)
66+
{
67+
var activity = ActivitySource.StartActivity($"{Prefix}.ExecuteServiceTask");
68+
activity?.SetInstanceId(instance);
69+
activity?.SetTag(InternalLabels.ProcessServiceTaskType, serviceTaskType);
70+
return activity;
71+
}
72+
6573
internal Activity? StartProcessEndActivity(Instance instance)
6674
{
6775
var activity = ActivitySource.StartActivity($"{Prefix}.End");

src/Altinn.App.Core/Features/Telemetry/Telemetry.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ internal static class InternalLabels
236236

237237
internal const string ProcessErrorType = "process.error.type";
238238
internal const string ProcessAction = "process.action";
239+
internal const string ProcessServiceTaskType = "process.service.task.type";
239240

240241
internal const string ProblemType = "problem.type";
241242
internal const string ProblemTitle = "problem.title";

0 commit comments

Comments
 (0)