Skip to content
Open
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
4 changes: 4 additions & 0 deletions charts/dim/templates/cronjob-processes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ spec:
value: "{{ .Values.processesworker.provisioning.encryptionConfigs.index0.paddingMode }}"
- name: "DIM__STATUSLISTTYPE"
value: "{{ .Values.processesworker.dim.statusListType }}"
- name: "DIM__ISSUERDID"
value: "{{ .Values.processesworker.dim.issuerDid }}"
- name: "DIM__ISSUERNAME"
value: "{{ .Values.processesworker.dim.issuerName }}"
- name: "PROVISIONING__CLIENTID"
value: "{{ .Values.processesworker.provisioning.clientId }}"
- name: "PROVISIONING__CLIENTSECRET"
Expand Down
2 changes: 2 additions & 0 deletions charts/dim/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ processesworker:
# -- Sets the type of the status list which will be created for the issuer wallet
# -- valid types are: StatusList2021, BitstringStatusList
statusListType: "StatusList2021"
issuerDid: ""
issuerName: ""
provisioning:
clientId: ""
clientSecret: ""
Expand Down
2 changes: 2 additions & 0 deletions environments/helm-values/values-int.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ processesworker:
default: "Debug"
dim:
applicationName: "catena-x-portal"
issuerDid: ""
issuerName: ""
provisioning:
clientId: "<path:portal/data/dim/int/provisioning#clientId>"
clientSecret: "<path:portal/data/dim/int/provisioning#clientSecret>"
Expand Down
2 changes: 2 additions & 0 deletions environments/helm-values/values-stable.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ processesworker:
default: "Debug"
dim:
applicationName: "catena-x-portal"
issuerDid: ""
issuerName: ""
provisioning:
clientId: "<path:portal/data/dim/stable/provisioning#clientId>"
clientSecret: "<path:portal/data/dim/stable/provisioning#clientSecret>"
Expand Down
28 changes: 28 additions & 0 deletions src/clients/Dim.Clients/Api/Dim/DimClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,34 @@ public async Task<CompanyData> GetCompanyData(BasicAuthSettings dimAuth, string
}
}

public async Task<string> UpdateCompanyStatus(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, CancellationToken cancellationToken)
{
var client = await basicAuthTokenService.GetBasicAuthorizedClient<DimClient>(dimAuth, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
var result = await client.PatchAsync($"{dimBaseUrl}/api/v2.0.0/companyIdentities/{companyId}/status", null, cancellationToken)
.CatchingIntoServiceExceptionFor("update-company-status", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE,
async m =>
{
var message = await m.Content.ReadAsStringAsync().ConfigureAwait(ConfigureAwaitOptions.None);
return (false, message);
}).ConfigureAwait(false);
try
{
var response = await result.Content
.ReadFromJsonAsync<CompanyStatusResponse>(JsonSerializerExtensions.Options, cancellationToken)
.ConfigureAwait(ConfigureAwaitOptions.None);
if (response?.Status == null || response.Status != "successful")
{
throw new ServiceException("Company status update failed", true);
}

return response.Status;
}
catch (JsonException je)
{
throw new ServiceException(je.Message);
}
}

public async Task<string> GetStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, StatusListType statusListType, CancellationToken cancellationToken)
{
var client = await basicAuthTokenService.GetBasicAuthorizedClient<DimClient>(dimAuth, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
Expand Down
1 change: 1 addition & 0 deletions src/clients/Dim.Clients/Api/Dim/IDimClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ namespace Dim.Clients.Api.Dim;
public interface IDimClient
{
Task<CompanyData> GetCompanyData(BasicAuthSettings dimAuth, string dimBaseUrl, string tenantName, string application, CancellationToken cancellationToken);
Task<string> UpdateCompanyStatus(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, CancellationToken cancellationToken);
Task<string> GetStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, StatusListType statusListType, CancellationToken cancellationToken);
Task<string> CreateStatusList(BasicAuthSettings dimAuth, string dimBaseUrl, Guid companyId, StatusListType statusListType, CancellationToken cancellationToken);
}
5 changes: 5 additions & 0 deletions src/clients/Dim.Clients/Api/Dim/Models/CompanyData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ public record CompanyData(
[property: JsonPropertyName("id")] Guid CompanyId,
[property: JsonPropertyName("downloadURL")] string DownloadUrl
);

public record CompanyStatusResponse(
[property: JsonPropertyName("operation")] string Operation,
[property: JsonPropertyName("status")] string Status
);
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2024 BMW Group AG
* Copyright (c) 2025 BMW Group AG
* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors.
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down
2 changes: 1 addition & 1 deletion src/clients/Dim.Clients/Api/Div/IProvisioningClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace Dim.Clients.Api.Div;

public interface IProvisioningClient
{
Task<Guid> CreateOperation(Guid customerId, string customerName, string applicationName, string companyName, string didDocumentLocation, bool isIssuer, CancellationToken cancellationToken);
Task<Guid> CreateOperation(Guid customerId, string customerName, string applicationName, string companyName, string didDocumentLocation, bool isIssuer, string issuerDid, string issuerName, CancellationToken cancellationToken);
Task<OperationResponse> GetOperation(Guid operationId, CancellationToken cancellationToken);
Task<Guid> CreateServiceKey(string technicalUserName, Guid walletId, CancellationToken cancellationToken);
Task<Guid?> DeleteServiceKey(Guid walletId, Guid serviceKeyId, CancellationToken cancellationToken);
Expand Down
10 changes: 8 additions & 2 deletions src/clients/Dim.Clients/Api/Div/Models/OperationRequest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2024 BMW Group AG
* Copyright (c) 2025 BMW Group AG
* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors.
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down Expand Up @@ -48,7 +48,7 @@ public record WalletApplication(
public record ApplicationCompany(
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("hostingURL")] string HostingUrl,
[property: JsonPropertyName("services")] IEnumerable<ApplicationCompanyService> Services,
[property: JsonPropertyName("protocols")] string[] Protocols,
[property: JsonPropertyName("keys")] IEnumerable<ApplicationCompanyKey> Keys
);

Expand All @@ -64,9 +64,15 @@ public record ApplicationCompanyKey(
public record TrustedIssuer(
[property: JsonPropertyName("name")] string Name,
[property: JsonPropertyName("did")] string Did,
[property: JsonPropertyName("credentialTypeConfiguration")] IEnumerable<CredentialTypeConfiguration> CredentialTypeConfiguration,
[property: JsonPropertyName("ignoreMissingHashlist")] bool IgnoreMissingHashlist
);

public record CredentialTypeConfiguration(
[property: JsonPropertyName("credentialType")] string CredentialType,
[property: JsonPropertyName("autoAcceptOffers")] bool AutoAcceptOffers
);

public record OperationRequest(
[property: JsonPropertyName("operationId")] Guid OperationId
);
24 changes: 19 additions & 5 deletions src/clients/Dim.Clients/Api/Div/ProvisioningClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/********************************************************************************
* Copyright (c) 2024 BMW Group AG
* Copyright (c) 2025 BMW Group AG
* Copyright 2024 SAP SE or an SAP affiliate company and ssi-dim-middle-layer contributors.
*
* See the NOTICE file(s) distributed with this work for additional
Expand Down Expand Up @@ -35,7 +35,7 @@ public class ProvisioningClient(IBasicAuthTokenService basicAuthTokenService, IO
{
private readonly ProvisioningSettings _settings = options.Value;

public async Task<Guid> CreateOperation(Guid customerId, string customerName, string applicationName, string companyName, string didDocumentLocation, bool isIssuer, CancellationToken cancellationToken)
public async Task<Guid> CreateOperation(Guid customerId, string customerName, string applicationName, string companyName, string didDocumentLocation, bool isIssuer, string issuerDid, string issuerName, CancellationToken cancellationToken)
{
var data = new OperationCreationRequest(
"provision",
Expand All @@ -50,7 +50,7 @@ public async Task<Guid> CreateOperation(Guid customerId, string customerName, st
Enumerable.Repeat(new ApplicationCompany(
companyName,
didDocumentLocation,
[new ApplicationCompanyService("CredentialService", "https://dis-agent-prod.eu10.dim.cloud.sap/api/v1.0.0/iatp")],
isIssuer ? ["dcp-issuer", "dcp-holder"] : ["dcp-holder"],
isIssuer ?
[
new("SIGNING"),
Expand All @@ -61,7 +61,21 @@ [new ApplicationCompanyService("CredentialService", "https://dis-agent-prod.eu10
new("SIGNING")
}
), 1),
Enumerable.Empty<TrustedIssuer>()
isIssuer
? Enumerable.Empty<TrustedIssuer>()
: new[]
{
new TrustedIssuer(
issuerName,
issuerDid,
[
new CredentialTypeConfiguration("BpnCredential", true),
new CredentialTypeConfiguration("MembershipCredential", true),
new CredentialTypeConfiguration("DataExchangeGovernanceCredential", true)
],
false
)
}
), 1)
)
)
Expand Down Expand Up @@ -139,7 +153,7 @@ public async Task<Guid> CreateServiceKey(string technicalUserName, Guid walletId
new ServiceKeyCreationPayloadData(
walletId,
technicalUserName,
new ServiceKeyParameter(new[] { "IatpOperations", "ReadCompanyIdentity", "ResolveDID" })
new ServiceKeyParameter(new[] { "IatpOperations", "DcpOperations", "ReadCompanyIdentity", "ResolveDID" })
)
);
var client = await basicAuthTokenService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public interface ITenantRepository
Task<(string? BaseUrl, WalletData WalletData)> GetCompanyRequestData(Guid tenantId);
Task<(bool Exists, Guid? CompanyId, string? BaseUrl, WalletData WalletData)> GetCompanyAndWalletDataForBpn(string bpn);
Task<(Guid? CompanyId, string? BaseUrl, WalletData WalletData)> GetStatusListCreationData(Guid tenantId);
Task<(string Bpn, string? BaseUrl, WalletData WalletData, string? Did, string? DownloadUrl)> GetCallbackData(Guid tenantId);
Task<(string Bpn, Guid? CompanyId, string? BaseUrl, WalletData WalletData, string? Did, string? DownloadUrl)> GetCallbackData(Guid tenantId);
Task<(string? DownloadUrl, bool IsIssuer)> GetDownloadUrlAndIsIssuer(Guid tenantId);
Task<ProcessData?> GetWalletProcessForTenant(string bpn, string companyName);
}
5 changes: 3 additions & 2 deletions src/database/Dim.DbAccess/Repositories/TenantRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,12 @@ public Task<bool> IsTenantExisting(string companyName, string bpn) =>
)))
.SingleOrDefaultAsync();

public Task<(string Bpn, string? BaseUrl, WalletData WalletData, string? Did, string? DownloadUrl)> GetCallbackData(Guid tenantId) =>
public Task<(string Bpn, Guid? CompanyId, string? BaseUrl, WalletData WalletData, string? Did, string? DownloadUrl)> GetCallbackData(Guid tenantId) =>
dbContext.Tenants
.Where(x => x.Id == tenantId)
.Select(x => new ValueTuple<string, string?, WalletData, string?, string?>(
.Select(x => new ValueTuple<string, Guid?, string?, WalletData, string?, string?>(
x.Bpn,
x.CompanyId,
x.BaseUrl,
new WalletData(
x.TokenAddress,
Expand Down
7 changes: 6 additions & 1 deletion src/processes/DimProcess.Library/Callback/CallbackService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Framework.HttpClientExtensions;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Token;
using System.Net;
using System.Net.Http.Json;
using System.Text.Json;

Expand All @@ -42,8 +43,12 @@ public async Task SendCallback(string bpn, AuthenticationDetail authenticationDe
didDocument,
authenticationDetail
);
ValueTask<(bool, string?)> CustomErrorHandling(HttpResponseMessage errorResponse) => new(
(errorResponse.StatusCode == HttpStatusCode.Conflict,
null));

await httpClient.PostAsJsonAsync($"/api/administration/registration/dim/{bpn}", data, JsonSerializerExtensions.Options, cancellationToken)
.CatchingIntoServiceExceptionFor("send-callback", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE)
.CatchingIntoServiceExceptionFor("send-callback", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE, CustomErrorHandling)
.ConfigureAwait(false);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@ public class DimHandlerSettings

[Required]
public StatusListType StatusListType { get; set; }

[Required]
public string IssuerDid { get; set; } = null!;

[Required]
public string IssuerName { get; set; } = null!;
}
19 changes: 17 additions & 2 deletions src/processes/DimProcess.Library/DimProcessHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public class DimProcessHandler(
throw new UnexpectedConditionException("DidDocumentLocation must always be set");
}

var operationId = await provisioningClient.CreateOperation(tenantId, tenantName, _settings.ApplicationName, tenantName, didDocumentLocation, isIssuer, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
var operationId = await provisioningClient.CreateOperation(tenantId, tenantName, _settings.ApplicationName, tenantName, didDocumentLocation, isIssuer, _settings.IssuerDid, _settings.IssuerName, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
tenantRepository.AttachAndModifyTenant(tenantId, t => t.OperationId = null, t => t.OperationId = operationId);

return new ValueTuple<IEnumerable<ProcessStepTypeId>?, ProcessStepStatusId, bool, string?>(
Expand Down Expand Up @@ -226,7 +226,7 @@ public class DimProcessHandler(

public async Task<(IEnumerable<ProcessStepTypeId>? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> SendCallback(Guid tenantId, CancellationToken cancellationToken)
{
var (bpn, baseUrl, walletData, did, downloadUrl) = await dimRepositories.GetInstance<ITenantRepository>().GetCallbackData(tenantId).ConfigureAwait(ConfigureAwaitOptions.None);
var (bpn, companyId, baseUrl, walletData, did, downloadUrl) = await dimRepositories.GetInstance<ITenantRepository>().GetCallbackData(tenantId).ConfigureAwait(ConfigureAwaitOptions.None);
var (tokenAddress, clientId, clientSecret, initializationVector, encryptionMode) = walletData.ValidateData();
if (baseUrl == null)
{
Expand All @@ -243,13 +243,28 @@ public class DimProcessHandler(
throw new UnexpectedConditionException("DownloadUrl must always be set");
}

if (companyId == null)
{
throw new UnexpectedConditionException("CompanyId must always be set");
}

var cryptoHelper = _settings.EncryptionConfigs.GetCryptoHelper(encryptionMode);
var secret = cryptoHelper.Decrypt(clientSecret, initializationVector);

var didDocument = await GetDidDocument(downloadUrl, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
var uaa = new AuthenticationDetail(tokenAddress, clientId, secret);
await callbackService.SendCallback(bpn, uaa, didDocument, did, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);

var dimAuth = new BasicAuthSettings
{
TokenAddress = $"{tokenAddress}/oauth/token",
ClientId = clientId,
ClientSecret = secret
};
await dimClient
.UpdateCompanyStatus(dimAuth, baseUrl, companyId.Value, cancellationToken)
.ConfigureAwait(ConfigureAwaitOptions.None);

return new ValueTuple<IEnumerable<ProcessStepTypeId>?, ProcessStepStatusId, bool, string?>(
null,
ProcessStepStatusId.DONE,
Expand Down
4 changes: 3 additions & 1 deletion src/processes/Processes.Worker/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
"PaddingMode": ""
}
],
"StatusListType": ""
"StatusListType": "",
"IssuerDid": "",
"IssuerName": ""
},
"Processes": {
"LockExpirySeconds": 300
Expand Down
Loading
Loading