Skip to content

Commit

Permalink
Deleting a SharedAttribute does not validate if it's possible to send…
Browse files Browse the repository at this point in the history
… the Notification (#398)

* feat: revoke relationship in status pending when the neded attribute is deleted

* chore: remove focused test

* feat: add error message when deleting an attribute while a relationship is still in Pending state

* revert: unwanted change

* chore: pr comments

* chore: pr comments

* Update packages/runtime/test/consumption/attributes.test.ts

Co-authored-by: Britta Stallknecht <[email protected]>

* Update packages/runtime/test/lib/testUtils.ts

Co-authored-by: Milena Czierlinski <[email protected]>

* Update packages/runtime/test/consumption/attributes.test.ts

Co-authored-by: Milena Czierlinski <[email protected]>

* chore: fix renaming

* chore: fix renaming

* chore: fix sending messsage when relationsip is not activatable anymore

* chore: improve return type and variable naming

* chore: pr comments

* Update packages/transport/src/modules/messages/MessageController.ts

Co-authored-by: Julian König <[email protected]>

* chore: make notificationId optional

* chore: make notificationId optional

* chore: fix tests

* chore: beauty changes

* chore: beauty changes

* chore: beauty changes

---------

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: Britta Stallknecht <[email protected]>
Co-authored-by: Milena Czierlinski <[email protected]>
Co-authored-by: Julian König <[email protected]>
  • Loading branch information
5 people authored Feb 10, 2025
1 parent be35b61 commit b3a47c1
Show file tree
Hide file tree
Showing 8 changed files with 277 additions and 26 deletions.
7 changes: 7 additions & 0 deletions packages/runtime/src/useCases/common/RuntimeErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,13 @@ class Attributes {
public setDefaultRepositoryAttributesIsDisabled(): ApplicationError {
return new ApplicationError("error.runtime.attributes.setDefaultRepositoryAttributesIsDisabled", "Setting default RepositoryAttributes is disabled for this Account.");
}

public cannotDeleteSharedAttributeWhileRelationshipIsPending(): ApplicationError {
return new ApplicationError(
"error.runtime.attributes.cannotDeleteSharedAttributeWhileRelationshipIsPending",
"The shared Attribute cannot be deleted while the Relationship to the peer is in status 'Pending'."
);
}
}

class IdentityDeletionProcess {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Result } from "@js-soft/ts-utils";
import { AttributesController, ConsumptionIds, LocalAttribute } from "@nmshd/consumption";
import { Notification, OwnSharedAttributeDeletedByOwnerNotificationItem } from "@nmshd/content";
import { CoreId } from "@nmshd/core-types";
import { AccountController, MessageController } from "@nmshd/transport";
import { AccountController, MessageController, RelationshipsController, RelationshipStatus } from "@nmshd/transport";
import { Inject } from "@nmshd/typescript-ioc";
import { AttributeIdString, NotificationIdString, RuntimeErrors, SchemaRepository, SchemaValidator, UseCase } from "../../common";

Expand All @@ -11,7 +11,7 @@ export interface DeleteOwnSharedAttributeAndNotifyPeerRequest {
}

export interface DeleteOwnSharedAttributeAndNotifyPeerResponse {
notificationId: NotificationIdString;
notificationId?: NotificationIdString;
}

class Validator extends SchemaValidator<DeleteOwnSharedAttributeAndNotifyPeerRequest> {
Expand All @@ -25,6 +25,7 @@ export class DeleteOwnSharedAttributeAndNotifyPeerUseCase extends UseCase<Delete
@Inject private readonly attributesController: AttributesController,
@Inject private readonly accountController: AccountController,
@Inject private readonly messageController: MessageController,
@Inject private readonly relationshipsController: RelationshipsController,
@Inject validator: Validator
) {
super(validator);
Expand All @@ -39,13 +40,23 @@ export class DeleteOwnSharedAttributeAndNotifyPeerUseCase extends UseCase<Delete
return Result.fail(RuntimeErrors.attributes.isNotOwnSharedAttribute(ownSharedAttributeId));
}

const relationshipWithStatusPending = await this.relationshipsController.getRelationshipToIdentity(ownSharedAttribute.shareInfo.peer, RelationshipStatus.Pending);
if (relationshipWithStatusPending) {
return Result.fail(RuntimeErrors.attributes.cannotDeleteSharedAttributeWhileRelationshipIsPending());
}

const validationResult = await this.attributesController.validateFullAttributeDeletionProcess(ownSharedAttribute);
if (validationResult.isError()) {
return Result.fail(validationResult.error);
}

await this.attributesController.executeFullAttributeDeletionProcess(ownSharedAttribute);

const messageRecipientsValidationResult = await this.messageController.validateMessageRecipients([ownSharedAttribute.shareInfo.peer]);
if (messageRecipientsValidationResult.isError) {
return Result.ok({});
}

const notificationId = await ConsumptionIds.notification.generate();
const notificationItem = OwnSharedAttributeDeletedByOwnerNotificationItem.from({ attributeId: ownSharedAttributeId });
const notification = Notification.from({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import { Result } from "@js-soft/ts-utils";
import { AttributesController, ConsumptionIds, LocalAttribute } from "@nmshd/consumption";
import { Notification, PeerSharedAttributeDeletedByPeerNotificationItem } from "@nmshd/content";
import { CoreId } from "@nmshd/core-types";
import { AccountController, MessageController } from "@nmshd/transport";
import { AccountController, MessageController, RelationshipsController } from "@nmshd/transport";
import { Inject } from "@nmshd/typescript-ioc";
import { RelationshipStatus } from "../../../types";
import { AttributeIdString, NotificationIdString, RuntimeErrors, SchemaRepository, SchemaValidator, UseCase } from "../../common";

export interface DeletePeerSharedAttributeAndNotifyOwnerRequest {
attributeId: AttributeIdString;
}

export interface DeletePeerSharedAttributeAndNotifyOwnerResponse {
notificationId: NotificationIdString;
notificationId?: NotificationIdString;
}

class Validator extends SchemaValidator<DeletePeerSharedAttributeAndNotifyOwnerRequest> {
Expand All @@ -25,6 +26,7 @@ export class DeletePeerSharedAttributeAndNotifyOwnerUseCase extends UseCase<Dele
@Inject private readonly attributesController: AttributesController,
@Inject private readonly accountController: AccountController,
@Inject private readonly messageController: MessageController,
@Inject private readonly relationshipsController: RelationshipsController,
@Inject validator: Validator
) {
super(validator);
Expand All @@ -39,13 +41,23 @@ export class DeletePeerSharedAttributeAndNotifyOwnerUseCase extends UseCase<Dele
return Result.fail(RuntimeErrors.attributes.isNotPeerSharedAttribute(peerSharedAttributeId));
}

const relationshipWithStatusPending = await this.relationshipsController.getRelationshipToIdentity(peerSharedAttribute.shareInfo.peer, RelationshipStatus.Pending);
if (relationshipWithStatusPending) {
return Result.fail(RuntimeErrors.attributes.cannotDeleteSharedAttributeWhileRelationshipIsPending());
}

const validationResult = await this.attributesController.validateFullAttributeDeletionProcess(peerSharedAttribute);
if (validationResult.isError()) {
return Result.fail(validationResult.error);
}

await this.attributesController.executeFullAttributeDeletionProcess(peerSharedAttribute);

const messageRecipientsValidationResult = await this.messageController.validateMessageRecipients([peerSharedAttribute.shareInfo.peer]);
if (messageRecipientsValidationResult.isError) {
return Result.ok({});
}

const notificationId = await ConsumptionIds.notification.generate();
const notificationItem = PeerSharedAttributeDeletedByPeerNotificationItem.from({ attributeId: peerSharedAttributeId });
const notification = Notification.from({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Result } from "@js-soft/ts-utils";
import { AttributesController, ConsumptionIds, LocalAttribute } from "@nmshd/consumption";
import { Notification, ThirdPartyRelationshipAttributeDeletedByPeerNotificationItem } from "@nmshd/content";
import { CoreId } from "@nmshd/core-types";
import { AccountController, MessageController } from "@nmshd/transport";
import { AccountController, MessageController, RelationshipsController, RelationshipStatus } from "@nmshd/transport";
import { Inject } from "@nmshd/typescript-ioc";
import { AttributeIdString, NotificationIdString, RuntimeErrors, SchemaRepository, SchemaValidator, UseCase } from "../../common";

Expand All @@ -11,7 +11,7 @@ export interface DeleteThirdPartyRelationshipAttributeAndNotifyPeerRequest {
}

export interface DeleteThirdPartyRelationshipAttributeAndNotifyPeerResponse {
notificationId: NotificationIdString;
notificationId?: NotificationIdString;
}

class Validator extends SchemaValidator<DeleteThirdPartyRelationshipAttributeAndNotifyPeerRequest> {
Expand All @@ -28,6 +28,7 @@ export class DeleteThirdPartyRelationshipAttributeAndNotifyPeerUseCase extends U
@Inject private readonly attributesController: AttributesController,
@Inject private readonly accountController: AccountController,
@Inject private readonly messageController: MessageController,
@Inject private readonly relationshipsController: RelationshipsController,
@Inject validator: Validator
) {
super(validator);
Expand All @@ -44,11 +45,24 @@ export class DeleteThirdPartyRelationshipAttributeAndNotifyPeerUseCase extends U
return Result.fail(RuntimeErrors.attributes.isNotThirdPartyRelationshipAttribute(thirdPartyRelationshipAttributeId));
}

const relationshipWithStatusPending = await this.relationshipsController.getRelationshipToIdentity(
thirdPartyRelationshipAttribute.shareInfo.peer,
RelationshipStatus.Pending
);
if (relationshipWithStatusPending) {
return Result.fail(RuntimeErrors.attributes.cannotDeleteSharedAttributeWhileRelationshipIsPending());
}

const validationResult = await this.attributesController.validateFullAttributeDeletionProcess(thirdPartyRelationshipAttribute);
if (validationResult.isError()) return Result.fail(validationResult.error);

await this.attributesController.executeFullAttributeDeletionProcess(thirdPartyRelationshipAttribute);

const messageRecipientsValidationResult = await this.messageController.validateMessageRecipients([thirdPartyRelationshipAttribute.shareInfo.peer]);
if (messageRecipientsValidationResult.isError) {
return Result.ok({});
}

const notificationId = await ConsumptionIds.notification.generate();
const notificationItem = ThirdPartyRelationshipAttributeDeletedByPeerNotificationItem.from({ attributeId: thirdPartyRelationshipAttributeId });
const notification = Notification.from({
Expand Down
Loading

0 comments on commit b3a47c1

Please sign in to comment.