Skip to content

Commit

Permalink
feat(issuer): add process and process step status to GET: /api/issuer
Browse files Browse the repository at this point in the history
Refs: #300
  • Loading branch information
Phil91 committed Dec 18, 2024
1 parent 893d5e1 commit bd1a6c5
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 104 deletions.
83 changes: 62 additions & 21 deletions docs/api/issuer-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,10 @@ paths:
type: string
format: uuid
responses:
'200':
description: OK
content:
application/json: { }
'401':
description: Unauthorized
content:
Expand Down Expand Up @@ -333,6 +337,10 @@ paths:
type: string
format: uuid
responses:
'200':
description: OK
content:
application/json: { }
'401':
description: Unauthorized
content:
Expand Down Expand Up @@ -384,6 +392,10 @@ paths:
schema:
$ref: '#/components/schemas/ProcessStepTypeId'
responses:
'200':
description: OK
content:
application/json: { }
'401':
description: Unauthorized
content:
Expand Down Expand Up @@ -429,6 +441,13 @@ paths:
type: string
format: uuid
responses:
'200':
description: OK
content:
application/json:
schema:
type: string
format: uuid
'401':
description: Unauthorized
content:
Expand All @@ -441,13 +460,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'200':
description: OK
content:
application/json:
schema:
type: string
format: uuid
'/api/revocation/credentials/{credentialId}':
post:
tags:
Expand All @@ -463,6 +475,13 @@ paths:
type: string
format: uuid
responses:
'200':
description: OK
content:
application/json:
schema:
type: string
format: uuid
'401':
description: Unauthorized
content:
Expand All @@ -475,13 +494,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'200':
description: OK
content:
application/json:
schema:
type: string
format: uuid
'/api/revocation/{processId}/retrigger-step/{processStepTypeId}':
post:
tags:
Expand All @@ -503,6 +515,10 @@ paths:
schema:
$ref: '#/components/schemas/ProcessStepTypeId'
responses:
'200':
description: OK
content:
application/json: { }
'401':
description: Unauthorized
content:
Expand Down Expand Up @@ -584,6 +600,13 @@ paths:
type: string
format: uuid
responses:
'200':
description: OK
content:
application/json:
schema:
type: string
format: binary
'401':
description: Unauthorized
content:
Expand All @@ -596,13 +619,6 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'200':
description: OK
content:
application/json:
schema:
type: string
format: binary
'409':
description: Conflict
content:
Expand Down Expand Up @@ -736,6 +752,15 @@ components:
$ref: '#/components/schemas/DocumentData'
externalTypeDetail:
$ref: '#/components/schemas/ExternalTypeDetailData'
processId:
type: string
format: uuid
nullable: true
processSteps:
type: array
items:
$ref: '#/components/schemas/ProcessStepDetailData'
nullable: true
additionalProperties: false
DocumentData:
type: object
Expand Down Expand Up @@ -843,6 +868,22 @@ components:
type: string
nullable: true
additionalProperties: false
ProcessStepDetailData:
type: object
properties:
processStepStatusId:
$ref: '#/components/schemas/ProcessStepStatusId'
processStepTypeId:
$ref: '#/components/schemas/ProcessStepTypeId'
additionalProperties: false
ProcessStepStatusId:
enum:
- TODO
- DONE
- SKIPPED
- FAILED
- DUPLICATE
type: string
ProcessStepTypeId:
enum:
- CREATE_SIGNED_CREDENTIAL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,12 @@ public record CredentialDetailData(
CompanySsiDetailStatusId ParticipantStatus,
DateTimeOffset? ExpiryDate,
IEnumerable<DocumentData> Documents,
ExternalTypeDetailData? ExternalTypeDetail
ExternalTypeDetailData? ExternalTypeDetail,
Guid? ProcessId,
IEnumerable<ProcessStepDetailData>? ProcessSteps
);

public record ProcessStepDetailData(
ProcessStepStatusId ProcessStepStatusId,
ProcessStepTypeId ProcessStepTypeId
);
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
********************************************************************************/

using Microsoft.EntityFrameworkCore;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities;
Expand Down Expand Up @@ -159,12 +160,46 @@ public Task<bool> CheckSsiDetailsExistsForCompany(string bpnl, VerifiedCredentia
.SingleOrDefaultAsync();

/// <inheritdoc />
public IQueryable<CompanySsiDetail> GetAllCredentialDetails(CompanySsiDetailStatusId? companySsiDetailStatusId, VerifiedCredentialTypeId? credentialTypeId, CompanySsiDetailApprovalType? approvalType) =>
context.CompanySsiDetails.AsNoTracking()
.Where(c =>
(!companySsiDetailStatusId.HasValue || c.CompanySsiDetailStatusId == companySsiDetailStatusId.Value) &&
(!credentialTypeId.HasValue || c.VerifiedCredentialTypeId == credentialTypeId) &&
(!approvalType.HasValue || (approvalType.Value == CompanySsiDetailApprovalType.Automatic && c.VerifiedCredentialType!.VerifiedCredentialTypeAssignedKind!.VerifiedCredentialTypeKindId == VerifiedCredentialTypeKindId.FRAMEWORK) || (approvalType.Value == CompanySsiDetailApprovalType.Manual && c.VerifiedCredentialType!.VerifiedCredentialTypeAssignedKind!.VerifiedCredentialTypeKindId != VerifiedCredentialTypeKindId.FRAMEWORK)));
public Func<int, int, Task<Pagination.Source<CredentialDetailData>?>> GetAllCredentialDetails(CompanySsiDetailSorting? sorting, CompanySsiDetailStatusId? companySsiDetailStatusId, VerifiedCredentialTypeId? credentialTypeId, CompanySsiDetailApprovalType? approvalType) =>
(skip, take) => Pagination.CreateSourceQueryAsync(
skip,
take,
context.CompanySsiDetails.AsNoTracking()
.Where(c =>
(!companySsiDetailStatusId.HasValue || c.CompanySsiDetailStatusId == companySsiDetailStatusId.Value) &&
(!credentialTypeId.HasValue || c.VerifiedCredentialTypeId == credentialTypeId) &&
(!approvalType.HasValue ||
(approvalType.Value == CompanySsiDetailApprovalType.Automatic && c.VerifiedCredentialType!.VerifiedCredentialTypeAssignedKind!.VerifiedCredentialTypeKindId == VerifiedCredentialTypeKindId.FRAMEWORK) ||
(approvalType.Value == CompanySsiDetailApprovalType.Manual && c.VerifiedCredentialType!.VerifiedCredentialTypeAssignedKind!.VerifiedCredentialTypeKindId != VerifiedCredentialTypeKindId.FRAMEWORK)))

Check notice

Code scanning / CodeQL

Complex condition Note

Complex condition: too many logical operations in this expression.
.GroupBy(x => x.IssuerBpn),
credentials => sorting == null || sorting == CompanySsiDetailSorting.BpnlAsc ?
credentials.OrderBy(c => c.Bpnl) :
credentials.OrderByDescending(c => c.Bpnl),
credential => new CredentialDetailData(
credential.Id,
credential.Bpnl,
credential.VerifiedCredentialTypeId,
credential.VerifiedCredentialType!.VerifiedCredentialTypeAssignedUseCase!.UseCase!.Name,
credential.CompanySsiDetailStatusId,
credential.ExpiryDate,
credential.Documents.Select(d => new DocumentData(d.Id, d.DocumentName, d.DocumentTypeId)),
credential.VerifiedCredentialExternalTypeDetailVersion == null
? null
: new ExternalTypeDetailData(
credential.VerifiedCredentialExternalTypeDetailVersion.Id,
credential.VerifiedCredentialExternalTypeDetailVersion.VerifiedCredentialExternalTypeId,
credential.VerifiedCredentialExternalTypeDetailVersion.Version,
credential.VerifiedCredentialExternalTypeDetailVersion.Template,
credential.VerifiedCredentialExternalTypeDetailVersion.ValidFrom,
credential.VerifiedCredentialExternalTypeDetailVersion.Expiry),
credential.ProcessId,
credential.ProcessId == null ?
null :
credential.Process!.ProcessSteps.Select(ps =>
new ProcessStepDetailData(
ps.ProcessStepStatusId,
ps.ProcessStepTypeId)))
).SingleOrDefaultAsync();

/// <inheritdoc />
public IAsyncEnumerable<OwnedVerifiedCredentialData> GetOwnCredentialDetails(string bpnl) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Models;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums;
Expand Down Expand Up @@ -83,11 +84,12 @@ public interface ICompanySsiDetailsRepository
/// <summary>
/// Gets all credential details
/// </summary>
/// <param name="sorting">The sorting of the result</param>
/// <param name="companySsiDetailStatusId">The status of the details</param>
/// <param name="credentialTypeId">OPTIONAL: The type of the credential that should be returned</param>
/// <param name="approvalType">OPTIONAL: The approval type of the credential</param>
/// <returns>Returns data to create the pagination</returns>
IQueryable<CompanySsiDetail> GetAllCredentialDetails(CompanySsiDetailStatusId? companySsiDetailStatusId, VerifiedCredentialTypeId? credentialTypeId, CompanySsiDetailApprovalType? approvalType);
Func<int, int, Task<Pagination.Source<CredentialDetailData>?>> GetAllCredentialDetails(CompanySsiDetailSorting? sorting, CompanySsiDetailStatusId? companySsiDetailStatusId, VerifiedCredentialTypeId? credentialTypeId, CompanySsiDetailApprovalType? approvalType);

/// <summary>
/// Gets all credentials for a specific bpn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.11" />
<PackageReference Include="Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling" Version="2.13.0" />
<PackageReference Include="Org.Eclipse.TractusX.Portal.Backend.Framework.Models" Version="2.13.0" />
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
Expand All @@ -29,7 +28,6 @@
using Org.Eclipse.TractusX.SsiCredentialIssuer.DBAccess.Repositories;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Entities;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Enums;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Entities.Extensions;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Portal.Service.Models;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Portal.Service.Services;
using Org.Eclipse.TractusX.SsiCredentialIssuer.Processes.Library;
Expand Down Expand Up @@ -97,45 +95,16 @@ public IAsyncEnumerable<CertificateParticipationData> GetSsiCertificatesAsync()
.GetSsiCertificates(_identity.Bpnl, _dateTimeProvider.OffsetNow);

/// <inheritdoc />
public Task<Pagination.Response<CredentialDetailData>> GetCredentials(int page, int size, CompanySsiDetailStatusId? companySsiDetailStatusId, VerifiedCredentialTypeId? credentialTypeId, CompanySsiDetailApprovalType? approvalType, CompanySsiDetailSorting? sorting)
{
var query = _repositories
.GetInstance<ICompanySsiDetailsRepository>()
.GetAllCredentialDetails(companySsiDetailStatusId, credentialTypeId, approvalType);
var sortedQuery = sorting switch
{
CompanySsiDetailSorting.BpnlAsc or null => query.OrderBy(c => c.Bpnl),
CompanySsiDetailSorting.BpnlDesc => query.OrderByDescending(c => c.Bpnl),
_ => query
};

return Pagination.CreateResponseAsync(page, size, _settings.MaxPageSize, (skip, take) =>
new Pagination.AsyncSource<CredentialDetailData>
(
query.CountAsync(),
sortedQuery
.Skip(skip)
.Take(take)
.Select(c => new CredentialDetailData(
c.Id,
c.Bpnl,
c.VerifiedCredentialTypeId,
c.VerifiedCredentialType!.VerifiedCredentialTypeAssignedUseCase!.UseCase!.Name,
c.CompanySsiDetailStatusId,
c.ExpiryDate,
c.Documents.Select(d => new DocumentData(d.Id, d.DocumentName, d.DocumentTypeId)),
c.VerifiedCredentialExternalTypeDetailVersion == null
? null
: new ExternalTypeDetailData(
c.VerifiedCredentialExternalTypeDetailVersion.Id,
c.VerifiedCredentialExternalTypeDetailVersion.VerifiedCredentialExternalTypeId,
c.VerifiedCredentialExternalTypeDetailVersion.Version,
c.VerifiedCredentialExternalTypeDetailVersion.Template,
c.VerifiedCredentialExternalTypeDetailVersion.ValidFrom,
c.VerifiedCredentialExternalTypeDetailVersion.Expiry))
).AsAsyncEnumerable()
));
}
public Task<Pagination.Response<CredentialDetailData>> GetCredentials(int page, int size, CompanySsiDetailStatusId? companySsiDetailStatusId, VerifiedCredentialTypeId? credentialTypeId, CompanySsiDetailApprovalType? approvalType, CompanySsiDetailSorting? sorting) =>
Pagination.CreateResponseAsync(
page,
size,
_settings.MaxPageSize,
_repositories.GetInstance<ICompanySsiDetailsRepository>().GetAllCredentialDetails(
sorting,
companySsiDetailStatusId,
credentialTypeId,
approvalType));

public IAsyncEnumerable<OwnedVerifiedCredentialData> GetCredentialsForBpn() =>
_repositories
Expand All @@ -152,7 +121,13 @@ public async Task ApproveCredential(Guid credentialId, CancellationToken cancell

var companySsiRepository = _repositories.GetInstance<ICompanySsiDetailsRepository>();
var (exists, data) = await companySsiRepository.GetSsiApprovalData(credentialId).ConfigureAwait(ConfigureAwaitOptions.None);
ValidateApprovalData(credentialId, exists, data);

if (!exists)
{
throw NotFoundException.Create(IssuerErrors.SSI_DETAILS_NOT_FOUND, new ErrorParameter[] { new("credentialId", credentialId.ToString()) });
}

ValidateApprovalData(credentialId, data);

var processId = CreateProcess();

Expand Down Expand Up @@ -212,13 +187,8 @@ private Guid CreateProcess()
return processId;
}

private static void ValidateApprovalData(Guid credentialId, bool exists, SsiApprovalData data)
private static void ValidateApprovalData(Guid credentialId, SsiApprovalData data)
{
if (!exists)
{
throw NotFoundException.Create(IssuerErrors.SSI_DETAILS_NOT_FOUND, new ErrorParameter[] { new("credentialId", credentialId.ToString()) });
}

if (data.Status != CompanySsiDetailStatusId.PENDING)
{
throw ConflictException.Create(IssuerErrors.CREDENTIAL_NOT_PENDING, new ErrorParameter[] { new("credentialId", credentialId.ToString()), new("status", CompanySsiDetailStatusId.PENDING.ToString()) });
Expand Down
Loading

0 comments on commit bd1a6c5

Please sign in to comment.