Skip to content

Commit

Permalink
feat(administration service): change error handling (#1192)
Browse files Browse the repository at this point in the history
* Error handling approach changed in administration services
---------
Co-authored-by: Norbert Truchsess <[email protected]>
  • Loading branch information
AnuragNagpure authored Dec 18, 2024
1 parent 07895a0 commit 75db806
Show file tree
Hide file tree
Showing 19 changed files with 678 additions and 266 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
********************************************************************************/

using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Async;
using Org.Eclipse.TractusX.Portal.Backend.Framework.DateTimeProvider;
Expand Down Expand Up @@ -57,7 +58,7 @@ public async Task<CompanyAddressDetailData> GetCompanyDetailsAsync()
.ConfigureAwait(ConfigureAwaitOptions.None);
if (result == null)
{
throw new ConflictException($"company {companyId} is not a valid company");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_CONFLICT_INVALID_COMPANY, new ErrorParameter[] { new(nameof(companyId), companyId.ToString()) });
}

return result;
Expand All @@ -77,7 +78,7 @@ public async Task<bool> CreateCompanyAssignedUseCaseDetailsAsync(Guid useCaseId)
.ConfigureAwait(ConfigureAwaitOptions.None);
if (!useCaseDetails.IsActiveCompanyStatus)
{
throw new ConflictException("Company Status is Incorrect");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_CONFLICT_INCORR_COMPANY_STATUS);
}

if (useCaseDetails.IsUseCaseIdExists)
Expand All @@ -99,12 +100,12 @@ public async Task RemoveCompanyAssignedUseCaseDetailsAsync(Guid useCaseId)
.ConfigureAwait(ConfigureAwaitOptions.None);
if (!useCaseDetails.IsActiveCompanyStatus)
{
throw new ConflictException("Company Status is Incorrect");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_CONFLICT_INCORR_COMPANY_STATUS);
}

if (!useCaseDetails.IsUseCaseIdExists)
{
throw new ConflictException($"UseCaseId {useCaseId} is not available");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_CONFLICT_USECASEID_NOT_AVAL);
}

companyRepositories.RemoveCompanyAssignedUseCase(companyId, useCaseId);
Expand All @@ -116,19 +117,19 @@ public async IAsyncEnumerable<CompanyRoleConsentViewData> GetCompanyRoleAndConse
var companyId = _identityData.CompanyId;
if (languageShortName != null && !await portalRepositories.GetInstance<ILanguageRepository>().IsValidLanguageCode(languageShortName).ConfigureAwait(ConfigureAwaitOptions.None))
{
throw new ControllerArgumentException($"language {languageShortName} is not a valid languagecode");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_LANG_CODE_NOT_VALID, new ErrorParameter[] { new(nameof(languageShortName), languageShortName) });
}

var companyRepositories = portalRepositories.GetInstance<ICompanyRepository>();
var statusData = await companyRepositories.GetCompanyStatusDataAsync(companyId).ConfigureAwait(ConfigureAwaitOptions.None);
if (statusData == default)
{
throw new NotFoundException($"company {companyId} does not exist");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_NOT_COMPANY_NOT_EXIST, new ErrorParameter[] { new(nameof(companyId), companyId.ToString()) });
}

if (!statusData.IsActive)
{
throw new ConflictException("Company Status is Incorrect");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_CONFLICT_INCORR_COMPANY_STATUS);
}

await foreach (var data in companyRepositories.GetCompanyRoleAndConsentAgreementDataAsync(companyId, languageShortName ?? Constants.DefaultLanguage).ConfigureAwait(false))
Expand Down Expand Up @@ -165,17 +166,17 @@ public async Task CreateCompanyRoleAndConsentAgreementDetailsAsync(IEnumerable<C
.ConfigureAwait(ConfigureAwaitOptions.None);
if (!result.IsValidCompany)
{
throw new ConflictException($"company {_identityData.CompanyId} does not exist");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_NOT_COMPANY_NOT_EXIST, new ErrorParameter[] { new("companyId", _identityData.CompanyId.ToString()) });
}

if (!result.IsCompanyActive)
{
throw new ConflictException("Company Status is Incorrect");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_CONFLICT_INCORR_COMPANY_STATUS);
}

if (result.CompanyRoleIds == null || result.ConsentStatusDetails == null)
{
throw new UnexpectedConditionException("neither CompanyRoleIds nor ConsentStatusDetails should ever be null here");
throw UnexpectedConditionException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_UNEXP_COMP_ROLES_NOR_DETAILS_NULL);
}

var agreementAssignedRoleData = await companyRepositories
Expand Down Expand Up @@ -204,18 +205,18 @@ public async Task CreateCompanyRoleAndConsentAgreementDetailsAsync(IEnumerable<C
var missing = joined.Where(x => x.MissingAgreementIds.Any() && !x.AllInActiveAgreements);
if (missing.Any())
{
throw new ControllerArgumentException($"All agreements need to get signed as Active or InActive. Missing consents: [{string.Join(", ", missing.Select(x => $"{x.CompanyRoleId}: [{string.Join(", ", x.MissingAgreementIds)}]"))}]");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_AGREEMENT_ACTIVE_INACTIVE_MISSING, new ErrorParameter[] { new("consentType", string.Join(", ", missing.Select(x => $"{x.CompanyRoleId}: [{string.Join(", ", x.MissingAgreementIds)}]"))) });
}

if (!joined.Exists(x => x.AllActiveAgreements))
{
throw new ConflictException("Company can't unassign from all roles, Atleast one Company role need to signed as active");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_CONFLICT_NOT_UNASSIGN_ALL_ROLES_ATLEAST_ONE_ACTIVE_NEEDED);
}

var extra = joined.Where(x => x.ExtraAgreementIds.Any());
if (extra.Any())
{
throw new ControllerArgumentException($"Agreements not associated with requested companyRoles: [{string.Join(", ", extra.Select(x => $"{x.CompanyRoleId}: [{string.Join(", ", x.ExtraAgreementIds)}]"))}]");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_AGREEMENT_NOT_ASSOCIATE_COMPANY_ROLES, new ErrorParameter[] { new("companyRoles", string.Join(", ", extra.Select(x => $"{x.CompanyRoleId}: [{string.Join(", ", x.ExtraAgreementIds)}]"))) });
}

portalRepositories.GetInstance<IConsentRepository>().AddAttachAndModifyConsents(
Expand Down Expand Up @@ -247,24 +248,24 @@ public async Task CreateCompanyCertificate(CompanyCertificateCreationData data,
{
if (data.ExternalCertificateNumber != null && !EcmRegex.IsMatch(data.ExternalCertificateNumber))
{
throw new ControllerArgumentException("ExternalCertificateNumber must be alphanumeric and length should not be greater than 36");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_EXTER_CERT_APLHA_LENGTH);
}

if (data.Sites != null && data.Sites.Any(bpn => !BpnsRegex.IsMatch(bpn)))
{
throw new ControllerArgumentException("BPN must contain exactly 16 characters and must be prefixed with BPNS");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_PREFIXED_BPNS_SIXTEEN_CHAR);
}

var now = dateTimeProvider.OffsetNow;

if (data.ValidFrom > now)
{
throw new ControllerArgumentException("ValidFrom date should not be greater than current date");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_NOT_GREATER_CURR_DATE);
}

if (data.ValidTill < now)
{
throw new ControllerArgumentException("ValidTill date should be greater than current date");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_SHOULD_GREATER_THAN_CURR_DATE);
}

if (data.Issuer != null && !data.Issuer.IsValidCompanyName())
Expand All @@ -278,7 +279,7 @@ public async Task CreateCompanyCertificate(CompanyCertificateCreationData data,
var companyCertificateRepository = portalRepositories.GetInstance<ICompanyCertificateRepository>();
if (!await companyCertificateRepository.CheckCompanyCertificateType(data.CertificateType).ConfigureAwait(ConfigureAwaitOptions.None))
{
throw new ControllerArgumentException($"{data.CertificateType} is not assigned to a certificate");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_CERT_TYPE_NOT_ASSIGN_CERTIFICATE, new ErrorParameter[] { new("certificateType", data.CertificateType.ToString()) });
}

await HandleCompanyCertificateCreationAsync(data.CertificateType, data.Document, documentContentType, companyCertificateRepository, data.ExternalCertificateNumber, data.Sites, data.ValidFrom, data.ValidTill, data.Issuer, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None);
Expand Down Expand Up @@ -322,15 +323,15 @@ public async IAsyncEnumerable<CompanyCertificateBpnData> GetCompanyCertificatesB
{
if (string.IsNullOrWhiteSpace(businessPartnerNumber))
{
throw new ControllerArgumentException("businessPartnerNumber must not be empty");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_BPN_NOT_EMPTY);
}

var companyCertificateRepository = portalRepositories.GetInstance<ICompanyCertificateRepository>();

var companyId = await companyCertificateRepository.GetCompanyIdByBpn(businessPartnerNumber).ConfigureAwait(ConfigureAwaitOptions.None);
if (companyId == Guid.Empty)
{
throw new ControllerArgumentException($"company does not exist for {businessPartnerNumber}");
throw ControllerArgumentException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_ARGUMENT_COMP_NOT_EXISTS_FOR_BPN, new ErrorParameter[] { new(nameof(businessPartnerNumber), businessPartnerNumber) });
}

await foreach (var data in companyCertificateRepository.GetCompanyCertificateData(companyId))
Expand Down Expand Up @@ -369,17 +370,17 @@ public async Task<int> DeleteCompanyCertificateAsync(Guid documentId)
var certificateCount = details.CompanyCertificateId.Count();
if (certificateCount > 1)
{
throw new ConflictException($"There must not be multiple active certificates for document {documentId}");
throw ConflictException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_CONFLICT_MULTIPLE_ACTIVE_CERT_NOT_ALLOWED_ONE_DOC, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}

if (details.DocumentId == Guid.Empty)
{
throw new NotFoundException("Document is not existing");
throw NotFoundException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_NOT_DOC_NOT_EXIST);
}

if (!details.IsSameCompany)
{
throw new ForbiddenException("User is not allowed to delete this document");
throw ForbiddenException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_FORBIDDEN_USER_NOT_ALLOW_DEL_DOC);
}

companyCertificateRepository.AttachAndModifyCompanyCertificateDocumentDetails(documentId, null, c =>
Expand Down Expand Up @@ -408,7 +409,7 @@ public async Task<int> DeleteCompanyCertificateAsync(Guid documentId)

if (!documentDetails.Exists)
{
throw new NotFoundException($"Company certificate document {documentId} does not exist");
throw NotFoundException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_NOT_COMP_CERT_DOC_NOT_EXIST, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}

return (documentDetails.FileName, documentDetails.Content, documentDetails.MediaTypeId.MapToMediaType());
Expand All @@ -423,12 +424,12 @@ public async Task<int> DeleteCompanyCertificateAsync(Guid documentId)

if (!documentDetails.Exists)
{
throw new NotFoundException($"Company certificate document {documentId} does not exist");
throw NotFoundException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_NOT_COMP_CERT_DOC_NOT_EXIST, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}

if (!documentDetails.IsStatusLocked)
{
throw new ForbiddenException($"Document {documentId} status is not locked");
throw ForbiddenException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_FORBIDDEN_DOC_STATUS_NOT_LOCKED, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}

return (documentDetails.FileName, documentDetails.Content, documentDetails.MediaTypeId.MapToMediaType());
Expand Down Expand Up @@ -463,7 +464,7 @@ public async Task RetriggerSelfDescriptionCreation(Guid processId)
var (validProcessId, processData) = await portalRepositories.GetInstance<IProcessStepRepository>().IsValidProcess(processId, ProcessTypeId.SELF_DESCRIPTION_CREATION, Enumerable.Repeat(StepToTrigger, 1)).ConfigureAwait(ConfigureAwaitOptions.None);
if (!validProcessId)
{
throw new NotFoundException($"process {processId} does not exist");
throw NotFoundException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_NOT_PROCESSID_NOT_EXIST, new ErrorParameter[] { new(nameof(processId), processId.ToString()) });
}

var context = processData.CreateManualProcessData(StepToTrigger, portalRepositories, () => $"processId {processId}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
********************************************************************************/

using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Extensions;
Expand Down Expand Up @@ -56,17 +57,17 @@ public DocumentsBusinessLogic(IPortalRepositories portalRepositories, IIdentityS
.ConfigureAwait(ConfigureAwaitOptions.None);
if (documentDetails == default)
{
throw new NotFoundException($"Document {documentId} does not exist");
throw NotFoundException.Create(AdministrationDocumentErrors.DOCUMENT_NOT_DOC_NOT_EXIST, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}

if (!documentDetails.IsUserInCompany)
{
throw new ForbiddenException("User is not allowed to access the document");
throw ForbiddenException.Create(AdministrationDocumentErrors.DOCUMENT_FORBIDDEN_USER_NOT_ALLOW_ACCESS_DOC);
}

if (documentDetails.Content == null)
{
throw new UnexpectedConditionException("documentContent should never be null here");
throw UnexpectedConditionException.Create(AdministrationDocumentErrors.DOCUMENT_UNEXPECT_DOC_CONTENT_NOT_NULL);
}

return (documentDetails.FileName, documentDetails.Content, documentDetails.MediaTypeId.MapToMediaType());
Expand All @@ -80,7 +81,7 @@ public DocumentsBusinessLogic(IPortalRepositories portalRepositories, IIdentityS
.ConfigureAwait(ConfigureAwaitOptions.None);
if (documentDetails == default)
{
throw new NotFoundException($"Self description document {documentId} does not exist");
throw NotFoundException.Create(AdministrationDocumentErrors.DOCUMENT_NOT_SELFDESP_DOC_NOT_EXIST, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}
return (documentDetails.FileName, documentDetails.Content, documentDetails.MediaTypeId.MapToMediaType());
}
Expand All @@ -93,17 +94,17 @@ public async Task<bool> DeleteDocumentAsync(Guid documentId)

if (details.DocumentId == Guid.Empty)
{
throw new NotFoundException("Document is not existing");
throw NotFoundException.Create(AdministrationDocumentErrors.DOCUMENT_NOT_DOC_NOT_EXIST, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}

if (!details.IsSameUser)
{
throw new ForbiddenException("User is not allowed to delete this document");
throw ForbiddenException.Create(AdministrationDocumentErrors.DOCUMENT_FORBIDDEN_USER_NOT_ALLOW_DEL_DOC);
}

if (details.DocumentStatusId == DocumentStatusId.LOCKED)
{
throw new ArgumentException("Incorrect document status");
throw ControllerArgumentException.Create(AdministrationDocumentErrors.DOCUMENT_ARGUMENT_INCORR_DOC_STATUS);
}

documentRepository.RemoveDocument(details.DocumentId);
Expand All @@ -121,15 +122,15 @@ public async Task<DocumentSeedData> GetSeedData(Guid documentId)
{
if (!_settings.EnableSeedEndpoint)
{
throw new ForbiddenException("Endpoint can only be used on dev environment");
throw ForbiddenException.Create(AdministrationDocumentErrors.DOCUMENT_FORBIDDEN_ENDPOINT_ALLOW_USE_IN_DEV_ENV);
}

var document = await _portalRepositories.GetInstance<IDocumentRepository>()
.GetDocumentSeedDataByIdAsync(documentId)
.ConfigureAwait(ConfigureAwaitOptions.None);
if (document == null)
{
throw new NotFoundException($"Document {documentId} does not exists.");
throw NotFoundException.Create(AdministrationDocumentErrors.DOCUMENT_NOT_DOC_NOT_EXIST, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}

return document;
Expand All @@ -143,11 +144,11 @@ public async Task<DocumentSeedData> GetSeedData(Guid documentId)
var documentDetails = await documentRepository.GetDocumentAsync(documentId, _settings.FrameDocumentTypeIds).ConfigureAwait(ConfigureAwaitOptions.None);
if (documentDetails == default)
{
throw new NotFoundException($"document {documentId} does not exist.");
throw NotFoundException.Create(AdministrationDocumentErrors.DOCUMENT_NOT_DOC_NOT_EXIST, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}
if (!documentDetails.IsDocumentTypeMatch)
{
throw new NotFoundException($"document {documentId} does not exist.");
throw NotFoundException.Create(AdministrationDocumentErrors.DOCUMENT_NOT_DOC_NOT_EXIST, new ErrorParameter[] { new(nameof(documentId), documentId.ToString()) });
}

return (documentDetails.FileName, documentDetails.Content);
Expand Down
Loading

0 comments on commit 75db806

Please sign in to comment.