From b851f7a314707efa2b4771f54eba00768b572d4c Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Wed, 27 May 2020 10:31:04 -0400 Subject: [PATCH] 6397 Basic creation functionality --- .../persona/AddAccountDialog.form | 2 +- .../persona/AddAccountDialog.java | 28 ++++----- .../persona/PersonaDetailsDialog.java | 17 ++---- .../persona/PersonaDetailsDialogCallback.java | 25 ++++++++ .../persona/PersonaDetailsPanel.java | 58 ++++++++++++++++++- .../persona/PersonaManagerTopComponent.form | 2 +- .../persona/PersonaManagerTopComponent.java | 40 +++++++++++-- 7 files changed, 136 insertions(+), 36 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsDialogCallback.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/AddAccountDialog.form b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/AddAccountDialog.form index 94dde18f8e..15a8e50db4 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/AddAccountDialog.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/AddAccountDialog.form @@ -100,7 +100,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/AddAccountDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/AddAccountDialog.java index 6bb88c2b25..332a659622 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/AddAccountDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/AddAccountDialog.java @@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.centralrepository.persona; import java.awt.Component; import java.io.Serializable; +import java.util.ArrayList; import java.util.logging.Level; import javax.swing.JDialog; import javax.swing.JFrame; @@ -29,8 +30,8 @@ import javax.swing.JOptionPane; import javax.swing.ListCellRenderer; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; -import org.sleuthkit.autopsy.centralrepository.datamodel.PersonaAccount; import org.sleuthkit.autopsy.coreutils.Logger; /** @@ -43,7 +44,7 @@ public class AddAccountDialog extends JDialog { private static final long serialVersionUID = 1L; - private final TypeChoiceRenderer ACC_CHOICE_RENDERER = new TypeChoiceRenderer(); + private final AccountChoiceRenderer ACC_CHOICE_RENDERER = new AccountChoiceRenderer(); private final PersonaDetailsPanel pdp; /** @@ -62,17 +63,17 @@ public class AddAccountDialog extends JDialog { } /** - * This class handles displaying and rendering drop down menu for account type choices + * This class handles displaying and rendering drop down menu for account choices */ - private class TypeChoiceRenderer extends JLabel implements ListCellRenderer, Serializable { + private class AccountChoiceRenderer extends JLabel implements ListCellRenderer, Serializable { private static final long serialVersionUID = 1L; @Override public Component getListCellRendererComponent( - JList list, PersonaAccount value, + JList list, CentralRepoAccount value, int index, boolean isSelected, boolean cellHasFocus) { - setText(value.getAccount().getTypeSpecificId()); + setText(value.getIdentifier()); return this; } } @@ -81,20 +82,19 @@ public class AddAccountDialog extends JDialog { "AddAccountDialog_get_types_exception_Title=Central Repository failure", "AddAccountDialog_get_types_exception_msg=Failed to access central repository", }) - private PersonaAccount[] getAllAccounts() { - PersonaAccount[] ret = new PersonaAccount[0]; + private CentralRepoAccount[] getAllAccounts() { + ArrayList allAccounts; try { - // todo change this to proper getAllAccounts function when that exists - // todo don't show accounts that are already assocated with this persona - ret = PersonaAccount.getPersonaAccountsForAccountIdentifier("").toArray(new PersonaAccount[0]); + allAccounts = new ArrayList<>(CentralRepoAccount.getAllAccounts()); } catch (CentralRepoException e) { logger.log(Level.SEVERE, "Failed to access central repository", e); JOptionPane.showMessageDialog(this, Bundle.AddAccountDialog_get_types_exception_Title(), Bundle.AddAccountDialog_get_types_exception_msg(), JOptionPane.ERROR_MESSAGE); + return new CentralRepoAccount[0]; } - return ret; + return allAccounts.toArray(new CentralRepoAccount[0]); } /** @@ -198,7 +198,7 @@ public class AddAccountDialog extends JDialog { "AddAccountDialog_dup_Title=Account add failure", "AddAccountDialog_dup_msg=This account is already added to the persona",}) private void okBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okBtnActionPerformed - if (pdp.addAccount(((PersonaAccount) accountsComboBox.getSelectedItem()).getAccount())) { + if (pdp.addAccount((CentralRepoAccount) accountsComboBox.getSelectedItem())) { dispose(); } else { JOptionPane.showMessageDialog(this, @@ -213,7 +213,7 @@ public class AddAccountDialog extends JDialog { }//GEN-LAST:event_cancelBtnActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JComboBox accountsComboBox; + private javax.swing.JComboBox accountsComboBox; private javax.swing.JLabel accountsLbl; private javax.swing.JButton cancelBtn; private javax.swing.JButton okBtn; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsDialog.java index e7ea6d2a4a..fc605200bf 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsDialog.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.centralrepository.persona; import java.awt.Component; -import java.util.logging.Level; import javax.swing.JDialog; import javax.swing.JFrame; import org.openide.util.NbBundle; @@ -32,17 +31,17 @@ import org.sleuthkit.autopsy.coreutils.Logger; */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives public class PersonaDetailsDialog extends JDialog { - private static final Logger logger = Logger.getLogger(PersonaDetailsDialog.class.getName()); private static final long serialVersionUID = 1L; private final Component parent; private final PersonaDetailsMode mode; + private final PersonaDetailsDialogCallback callback; @NbBundle.Messages({ "PersonaDetailsDialogCreateTitle=Create Persona", "PersonaDetailsDialogEditTitle=Edit Persona",}) - PersonaDetailsDialog(Component parent, PersonaDetailsMode mode, Persona persona) { + PersonaDetailsDialog(Component parent, PersonaDetailsMode mode, Persona persona, PersonaDetailsDialogCallback callback) { super((JFrame) WindowManager.getDefault().getMainWindow(), mode == PersonaDetailsMode.CREATE ? Bundle.PersonaDetailsDialogCreateTitle() : @@ -50,6 +49,7 @@ public class PersonaDetailsDialog extends JDialog { false); this.parent = parent; this.mode = mode; + this.callback = callback; initComponents(); @@ -130,16 +130,7 @@ public class PersonaDetailsDialog extends JDialog { } private void okBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okBtnActionPerformed - switch (mode) { - case CREATE: - // todo implement - break; - case EDIT: - // todo implement - break; - default: - logger.log(Level.SEVERE, "Unsupported mode: {0}", mode); - } + callback.callback(pdp.okHandler()); dispose(); }//GEN-LAST:event_okBtnActionPerformed diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsDialogCallback.java b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsDialogCallback.java new file mode 100644 index 0000000000..64737f3a02 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsDialogCallback.java @@ -0,0 +1,25 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * 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.sleuthkit.autopsy.centralrepository.persona; + +import org.sleuthkit.autopsy.centralrepository.datamodel.Persona; + +public interface PersonaDetailsDialogCallback { + void callback(Persona persona); +} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsPanel.java index f119e9342b..61f55932b1 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaDetailsPanel.java @@ -30,6 +30,7 @@ import javax.swing.JOptionPane; import javax.swing.JTable; import javax.swing.event.ListSelectionEvent; import javax.swing.table.DefaultTableModel; +import org.openide.util.Exceptions; import org.openide.windows.TopComponent; import org.openide.util.NbBundle.Messages; import org.openide.windows.RetainLocation; @@ -145,7 +146,7 @@ public final class PersonaDetailsPanel extends javax.swing.JPanel { } boolean addAccount(CentralRepoAccount account) { - if (currentAccounts.contains(account)) { + if (currentAccounts.stream().anyMatch((acc) -> (acc.getId() == account.getId()))) { return false; } currentAccounts.add(account); @@ -153,6 +154,57 @@ public final class PersonaDetailsPanel extends javax.swing.JPanel { return true; } + Collection getCurrentAccounts() { + return currentAccounts; + } + + @Messages({ + "PersonaDetailsPanel_NotEnoughAccounts_msg=Two or more accounts are necessary to create a persona", + "PersonaDetailsPanel_NotEnoughAccounts_Title=Not enough accounts", + "PersonaDetailsPanel_CentralRepoErr_msg=Failure to write to Central Repository", + "PersonaDetailsPanel_CentralRepoErr_Title=Central Repository failure",}) + Persona okHandler() { + Persona ret = null; + switch (mode) { + case CREATE: + if (currentAccounts.size() < 2) { + JOptionPane.showMessageDialog(this, + Bundle.PersonaDetailsPanel_NotEnoughAccounts_msg(), + Bundle.PersonaDetailsPanel_NotEnoughAccounts_Title(), + JOptionPane.ERROR_MESSAGE); + break; + } + try { + ret = Persona.createPersonaForAccount(currentName, + "", Persona.PersonaStatus.ACTIVE, currentAccounts.get(0), + "", Persona.Confidence.UNKNOWN); + for (int i = 1; i < currentAccounts.size(); i++) { + ret.addAccountToPersona(currentAccounts.get(i), "", Persona.Confidence.UNKNOWN); + } + for (PMetadata md : metadataToAdd) { + ret.addMetadata(md.name, md.value, md.justification, md.confidence); + } + for (PAlias pa : aliasesToAdd) { + ret.addAlias(pa.alias, pa.justification, pa.confidence); + } + } catch (CentralRepoException e) { + logger.log(Level.SEVERE, "Failed to access central repository", e); + JOptionPane.showMessageDialog(this, + Bundle.PersonaDetailsPanel_CentralRepoErr_msg(), + Bundle.PersonaDetailsPanel_CentralRepoErr_Title(), + JOptionPane.ERROR_MESSAGE); + break; + } + break; + case EDIT: + // todo implement + break; + default: + logger.log(Level.SEVERE, "Unsupported mode: {0}", mode); + } + return ret; + } + /** * A data bucket class for yet-to-be-created PersonaMetadata */ @@ -563,13 +615,13 @@ public final class PersonaDetailsPanel extends javax.swing.JPanel { for (CentralRepoAccount account : currentAccounts) { rows[i] = new Object[]{ account.getAccountType().getAcctType().getDisplayName(), - account.getTypeSpecificId() + account.getIdentifier() }; i++; } accountsModel = new PersonaDetailsTableModel( rows, - new String[]{"Type", "ID"} + new String[]{"Type", "Identifier"} ); accountsTable.setModel(accountsModel); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaManagerTopComponent.form b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaManagerTopComponent.form index b159b4d1ad..b2bea7dc26 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaManagerTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaManagerTopComponent.form @@ -51,7 +51,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaManagerTopComponent.java b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaManagerTopComponent.java index 285e79916a..4a45f57d1b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaManagerTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/persona/PersonaManagerTopComponent.java @@ -49,6 +49,8 @@ import org.sleuthkit.autopsy.coreutils.Logger; public final class PersonaManagerTopComponent extends TopComponent { private static final Logger logger = Logger.getLogger(PersonaManagerTopComponent.class.getName()); + + private PersonaDetailsDialog currentDialog; private List currentResults = null; private Persona selectedPersona = null; @@ -71,27 +73,53 @@ public final class PersonaManagerTopComponent extends TopComponent { editBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - PersonaDetailsDialog editDialog = - new PersonaDetailsDialog(PersonaManagerTopComponent.this, PersonaDetailsMode.EDIT, selectedPersona); + currentDialog = new PersonaDetailsDialog(PersonaManagerTopComponent.this, + PersonaDetailsMode.EDIT, selectedPersona, new EditCallbackImpl()); + editBtn.setEnabled(false); + createBtn.setEnabled(false); } }); createBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - PersonaDetailsDialog createDialog = - new PersonaDetailsDialog(PersonaManagerTopComponent.this, PersonaDetailsMode.CREATE, selectedPersona); + currentDialog = new PersonaDetailsDialog(PersonaManagerTopComponent.this, + PersonaDetailsMode.CREATE, selectedPersona, new CreateCallbackImpl()); + editBtn.setEnabled(false); + createBtn.setEnabled(false); } }); // Results table resultsTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); resultsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override public void valueChanged(ListSelectionEvent e) { handleSelectionChange(e); } }); } + + class CreateCallbackImpl implements PersonaDetailsDialogCallback { + @Override + public void callback(Persona persona) { + if (persona != null) { + searchField.setText(""); + executeSearch(); + int newPersonaRow = currentResults.size() - 1; + resultsTable.getSelectionModel().setSelectionInterval(newPersonaRow, newPersonaRow); + handleSelectionChange(); + } + currentDialog = null; + } + } + + class EditCallbackImpl implements PersonaDetailsDialogCallback { + @Override + public void callback(Persona persona) { + currentDialog = null; + } + } void setPersona(int index) { Persona persona = currentResults.get(index); @@ -120,6 +148,10 @@ public final class PersonaManagerTopComponent extends TopComponent { if (e.getValueIsAdjusting()) { return; } + handleSelectionChange(); + } + + private void handleSelectionChange() { int selectedRow = resultsTable.getSelectedRow(); if (selectedRow != -1) { setPersona(resultsTable.getSelectedRow());