diff --git a/src/main/java/at/esque/kafka/acl/viewer/Acl.java b/src/main/java/at/esque/kafka/acl/viewer/Acl.java index 1187327..f586e22 100644 --- a/src/main/java/at/esque/kafka/acl/viewer/Acl.java +++ b/src/main/java/at/esque/kafka/acl/viewer/Acl.java @@ -2,6 +2,7 @@ import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import org.apache.kafka.common.acl.AclBinding; import org.apache.kafka.common.acl.AclOperation; import org.apache.kafka.common.acl.AclPermissionType; import org.apache.kafka.common.resource.PatternType; @@ -15,16 +16,18 @@ public class Acl { private StringProperty operation = new SimpleStringProperty(); private StringProperty permissionType = new SimpleStringProperty(); private StringProperty host = new SimpleStringProperty(); + private AclBinding aclBinding; - public Acl(ResourceType resourceType, String resourceName, PatternType patternType, String principal, AclOperation operation, AclPermissionType permissionType, String host) + public Acl(AclBinding aclBinding) { - this.resourceType.set(resourceType.toString()); - this.resourceName.set(resourceName); - this.patternType.set(patternType.toString()); - this.principal.set(principal); - this.operation.set(operation.toString()); - this.permissionType.set(permissionType.toString()); - this.host.set(host); + this.aclBinding = aclBinding; + this.resourceType.set(aclBinding.pattern().resourceType().toString()); + this.resourceName.set(aclBinding.pattern().name()); + this.patternType.set(aclBinding.pattern().patternType().toString()); + this.principal.set(aclBinding.entry().principal()); + this.operation.set(aclBinding.entry().operation().toString()); + this.permissionType.set(aclBinding.entry().permissionType().toString()); + this.host.set(aclBinding.entry().host()); } public String getResourceType() { @@ -82,6 +85,11 @@ public String getHost() { public StringProperty hostProperty() { return host; } + + public AclBinding getAclBinding() + { + return aclBinding; + } } diff --git a/src/main/java/at/esque/kafka/acl/viewer/AclViewerController.java b/src/main/java/at/esque/kafka/acl/viewer/AclViewerController.java index 2814ecd..7585d00 100644 --- a/src/main/java/at/esque/kafka/acl/viewer/AclViewerController.java +++ b/src/main/java/at/esque/kafka/acl/viewer/AclViewerController.java @@ -11,9 +11,11 @@ import javafx.beans.property.SimpleBooleanProperty; import javafx.collections.FXCollections; import javafx.event.ActionEvent; +import javafx.event.EventHandler; import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; +import javafx.util.Callback; import org.apache.kafka.clients.consumer.KafkaConsumer; import org.apache.kafka.clients.consumer.OffsetAndMetadata; import org.apache.kafka.common.TopicPartition; @@ -22,6 +24,8 @@ import org.apache.kafka.common.resource.ResourcePattern; import org.apache.kafka.common.resource.ResourceType; +import javax.swing.*; +import java.awt.event.MouseEvent; import java.util.*; public class AclViewerController { @@ -80,6 +84,44 @@ public void initialize() { permissionTypeColumn.setCellValueFactory(new PropertyValueFactory<>("permissionType")); hostColumn.setCellValueFactory(new PropertyValueFactory<>("host")); + MenuItem mi1 = new MenuItem("Menu item 1"); + mi1.setOnAction((ActionEvent event) -> { + System.out.println("Menu item 1"); + Object item = resultView.getSelectionModel().getSelectedItem(); + System.out.println("Selected item: " + item); + }); + + // Add Delete Context Menu to Table Rows + resultView.setRowFactory( + new Callback, TableRow>() { + @Override + public TableRow call(TableView tableView) { + final TableRow row = new TableRow<>(); + final ContextMenu rowMenu = new ContextMenu(); + MenuItem removeItem = new MenuItem("Delete"); + removeItem.setOnAction(new EventHandler() { + + @Override + public void handle(ActionEvent event) { + Object item = resultView.getSelectionModel().getSelectedItem(); + + if (item instanceof Acl) + { + Acl selectedAcl = (Acl) item; + adminClient.deleteAcl(selectedAcl.getAclBinding()); + } + + startSearch(null); + + } + }); + rowMenu.getItems().addAll(removeItem); + row.contextMenuProperty().set(rowMenu); + + return row; + } + }); + } public void setup(KafkaesqueAdminClient adminClient, KafkaConsumer kafkaConsumer) { @@ -97,13 +139,7 @@ private void startSearch(ActionEvent actionEvent) { List aclList = new ArrayList<>(); adminClient.getACLs(resourceTypeCombo.getValue(), resourcePatternCombo.getValue(), resourceName.getText()) - .forEach(acl -> aclList.add(new Acl(acl.pattern().resourceType(), - acl.pattern().name(), - acl.pattern().patternType(), - acl.entry().principal(), - acl.entry().operation(), - acl.entry().permissionType(), - acl.entry().host()))); + .forEach(acl -> aclList.add(new Acl(acl))); resultView.setItems(FXCollections.observableArrayList(aclList)); }); @@ -111,6 +147,7 @@ private void startSearch(ActionEvent actionEvent) { }); } + public void stop(){ kafkaConsumer = null; } diff --git a/src/main/java/at/esque/kafka/cluster/KafkaesqueAdminClient.java b/src/main/java/at/esque/kafka/cluster/KafkaesqueAdminClient.java index 8ff19a0..7931296 100644 --- a/src/main/java/at/esque/kafka/cluster/KafkaesqueAdminClient.java +++ b/src/main/java/at/esque/kafka/cluster/KafkaesqueAdminClient.java @@ -12,14 +12,7 @@ import org.apache.kafka.common.resource.ResourcePatternFilter; import org.apache.kafka.common.resource.ResourceType; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -124,6 +117,19 @@ public List getACLs(ResourceType resourceType, PatternType resourceP return Collections.EMPTY_LIST; } + public void deleteAcl(AclBinding aclBinding) + { + try { + AclBindingFilter aclBindingFilter = new AclBindingFilter(new ResourcePatternFilter(aclBinding.pattern().resourceType(), aclBinding.pattern().name(), aclBinding.pattern().patternType()), + new AccessControlEntryFilter(aclBinding.entry().principal(), aclBinding.entry().host(), aclBinding.entry().operation(), aclBinding.entry().permissionType())); + + adminClient.deleteAcls(Collections.singletonList(aclBindingFilter)); + + } catch (Exception e) { + ErrorAlert.show(e); + } + } + public ListConsumerGroupOffsetsResult listConsumerGroupOffsets(String groupId){ return adminClient.listConsumerGroupOffsets(groupId); } diff --git a/src/main/java/at/esque/kafka/dialogs/ClusterConfigDialog.java b/src/main/java/at/esque/kafka/dialogs/ClusterConfigDialog.java index ef14298..e1832db 100644 --- a/src/main/java/at/esque/kafka/dialogs/ClusterConfigDialog.java +++ b/src/main/java/at/esque/kafka/dialogs/ClusterConfigDialog.java @@ -89,6 +89,12 @@ public static Optional show(ClusterConfig existingConfig) { .bind(copy.trustStorePasswordProperty()) ), Group.of( + Field.ofStringType(copy.getSaslSecurityProtocol()==null?"":copy.getSaslSecurityProtocol()) + .label("Security Protocol") + .tooltip("SecurityProtocol") + .placeholder("SASL_PLAIN") + .format(new NullFormatStringConverter()) + .bind(copy.saslSecurityProtocolProperty()), Field.ofStringType(copy.getSaslMechanism()==null?"":copy.getSaslMechanism()) .label("SASL Mechanism") .tooltip("SASL Mechanism") diff --git a/src/main/resources/fxml/aclViewer.fxml b/src/main/resources/fxml/aclViewer.fxml index 76617c8..41f56fa 100644 --- a/src/main/resources/fxml/aclViewer.fxml +++ b/src/main/resources/fxml/aclViewer.fxml @@ -7,7 +7,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + +