/******************************************************************************* * Copyright (c) 2011, 2016 Eurotech and/or its affiliates * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eurotech *******************************************************************************/ package org.eclipse.kura.web.client.ui.Firewall; import java.util.ArrayList; import java.util.List; import org.eclipse.kura.web.client.messages.Messages; import org.eclipse.kura.web.client.ui.EntryClassUi; import org.eclipse.kura.web.client.ui.Tab; import org.eclipse.kura.web.client.util.FailureHandler; import org.eclipse.kura.web.client.util.TextFieldValidator.FieldType; import org.eclipse.kura.web.shared.model.GwtFirewallNatEntry; import org.eclipse.kura.web.shared.model.GwtFirewallNatMasquerade; import org.eclipse.kura.web.shared.model.GwtFirewallNatProtocol; import org.eclipse.kura.web.shared.model.GwtXSRFToken; import org.eclipse.kura.web.shared.service.GwtNetworkService; import org.eclipse.kura.web.shared.service.GwtNetworkServiceAsync; import org.eclipse.kura.web.shared.service.GwtSecurityTokenService; import org.eclipse.kura.web.shared.service.GwtSecurityTokenServiceAsync; import org.gwtbootstrap3.client.shared.event.ModalHideEvent; import org.gwtbootstrap3.client.shared.event.ModalHideHandler; import org.gwtbootstrap3.client.ui.Alert; import org.gwtbootstrap3.client.ui.Button; import org.gwtbootstrap3.client.ui.FormGroup; import org.gwtbootstrap3.client.ui.FormLabel; import org.gwtbootstrap3.client.ui.ListBox; import org.gwtbootstrap3.client.ui.Modal; import org.gwtbootstrap3.client.ui.ModalBody; import org.gwtbootstrap3.client.ui.ModalFooter; import org.gwtbootstrap3.client.ui.TextBox; import org.gwtbootstrap3.client.ui.Tooltip; import org.gwtbootstrap3.client.ui.constants.ValidationState; import org.gwtbootstrap3.client.ui.gwt.CellTable; import org.gwtbootstrap3.client.ui.html.Span; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.cellview.client.TextColumn; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.view.client.ListDataProvider; import com.google.gwt.view.client.SingleSelectionModel; public class NatTabUi extends Composite implements Tab { private static NatTabUiUiBinder uiBinder = GWT.create(NatTabUiUiBinder.class); interface NatTabUiUiBinder extends UiBinder<Widget, NatTabUi> { } private static final Messages MSGS = GWT.create(Messages.class); private final GwtSecurityTokenServiceAsync gwtXSRFService = GWT.create(GwtSecurityTokenService.class); private final GwtNetworkServiceAsync gwtNetworkService = GWT.create(GwtNetworkService.class); private final ListDataProvider<GwtFirewallNatEntry> natDataProvider = new ListDataProvider<GwtFirewallNatEntry>(); final SingleSelectionModel<GwtFirewallNatEntry> selectionModel = new SingleSelectionModel<GwtFirewallNatEntry>(); private boolean m_dirty; private GwtFirewallNatEntry newNatEntry; private GwtFirewallNatEntry editNatEntry; @UiField Button apply, create, edit, delete; @UiField Alert notification; @UiField CellTable<GwtFirewallNatEntry> natGrid = new CellTable<GwtFirewallNatEntry>(); @UiField Modal natForm; @UiField FormGroup groupInput, groupOutput, groupProtocol, groupSource, groupDestination, groupEnable; @UiField FormLabel labelInput, labelOutput, labelProtocol, labelSource, labelDestination, labelEnable; @UiField Tooltip tooltipInput, tooltipOutput, tooltipProtocol, tooltipSource, tooltipDestination, tooltipEnable; @UiField TextBox input, output, source, destination; @UiField ListBox protocol, enable; @UiField Button submit, cancel; public NatTabUi() { initWidget(uiBinder.createAndBindUi(this)); initButtons(); initTable(); initModal(); } // // Public methods // @Override public void refresh() { EntryClassUi.showWaitModal(); this.natDataProvider.getList().clear(); this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() { @Override public void onFailure(Throwable ex) { EntryClassUi.hideWaitModal(); FailureHandler.handle(ex); } @Override public void onSuccess(GwtXSRFToken token) { NatTabUi.this.gwtNetworkService.findDeviceFirewallNATs(token, new AsyncCallback<List<GwtFirewallNatEntry>>() { @Override public void onFailure(Throwable caught) { EntryClassUi.hideWaitModal(); FailureHandler.handle(caught); } @Override public void onSuccess(List<GwtFirewallNatEntry> result) { for (GwtFirewallNatEntry pair : result) { NatTabUi.this.natDataProvider.getList().add(pair); } refreshTable(); NatTabUi.this.apply.setEnabled(false); EntryClassUi.hideWaitModal(); } }); } }); } @Override public boolean isDirty() { return this.m_dirty; } @Override public void setDirty(boolean b) { this.m_dirty = b; } @Override public boolean isValid() { // TODO Auto-generated method stub return false; } // // Private methods // private void initTable() { TextColumn<GwtFirewallNatEntry> col1 = new TextColumn<GwtFirewallNatEntry>() { @Override public String getValue(GwtFirewallNatEntry object) { if (object.getInInterface() != null) { return String.valueOf(object.getInInterface()); } else { return ""; } } }; col1.setCellStyleNames("status-table-row"); this.natGrid.addColumn(col1, MSGS.firewallNatInInterface()); TextColumn<GwtFirewallNatEntry> col2 = new TextColumn<GwtFirewallNatEntry>() { @Override public String getValue(GwtFirewallNatEntry object) { if (object.getOutInterface() != null) { return String.valueOf(object.getOutInterface()); } else { return ""; } } }; col2.setCellStyleNames("status-table-row"); this.natGrid.addColumn(col2, MSGS.firewallNatOutInterface()); TextColumn<GwtFirewallNatEntry> col3 = new TextColumn<GwtFirewallNatEntry>() { @Override public String getValue(GwtFirewallNatEntry object) { if (object.getProtocol() != null) { return String.valueOf(object.getProtocol()); } else { return ""; } } }; col3.setCellStyleNames("status-table-row"); this.natGrid.addColumn(col3, MSGS.firewallNatProtocol()); TextColumn<GwtFirewallNatEntry> col4 = new TextColumn<GwtFirewallNatEntry>() { @Override public String getValue(GwtFirewallNatEntry object) { if (object.getSourceNetwork() != null) { return String.valueOf(object.getSourceNetwork()); } else { return ""; } } }; col4.setCellStyleNames("status-table-row"); this.natGrid.addColumn(col4, MSGS.firewallNatSourceNetwork()); TextColumn<GwtFirewallNatEntry> col5 = new TextColumn<GwtFirewallNatEntry>() { @Override public String getValue(GwtFirewallNatEntry object) { if (object.getDestinationNetwork() != null) { return String.valueOf(object.getDestinationNetwork()); } else { return ""; } } }; col5.setCellStyleNames("status-table-row"); this.natGrid.addColumn(col5, MSGS.firewallNatDestinationNetwork()); TextColumn<GwtFirewallNatEntry> col6 = new TextColumn<GwtFirewallNatEntry>() { @Override public String getValue(GwtFirewallNatEntry object) { if (object.getMasquerade() != null) { return String.valueOf(object.getMasquerade()); } else { return ""; } } }; col6.setCellStyleNames("status-table-row"); this.natGrid.addColumn(col6, MSGS.firewallNatMasquerade()); this.natDataProvider.addDataDisplay(this.natGrid); this.natGrid.setSelectionModel(this.selectionModel); } private void refreshTable() { int size = this.natDataProvider.getList().size(); this.natGrid.setVisibleRange(0, size); this.natDataProvider.flush(); if (this.natDataProvider.getList().isEmpty()) { this.natGrid.setVisible(false); this.notification.setVisible(true); this.notification.setText(MSGS.firewallPortForwardTableNoPorts()); } else { this.natGrid.setVisible(true); this.notification.setVisible(false); } this.natGrid.redraw(); } // Initialize tab buttons private void initButtons() { initApplyButton(); initCreateButton(); initEditButton(); initDeleteButton(); } private void initDeleteButton() { this.delete.setText(MSGS.deleteButton()); this.delete.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { final GwtFirewallNatEntry selection = NatTabUi.this.selectionModel.getSelectedObject(); if (selection != null) { // TODO: this part should be structured the same as the other firewall tabs final Modal confirm = new Modal(); ModalBody confirmBody = new ModalBody(); ModalFooter confirmFooter = new ModalFooter(); confirm.setTitle(MSGS.confirm()); confirmBody.add(new Span(MSGS.firewallNatDeleteConfirmation(selection.getInInterface()))); confirmFooter.add(new Button(MSGS.yesButton(), new ClickHandler() { @Override public void onClick(ClickEvent event) { NatTabUi.this.natDataProvider.getList().remove(selection); refreshTable(); NatTabUi.this.apply.setEnabled(true); confirm.hide(); setDirty(true); } })); confirmFooter.add(new Button(MSGS.noButton(), new ClickHandler() { @Override public void onClick(ClickEvent event) { confirm.hide(); } })); confirm.add(confirmBody); confirm.add(confirmFooter); confirm.show(); } } }); } private void initEditButton() { this.edit.setText(MSGS.editButton()); this.edit.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { GwtFirewallNatEntry selection = NatTabUi.this.selectionModel.getSelectedObject(); if (selection != null) { showModal(selection); } } }); this.natForm.addHideHandler(new ModalHideHandler() { @Override public void onHide(ModalHideEvent evt) { if (NatTabUi.this.editNatEntry != null) { GwtFirewallNatEntry oldEntry = NatTabUi.this.selectionModel.getSelectedObject(); NatTabUi.this.natDataProvider.getList().remove(oldEntry); if (!duplicateEntry(NatTabUi.this.editNatEntry)) { NatTabUi.this.natDataProvider.getList().add(NatTabUi.this.editNatEntry); NatTabUi.this.natDataProvider.flush(); NatTabUi.this.apply.setEnabled(true); NatTabUi.this.editNatEntry = null; } else { // end duplicate NatTabUi.this.natDataProvider.getList().add(oldEntry); NatTabUi.this.natDataProvider.flush(); } } } }); } private void initCreateButton() { this.create.setText(MSGS.newButton()); this.create.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { showModal(null); } }); this.natForm.addHideHandler(new ModalHideHandler() { @Override public void onHide(ModalHideEvent evt) { if (NatTabUi.this.newNatEntry != null && !duplicateEntry(NatTabUi.this.newNatEntry)) { NatTabUi.this.natDataProvider.getList().add(NatTabUi.this.newNatEntry); refreshTable(); NatTabUi.this.apply.setEnabled(true); NatTabUi.this.newNatEntry = null; } } }); } private void initApplyButton() { this.apply.setText(MSGS.firewallApply()); this.apply.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { List<GwtFirewallNatEntry> intermediateList = NatTabUi.this.natDataProvider.getList(); ArrayList<GwtFirewallNatEntry> tempList = new ArrayList<GwtFirewallNatEntry>(); final List<GwtFirewallNatEntry> updatedNatConf = tempList; for (GwtFirewallNatEntry entry : intermediateList) { tempList.add(entry); } if (updatedNatConf != null) { EntryClassUi.showWaitModal(); NatTabUi.this.gwtXSRFService.generateSecurityToken(new AsyncCallback<GwtXSRFToken>() { @Override public void onFailure(Throwable ex) { EntryClassUi.hideWaitModal(); FailureHandler.handle(ex); } @Override public void onSuccess(GwtXSRFToken token) { NatTabUi.this.gwtNetworkService.updateDeviceFirewallNATs(token, updatedNatConf, new AsyncCallback<Void>() { @Override public void onFailure(Throwable caught) { EntryClassUi.hideWaitModal(); FailureHandler.handle(caught); } @Override public void onSuccess(Void result) { setDirty(false); NatTabUi.this.apply.setEnabled(false); EntryClassUi.hideWaitModal(); } }); } }); } } }); } private void initModal() { // Handle Buttons this.cancel.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { NatTabUi.this.natForm.hide(); } }); this.submit.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { checkFieldsValues(); if (NatTabUi.this.groupInput.getValidationState() == ValidationState.ERROR || NatTabUi.this.groupOutput.getValidationState() == ValidationState.ERROR || NatTabUi.this.groupSource.getValidationState() == ValidationState.ERROR || NatTabUi.this.groupDestination.getValidationState() == ValidationState.ERROR) { return; } // Fetch form data GwtFirewallNatEntry natEntry = new GwtFirewallNatEntry(); natEntry.setInInterface(NatTabUi.this.input.getText()); natEntry.setOutInterface(NatTabUi.this.output.getText()); natEntry.setProtocol(NatTabUi.this.protocol.getSelectedItemText()); natEntry.setSourceNetwork(NatTabUi.this.source.getText()); natEntry.setDestinationNetwork(NatTabUi.this.destination.getText()); natEntry.setMasquerade(NatTabUi.this.enable.getSelectedItemText()); if (NatTabUi.this.submit.getId().equals("new")) { NatTabUi.this.newNatEntry = natEntry; NatTabUi.this.editNatEntry = null; } else if (NatTabUi.this.submit.getId().equals("edit")) { NatTabUi.this.editNatEntry = natEntry; NatTabUi.this.newNatEntry = null; } NatTabUi.this.natForm.hide(); setDirty(true); } }); } private void showModal(final GwtFirewallNatEntry existingEntry) { if (existingEntry == null) { this.natForm.setTitle(MSGS.firewallNatFormInformation()); } else { this.natForm.setTitle(MSGS.firewallNatFormUpdate(existingEntry.getOutInterface())); } setModalFieldsLabels(); setModalFieldsValues(existingEntry); setModalFieldsTooltips(); setModalFieldsHandlers(); if (existingEntry == null) { this.submit.setId("new"); } else { this.submit.setId("edit"); } this.natForm.show(); } private void setModalFieldsHandlers() { // Set up validation this.input.addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent event) { if (!NatTabUi.this.input.getText().trim().matches(FieldType.ALPHANUMERIC.getRegex()) || NatTabUi.this.input.getText().trim().isEmpty()) { NatTabUi.this.groupInput.setValidationState(ValidationState.ERROR); } else { NatTabUi.this.groupInput.setValidationState(ValidationState.NONE); } } }); this.output.addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent event) { if (!NatTabUi.this.output.getText().trim().matches(FieldType.ALPHANUMERIC.getRegex()) || NatTabUi.this.output.getText().trim().isEmpty()) { NatTabUi.this.groupOutput.setValidationState(ValidationState.ERROR); } else { NatTabUi.this.groupOutput.setValidationState(ValidationState.NONE); } } }); this.source.addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent event) { if (!NatTabUi.this.source.getText().trim().isEmpty() && !NatTabUi.this.source.getText().trim().matches(FieldType.NETWORK.getRegex())) { NatTabUi.this.groupSource.setValidationState(ValidationState.ERROR); } else { NatTabUi.this.groupSource.setValidationState(ValidationState.NONE); } } }); this.destination.addBlurHandler(new BlurHandler() { @Override public void onBlur(BlurEvent event) { if (!NatTabUi.this.destination.getText().trim().isEmpty() && !NatTabUi.this.destination.getText().trim().matches(FieldType.NETWORK.getRegex())) { NatTabUi.this.groupDestination.setValidationState(ValidationState.ERROR); } else { NatTabUi.this.groupDestination.setValidationState(ValidationState.NONE); } } }); } private void setModalFieldsValues(final GwtFirewallNatEntry existingEntry) { // populate existing values if (existingEntry != null) { this.input.setText(existingEntry.getInInterface()); this.output.setText(existingEntry.getOutInterface()); this.source.setText(existingEntry.getSourceNetwork()); this.destination.setText(existingEntry.getDestinationNetwork()); for (int i = 0; i < this.protocol.getItemCount(); i++) { if (existingEntry.getProtocol().equals(this.protocol.getItemText(i))) { this.protocol.setSelectedIndex(i); break; } } for (int i = 0; i < this.enable.getItemCount(); i++) { if (existingEntry.getMasquerade().equals(this.enable.getItemText(i))) { this.enable.setSelectedIndex(i); break; } } } else { this.input.setText(""); this.output.setText(""); this.source.setText(""); this.destination.setText(""); this.protocol.setSelectedIndex(0); this.enable.setSelectedIndex(0); } } private void setModalFieldsTooltips() { // set Tooltips this.tooltipInput.setTitle(MSGS.firewallNatFormInputInterfaceToolTip()); this.tooltipOutput.setTitle(MSGS.firewallNatFormOutputInterfaceToolTip()); this.tooltipProtocol.setTitle(MSGS.firewallNatFormProtocolToolTip()); this.tooltipSource.setTitle(MSGS.firewallNatFormSourceNetworkToolTip()); this.tooltipDestination.setTitle(MSGS.firewallNatFormDestinationNetworkToolTip()); this.tooltipEnable.setTitle(MSGS.firewallNatFormMasqueradingToolTip()); this.tooltipInput.reconfigure(); this.tooltipOutput.reconfigure(); this.tooltipProtocol.reconfigure(); this.tooltipSource.reconfigure(); this.tooltipDestination.reconfigure(); this.tooltipEnable.reconfigure(); } private void setModalFieldsLabels() { // set Labels this.labelInput.setText(MSGS.firewallNatFormInInterfaceName() + "*"); this.labelOutput.setText(MSGS.firewallNatFormOutInterfaceName() + "*"); this.labelProtocol.setText(MSGS.firewallNatFormProtocol()); this.labelSource.setText(MSGS.firewallNatFormSourceNetwork()); this.labelDestination.setText(MSGS.firewallNatFormDestinationNetwork()); this.labelEnable.setText(MSGS.firewallNatFormMasquerade()); this.submit.setText(MSGS.submitButton()); this.cancel.setText(MSGS.cancelButton()); // set ListBox this.protocol.clear(); for (GwtFirewallNatProtocol prot : GwtFirewallNatProtocol.values()) { this.protocol.addItem(prot.name()); } this.enable.clear(); for (GwtFirewallNatMasquerade masquerade : GwtFirewallNatMasquerade.values()) { this.enable.addItem(masquerade.name()); } } private boolean duplicateEntry(GwtFirewallNatEntry firewallNatEntry) { boolean isDuplicateEntry = false; List<GwtFirewallNatEntry> entries = this.natDataProvider.getList(); if (entries != null && firewallNatEntry != null) { for (GwtFirewallNatEntry entry : entries) { String sourceNetwork = entry.getSourceNetwork() != null ? entry.getSourceNetwork() : "0.0.0.0/0"; String destinationNetwork = entry.getDestinationNetwork() != null ? entry.getDestinationNetwork() : "0.0.0.0/0"; String newSourceNetwork = firewallNatEntry.getSourceNetwork() != null ? firewallNatEntry.getSourceNetwork() : "0.0.0.0/0"; String newDestinationNetwork = firewallNatEntry.getDestinationNetwork() != null ? firewallNatEntry.getDestinationNetwork() : "0.0.0.0/0"; if (entry.getInInterface().equals(firewallNatEntry.getInInterface()) && entry.getOutInterface().equals(firewallNatEntry.getOutInterface()) && entry.getProtocol().equals(firewallNatEntry.getProtocol()) && sourceNetwork.equals(newSourceNetwork) && destinationNetwork.equals(newDestinationNetwork)) { isDuplicateEntry = true; break; } } } return isDuplicateEntry; } private void checkFieldsValues() { // make the required fields in error state by default if (this.input.getText() == null || "".equals(this.input.getText().trim())) { this.groupInput.setValidationState(ValidationState.ERROR); } if (this.output.getText() == null || "".equals(this.output.getText().trim())) { this.groupOutput.setValidationState(ValidationState.ERROR); } } }