< Summary

Information
Class: Elsa.Bpmn.Interchange.Endpoints.Bpmn.Export.Export
Assembly: Elsa.Bpmn.Interchange
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Bpmn.Interchange/Endpoints/Bpmn/Export/Endpoint.cs
Line coverage
86%
Covered lines: 26
Uncovered lines: 4
Coverable lines: 30
Total lines: 83
Line coverage: 86.6%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Configure()100%11100%
HandleAsync()100%4484.61%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Bpmn.Interchange/Endpoints/Bpmn/Export/Endpoint.cs

#LineLine coverage
 1using Elsa.Authorization;
 2using Bpmn.Interchange;
 3using Elsa.Abstractions;
 4using Elsa.Bpmn.Interchange.Exceptions;
 5using Elsa.Bpmn.Interchange.Services;
 6using Elsa.Common.Models;
 7using Elsa.Workflows.Management;
 8using Elsa.Workflows.Models;
 9using JetBrains.Annotations;
 10using Microsoft.AspNetCore.Http;
 11
 12namespace Elsa.Bpmn.Interchange.Endpoints.Bpmn.Export;
 13
 14/// <summary>Writes a stored workflow definition back out as BPMN 2.0 XML.</summary>
 15/// <remarks>
 16/// A thin wrapper over <see cref="BpmnInterchangeDocumentService.Export(Elsa.Workflows.Management.Entities.WorkflowDefi
 17/// See that type's remarks for why this re-reads the original document rather than reconstructing one from the Elsa
 18/// activity graph the definition runs, and for why a missing or stale source is refused rather than exported anyway.
 19/// </remarks>
 20[UsedImplicitly]
 1521internal sealed class Export(IWorkflowDefinitionStore store, BpmnInterchangeDocumentService documentService) : ElsaEndpo
 22{
 23    /// <inheritdoc />
 24    public override void Configure()
 25    {
 1126        Get("bpmn/definitions/{definitionId}/export");
 1127        RequirePermission(Elsa.Bpmn.Interchange.Permissions.BpmnPermissions.Definitions, CoreVerbs.View);
 1128    }
 29
 30    /// <inheritdoc />
 31    public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
 32    {
 33        VersionOptions versionOptions;
 34
 435        if (string.IsNullOrWhiteSpace(request.VersionOptions))
 36        {
 337            versionOptions = VersionOptions.Latest;
 38        }
 39        else
 40        {
 41            try
 42            {
 43                // VersionOptions.TryParse always returns true and still throws through FromString for a value it
 44                // cannot make sense of, so it buys nothing over calling FromString directly — catch what it can
 45                // actually throw instead: a non-numeric or out-of-range value that is not one of its named options.
 146                versionOptions = VersionOptions.FromString(request.VersionOptions);
 047            }
 148            catch (Exception exception) when (exception is FormatException or OverflowException)
 49            {
 150                AddError(
 151                    $"'{request.VersionOptions}' is not a valid version. Specify a whole number, or one of: AllVersions,
 152                    + "LatestOrPublished, LatestAndPublished.");
 153                await Send.ErrorsAsync(StatusCodes.Status400BadRequest, cancellationToken);
 154                return;
 55            }
 56        }
 57
 358        var filter = WorkflowDefinitionHandle.ByDefinitionId(request.DefinitionId, versionOptions).ToFilter();
 359        var definition = await store.FindAsync(filter, cancellationToken);
 60
 361        if (definition == null)
 62        {
 163            await Send.NotFoundAsync(cancellationToken);
 164            return;
 65        }
 66
 67        try
 68        {
 269            var bytes = documentService.Export(definition);
 170            await Send.BytesAsync(bytes, $"{request.DefinitionId}.bpmn", "application/xml", cancellation: cancellationTo
 171        }
 172        catch (BpmnExportUnavailableException exception)
 73        {
 174            AddError(exception.Message);
 175            await Send.ErrorsAsync(StatusCodes.Status422UnprocessableEntity, cancellationToken);
 176        }
 077        catch (BpmnInterchangeException exception)
 78        {
 079            AddError(exception.Message);
 080            await Send.ErrorsAsync(StatusCodes.Status400BadRequest, cancellationToken);
 81        }
 482    }
 83}