Skip to content
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
24 changes: 15 additions & 9 deletions src/Altinn.App.Api/Controllers/ActionsController.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using Altinn.App.Api.Infrastructure.Filters;
using Altinn.App.Api.Models;
using Altinn.App.Core.Extensions;
using Altinn.App.Core.Features;
using Altinn.App.Core.Features.Action;
using Altinn.App.Core.Helpers;
using Altinn.App.Core.Internal.App;
using Altinn.App.Core.Internal.Data;
using Altinn.App.Core.Internal.Instances;
using Altinn.App.Core.Internal.Process;
using Altinn.App.Core.Internal.Validation;
using Altinn.App.Core.Models;
using Altinn.App.Core.Models.Process;
Expand Down Expand Up @@ -72,6 +74,7 @@ public ActionsController(
[Authorize]
[ProducesResponseType(typeof(UserActionResponse), 200)]
[ProducesResponseType(typeof(ProblemDetails), 400)]
[ProducesResponseType(typeof(RedirectResult), 302)]
[ProducesResponseType(409)]
[ProducesResponseType(500)]
[ProducesResponseType(401)]
Expand All @@ -83,7 +86,7 @@ public async Task<ActionResult<UserActionResponse>> Perform(
[FromBody] UserActionRequest actionRequest,
[FromQuery] string? language = null)
{
var action = actionRequest.Action;
string? action = actionRequest.Action;
if (action == null)
{
return new BadRequestObjectResult(new ProblemDetails()
Expand All @@ -95,8 +98,7 @@ public async Task<ActionResult<UserActionResponse>> Perform(
});
}

var instance = await _instanceClient.GetInstance(app, org, instanceOwnerPartyId, instanceGuid);

Instance instance = await _instanceClient.GetInstance(app, org, instanceOwnerPartyId, instanceGuid);
if (instance?.Process == null)
{
return Conflict($"Process is not started.");
Expand All @@ -107,20 +109,20 @@ public async Task<ActionResult<UserActionResponse>> Perform(
return Conflict($"Process is ended.");
}

var userId = HttpContext.User.GetUserIdAsInt();
int? userId = HttpContext.User.GetUserIdAsInt();
if (userId == null)
{
return Unauthorized();
}

var authorized = await _authorization.AuthorizeAction(new AppIdentifier(org, app), new InstanceIdentifier(instanceOwnerPartyId, instanceGuid), HttpContext.User, action, instance.Process?.CurrentTask?.ElementId);
bool authorized = await _authorization.AuthorizeAction(new AppIdentifier(org, app), new InstanceIdentifier(instanceOwnerPartyId, instanceGuid), HttpContext.User, action, instance.Process?.CurrentTask?.ElementId);
if (!authorized)
{
return Forbid();
}

UserActionContext userActionContext = new UserActionContext(instance, userId.Value, actionRequest.ButtonId, actionRequest.Metadata);
var actionHandler = _userActionService.GetActionHandler(action);
UserActionContext userActionContext = new(instance, userId.Value, actionRequest.ButtonId, actionRequest.Metadata);
IUserAction? actionHandler = _userActionService.GetActionHandler(action);
if (actionHandler == null)
{
return new NotFoundObjectResult(new UserActionResponse()
Expand All @@ -133,9 +135,13 @@ public async Task<ActionResult<UserActionResponse>> Perform(
});
}

var result = await actionHandler.HandleAction(userActionContext);
UserActionResult result = await actionHandler.HandleAction(userActionContext);
if (result.ResultType == ResultType.Redirect)
{
return new RedirectResult(result.RedirectUrl ?? throw new ProcessException("Redirect URL missing"));
}

if (!result.Success)
if (result.ResultType != ResultType.Success)
{
return StatusCode(
statusCode: result.ErrorType switch
Expand Down
53 changes: 15 additions & 38 deletions src/Altinn.App.Api/Controllers/InstancesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ public async Task<ActionResult<Instance>> Post(
}

ApplicationMetadata application = await _appMetadata.GetApplicationMetadata();

RequestPartValidator requestValidator = new RequestPartValidator(application);
RequestPartValidator requestValidator = new(application);
string? multipartError = requestValidator.ValidateParts(parsedRequest.Parts);

if (!string.IsNullOrEmpty(multipartError))
Expand Down Expand Up @@ -250,7 +249,6 @@ public async Task<ActionResult<Instance>> Post(
}

EnforcementResult enforcementResult = await AuthorizeAction(org, app, party.PartyId, null, "instantiate");

if (!enforcementResult.Authorized)
{
return Forbidden(enforcementResult);
Expand Down Expand Up @@ -278,13 +276,13 @@ public async Task<ActionResult<Instance>> Post(
try
{
// start process and goto next task
ProcessStartRequest processStartRequest = new ProcessStartRequest
ProcessStartRequest processStartRequest = new()
{
Instance = instanceTemplate,
User = User,
Dryrun = true
User = User
};
var result = await _processEngine.StartProcess(processStartRequest);

ProcessChangeResult result = await _processEngine.GenerateProcessStartEvents(processStartRequest);
if (!result.Success)
{
return Conflict(result.ErrorMessage);
Expand All @@ -308,14 +306,8 @@ public async Task<ActionResult<Instance>> Post(
instance = await _instanceClient.GetInstance(app, org, int.Parse(instance.InstanceOwner.PartyId), Guid.Parse(instance.Id.Split("/")[1]));

// notify app and store events
var request = new ProcessStartRequest()
{
Instance = instance,
User = User,
Dryrun = false,
};
_logger.LogInformation("Events sent to process engine: {Events}", change?.Events);
await _processEngine.UpdateInstanceAndRerunEvents(request, change?.Events);
await _processEngine.HandleEventsAndUpdateStorage(instance, null, change?.Events);
}
catch (Exception exception)
{
Expand Down Expand Up @@ -409,14 +401,14 @@ public async Task<ActionResult<Instance>> PostSimplified(
return StatusCode((int)HttpStatusCode.Forbidden, $"Party {party.PartyId} is not allowed to instantiate this application {org}/{app}");
}

Instance instanceTemplate = new Instance()
Instance instanceTemplate = new()
{
InstanceOwner = instansiationInstance.InstanceOwner,
VisibleAfter = instansiationInstance.VisibleAfter,
DueBefore = instansiationInstance.DueBefore
DueBefore = instansiationInstance.DueBefore,
Org = application.Org
};

instanceTemplate.Org = application.Org;
ConditionallySetReadStatus(instanceTemplate);

// Run custom app logic to validate instantiation
Expand All @@ -437,11 +429,10 @@ public async Task<ActionResult<Instance>> PostSimplified(
{
Instance = instanceTemplate,
User = User,
Dryrun = true,
Prefill = instansiationInstance.Prefill
};

processResult = await _processEngine.StartProcess(request);
processResult = await _processEngine.GenerateProcessStartEvents(request);

Instance? source = null;

Expand Down Expand Up @@ -473,15 +464,7 @@ public async Task<ActionResult<Instance>> PostSimplified(
}

instance = await _instanceClient.GetInstance(instance);

var updateRequest = new ProcessStartRequest()
{
Instance = instance,
User = User,
Dryrun = false,
Prefill = instansiationInstance.Prefill
};
await _processEngine.UpdateInstanceAndRerunEvents(updateRequest, processResult.ProcessStateChange?.Events);
await _processEngine.HandleEventsAndUpdateStorage(instance, instansiationInstance.Prefill, processResult.ProcessStateChange?.Events);
}
catch (Exception exception)
{
Expand Down Expand Up @@ -573,24 +556,18 @@ public async Task<ActionResult> CopyInstance(
ProcessStartRequest processStartRequest = new()
{
Instance = targetInstance,
User = User,
Dryrun = true
User = User
};
var startResult = await _processEngine.StartProcess(processStartRequest);

ProcessChangeResult startResult = await _processEngine.GenerateProcessStartEvents(processStartRequest);

targetInstance = await _instanceClient.CreateInstance(org, app, targetInstance);

await CopyDataFromSourceInstance(application, targetInstance, sourceInstance);

targetInstance = await _instanceClient.GetInstance(targetInstance);

ProcessStartRequest rerunRequest = new()
{
Instance = targetInstance,
Dryrun = false,
User = User
};
await _processEngine.UpdateInstanceAndRerunEvents(rerunRequest, startResult.ProcessStateChange?.Events);
await _processEngine.HandleEventsAndUpdateStorage(targetInstance, null, startResult.ProcessStateChange?.Events);

await RegisterEvent("app.instance.created", targetInstance);

Expand Down
7 changes: 4 additions & 3 deletions src/Altinn.App.Api/Controllers/ProcessController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,16 @@ public async Task<ActionResult<AppProcessState>> StartProcess(
{
Instance = instance,
StartEventId = startEvent,
User = User,
Dryrun = false
User = User
};
var result = await _processEngine.StartProcess(request);
ProcessChangeResult result = await _processEngine.GenerateProcessStartEvents(request);
if (!result.Success)
{
return Conflict(result.ErrorMessage);
}

await _processEngine.HandleEventsAndUpdateStorage(instance, null, result.ProcessStateChange?.Events);

AppProcessState appProcessState = await ConvertAndAuthorizeActions(instance, result.ProcessStateChange?.NewProcessState);
return Ok(appProcessState);
}
Expand Down
38 changes: 34 additions & 4 deletions src/Altinn.App.Core/Extensions/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
using Altinn.App.Core.Internal.Pdf;
using Altinn.App.Core.Internal.Prefill;
using Altinn.App.Core.Internal.Process;
using Altinn.App.Core.Internal.Process.Action;
using Altinn.App.Core.Internal.Process.EventHandlers;
using Altinn.App.Core.Internal.Process.EventHandlers.ProcessTask;
using Altinn.App.Core.Internal.Process.ProcessTasks;
using Altinn.App.Core.Internal.Process.ServiceTasks;
using Altinn.App.Core.Internal.Profile;
using Altinn.App.Core.Internal.Registers;
using Altinn.App.Core.Internal.Secrets;
using Altinn.App.Core.Internal.Sign;
using Altinn.App.Core.Internal.Texts;
using Altinn.App.Core.Internal.Validation;
using Altinn.App.Core.Models;
Expand All @@ -53,6 +55,8 @@
using IProcessReader = Altinn.App.Core.Internal.Process.IProcessReader;
using ProcessEngine = Altinn.App.Core.Internal.Process.ProcessEngine;
using ProcessReader = Altinn.App.Core.Internal.Process.ProcessReader;
using Altinn.App.Core.Internal.Sign;
using Altinn.App.Core.Internal.Process.Authorization;

namespace Altinn.App.Core.Extensions
{
Expand Down Expand Up @@ -140,7 +144,6 @@ public static void AddAppServices(this IServiceCollection services, IConfigurati
services.TryAddSingleton<IAppMetadata, AppMetadata>();
services.TryAddSingleton<IFrontendFeatures, FrontendFeatures>();
services.TryAddTransient<IAppEvents, DefaultAppEvents>();
services.TryAddTransient<ITaskEvents, DefaultTaskEvents>();
#pragma warning disable CS0618, CS0612 // Type or member is obsolete
services.TryAddTransient<IPageOrder, DefaultPageOrder>();
#pragma warning restore CS0618, CS0612 // Type or member is obsolete
Expand All @@ -152,14 +155,17 @@ public static void AddAppServices(this IServiceCollection services, IConfigurati
services.TryAddTransient<IDataListsService, DataListsService>();
services.TryAddTransient<LayoutEvaluatorStateInitializer>();
services.TryAddTransient<IPatchService, PatchService>();
services.AddTransient<IDataService, DataService>();
services.Configure<Altinn.Common.PEP.Configuration.PepSettings>(configuration.GetSection("PEPSettings"));
services.Configure<Altinn.Common.PEP.Configuration.PlatformSettings>(configuration.GetSection("PlatformSettings"));
services.Configure<AccessTokenSettings>(configuration.GetSection("AccessTokenSettings"));
services.Configure<FrontEndSettings>(configuration.GetSection(nameof(FrontEndSettings)));
services.Configure<PdfGeneratorSettings>(configuration.GetSection(nameof(PdfGeneratorSettings)));

AddAppOptions(services);
AddActionServices(services);
AddPdfServices(services);
AddSignatureServices(services);
AddEventServices(services);
AddProcessServices(services);
AddFileAnalyserServices(services);
Expand Down Expand Up @@ -237,6 +243,11 @@ private static void AddPdfServices(IServiceCollection services)
#pragma warning restore CS0618 // Type or member is obsolete
}

private static void AddSignatureServices(IServiceCollection services)
{
services.AddHttpClient<ISignClient, SignClient>();
}

private static void AddAppOptions(IServiceCollection services)
{
// Main service for interacting with options
Expand All @@ -256,16 +267,35 @@ private static void AddProcessServices(IServiceCollection services)
services.TryAddTransient<IProcessEngine, ProcessEngine>();
services.TryAddTransient<IProcessNavigator, ProcessNavigator>();
services.TryAddSingleton<IProcessReader, ProcessReader>();
services.TryAddSingleton<IProcessEventHandlerDelegator, ProcessEventHandlingDelegator>();
services.TryAddTransient<IProcessEventDispatcher, ProcessEventDispatcher>();
services.AddTransient<IProcessExclusiveGateway, ExpressionsExclusiveGateway>();
services.TryAddTransient<ExclusiveGatewayFactory>();

services.AddTransient<IProcessTaskInitializer, ProcessTaskInitializer>();
services.AddTransient<IProcessTaskFinalizer, ProcessTaskFinalizer>();
services.AddTransient<IProcessTaskDataLocker, ProcessTaskDataLocker>();
services.AddTransient<IStartTaskEventHandler, StartTaskEventHandler>();
services.AddTransient<IEndTaskEventHandler, EndTaskEventHandler>();
services.AddTransient<IAbandonTaskEventHandler, AbandonTaskEventHandler>();
services.AddTransient<IEndEventEventHandler, EndEventEventHandler>();

//PROCESS TASKS
services.AddTransient<IProcessTask, DataProcessTask>();
services.AddTransient<IProcessTask, ConfirmationProcessTask>();
services.AddTransient<IProcessTask, FeedbackProcessTask>();
services.AddTransient<IProcessTask, SigningProcessTask>();
services.AddTransient<IProcessTask, NullTypeProcessTask>();

//SERVICE TASKS
services.AddKeyedTransient<IServiceTask, PdfServiceTask>("pdfService");
services.AddKeyedTransient<IServiceTask, EformidlingServiceTask>("eFormidlingService");
}

private static void AddActionServices(IServiceCollection services)
{
services.TryAddTransient<UserActionService>();
services.AddTransient<IUserAction, SigningUserAction>();
services.AddHttpClient<ISignClient, SignClient>();
services.AddTransientUserActionAuthorizerForActionInAllTasks<UniqueSignatureAuthorizer>("sign");
}

Expand Down
Loading