diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/Event.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/Event.java new file mode 100644 index 000000000..5472f250d --- /dev/null +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/Event.java @@ -0,0 +1,4 @@ +package org.hyperledger.bpa.api.notification; + +public class Event { +} diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerAcceptedEvent.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerAcceptedEvent.java index 56e2a9e20..f6a53bb15 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerAcceptedEvent.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerAcceptedEvent.java @@ -27,7 +27,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter -public class PartnerAcceptedEvent { +public class PartnerAcceptedEvent extends Event { private Partner partner; } diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerAddedEvent.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerAddedEvent.java index 150f1212f..05b86be77 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerAddedEvent.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerAddedEvent.java @@ -27,7 +27,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter -public class PartnerAddedEvent { +public class PartnerAddedEvent extends Event { private Partner partner; } diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRemovedEvent.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRemovedEvent.java index 6b35ac009..0b9a41df2 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRemovedEvent.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRemovedEvent.java @@ -27,7 +27,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter -public class PartnerRemovedEvent { +public class PartnerRemovedEvent extends Event { private Partner partner; } diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRequestCompletedEvent.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRequestCompletedEvent.java index d06ad40bb..3cb012969 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRequestCompletedEvent.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRequestCompletedEvent.java @@ -27,7 +27,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter -public class PartnerRequestCompletedEvent { +public class PartnerRequestCompletedEvent extends Event { private Partner partner; diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRequestReceivedEvent.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRequestReceivedEvent.java index 67fe97d22..a4f95ded7 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRequestReceivedEvent.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/api/notification/PartnerRequestReceivedEvent.java @@ -27,7 +27,7 @@ @NoArgsConstructor @AllArgsConstructor @Getter -public class PartnerRequestReceivedEvent { +public class PartnerRequestReceivedEvent extends Event { private Partner partner; diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/CredentialRuleEventHandler.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/CredentialRuleEventHandler.java index 9970bd0cb..51e12b4e8 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/CredentialRuleEventHandler.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/CredentialRuleEventHandler.java @@ -23,48 +23,48 @@ public class CredentialRuleEventHandler { @EventListener @Async - public void onCredentialAcceptedEvent (CredentialAcceptedEvent event) { + public void onCredentialAcceptedEvent(CredentialAcceptedEvent event) { log.debug("detected {}", event.getClass()); } @EventListener @Async - public void onCredentialAddedEvent (CredentialAddedEvent event) { + public void onCredentialAddedEvent(CredentialAddedEvent event) { log.debug("detected {}", event.getClass()); } @EventListener @Async - public void onCredentialIssuedEvent (CredentialIssuedEvent event) { + public void onCredentialIssuedEvent(CredentialIssuedEvent event) { log.debug("detected {}", event.getClass()); } @EventListener @Async - public void onCredentialOfferedEvent (CredentialOfferedEvent event) { + public void onCredentialOfferedEvent(CredentialOfferedEvent event) { log.debug("detected {}", event.getClass()); } @EventListener @Async - public void onCredentialProblemEvent (CredentialProblemEvent event) { + public void onCredentialProblemEvent(CredentialProblemEvent event) { log.debug("detected {}", event.getClass()); } @EventListener @Async - public void onCredentialProposalEvent (CredentialProposalEvent event) { + public void onCredentialProposalEvent(CredentialProposalEvent event) { log.debug("detected {}", event.getClass()); } - public void runRule (Object event) { + public void runRule(Object event) { List rules = rs.getAll(); log.debug("Running event against {} active rules", rules.size()); rules.parallelStream().forEach(r -> { // if (r.getTrigger().apply(event)) { - // log.debug("Run rule with id: {}", r.getRuleId()); - // r.getAction().run(event); - //} + // log.debug("Run rule with id: {}", r.getRuleId()); + // r.getAction().run(event); + // } }); } } diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/EventContext.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/EventContext.java index 3754c4d25..d62858afe 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/EventContext.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/EventContext.java @@ -1,10 +1,15 @@ package org.hyperledger.bpa.impl.rules; + import io.micronaut.context.ApplicationContext; import lombok.Builder; import lombok.Data; import org.hyperledger.aries.api.connection.ConnectionRecord; import org.hyperledger.aries.api.present_proof.PresentationExchangeRecord; +import org.hyperledger.bpa.impl.PartnerManager; +import org.hyperledger.bpa.impl.TagService; import org.hyperledger.bpa.persistence.model.Partner; +import org.hyperledger.bpa.persistence.repository.PartnerRepository; +import org.hyperledger.bpa.persistence.repository.TagRepository; @Data @Builder @@ -13,4 +18,8 @@ public class EventContext { private PresentationExchangeRecord presEx; private ConnectionRecord connRec; private ApplicationContext ctx; + private PartnerRepository partnerRepo; + private TagService tagService; + private TagRepository tagRepo; + private PartnerManager partnerManager; } diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/PartnerRuleEventHandler.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/PartnerRuleEventHandler.java index 9b328f34b..bcdda4e9b 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/PartnerRuleEventHandler.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/PartnerRuleEventHandler.java @@ -1,13 +1,15 @@ package org.hyperledger.bpa.impl.rules; -import io.micronaut.context.ApplicationContext; import io.micronaut.runtime.event.annotation.EventListener; import io.micronaut.scheduling.annotation.Async; import jakarta.inject.Inject; import jakarta.inject.Singleton; import lombok.extern.slf4j.Slf4j; import org.hyperledger.bpa.api.notification.*; +import org.hyperledger.bpa.impl.PartnerManager; +import org.hyperledger.bpa.impl.TagService; import org.hyperledger.bpa.persistence.repository.PartnerRepository; +import org.hyperledger.bpa.persistence.repository.TagRepository; import java.util.List; @@ -16,53 +18,67 @@ public class PartnerRuleEventHandler { @Inject - PartnerRepository pr; + RulesService rs; @Inject - RulesService rs; + PartnerRepository partnerRepo; + + @Inject + TagService tagService; + + @Inject + PartnerManager partnerManager; @Inject - ApplicationContext appCtx; + TagRepository tagRepo; @EventListener @Async - public void onPartnerAddedEvent (PartnerAddedEvent event) { + public void onPartnerAddedEvent(PartnerAddedEvent event) { log.debug("detected {}", event.getClass()); + runRule(event); } @EventListener @Async - public void onPartnerAcceptedEvent (PartnerAcceptedEvent event) { + public void onPartnerAcceptedEvent(PartnerAcceptedEvent event) { log.debug("detected {}", event.getClass()); runRule(event); } @EventListener @Async - public void onPartnerRemovedEvent (PartnerRemovedEvent event) { + public void onPartnerRemovedEvent(PartnerRemovedEvent event) { log.debug("detected {}", event.getClass()); + runRule(event); } @EventListener @Async - public void onPartnerRequestReceivedEvent (PartnerRequestReceivedEvent event) { + public void onPartnerRequestReceivedEvent(PartnerRequestReceivedEvent event) { log.debug("detected {}", event.getClass()); + runRule(event); } @EventListener @Async - public void onPartnerRequestCompletedEvent (PartnerRequestCompletedEvent event) { + public void onPartnerRequestCompletedEvent(PartnerRequestCompletedEvent event) { log.debug("detected {}", event.getClass()); + runRule(event); } - public void runRule (Object event) { + public void runRule(Event event) { List rules = rs.getAll(); - log.debug("Running event against {} active rules", rules.size()); + log.debug("Running event against {} active rules", rs.getAll().size()); + log.debug("Count of Partners {}", partnerRepo.findAll()); + EventContext ctx = EventContext.builder().partnerRepo(partnerRepo) + .tagService(tagService).partnerManager(partnerManager) + .tagRepo(tagRepo).build(); rules.parallelStream().forEach(r -> { - // if (r.getTrigger().apply(event)) { - // log.debug("Run rule with id: {}", r.getRuleId()); - // r.getAction().run(event); - //} + if (r.getTrigger().apply(event)) { + log.debug("Run rule with event id: {}", r.getRuleId()); + r.getAction().run(ctx); + } }); } } diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/RulesData.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/RulesData.java index a8dde722f..ec962f8b5 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/RulesData.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/RulesData.java @@ -3,13 +3,22 @@ import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeName; -import jdk.jfr.Event; + import lombok.*; import lombok.extern.slf4j.Slf4j; import org.hyperledger.aries.api.connection.ConnectionRecord; import org.hyperledger.aries.api.connection.ConnectionState; import org.hyperledger.aries.api.connection.ConnectionTheirRole; +import org.hyperledger.bpa.api.TagAPI; +import org.hyperledger.bpa.api.notification.Event; +import org.hyperledger.bpa.controller.api.partner.UpdatePartnerRequest; import org.hyperledger.bpa.persistence.model.ActiveRules; +import org.hyperledger.bpa.persistence.model.Partner; +import org.hyperledger.bpa.persistence.model.Tag; + +import java.util.List; +import java.util.Optional; +import java.util.Set; import java.util.UUID; @Slf4j @@ -26,16 +35,22 @@ public class RulesData { property = "type") @JsonSubTypes({ @JsonSubTypes.Type(value = Trigger.ConnectionTrigger.class, name = Trigger.CONNECTION_TRIGGER_NAME), - @JsonSubTypes.Type(value = Trigger.ProofReceivedTrigger.class, name = Trigger.PROOF_RECEIVED_TRIGGER_NAME) + @JsonSubTypes.Type(value = Trigger.ProofReceivedTrigger.class, name = Trigger.PROOF_RECEIVED_TRIGGER_NAME), + @JsonSubTypes.Type(value = Trigger.EventTrigger.class, name = Trigger.EVENT_TRIGGER_NAME) }) @NoArgsConstructor public abstract static class Trigger { public static final String CONNECTION_TRIGGER_NAME = "connection"; public static final String PROOF_RECEIVED_TRIGGER_NAME = "proof_received"; + public static final String EVENT_TRIGGER_NAME = "event"; abstract boolean apply(EventContext ctx); + boolean apply(Event event) { + return false; + } + @SuppressWarnings("unused") private String type; @@ -61,6 +76,26 @@ public boolean apply(EventContext ctx) { } } + @JsonTypeName(Trigger.EVENT_TRIGGER_NAME) + @Builder + @Data + @EqualsAndHashCode(callSuper = true) + @NoArgsConstructor + @AllArgsConstructor + public static class EventTrigger extends Trigger { + private String eventClassName; + + @Override + public boolean apply(EventContext ctx) { + return false; + } + + @Override + public boolean apply(Event event) { + return event.getClass().getSimpleName().equals(this.eventClassName); + } + } + @JsonTypeName(Trigger.PROOF_RECEIVED_TRIGGER_NAME) @Builder @Data @@ -108,7 +143,18 @@ public static class TagConnection extends Action { @Override void run(EventContext ctx) { - log.debug("tag: {}", tag); + // TODO: get partner by connection Id and update tags + Optional partner = ctx.getPartnerRepo().findByConnectionId(connectionId); + + if (partner.isPresent()) { + TagAPI tagApi = ctx.getTagService().addTag(tag); + ctx.getPartnerManager().updatePartner(partner.get().getId(), + UpdatePartnerRequest.builder().tag(List.of(Tag.builder().id(tagApi.getId()) + .name(tagApi.getName()).build())).build()); + + log.debug("partner tagged with tag: {}", tag); + } + log.debug("tag: {}, connectionId: {}", tag, connectionId); } } diff --git a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/RulesService.java b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/RulesService.java index 592ca802f..88a5c4c23 100644 --- a/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/RulesService.java +++ b/backend/business-partner-agent/src/main/java/org/hyperledger/bpa/impl/rules/RulesService.java @@ -4,6 +4,7 @@ import jakarta.inject.Singleton; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import org.hyperledger.bpa.api.notification.Event; import org.hyperledger.bpa.persistence.model.ActiveRules; import org.hyperledger.bpa.persistence.repository.RulesRepository; diff --git a/backend/business-partner-agent/src/main/resources/databasemigrations/V1.34__add-active-rules-table.sql b/backend/business-partner-agent/src/main/resources/databasemigrations/V1.34__add-active-rules-table.sql new file mode 100644 index 000000000..306a54ea0 --- /dev/null +++ b/backend/business-partner-agent/src/main/resources/databasemigrations/V1.34__add-active-rules-table.sql @@ -0,0 +1,7 @@ +CREATE TABLE active_rules ( + id uuid PRIMARY KEY, + created_at timestamp without time zone, + updated_at timestamp without time zone, + trigger jsonb, + action jsonb +); \ No newline at end of file diff --git a/backend/business-partner-agent/src/test/java/org/hyperledger/bpa/impl/rules/PartnerRuleEventHandlerTest.java b/backend/business-partner-agent/src/test/java/org/hyperledger/bpa/impl/rules/PartnerRuleEventHandlerTest.java new file mode 100644 index 000000000..ff6c6d589 --- /dev/null +++ b/backend/business-partner-agent/src/test/java/org/hyperledger/bpa/impl/rules/PartnerRuleEventHandlerTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2020-2022 - for information on the respective copyright owner + * see the NOTICE file and/or the repository at + * https://github.com/hyperledger-labs/business-partner-agent + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.hyperledger.bpa.impl.rules; + +import io.micronaut.context.event.ApplicationEventPublisher; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import lombok.extern.slf4j.Slf4j; +import jakarta.inject.Inject; +import org.hyperledger.bpa.api.notification.PartnerAddedEvent; +import org.hyperledger.bpa.impl.aries.connection.ConnectionManager; +import org.hyperledger.bpa.persistence.model.Partner; +import org.hyperledger.bpa.persistence.repository.PartnerRepository; +import org.hyperledger.bpa.persistence.model.Tag; +import org.hyperledger.bpa.impl.aries.AriesEventHandler; +import org.hyperledger.bpa.persistence.repository.RulesRepository; +import org.hyperledger.bpa.persistence.repository.TagRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +@Slf4j +@MicronautTest(transactional = false) +public class PartnerRuleEventHandlerTest { + + @Inject + PartnerRuleEventHandler partnerRuleEventHandler; + + @Inject + RulesService rulesService; + + @Inject + AriesEventHandler ariesEventHandler; + + @Inject + ConnectionManager manager; + + @Inject + PartnerRepository partnerRepo; + + @Inject + RulesRepository rulesRepo; + + @Inject + TagRepository tagRepo; + + @Inject + ApplicationEventPublisher eventPublisher; + + @Test + void testTagPartnerOnConnection() throws InterruptedException { + + String connectionId = "de0d51e8-4c7f-4dc9-8b7b-a8f57182d8a5"; + String did = "did:1"; + String tag = "some-tag"; + + RulesData data = rulesService.add(new RulesData.Trigger.EventTrigger(PartnerAddedEvent.class.getSimpleName()), + new RulesData.Action.TagConnection(connectionId, tag)); + + log.debug(data.toString()); + assertEquals(rulesService.getAll().size(), 1); + log.debug(rulesService.getAll().toString()); + + partnerRepo.save(Partner + .builder() + .ariesSupport(Boolean.TRUE) + .did(did) + .connectionId(connectionId) + .build()); + + Assertions.assertEquals(partnerRepo.count(),1); + + Optional pBefore = partnerRepo.findByConnectionId(connectionId); + assert (pBefore.isPresent()); + Assertions.assertEquals(Set.of(), pBefore.get().getTags()); + + eventPublisher.publishEvent(PartnerAddedEvent.builder().partner(pBefore.get()).build()); + + Assertions.assertEquals(partnerRepo.count(),1); + Assertions.assertEquals(tagRepo.count(),1); + + Optional pAfter = partnerRepo.findByConnectionId(connectionId); + assert (pAfter.isPresent()); + Assertions.assertNotEquals(Set.of(), pAfter.get().getTags()); + + log.debug("partner: {}", pAfter.get()); + checkTagOnPartner(pAfter.get().getId(), tag); + } + + private void checkTagOnPartner(UUID partnerId, String... tagName) { + Optional dbP = partnerRepo.findById(partnerId); + Assertions.assertTrue(dbP.isPresent()); + Assertions.assertNotNull(dbP.get().getTags()); + List pTags = dbP.get().getTags().stream().map(Tag::getName).toList(); + Assertions.assertEquals(tagName.length, pTags.size()); + Arrays.stream(tagName).forEach(tn -> Assertions.assertTrue(pTags.contains(tn))); + } +}