-
Notifications
You must be signed in to change notification settings - Fork 49
Feature/simple rules #470
base: main
Are you sure you want to change the base?
Feature/simple rules #470
Changes from 18 commits
c5b146f
60f15b4
602bdf2
3cda8ca
9ed4100
1624300
14e8834
6b485bf
e0a3bdd
6591a84
337c8b8
03df182
9e59b53
60e00ce
329901e
8e4229c
d7b5397
00bcf3a
d72f01c
2e6bcda
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright (c) 2020-2021 - 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.controller; | ||
|
||
import io.micronaut.http.HttpResponse; | ||
import io.micronaut.http.annotation.*; | ||
import io.micronaut.scheduling.TaskExecutors; | ||
import io.micronaut.scheduling.annotation.ExecuteOn; | ||
import io.micronaut.security.annotation.Secured; | ||
import io.micronaut.security.rules.SecurityRule; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import org.hyperledger.bpa.controller.api.rules.RuleRequest; | ||
import org.hyperledger.bpa.impl.rules.RulesData; | ||
import org.hyperledger.bpa.impl.rules.RulesService; | ||
|
||
import javax.inject.Inject; | ||
import java.util.List; | ||
import java.util.Optional; | ||
import java.util.UUID; | ||
|
||
@Controller("/api/rules") | ||
@Tag(name = "Rules") | ||
@Secured(SecurityRule.IS_AUTHENTICATED) | ||
@ExecuteOn(TaskExecutors.IO) | ||
public class RulesController { | ||
|
||
@Inject | ||
RulesService rules; | ||
|
||
/** | ||
* Add new rule with trigger and action | ||
* | ||
* @param ruleRequest {@link RuleRequest} | ||
* @return {@link RulesData} | ||
*/ | ||
@Post | ||
public HttpResponse<RulesData> addRule(@Body RuleRequest ruleRequest) { | ||
return HttpResponse.ok(rules.add(ruleRequest.getTrigger(), ruleRequest.getAction())); | ||
} | ||
|
||
/** | ||
* Update rule | ||
* | ||
* @param id {@link UUID} rule id | ||
* @param ruleRequest {@link RuleRequest} | ||
* @return {@link RulesData} | ||
*/ | ||
@Put("/{id}") | ||
public HttpResponse<RulesData> updateRule(@PathVariable String id, @Body RuleRequest ruleRequest) { | ||
Optional<RulesData> updated = rules.update( | ||
UUID.fromString(id), ruleRequest.getTrigger(), ruleRequest.getAction()); | ||
if (updated.isPresent()) { | ||
return HttpResponse.ok(updated.get()); | ||
} | ||
return HttpResponse.notFound(); | ||
} | ||
|
||
/** | ||
* Dele rule by id | ||
* | ||
* @param id {@link UUID} rule id | ||
* @return {@link HttpResponse} | ||
*/ | ||
@Delete("/{id}") | ||
public HttpResponse<Void> deleteRule(@PathVariable String id) { | ||
rules.delete(UUID.fromString(id)); | ||
return HttpResponse.ok(); | ||
} | ||
|
||
/** | ||
* List configured rules | ||
* | ||
* @return list of {@link RulesData} | ||
*/ | ||
@Get | ||
public HttpResponse<List<RulesData>> listRules() { | ||
return HttpResponse.ok(rules.getAll()); | ||
} | ||
|
||
/** | ||
* Get configured rule by id | ||
* | ||
* @param id {@link UUID} rule id | ||
* @return {@link RulesData} | ||
*/ | ||
@Get("/{id}") | ||
public HttpResponse<RulesData> getById(@PathVariable String id) { | ||
Optional<RulesData> rule = rules.get(UUID.fromString(id)); | ||
if (rule.isPresent()) { | ||
return HttpResponse.ok(rule.get()); | ||
} | ||
return HttpResponse.notFound(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Copyright (c) 2020-2021 - 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.controller.api.rules; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
import org.hyperledger.bpa.impl.rules.RulesData; | ||
|
||
@Data | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public class RuleRequest { | ||
private RulesData.Trigger trigger; | ||
private RulesData.Action action; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright (c) 2020-2021 - 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.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.model.Partner; | ||
|
||
@Data | ||
@Builder | ||
public class EventContext { | ||
private Partner partner; | ||
private PresentationExchangeRecord presEx; | ||
private ConnectionRecord connRec; | ||
private ApplicationContext ctx; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* Copyright (c) 2020-2021 - 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 com.fasterxml.jackson.annotation.JsonSubTypes; | ||
import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||
import com.fasterxml.jackson.annotation.JsonTypeName; | ||
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.model.ActiveRules; | ||
|
||
import java.util.UUID; | ||
|
||
@Slf4j | ||
@Data | ||
@Builder | ||
public class RulesData { | ||
|
||
private UUID ruleId; | ||
private Trigger trigger; | ||
private Action action; | ||
|
||
@JsonTypeInfo( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I used @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) to store the type information. Is there a decision, which one to use? |
||
use = JsonTypeInfo.Id.NAME, | ||
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) | ||
}) | ||
@NoArgsConstructor | ||
public abstract static class Trigger { | ||
|
||
public static final String CONNECTION_TRIGGER_NAME = "connection"; | ||
public static final String PROOF_RECEIVED_TRIGGER_NAME = "proof_received"; | ||
|
||
abstract boolean apply(EventContext ctx); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apply is a very generic name. |
||
|
||
@SuppressWarnings("unused") | ||
private String type; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the purpose of this field? It's not used via accessors and builders. The database stores Triggers as jsonb. How about pulling this field into the subclasses, if there is a purpose for it. And then change Trigger to an interface, which is the also a functional one. Or does that create serialization issues? |
||
|
||
@JsonTypeName(Trigger.CONNECTION_TRIGGER_NAME) | ||
@Builder | ||
@Data | ||
@EqualsAndHashCode(callSuper = true) | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public static class ConnectionTrigger extends Trigger { | ||
private ConnectionTheirRole role; | ||
private String tag; | ||
private String goalCode; | ||
|
||
@Override | ||
public boolean apply(EventContext ctx) { | ||
ConnectionRecord connRec = ctx.getConnRec(); | ||
boolean apply = connRec != null && ConnectionState.REQUEST.equals(connRec.getState()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. boolean isRequest = connRec != null && ConnectionState.REQUEST.equals(connRec.getState()); |
||
if (role != null) { | ||
apply = apply && role.equals(connRec.getTheirRole()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. connRec could be null? |
||
} | ||
return apply; | ||
} | ||
} | ||
|
||
@JsonTypeName(Trigger.PROOF_RECEIVED_TRIGGER_NAME) | ||
@Builder | ||
@Data | ||
@EqualsAndHashCode(callSuper = true) | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public static class ProofReceivedTrigger extends Trigger { | ||
private String tag; | ||
private UUID proofTemplateId; | ||
|
||
@Override | ||
public boolean apply(EventContext ctx) { | ||
return false; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe add a TODO, that this can be implemented as soon as proof templates are available? |
||
} | ||
} | ||
} | ||
|
||
@JsonTypeInfo( | ||
use = JsonTypeInfo.Id.NAME, | ||
property = "type") | ||
@JsonSubTypes({ | ||
@JsonSubTypes.Type(value = Action.TagConnection.class, name = Action.TAG_CONNECTION_ACTION_NAME), | ||
@JsonSubTypes.Type(value = Action.SendProofRequest.class, name = Action.SEND_PROOF_REQUEST_ACTION_NAME) | ||
}) | ||
@NoArgsConstructor | ||
public abstract static class Action { | ||
|
||
public static final String TAG_CONNECTION_ACTION_NAME = "tag_connection"; | ||
public static final String SEND_PROOF_REQUEST_ACTION_NAME = "send_proof_request"; | ||
|
||
abstract void run(EventContext ctx); | ||
|
||
@SuppressWarnings("unused") | ||
private String type; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as Trigger.type? |
||
|
||
@JsonTypeName(Action.TAG_CONNECTION_ACTION_NAME) | ||
@Builder | ||
@Data | ||
@EqualsAndHashCode(callSuper = true) | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public static class TagConnection extends Action { | ||
private String connectionId; | ||
private String tag; | ||
|
||
@Override | ||
void run(EventContext ctx) { | ||
log.debug("tag: {}", tag); | ||
} | ||
} | ||
|
||
@JsonTypeName(Action.SEND_PROOF_REQUEST_ACTION_NAME) | ||
@Builder | ||
@Data | ||
@EqualsAndHashCode(callSuper = true) | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
public static class SendProofRequest extends Action { | ||
private String connectionId; | ||
private UUID proofTemplateId; | ||
|
||
@Override | ||
void run(EventContext ctx) { | ||
|
||
} | ||
} | ||
} | ||
|
||
public static RulesData fromActive(@NonNull ActiveRules ar) { | ||
return RulesData.builder() | ||
.ruleId(ar.getId()) | ||
.trigger(ar.getTrigger()) | ||
.action(ar.getAction()) | ||
.build(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename method? It does not solely log.
accept event? consume?