mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 10:17:41 +00:00
Refactor multi-user case UI for reuse, create admin case dashboard UI
This commit is contained in:
parent
52df9894ea
commit
f3ddd206a2
@ -313,6 +313,8 @@
|
|||||||
<package>org.sleuthkit.autopsy.appservices</package>
|
<package>org.sleuthkit.autopsy.appservices</package>
|
||||||
<package>org.sleuthkit.autopsy.casemodule</package>
|
<package>org.sleuthkit.autopsy.casemodule</package>
|
||||||
<package>org.sleuthkit.autopsy.casemodule.events</package>
|
<package>org.sleuthkit.autopsy.casemodule.events</package>
|
||||||
|
<package>org.sleuthkit.autopsy.casemodule.multiusercases</package>
|
||||||
|
<package>org.sleuthkit.autopsy.casemodule.multiusercasesbrowser</package>
|
||||||
<package>org.sleuthkit.autopsy.casemodule.services</package>
|
<package>org.sleuthkit.autopsy.casemodule.services</package>
|
||||||
<package>org.sleuthkit.autopsy.contentviewers</package>
|
<package>org.sleuthkit.autopsy.contentviewers</package>
|
||||||
<package>org.sleuthkit.autopsy.coordinationservice</package>
|
<package>org.sleuthkit.autopsy.coordinationservice</package>
|
||||||
|
@ -233,7 +233,10 @@ ImageFilePanel.md5HashTextField.text=
|
|||||||
ImageFilePanel.errorLabel.text=Error Label
|
ImageFilePanel.errorLabel.text=Error Label
|
||||||
ImageFilePanel.hashValuesNoteLabel.text=NOTE: These values will not be validated when the data source is added.
|
ImageFilePanel.hashValuesNoteLabel.text=NOTE: These values will not be validated when the data source is added.
|
||||||
ImageFilePanel.hashValuesLabel.text=Hash Values (optional):
|
ImageFilePanel.hashValuesLabel.text=Hash Values (optional):
|
||||||
OpenMultiUserCasePanel.searchLabel.text=Select any case and start typing to search by case name
|
|
||||||
OpenMultiUserCasePanel.cancelButton.text=Cancel
|
OpenMultiUserCasePanel.cancelButton.text=Cancel
|
||||||
OpenMultiUserCasePanel.openSelectedCaseButton.text=Open Selected Case
|
# To change this license header, choose License Headers in Project Properties.
|
||||||
|
# To change this template file, choose Tools | Templates
|
||||||
|
# and open the template in the editor.
|
||||||
OpenMultiUserCasePanel.openSingleUserCaseButton.text=Open Single-User Case...
|
OpenMultiUserCasePanel.openSingleUserCaseButton.text=Open Single-User Case...
|
||||||
|
OpenMultiUserCasePanel.openSelectedCaseButton.text=Open Selected Case
|
||||||
|
OpenMultiUserCasePanel.searchLabel.text=Select any case and start typing to search by case name
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
import java.awt.Frame;
|
import java.awt.Frame;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
@ -88,7 +88,7 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
|
|||||||
* metadata file (.aut file). Upon confirming the selection, it will attempt
|
* metadata file (.aut file). Upon confirming the selection, it will attempt
|
||||||
* to open the case described by the file.
|
* to open the case described by the file.
|
||||||
*/
|
*/
|
||||||
void openCaseSelectionWindow() {
|
public void openCaseSelectionWindow() {
|
||||||
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
|
String optionsDlgTitle = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning.title");
|
||||||
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
|
String optionsDlgMessage = NbBundle.getMessage(Case.class, "CloseCaseWhileIngesting.Warning");
|
||||||
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
|
if (IngestRunningCheck.checkAndConfirmProceed(optionsDlgTitle, optionsDlgMessage)) {
|
||||||
|
@ -24,7 +24,7 @@ import java.util.logging.Level;
|
|||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
|||||||
* An action that opens a multi-user case and hides the open multi-user case
|
* An action that opens a multi-user case and hides the open multi-user case
|
||||||
* dialog given the coordination service node data for the case.
|
* dialog given the coordination service node data for the case.
|
||||||
*/
|
*/
|
||||||
final class OpenMultiUserCaseAction extends AbstractAction {
|
public final class OpenMultiUserCaseAction extends AbstractAction {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Logger logger = Logger.getLogger(OpenMultiUserCaseAction.class.getName());
|
private static final Logger logger = Logger.getLogger(OpenMultiUserCaseAction.class.getName());
|
||||||
@ -42,11 +42,14 @@ final class OpenMultiUserCaseAction extends AbstractAction {
|
|||||||
* Constructs an action that opens a multi-user case and hides the open
|
* Constructs an action that opens a multi-user case and hides the open
|
||||||
* multi-user case dialog given the coordination service node data for the
|
* multi-user case dialog given the coordination service node data for the
|
||||||
* case.
|
* case.
|
||||||
|
*
|
||||||
|
* @param caseNodeData The coordination service node data for the case
|
||||||
|
* associated with this action.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"OpenMultiUserCaseAction.menuItemText=Open Case"
|
"OpenMultiUserCaseAction.menuItemText=Open Case"
|
||||||
})
|
})
|
||||||
OpenMultiUserCaseAction(CaseNodeData caseNodeData) {
|
public OpenMultiUserCaseAction(CaseNodeData caseNodeData) {
|
||||||
super(Bundle.OpenMultiUserCaseAction_menuItemText());
|
super(Bundle.OpenMultiUserCaseAction_menuItemText());
|
||||||
this.caseNodeData = caseNodeData;
|
this.caseNodeData = caseNodeData;
|
||||||
}
|
}
|
||||||
@ -92,7 +95,6 @@ final class OpenMultiUserCaseAction extends AbstractAction {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenMultiUserCaseAction clone() throws CloneNotSupportedException {
|
public OpenMultiUserCaseAction clone() throws CloneNotSupportedException {
|
||||||
super.clone();
|
|
||||||
throw new CloneNotSupportedException();
|
throw new CloneNotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ import org.openide.windows.WindowManager;
|
|||||||
/**
|
/**
|
||||||
* A singleton JDialog that allows a user to open a multi-user case.
|
* A singleton JDialog that allows a user to open a multi-user case.
|
||||||
*/
|
*/
|
||||||
final class OpenMultiUserCaseDialog extends JDialog {
|
public final class OpenMultiUserCaseDialog extends JDialog {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static OpenMultiUserCaseDialog instance;
|
private static OpenMultiUserCaseDialog instance;
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019-2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.casemodule;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.Action;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrowserCustomizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A customizer for a multi-user case browser panel that presents a tabular view
|
||||||
|
* of the multi-user cases known to the coordination service in the open
|
||||||
|
* multi-user case dialog.
|
||||||
|
*/
|
||||||
|
final class OpenMultiUserCaseNodeCustomizer implements MultiUserCaseBrowserCustomizer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Column> getColumns() {
|
||||||
|
List<Column> properties = new ArrayList<>();
|
||||||
|
// properties.add(Column.DISPLAY_NAME);
|
||||||
|
properties.add(Column.CREATE_DATE);
|
||||||
|
properties.add(Column.DIRECTORY);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SortColumn> getSortColumns() {
|
||||||
|
List<SortColumn> sortColumns = new ArrayList<>();
|
||||||
|
sortColumns.add(new SortColumn(Column.CREATE_DATE, false, 1));
|
||||||
|
return sortColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowMultiSelect() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Action> getActions(CaseNodeData nodeData) {
|
||||||
|
List<Action> actions = new ArrayList<>();
|
||||||
|
actions.add(new OpenMultiUserCaseAction(nodeData));
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action getPreferredAction(CaseNodeData nodeData) {
|
||||||
|
return new OpenMultiUserCaseAction(nodeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -24,28 +24,28 @@
|
|||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" alignment="1" attributes="0">
|
<Group type="102" alignment="1" attributes="0">
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="1" attributes="0">
|
<Component id="searchLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="caseExplorerScrollPane" max="32767" attributes="0"/>
|
<EmptySpace min="-2" pref="32" max="-2" attributes="0"/>
|
||||||
<Group type="102" attributes="0">
|
<Component id="openSingleUserCaseButton" linkSize="10" min="-2" pref="172" max="-2" attributes="0"/>
|
||||||
<Component id="searchLabel" min="-2" max="-2" attributes="0"/>
|
<EmptySpace pref="74" max="32767" attributes="0"/>
|
||||||
<EmptySpace min="-2" pref="32" max="-2" attributes="0"/>
|
<Component id="openSelectedCaseButton" linkSize="10" min="-2" pref="160" max="-2" attributes="0"/>
|
||||||
<Component id="openSingleUserCaseButton" linkSize="10" min="-2" pref="172" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace pref="96" max="32767" attributes="0"/>
|
|
||||||
<Component id="openSelectedCaseButton" linkSize="10" min="-2" pref="160" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Component id="cancelButton" linkSize="10" min="-2" max="-2" attributes="0"/>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="cancelButton" linkSize="10" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="caseBrowserScrollPane" pref="948" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
<DimensionLayout dim="1">
|
<DimensionLayout dim="1">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
|
<EmptySpace min="-2" pref="462" max="-2" attributes="0"/>
|
||||||
<Component id="caseExplorerScrollPane" min="-2" pref="450" max="-2" attributes="0"/>
|
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
|
||||||
<Group type="103" groupAlignment="3" attributes="0">
|
<Group type="103" groupAlignment="3" attributes="0">
|
||||||
<Component id="cancelButton" linkSize="7" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="cancelButton" linkSize="7" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="openSingleUserCaseButton" linkSize="7" alignment="3" min="-2" max="-2" attributes="0"/>
|
<Component id="openSingleUserCaseButton" linkSize="7" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||||
@ -54,6 +54,13 @@
|
|||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="caseBrowserScrollPane" min="-2" pref="445" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace pref="49" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
</Layout>
|
</Layout>
|
||||||
@ -100,10 +107,6 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
<Container class="javax.swing.JScrollPane" name="caseExplorerScrollPane">
|
|
||||||
|
|
||||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
|
||||||
</Container>
|
|
||||||
<Component class="javax.swing.JButton" name="openSelectedCaseButton">
|
<Component class="javax.swing.JButton" name="openSelectedCaseButton">
|
||||||
<Properties>
|
<Properties>
|
||||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
@ -114,5 +117,9 @@
|
|||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openSelectedCaseButtonActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="openSelectedCaseButtonActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="caseBrowserScrollPane">
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
</Container>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -18,13 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule;
|
||||||
|
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCasesBrowserPanel;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
import org.openide.util.Lookup;
|
import org.openide.util.Lookup;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JPanel that allows a user to open a multi-user case.
|
* A JPanel that allows a user to open a multi-user case.
|
||||||
@ -46,9 +48,9 @@ final class OpenMultiUserCasePanel extends JPanel {
|
|||||||
OpenMultiUserCasePanel(JDialog parentDialog) {
|
OpenMultiUserCasePanel(JDialog parentDialog) {
|
||||||
this.parentDialog = parentDialog;
|
this.parentDialog = parentDialog;
|
||||||
initComponents(); // Machine generated code
|
initComponents(); // Machine generated code
|
||||||
caseBrowserPanel = new MultiUserCasesBrowserPanel();
|
caseBrowserPanel = new MultiUserCasesBrowserPanel(new ExplorerManager(), new OpenMultiUserCaseNodeCustomizer());
|
||||||
caseExplorerScrollPane.add(caseBrowserPanel);
|
caseBrowserScrollPane.add(caseBrowserPanel);
|
||||||
caseExplorerScrollPane.setViewportView(caseBrowserPanel);
|
caseBrowserScrollPane.setViewportView(caseBrowserPanel);
|
||||||
openSelectedCaseButton.setEnabled(false);
|
openSelectedCaseButton.setEnabled(false);
|
||||||
caseBrowserPanel.addListSelectionListener((ListSelectionEvent event) -> {
|
caseBrowserPanel.addListSelectionListener((ListSelectionEvent event) -> {
|
||||||
openSelectedCaseButton.setEnabled(caseBrowserPanel.getExplorerManager().getSelectedNodes().length > 0);
|
openSelectedCaseButton.setEnabled(caseBrowserPanel.getExplorerManager().getSelectedNodes().length > 0);
|
||||||
@ -60,7 +62,7 @@ final class OpenMultiUserCasePanel extends JPanel {
|
|||||||
* the coordination service..
|
* the coordination service..
|
||||||
*/
|
*/
|
||||||
void refreshDisplay() {
|
void refreshDisplay() {
|
||||||
caseBrowserPanel.refreshCases();
|
caseBrowserPanel.displayCases();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,8 +77,8 @@ final class OpenMultiUserCasePanel extends JPanel {
|
|||||||
openSingleUserCaseButton = new javax.swing.JButton();
|
openSingleUserCaseButton = new javax.swing.JButton();
|
||||||
cancelButton = new javax.swing.JButton();
|
cancelButton = new javax.swing.JButton();
|
||||||
searchLabel = new javax.swing.JLabel();
|
searchLabel = new javax.swing.JLabel();
|
||||||
caseExplorerScrollPane = new javax.swing.JScrollPane();
|
|
||||||
openSelectedCaseButton = new javax.swing.JButton();
|
openSelectedCaseButton = new javax.swing.JButton();
|
||||||
|
caseBrowserScrollPane = new javax.swing.JScrollPane();
|
||||||
|
|
||||||
setName("Completed Cases"); // NOI18N
|
setName("Completed Cases"); // NOI18N
|
||||||
setPreferredSize(new java.awt.Dimension(960, 485));
|
setPreferredSize(new java.awt.Dimension(960, 485));
|
||||||
@ -115,17 +117,19 @@ final class OpenMultiUserCasePanel extends JPanel {
|
|||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||||
.addContainerGap()
|
.addContainerGap()
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
.addComponent(searchLabel)
|
||||||
.addComponent(caseExplorerScrollPane)
|
.addGap(32, 32, 32)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addComponent(openSingleUserCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 172, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(searchLabel)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 74, Short.MAX_VALUE)
|
||||||
.addGap(32, 32, 32)
|
.addComponent(openSelectedCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(openSingleUserCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 172, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 96, Short.MAX_VALUE)
|
.addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(openSelectedCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(caseBrowserScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 948, Short.MAX_VALUE)
|
||||||
|
.addContainerGap()))
|
||||||
);
|
);
|
||||||
|
|
||||||
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cancelButton, openSelectedCaseButton, openSingleUserCaseButton});
|
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cancelButton, openSelectedCaseButton, openSingleUserCaseButton});
|
||||||
@ -133,15 +137,18 @@ final class OpenMultiUserCasePanel extends JPanel {
|
|||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGap(6, 6, 6)
|
.addGap(462, 462, 462)
|
||||||
.addComponent(caseExplorerScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)
|
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||||
.addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(cancelButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(openSingleUserCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(openSingleUserCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addComponent(searchLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(searchLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(openSelectedCaseButton))
|
.addComponent(openSelectedCaseButton))
|
||||||
.addContainerGap())
|
.addContainerGap())
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(caseBrowserScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 445, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addContainerGap(49, Short.MAX_VALUE)))
|
||||||
);
|
);
|
||||||
|
|
||||||
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {cancelButton, openSelectedCaseButton, openSingleUserCaseButton});
|
layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {cancelButton, openSelectedCaseButton, openSingleUserCaseButton});
|
||||||
@ -179,14 +186,14 @@ final class OpenMultiUserCasePanel extends JPanel {
|
|||||||
Node[] selectedNodes = explorerManager.getSelectedNodes();
|
Node[] selectedNodes = explorerManager.getSelectedNodes();
|
||||||
if (selectedNodes.length > 0 && selectedNodes[0] instanceof MultiUserCaseNode) {
|
if (selectedNodes.length > 0 && selectedNodes[0] instanceof MultiUserCaseNode) {
|
||||||
MultiUserCaseNode caseNode = (MultiUserCaseNode) selectedNodes[0];
|
MultiUserCaseNode caseNode = (MultiUserCaseNode) selectedNodes[0];
|
||||||
CaseNodeData nodeData = caseNode.getCaseNodeData();
|
CaseNodeData nodeData = caseNode.getLookup().lookup(CaseNodeData.class);
|
||||||
new OpenMultiUserCaseAction(nodeData).actionPerformed(evt);
|
new OpenMultiUserCaseAction(nodeData).actionPerformed(evt);
|
||||||
}
|
}
|
||||||
}//GEN-LAST:event_openSelectedCaseButtonActionPerformed
|
}//GEN-LAST:event_openSelectedCaseButtonActionPerformed
|
||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton cancelButton;
|
private javax.swing.JButton cancelButton;
|
||||||
private javax.swing.JScrollPane caseExplorerScrollPane;
|
private javax.swing.JScrollPane caseBrowserScrollPane;
|
||||||
private javax.swing.JButton openSelectedCaseButton;
|
private javax.swing.JButton openSelectedCaseButton;
|
||||||
private javax.swing.JButton openSingleUserCaseButton;
|
private javax.swing.JButton openSingleUserCaseButton;
|
||||||
private javax.swing.JLabel searchLabel;
|
private javax.swing.JLabel searchLabel;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.coordinationservice;
|
package org.sleuthkit.autopsy.casemodule.multiusercases;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
@ -16,9 +16,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule.multiusercases;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.LinkOption;
|
import java.nio.file.LinkOption;
|
||||||
@ -28,6 +27,7 @@ import java.text.ParseException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
* Queries the coordination service to collect the multi-user case node data
|
* Queries the coordination service to collect the multi-user case node data
|
||||||
* stored in the case directory lock ZooKeeper nodes.
|
* stored in the case directory lock ZooKeeper nodes.
|
||||||
*/
|
*/
|
||||||
final class MultiUserCaseNodeDataCollector {
|
final public class MultiUserCaseNodeDataCollector {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(MultiUserCaseNodeDataCollector.class.getName());
|
private static final Logger logger = Logger.getLogger(MultiUserCaseNodeDataCollector.class.getName());
|
||||||
private static final String CASE_AUTO_INGEST_LOG_NAME = "AUTO_INGEST_LOG.TXT"; //NON-NLS
|
private static final String CASE_AUTO_INGEST_LOG_NAME = "AUTO_INGEST_LOG.TXT"; //NON-NLS
|
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019-2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.casemodule.multiusercasesbrowser;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.Action;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface for defining a customizer for a multi-user case browser panel
|
||||||
|
* that presents a tabular view of the multi-user cases known to the
|
||||||
|
* coordination service.
|
||||||
|
*/
|
||||||
|
public interface MultiUserCaseBrowserCustomizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration of the columns that can be added to the browser's tabular
|
||||||
|
* view. NOTE THAT THE DISPLAY_NAME COLUMN IS ADDED AUTOMATICALLY BY THE
|
||||||
|
* BROWSER AND ALL OTHER COLUMNS ARE OPTIONAL.
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"MultiUserCaseBrowserCustomizer.column.displayName=Name",
|
||||||
|
"MultiUserCaseBrowserCustomizer.column.createTime=Create Time",
|
||||||
|
"MultiUserCaseBrowserCustomizer.column.directory=Directory"
|
||||||
|
})
|
||||||
|
public enum Column {
|
||||||
|
DISPLAY_NAME(Bundle.MultiUserCaseBrowserCustomizer_column_displayName()),
|
||||||
|
CREATE_DATE(Bundle.MultiUserCaseBrowserCustomizer_column_createTime()),
|
||||||
|
DIRECTORY(Bundle.MultiUserCaseBrowserCustomizer_column_directory());
|
||||||
|
|
||||||
|
private final String displayName;
|
||||||
|
|
||||||
|
private Column(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the columns the tabular view in the browser should display. The
|
||||||
|
* columns will be displayed in the order in which they appear in the list.
|
||||||
|
* NOTE THAT THE DISPLAY_NAME COLUMN IS ADDED AS THE FIRST COLUMN
|
||||||
|
* AUTOMATICALLY AND SHOULD NOT BE INCLUDED IN THIS LIST.
|
||||||
|
*
|
||||||
|
* @return A Column object.
|
||||||
|
*/
|
||||||
|
List<Column> getColumns();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a specification of the columns, if any, that define the default
|
||||||
|
* sorting of the MultiUserCaseNodes in the browser.
|
||||||
|
*
|
||||||
|
* @return A list, possibly empty, of SortColumn objects.
|
||||||
|
*/
|
||||||
|
List<SortColumn> getSortColumns();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the browser should allow multiple selection of the
|
||||||
|
* MultiUserCaseNodes displayed in the browser.
|
||||||
|
*
|
||||||
|
* @return True or false.
|
||||||
|
*/
|
||||||
|
boolean allowMultiSelect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the context menu Actions for the MultiUserCaseNodes diplayed in the
|
||||||
|
* browser. Can include actions that work with multiple node selection.
|
||||||
|
*
|
||||||
|
* @param nodeData The coordination service node data for a given
|
||||||
|
* MultiUserCaseNode. Ignored for multi-select actions.
|
||||||
|
*
|
||||||
|
* @return A list of Actions.
|
||||||
|
*/
|
||||||
|
List<Action> getActions(CaseNodeData nodeData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the preferred action for the MultiUserCaseNodes displayed in the
|
||||||
|
* browser, i.e., the action to be performed when a node is double clicked.
|
||||||
|
*
|
||||||
|
* @param nodeData The coordination service node data for a given
|
||||||
|
* MultiUserCaseNode.
|
||||||
|
*
|
||||||
|
* @return The preferred action.
|
||||||
|
*/
|
||||||
|
Action getPreferredAction(CaseNodeData nodeData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A specification of the sorting details for a column in the browser's
|
||||||
|
* OutlineView.
|
||||||
|
*/
|
||||||
|
public final static class SortColumn {
|
||||||
|
|
||||||
|
private final Column column;
|
||||||
|
private final boolean sortAscending;
|
||||||
|
private final int sortRank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constucts a specification of the sorting details for a column in the
|
||||||
|
* browser's OutlineView.
|
||||||
|
*
|
||||||
|
* @param column
|
||||||
|
* @param sortAscending
|
||||||
|
* @param sortRank
|
||||||
|
*/
|
||||||
|
public SortColumn(Column column, boolean sortAscending, int sortRank) {
|
||||||
|
this.column = column;
|
||||||
|
this.sortAscending = sortAscending;
|
||||||
|
this.sortRank = sortRank;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the column to be sorted.
|
||||||
|
*
|
||||||
|
* @return The column.
|
||||||
|
*/
|
||||||
|
public Column column() {
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not the sort should be ascending.
|
||||||
|
*
|
||||||
|
* @return True or false.
|
||||||
|
*/
|
||||||
|
public boolean sortAscending() {
|
||||||
|
return sortAscending;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the rank of the sort, i.e., should it be the first column to be
|
||||||
|
* sorted, the second column, etc.
|
||||||
|
*
|
||||||
|
* @return The sort rank.
|
||||||
|
*/
|
||||||
|
public int sortRank() {
|
||||||
|
return sortRank;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,44 +16,45 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule.multiusercasesbrowser;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.swing.Action;
|
import javax.swing.Action;
|
||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Sheet;
|
import org.openide.nodes.Sheet;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.lookup.Lookups;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrowserCustomizer.Column;
|
||||||
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
import org.sleuthkit.autopsy.datamodel.NodeProperty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A NetBeans Explorer View node that represents a multi-user case.
|
* A NetBeans Explorer View node that represents a multi-user case in a
|
||||||
|
* multi-user cases browser panel.
|
||||||
*/
|
*/
|
||||||
final class MultiUserCaseNode extends AbstractNode {
|
public final class MultiUserCaseNode extends AbstractNode {
|
||||||
|
|
||||||
private final CaseNodeData caseNodeData;
|
private final CaseNodeData caseNodeData;
|
||||||
|
private final MultiUserCaseBrowserCustomizer customizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a NetBeans Explorer View node that represents a multi-user
|
* Constructs a NetBeans Explorer View node that represents a multi-user
|
||||||
* case.
|
* casein a multi-user cases browser panel.
|
||||||
*
|
*
|
||||||
* @param caseNodeData The coordination service node data for the case.
|
* @param caseNodeData The coordination service node data for the case.
|
||||||
|
* @param customizer A browser customizer that supplies the actions and
|
||||||
|
* property sheet properties of the node.
|
||||||
*/
|
*/
|
||||||
MultiUserCaseNode(CaseNodeData caseNodeData) {
|
MultiUserCaseNode(CaseNodeData caseNodeData, MultiUserCaseBrowserCustomizer customizer) {
|
||||||
super(Children.LEAF);
|
super(Children.LEAF, Lookups.fixed(caseNodeData));
|
||||||
super.setName(caseNodeData.getDisplayName());
|
super.setName(caseNodeData.getDisplayName());
|
||||||
setName(caseNodeData.getDisplayName());
|
super.setDisplayName(caseNodeData.getDisplayName());
|
||||||
setDisplayName(caseNodeData.getDisplayName());
|
|
||||||
this.caseNodeData = caseNodeData;
|
this.caseNodeData = caseNodeData;
|
||||||
|
this.customizer = customizer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({
|
|
||||||
"MultiUserCaseNode.column.name=Name",
|
|
||||||
"MultiUserCaseNode.column.createTime=Create Time",
|
|
||||||
"MultiUserCaseNode.column.path=Path"
|
|
||||||
})
|
|
||||||
@Override
|
@Override
|
||||||
protected Sheet createSheet() {
|
protected Sheet createSheet() {
|
||||||
Sheet sheet = super.createSheet();
|
Sheet sheet = super.createSheet();
|
||||||
@ -62,42 +63,33 @@ final class MultiUserCaseNode extends AbstractNode {
|
|||||||
sheetSet = Sheet.createPropertiesSet();
|
sheetSet = Sheet.createPropertiesSet();
|
||||||
sheet.put(sheetSet);
|
sheet.put(sheetSet);
|
||||||
}
|
}
|
||||||
sheetSet.put(new NodeProperty<>(Bundle.MultiUserCaseNode_column_name(),
|
for (Column property : customizer.getColumns()) {
|
||||||
Bundle.MultiUserCaseNode_column_name(),
|
String propName = property.getDisplayName();
|
||||||
Bundle.MultiUserCaseNode_column_name(),
|
switch (property) {
|
||||||
caseNodeData.getDisplayName()));
|
case CREATE_DATE:
|
||||||
sheetSet.put(new NodeProperty<>(Bundle.MultiUserCaseNode_column_createTime(),
|
sheetSet.put(new NodeProperty<>(propName, propName, propName, caseNodeData.getCreateDate()));
|
||||||
Bundle.MultiUserCaseNode_column_createTime(),
|
break;
|
||||||
Bundle.MultiUserCaseNode_column_createTime(),
|
case DIRECTORY:
|
||||||
caseNodeData.getCreateDate()));
|
sheetSet.put(new NodeProperty<>(propName, propName, propName, caseNodeData.getDirectory().toString()));
|
||||||
sheetSet.put(new NodeProperty<>(Bundle.MultiUserCaseNode_column_path(),
|
break;
|
||||||
Bundle.MultiUserCaseNode_column_path(),
|
default:
|
||||||
Bundle.MultiUserCaseNode_column_path(),
|
break;
|
||||||
caseNodeData.getDirectory().toString()));
|
}
|
||||||
|
}
|
||||||
return sheet;
|
return sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Action[] getActions(boolean context) {
|
public Action[] getActions(boolean context) {
|
||||||
List<Action> actions = new ArrayList<>();
|
List<Action> actions = new ArrayList<>();
|
||||||
actions.add(new OpenMultiUserCaseAction(this.caseNodeData));
|
actions.addAll(customizer.getActions(caseNodeData));
|
||||||
actions.add(new OpenCaseAutoIngestLogAction(this.caseNodeData));
|
actions.addAll(Arrays.asList(super.getActions(context)));
|
||||||
return actions.toArray(new Action[actions.size()]);
|
return actions.toArray(new Action[actions.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Action getPreferredAction() {
|
public Action getPreferredAction() {
|
||||||
return new OpenMultiUserCaseAction(this.caseNodeData);
|
return customizer.getPreferredAction(caseNodeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the coordintaion service case node data this Explorer View node
|
|
||||||
* represents.
|
|
||||||
*
|
|
||||||
* @return The case node data.
|
|
||||||
*/
|
|
||||||
CaseNodeData getCaseNodeData() {
|
|
||||||
return this.caseNodeData;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -32,7 +32,7 @@
|
|||||||
</Property>
|
</Property>
|
||||||
<Property name="opaque" type="boolean" value="false"/>
|
<Property name="opaque" type="boolean" value="false"/>
|
||||||
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
|
||||||
<Dimension value="[5, 5]"/>
|
<Dimension value="[500, 500]"/>
|
||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
<Constraints>
|
<Constraints>
|
@ -16,80 +16,60 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule.multiusercasesbrowser;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
import javax.swing.table.TableColumnModel;
|
|
||||||
import org.netbeans.swing.etable.ETableColumn;
|
|
||||||
import org.netbeans.swing.etable.ETableColumnModel;
|
|
||||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||||
import org.netbeans.swing.outline.Outline;
|
import org.netbeans.swing.outline.Outline;
|
||||||
import org.openide.explorer.ExplorerManager;
|
import org.openide.explorer.ExplorerManager;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.explorer.view.OutlineView;
|
import org.openide.explorer.view.OutlineView;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrowserCustomizer.Column;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrowserCustomizer.SortColumn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JPanel with a scroll pane child component that contains a NetBeans
|
* A JPanel that contains a NetBeans OutlineView that is used to provide a
|
||||||
* OutlineView that can be used to display a list of the multi-user cases known
|
* tabular view of the multi-user cases known to the coordination service. The
|
||||||
* to the coordination service.
|
* outline view set up, including the property sheets and actions of the
|
||||||
|
* MultiUserCaseNodes it displays, are defined using a
|
||||||
|
* MultiUserCaseBrowserCustomizer. Each MultiUserCaseNode has a CaseNodeData
|
||||||
|
* object in its Lookup.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("PMD.SingularField") // Matisse-generated UI widgets cause lots of false positives
|
@SuppressWarnings("PMD.SingularField") // Matisse-generated UI widgets cause lots of false positives for this in PMD
|
||||||
final class MultiUserCasesBrowserPanel extends javax.swing.JPanel implements ExplorerManager.Provider {
|
public final class MultiUserCasesBrowserPanel extends javax.swing.JPanel implements ExplorerManager.Provider {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private final ExplorerManager explorerManager;
|
private final ExplorerManager explorerManager;
|
||||||
|
private final MultiUserCaseBrowserCustomizer customizer;
|
||||||
private final OutlineView outlineView;
|
private final OutlineView outlineView;
|
||||||
private final Outline outline;
|
private final Outline outline;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a JPanel with a scroll pane child component that contains a
|
* Constructs a JPanel that contains a NetBeans OutlineView that is used to
|
||||||
* NetBeans OutlineView that can be used to display a list of the multi-user
|
* provide a tabular view of the multi-user cases known to the coordination
|
||||||
* cases known to the coordination service.
|
* service. The outline view set up, including the property sheets and
|
||||||
|
* actions of the MultiUserCaseNodes it displays, are defined using a
|
||||||
|
* MultiUserCaseBrowserCustomizer. Each MultiUserCaseNode has a CaseNodeData
|
||||||
|
* object in its Lookup.
|
||||||
|
*
|
||||||
|
* @param explorerManager The ExplorerManager for the browser's OutlineView.
|
||||||
|
* @param customizer A customizer for the browser.
|
||||||
*/
|
*/
|
||||||
MultiUserCasesBrowserPanel() {
|
public MultiUserCasesBrowserPanel(ExplorerManager explorerManager, MultiUserCaseBrowserCustomizer customizer) {
|
||||||
explorerManager = new ExplorerManager();
|
this.explorerManager = explorerManager;
|
||||||
outlineView = new org.openide.explorer.view.OutlineView();
|
this.customizer = customizer;
|
||||||
initComponents();
|
initComponents();
|
||||||
outline = outlineView.getOutline();
|
outlineView = new org.openide.explorer.view.OutlineView();
|
||||||
|
outline = this.outlineView.getOutline();
|
||||||
configureOutlineView();
|
configureOutlineView();
|
||||||
explorerManager.setRootContext(new MultiUserCasesRootNode());
|
caseTableScrollPane.add(outlineView);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configures the child scroll pane component's child OutlineView component.
|
|
||||||
*/
|
|
||||||
private void configureOutlineView() {
|
|
||||||
outlineView.setPropertyColumns(
|
|
||||||
Bundle.MultiUserCaseNode_column_createTime(), Bundle.MultiUserCaseNode_column_createTime(),
|
|
||||||
Bundle.MultiUserCaseNode_column_path(), Bundle.MultiUserCaseNode_column_path());
|
|
||||||
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Bundle.MultiUserCaseNode_column_name());
|
|
||||||
outline.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
|
||||||
TableColumnModel columnModel = outline.getColumnModel();
|
|
||||||
int pathColumnIndex = 0;
|
|
||||||
int dateColumnIndex = 0;
|
|
||||||
for (int index = 0; index < columnModel.getColumnCount(); index++) {
|
|
||||||
if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.MultiUserCaseNode_column_path())) {
|
|
||||||
pathColumnIndex = index;
|
|
||||||
} else if (columnModel.getColumn(index).getHeaderValue().toString().equals(Bundle.MultiUserCaseNode_column_createTime())) {
|
|
||||||
dateColumnIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hide path column by default (user can unhide it)
|
|
||||||
*/
|
|
||||||
ETableColumn column = (ETableColumn) columnModel.getColumn(pathColumnIndex);
|
|
||||||
((ETableColumnModel) columnModel).setColumnHidden(column, true);
|
|
||||||
outline.setRootVisible(false);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sort on Created date column in descending order by default.
|
|
||||||
*/
|
|
||||||
outline.setColumnSorted(dateColumnIndex, false, 1);
|
|
||||||
|
|
||||||
caseTableScrollPane.setViewportView(outlineView);
|
caseTableScrollPane.setViewportView(outlineView);
|
||||||
this.setVisible(true);
|
this.setVisible(true);
|
||||||
|
displayCases();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -97,23 +77,58 @@ final class MultiUserCasesBrowserPanel extends javax.swing.JPanel implements Exp
|
|||||||
return explorerManager;
|
return explorerManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the child scroll pane component's child OutlineView component.
|
||||||
|
*/
|
||||||
|
private void configureOutlineView() {
|
||||||
|
/*
|
||||||
|
* Set up the outline view columns and sorting.
|
||||||
|
*/
|
||||||
|
Map<Column, SortColumn> sortColumns = new HashMap<>();
|
||||||
|
for (SortColumn sortColumn : customizer.getSortColumns()) {
|
||||||
|
sortColumns.put(sortColumn.column(), sortColumn);
|
||||||
|
}
|
||||||
|
((DefaultOutlineModel) outline.getOutlineModel()).setNodesColumnLabel(Column.DISPLAY_NAME.getDisplayName());
|
||||||
|
if (sortColumns.containsKey(Column.DISPLAY_NAME)) {
|
||||||
|
SortColumn sortColumn = sortColumns.get(Column.DISPLAY_NAME);
|
||||||
|
outline.setColumnSorted(0, sortColumn.sortAscending(), sortColumn.sortRank());
|
||||||
|
}
|
||||||
|
List<Column> sheetProperties = customizer.getColumns();
|
||||||
|
for (int index = 0; index < sheetProperties.size(); ++index) {
|
||||||
|
Column property = sheetProperties.get(index);
|
||||||
|
String propertyName = property.getDisplayName();
|
||||||
|
outlineView.addPropertyColumn(propertyName, propertyName, propertyName);
|
||||||
|
if (sortColumns.containsKey(property)) {
|
||||||
|
SortColumn sortColumn = sortColumns.get(property);
|
||||||
|
outline.setColumnSorted(index + 1, sortColumn.sortAscending(), sortColumn.sortRank());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hide the root node and configure the node selection mode.
|
||||||
|
*/
|
||||||
|
outline.setRootVisible(false);
|
||||||
|
outline.setSelectionMode(customizer.allowMultiSelect() ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a listener to changes in case selection in this browser.
|
* Adds a listener to changes in case selection in this browser.
|
||||||
*
|
*
|
||||||
* @param listener the ListSelectionListener to add
|
* @param listener the ListSelectionListener to add
|
||||||
*/
|
*/
|
||||||
void addListSelectionListener(ListSelectionListener listener) {
|
public void addListSelectionListener(ListSelectionListener listener) {
|
||||||
outline.getSelectionModel().addListSelectionListener(listener);
|
outline.getSelectionModel().addListSelectionListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the list of multi-user cases in this browser.
|
* Fetches and displays the list of multi-user cases known to the
|
||||||
|
* coordination service in this browser.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"MultiUserCasesBrowserPanel.waitNode.message=Please Wait..."
|
"MultiUserCasesBrowserPanel.waitNode.message=Please Wait..."
|
||||||
})
|
})
|
||||||
void refreshCases() {
|
public void displayCases() {
|
||||||
explorerManager.setRootContext(new MultiUserCasesRootNode());
|
explorerManager.setRootContext(new MultiUserCasesRootNode(customizer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,7 +149,7 @@ final class MultiUserCasesBrowserPanel extends javax.swing.JPanel implements Exp
|
|||||||
caseTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
caseTableScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
caseTableScrollPane.setMinimumSize(new java.awt.Dimension(0, 5));
|
caseTableScrollPane.setMinimumSize(new java.awt.Dimension(0, 5));
|
||||||
caseTableScrollPane.setOpaque(false);
|
caseTableScrollPane.setOpaque(false);
|
||||||
caseTableScrollPane.setPreferredSize(new java.awt.Dimension(5, 5));
|
caseTableScrollPane.setPreferredSize(new java.awt.Dimension(500, 500));
|
||||||
add(caseTableScrollPane, java.awt.BorderLayout.CENTER);
|
add(caseTableScrollPane, java.awt.BorderLayout.CENTER);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
@ -16,15 +16,16 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.casemodule.multiusercasesbrowser;
|
||||||
|
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import org.openide.nodes.AbstractNode;
|
import org.openide.nodes.AbstractNode;
|
||||||
import org.openide.nodes.ChildFactory;
|
import org.openide.nodes.ChildFactory;
|
||||||
import org.openide.nodes.Children;
|
import org.openide.nodes.Children;
|
||||||
import org.openide.nodes.Node;
|
import org.openide.nodes.Node;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.MultiUserCaseNodeDataCollector;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
|
||||||
@ -42,8 +43,8 @@ final class MultiUserCasesRootNode extends AbstractNode {
|
|||||||
* @param case A list of coordination service node data objects representing
|
* @param case A list of coordination service node data objects representing
|
||||||
* multi-user cases.
|
* multi-user cases.
|
||||||
*/
|
*/
|
||||||
MultiUserCasesRootNode() {
|
MultiUserCasesRootNode(MultiUserCaseBrowserCustomizer childNodeCustomizer) {
|
||||||
super(Children.create(new MultiUserCasesRootNodeChildren(), true));
|
super(Children.create(new MultiUserCasesRootNodeChildren(childNodeCustomizer), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,6 +54,12 @@ final class MultiUserCasesRootNode extends AbstractNode {
|
|||||||
*/
|
*/
|
||||||
private static class MultiUserCasesRootNodeChildren extends ChildFactory<CaseNodeData> {
|
private static class MultiUserCasesRootNodeChildren extends ChildFactory<CaseNodeData> {
|
||||||
|
|
||||||
|
private MultiUserCaseBrowserCustomizer nodeCustomizer;
|
||||||
|
|
||||||
|
MultiUserCasesRootNodeChildren(MultiUserCaseBrowserCustomizer nodeCustomizer) {
|
||||||
|
this.nodeCustomizer = nodeCustomizer;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean createKeys(List<CaseNodeData> keys) {
|
protected boolean createKeys(List<CaseNodeData> keys) {
|
||||||
try {
|
try {
|
||||||
@ -66,7 +73,7 @@ final class MultiUserCasesRootNode extends AbstractNode {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Node createNodeForKey(CaseNodeData key) {
|
protected Node createNodeForKey(CaseNodeData key) {
|
||||||
return new MultiUserCaseNode(key);
|
return new MultiUserCaseNode(key, this.nodeCustomizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,4 +4,4 @@ OpenIDE-Module: org.sleuthkit.autopsy.experimental
|
|||||||
OpenIDE-Module-Layer: org/sleuthkit/autopsy/experimental/autoingest/layer.xml
|
OpenIDE-Module-Layer: org/sleuthkit/autopsy/experimental/autoingest/layer.xml
|
||||||
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties
|
OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties
|
||||||
OpenIDE-Module-Requires: org.openide.windows.WindowManager
|
OpenIDE-Module-Requires: org.openide.windows.WindowManager
|
||||||
OpenIDE-Module-Specification-Version: 1.0
|
OpenIDE-Module-Specification-Version: 1.0
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019-2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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
|
||||||
|
* 9
|
||||||
|
* 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.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.Action;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCaseBrowserCustomizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A customizer for a multi-user case browser panel that presents a tabular view
|
||||||
|
* of the multi-user cases known to the coordination service in the
|
||||||
|
* administrative dashboard for auto ingest cases.
|
||||||
|
*/
|
||||||
|
final class AutoIngestCasesDashboardNodeCustomizer implements MultiUserCaseBrowserCustomizer {
|
||||||
|
|
||||||
|
private final DeleteCaseInputDirectoriesAction deleteCaseInputAction;
|
||||||
|
private final DeleteCasesForReprocessingAction deleteCaseOutputAction;
|
||||||
|
private final DeleteCasesAction deleteCaseAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a customizer for a multi-user case browser panel that presents
|
||||||
|
* a tabular view of the multi-user cases known to the coordination service
|
||||||
|
* in the administrative dashboard for auto ingest cases.
|
||||||
|
*/
|
||||||
|
AutoIngestCasesDashboardNodeCustomizer() {
|
||||||
|
/*
|
||||||
|
* These actions are shared by all nodes in order to support multiple
|
||||||
|
* selection.
|
||||||
|
*/
|
||||||
|
deleteCaseInputAction = new DeleteCaseInputDirectoriesAction();
|
||||||
|
deleteCaseOutputAction = new DeleteCasesForReprocessingAction();
|
||||||
|
deleteCaseAction = new DeleteCasesAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Column> getColumns() {
|
||||||
|
List<Column> properties = new ArrayList<>();
|
||||||
|
properties.add(Column.CREATE_DATE);
|
||||||
|
properties.add(Column.DIRECTORY);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SortColumn> getSortColumns() {
|
||||||
|
List<SortColumn> sortColumns = new ArrayList<>();
|
||||||
|
sortColumns.add(new SortColumn(Column.DISPLAY_NAME, true, 1));
|
||||||
|
return sortColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allowMultiSelect() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Action> getActions(CaseNodeData nodeData) {
|
||||||
|
List<Action> actions = new ArrayList<>();
|
||||||
|
actions.add(new OpenCaseAction(nodeData));
|
||||||
|
actions.add(new OpenAutoIngestLogAction(nodeData));
|
||||||
|
actions.add(deleteCaseInputAction);
|
||||||
|
actions.add(deleteCaseOutputAction);
|
||||||
|
actions.add(deleteCaseAction);
|
||||||
|
actions.add(new ShowCaseDeletionStatusAction(nodeData));
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Action getPreferredAction(CaseNodeData nodeData) {
|
||||||
|
return new OpenCaseAction(nodeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -81,6 +81,7 @@ public final class AutoIngestDashboardTopComponent extends TopComponent {
|
|||||||
if (AutoIngestDashboard.isAdminAutoIngestDashboard()) {
|
if (AutoIngestDashboard.isAdminAutoIngestDashboard()) {
|
||||||
EventQueue.invokeLater(() -> {
|
EventQueue.invokeLater(() -> {
|
||||||
AinStatusDashboardTopComponent.openTopComponent(dashboard.getMonitor());
|
AinStatusDashboardTopComponent.openTopComponent(dashboard.getMonitor());
|
||||||
|
MultiUserCasesDashboardTopComponent.openTopComponent();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
tc.open();
|
tc.open();
|
||||||
|
@ -63,7 +63,7 @@ import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
|||||||
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
||||||
import org.sleuthkit.autopsy.casemodule.CaseDetails;
|
import org.sleuthkit.autopsy.casemodule.CaseDetails;
|
||||||
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
import org.sleuthkit.autopsy.coordinationservice.CoordinationService;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
|
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
|
import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Lock;
|
||||||
|
@ -262,3 +262,8 @@ AinStatusDashboard.refreshButton.text=&Refresh
|
|||||||
AinStatusDashboard.clusterMetricsButton.text=Auto Ingest &Metrics
|
AinStatusDashboard.clusterMetricsButton.text=Auto Ingest &Metrics
|
||||||
AinStatusDashboard.nodeStatusTableTitle.text=Auto Ingest Nodes
|
AinStatusDashboard.nodeStatusTableTitle.text=Auto Ingest Nodes
|
||||||
AinStatusDashboard.healthMonitorButton.text=Health Monitor
|
AinStatusDashboard.healthMonitorButton.text=Health Monitor
|
||||||
|
|
||||||
|
# To change this license header, choose License Headers in Project Properties.
|
||||||
|
# To change this template file, choose Tools | Templates
|
||||||
|
# and open the template in the editor.
|
||||||
|
MultiUserCasesDashboardTopComponent.refreshButton.text=Refresh
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019-2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action that deletes the auto ingest job input directories associated with
|
||||||
|
* one or more multi-user cases. The coordination service nodes for the auto
|
||||||
|
* ingest jobs are not deleted. This supports the use case where the directories
|
||||||
|
* may need to be directed to reclaim space, but the option to restore the
|
||||||
|
* directories without having the jobs be reprocessed is retained.
|
||||||
|
*
|
||||||
|
* This cases to delete are discovered by querying the actions global context
|
||||||
|
* lookup for CaseNodeData objects. See
|
||||||
|
* https://platform.netbeans.org/tutorials/nbm-selection-1.html and
|
||||||
|
* https://platform.netbeans.org/tutorials/nbm-selection-2.html for details.
|
||||||
|
*/
|
||||||
|
final class DeleteCaseInputDirectoriesAction extends AbstractAction {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"DeleteCaseInputDirectoriesAction.menuItemText=Delete Input Directories"
|
||||||
|
})
|
||||||
|
DeleteCaseInputDirectoriesAction() {
|
||||||
|
super(Bundle.DeleteCaseInputDirectoriesAction_menuItemText());
|
||||||
|
setEnabled(false); // RJCTODO: Enable when implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
final Collection<CaseNodeData> selectedNodeData = new ArrayList<>(Utilities.actionsGlobalContext().lookupAll(CaseNodeData.class));
|
||||||
|
if (!selectedNodeData.isEmpty()) {
|
||||||
|
/*
|
||||||
|
* RJCTODO: Create a background task that does the deletion and
|
||||||
|
* displays results in a dialog with a scrolling text pane.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeleteCaseInputDirectoriesAction clone() throws CloneNotSupportedException {
|
||||||
|
throw new CloneNotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019-2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action that completely deletes one or more multi-user cases, including any
|
||||||
|
* associated auto ingest job input directories and coordination service nodes.
|
||||||
|
*
|
||||||
|
* This cases to delete are discovered by querying the actions global context
|
||||||
|
* lookup for CaseNodeData objects. See
|
||||||
|
* https://platform.netbeans.org/tutorials/nbm-selection-1.html and
|
||||||
|
* https://platform.netbeans.org/tutorials/nbm-selection-2.html for details.
|
||||||
|
*/
|
||||||
|
final class DeleteCasesAction extends AbstractAction {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"DeleteCasesAction.menuItemText=Delete Case and Jobs"
|
||||||
|
})
|
||||||
|
DeleteCasesAction() {
|
||||||
|
super(Bundle.DeleteCasesAction_menuItemText());
|
||||||
|
setEnabled(false); // RJCTODO: Enable when implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
final Collection<CaseNodeData> selectedNodeData = new ArrayList<>(Utilities.actionsGlobalContext().lookupAll(CaseNodeData.class));
|
||||||
|
if (!selectedNodeData.isEmpty()) {
|
||||||
|
/*
|
||||||
|
* RJCTODO: Create a background task that does the deletion and
|
||||||
|
* displays results in a dialog with a scrolling text pane.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeleteCasesAction clone() throws CloneNotSupportedException {
|
||||||
|
throw new CloneNotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019-2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.util.Utilities;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action that deletes everything except the auto ingest job input
|
||||||
|
* directories for one or more multi-user cases. This supports the use case
|
||||||
|
* where a case needs to be reprocessed, so the input directories are not
|
||||||
|
* deleted even though the coordination service nodes for the auto ingest jobs
|
||||||
|
* are deleted.
|
||||||
|
*
|
||||||
|
* This cases to delete are discovered by querying the actions global context
|
||||||
|
* lookup for CaseNodeData objects. See
|
||||||
|
* https://platform.netbeans.org/tutorials/nbm-selection-1.html and
|
||||||
|
* https://platform.netbeans.org/tutorials/nbm-selection-2.html for details.
|
||||||
|
*/
|
||||||
|
final class DeleteCasesForReprocessingAction extends AbstractAction {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"DeleteCasesForReprocessingAction.menuItemText=Delete for Reprocessing"
|
||||||
|
})
|
||||||
|
DeleteCasesForReprocessingAction() {
|
||||||
|
super(Bundle.DeleteCasesForReprocessingAction_menuItemText());
|
||||||
|
setEnabled(false); // RJCTODO: Enable when implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
final Collection<CaseNodeData> selectedNodeData = new ArrayList<>(Utilities.actionsGlobalContext().lookupAll(CaseNodeData.class));
|
||||||
|
if (!selectedNodeData.isEmpty()) {
|
||||||
|
/*
|
||||||
|
* RJCTODO: Create a background task that does the deletion and
|
||||||
|
* displays results in a dialog with a scrolling text pane.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeleteCasesForReprocessingAction clone() throws CloneNotSupportedException {
|
||||||
|
throw new CloneNotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||||
|
<AuxValues>
|
||||||
|
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||||
|
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||||
|
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||||
|
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||||
|
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||||
|
</AuxValues>
|
||||||
|
|
||||||
|
<Layout>
|
||||||
|
<DimensionLayout dim="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace min="0" pref="458" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<Group type="102" alignment="1" attributes="0">
|
||||||
|
<Component id="caseBrowserScrollPane" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
<DimensionLayout dim="1">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" alignment="0" attributes="0">
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="caseBrowserScrollPane" pref="246" max="32767" attributes="0"/>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</DimensionLayout>
|
||||||
|
</Layout>
|
||||||
|
<SubComponents>
|
||||||
|
<Component class="javax.swing.JButton" name="refreshButton">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/experimental/autoingest/Bundle.properties" key="MultiUserCasesDashboardTopComponent.refreshButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="refreshButtonActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
|
<Container class="javax.swing.JScrollPane" name="caseBrowserScrollPane">
|
||||||
|
|
||||||
|
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||||
|
</Container>
|
||||||
|
</SubComponents>
|
||||||
|
</Form>
|
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019-2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.experimental.autoingest;
|
||||||
|
|
||||||
|
import org.openide.explorer.ExplorerManager;
|
||||||
|
import org.openide.explorer.ExplorerUtils;
|
||||||
|
import org.openide.windows.TopComponent;
|
||||||
|
import org.openide.util.NbBundle.Messages;
|
||||||
|
import org.openide.windows.Mode;
|
||||||
|
import org.openide.windows.WindowManager;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercasesbrowser.MultiUserCasesBrowserPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A top component that provides an adminstrative dashboard for multi-user
|
||||||
|
* cases.
|
||||||
|
*/
|
||||||
|
@TopComponent.Description(
|
||||||
|
preferredID = "MultiUserCasesDashboardTopComponent",
|
||||||
|
persistenceType = TopComponent.PERSISTENCE_ALWAYS
|
||||||
|
)
|
||||||
|
@TopComponent.Registration(
|
||||||
|
mode = "dashboard",
|
||||||
|
openAtStartup = false
|
||||||
|
)
|
||||||
|
@TopComponent.OpenActionRegistration(
|
||||||
|
displayName = "#CTL_MultiUserCasesDashboardAction",
|
||||||
|
preferredID = "MultiUserCasesDashboardTopComponent"
|
||||||
|
)
|
||||||
|
@Messages({
|
||||||
|
"CTL_MultiUserCasesDashboardAction=Multi-User Cases Dashboard",
|
||||||
|
"CTL_MultiUserCasesDashboardTopComponent=Cases",
|
||||||
|
"HINT_MultiUserCasesDashboardTopComponent=This is an adminstrative dashboard for multi-user cases"
|
||||||
|
})
|
||||||
|
@SuppressWarnings("PMD.SingularField") // Prevent these warnings about generated code
|
||||||
|
public final class MultiUserCasesDashboardTopComponent extends TopComponent implements ExplorerManager.Provider {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final ExplorerManager explorerManager;
|
||||||
|
private final MultiUserCasesBrowserPanel caseBrowserPanel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a singleton top component that provides an adminstrative dashboard
|
||||||
|
* for multi-user cases. The top component is docked into the "dashboard
|
||||||
|
* mode" defined by the auto ingest jobs top component.
|
||||||
|
*/
|
||||||
|
// RJCTODO: Consider moving all of the dashboard code into its own
|
||||||
|
// admindashboards or dashboards package.
|
||||||
|
public static void openTopComponent() {
|
||||||
|
MultiUserCasesDashboardTopComponent topComponent = (MultiUserCasesDashboardTopComponent) WindowManager.getDefault().findTopComponent("MultiUserCasesDashboardTopComponent");
|
||||||
|
if (topComponent != null) {
|
||||||
|
if (!topComponent.isOpened()) {
|
||||||
|
Mode mode = WindowManager.getDefault().findMode("dashboard"); // NON-NLS
|
||||||
|
if (mode != null) {
|
||||||
|
mode.dockInto(topComponent);
|
||||||
|
}
|
||||||
|
topComponent.open();
|
||||||
|
}
|
||||||
|
topComponent.toFront();
|
||||||
|
topComponent.requestActive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultiUserCasesDashboardTopComponent() {
|
||||||
|
initComponents();
|
||||||
|
setName(Bundle.CTL_MultiUserCasesDashboardTopComponent());
|
||||||
|
setToolTipText(Bundle.HINT_MultiUserCasesDashboardTopComponent());
|
||||||
|
explorerManager = new ExplorerManager();
|
||||||
|
associateLookup(ExplorerUtils.createLookup(explorerManager, getActionMap()));
|
||||||
|
caseBrowserPanel = new MultiUserCasesBrowserPanel(explorerManager, new AutoIngestCasesDashboardNodeCustomizer());
|
||||||
|
caseBrowserScrollPane.add(caseBrowserPanel);
|
||||||
|
caseBrowserScrollPane.setViewportView(caseBrowserPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentOpened() {
|
||||||
|
//caseBrowserPanel.displayCases();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentClosed() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExplorerManager getExplorerManager() {
|
||||||
|
return explorerManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called from within the constructor to initialize the form.
|
||||||
|
* WARNING: Do NOT modify this code. The content of this method is always
|
||||||
|
* regenerated by the Form Editor.
|
||||||
|
*/
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
refreshButton = new javax.swing.JButton();
|
||||||
|
caseBrowserScrollPane = new javax.swing.JScrollPane();
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(MultiUserCasesDashboardTopComponent.class, "MultiUserCasesDashboardTopComponent.refreshButton.text")); // NOI18N
|
||||||
|
refreshButton.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
refreshButtonActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
|
this.setLayout(layout);
|
||||||
|
layout.setHorizontalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addComponent(refreshButton)
|
||||||
|
.addGap(0, 458, Short.MAX_VALUE))
|
||||||
|
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
|
||||||
|
.addComponent(caseBrowserScrollPane)
|
||||||
|
.addContainerGap())))
|
||||||
|
);
|
||||||
|
layout.setVerticalGroup(
|
||||||
|
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addContainerGap()
|
||||||
|
.addComponent(caseBrowserScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 246, Short.MAX_VALUE)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(refreshButton)
|
||||||
|
.addContainerGap())
|
||||||
|
);
|
||||||
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
|
private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
|
||||||
|
caseBrowserPanel.displayCases();
|
||||||
|
}//GEN-LAST:event_refreshButtonActionPerformed
|
||||||
|
|
||||||
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
|
private javax.swing.JScrollPane caseBrowserScrollPane;
|
||||||
|
private javax.swing.JButton refreshButton;
|
||||||
|
// End of variables declaration//GEN-END:variables
|
||||||
|
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.casemodule;
|
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||||
|
|
||||||
import java.awt.Desktop;
|
import java.awt.Desktop;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
@ -26,7 +26,7 @@ import java.nio.file.Paths;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javax.swing.AbstractAction;
|
import javax.swing.AbstractAction;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.coordinationservice.CaseNodeData;
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
|
|
||||||
@ -34,10 +34,10 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
|||||||
* An action that opens a case auto ingest log given the coordination service
|
* An action that opens a case auto ingest log given the coordination service
|
||||||
* node data for the case.
|
* node data for the case.
|
||||||
*/
|
*/
|
||||||
final class OpenCaseAutoIngestLogAction extends AbstractAction {
|
public final class OpenAutoIngestLogAction extends AbstractAction {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Logger logger = Logger.getLogger(OpenCaseAutoIngestLogAction.class.getName());
|
private static final Logger logger = Logger.getLogger(OpenAutoIngestLogAction.class.getName());
|
||||||
private static final String CASE_AUTO_INGEST_LOG_FILE_NAME = "auto_ingest_log.txt";
|
private static final String CASE_AUTO_INGEST_LOG_FILE_NAME = "auto_ingest_log.txt";
|
||||||
private final Path caseAutoIngestLogFilePath;
|
private final Path caseAutoIngestLogFilePath;
|
||||||
|
|
||||||
@ -48,17 +48,17 @@ final class OpenCaseAutoIngestLogAction extends AbstractAction {
|
|||||||
* @param caseNodeData The coordination service node data for the case.
|
* @param caseNodeData The coordination service node data for the case.
|
||||||
*/
|
*/
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"OpenCaseAutoIngestLogAction.menuItemText=Open Auto Ingest Log File"
|
"OpenAutoIngestLogAction.menuItemText=Open Auto Ingest Log File"
|
||||||
})
|
})
|
||||||
OpenCaseAutoIngestLogAction(CaseNodeData caseNodeData) {
|
public OpenAutoIngestLogAction(CaseNodeData caseNodeData) {
|
||||||
super(Bundle.OpenCaseAutoIngestLogAction_menuItemText());
|
super(Bundle.OpenAutoIngestLogAction_menuItemText());
|
||||||
this.caseAutoIngestLogFilePath = Paths.get(caseNodeData.getDirectory().toString(), CASE_AUTO_INGEST_LOG_FILE_NAME);
|
this.caseAutoIngestLogFilePath = Paths.get(caseNodeData.getDirectory().toString(), CASE_AUTO_INGEST_LOG_FILE_NAME);
|
||||||
this.setEnabled(caseAutoIngestLogFilePath.toFile().exists());
|
this.setEnabled(caseAutoIngestLogFilePath.toFile().exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"OpenCaseAutoIngestLogAction.deletedLogErrorMsg=The case auto ingest log has been deleted.",
|
"OpenAutoIngestLogAction.deletedLogErrorMsg=The case auto ingest log has been deleted.",
|
||||||
"OpenCaseAutoIngestLogAction.logOpenFailedErrorMsg=Failed to open case auto ingest log. See application log for details."
|
"OpenAutoIngestLogAction.logOpenFailedErrorMsg=Failed to open case auto ingest log. See application log for details."
|
||||||
})
|
})
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent event) {
|
public void actionPerformed(ActionEvent event) {
|
||||||
@ -66,16 +66,16 @@ final class OpenCaseAutoIngestLogAction extends AbstractAction {
|
|||||||
if (caseAutoIngestLogFilePath.toFile().exists()) {
|
if (caseAutoIngestLogFilePath.toFile().exists()) {
|
||||||
Desktop.getDesktop().edit(caseAutoIngestLogFilePath.toFile());
|
Desktop.getDesktop().edit(caseAutoIngestLogFilePath.toFile());
|
||||||
} else {
|
} else {
|
||||||
MessageNotifyUtil.Message.error(Bundle.OpenCaseAutoIngestLogAction_deletedLogErrorMsg());
|
MessageNotifyUtil.Message.error(Bundle.OpenAutoIngestLogAction_deletedLogErrorMsg());
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
logger.log(Level.SEVERE, String.format("Error opening case auto ingest log file at %s", caseAutoIngestLogFilePath), ex); //NON-NLS
|
logger.log(Level.SEVERE, String.format("Error opening case auto ingest log file at %s", caseAutoIngestLogFilePath), ex); //NON-NLS
|
||||||
MessageNotifyUtil.Message.error(Bundle.OpenCaseAutoIngestLogAction_logOpenFailedErrorMsg());
|
MessageNotifyUtil.Message.error(Bundle.OpenAutoIngestLogAction_logOpenFailedErrorMsg());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OpenCaseAutoIngestLogAction clone() throws CloneNotSupportedException {
|
public OpenAutoIngestLogAction clone() throws CloneNotSupportedException {
|
||||||
super.clone();
|
super.clone();
|
||||||
throw new CloneNotSupportedException();
|
throw new CloneNotSupportedException();
|
||||||
}
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2019-2019 Basis Technology Corp.
|
||||||
|
* Contact: carrier <at> sleuthkit <dot> 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.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.CaseActionCancelledException;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.CaseMetadata;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.OpenMultiUserCaseDialog;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action that opens a multi-user case known to the coordination service.
|
||||||
|
*/
|
||||||
|
final class OpenCaseAction extends AbstractAction {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Logger logger = Logger.getLogger(org.sleuthkit.autopsy.casemodule.OpenMultiUserCaseAction.class.getName());
|
||||||
|
private final CaseNodeData caseNodeData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an action that opens a multi-user case known to the
|
||||||
|
* coordination service.
|
||||||
|
*
|
||||||
|
* @param caseNodeData The coordination service node data for the case.
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"OpenCaseAction.menuItemText=Open"
|
||||||
|
})
|
||||||
|
public OpenCaseAction(CaseNodeData caseNodeData) {
|
||||||
|
super(Bundle.OpenCaseAction_menuItemText());
|
||||||
|
this.caseNodeData = caseNodeData;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"# {0} - caseErrorMessage", "OpenCaseAction.errorMsg=Failed to open case: {0}"
|
||||||
|
})
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
new Thread(() -> {
|
||||||
|
String caseMetadataFilePath = null;
|
||||||
|
File caseDirectory = caseNodeData.getDirectory().toFile();
|
||||||
|
File[] filesInDirectory = caseDirectory.listFiles();
|
||||||
|
if (filesInDirectory != null) {
|
||||||
|
for (File file : filesInDirectory) {
|
||||||
|
if (file.getName().toLowerCase().endsWith(CaseMetadata.getFileExtension()) && file.isFile()) {
|
||||||
|
caseMetadataFilePath = file.getPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (caseMetadataFilePath != null) {
|
||||||
|
try {
|
||||||
|
Case.openAsCurrentCase(caseMetadataFilePath);
|
||||||
|
} catch (CaseActionException ex) {
|
||||||
|
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
|
||||||
|
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
|
||||||
|
}
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
MessageNotifyUtil.Message.error(Bundle.OpenCaseAction_errorMsg(ex.getLocalizedMessage()));
|
||||||
|
StartupWindowProvider.getInstance().open();
|
||||||
|
OpenMultiUserCaseDialog.getInstance().setVisible(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
MessageNotifyUtil.Message.error(Bundle.OpenCaseAction_errorMsg("Could not locate case metadata file."));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OpenCaseAction clone() throws CloneNotSupportedException {
|
||||||
|
throw new CloneNotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.experimental.autoingest;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import org.openide.util.NbBundle;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.multiusercases.CaseNodeData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An action that shows a popup that enumerates the deletion status of the
|
||||||
|
* various parts of a multi-user case known to the coordination service.
|
||||||
|
*/
|
||||||
|
final class ShowCaseDeletionStatusAction extends AbstractAction {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final CaseNodeData caseNodeData;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an action that shows a popup that enumerates the deletion
|
||||||
|
* status of the various parts of a multi-user case known to the
|
||||||
|
* coordination service.
|
||||||
|
*
|
||||||
|
* @param caseNodeData The coordination service node data for the case.
|
||||||
|
*/
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"ShowCaseDeletionStatusAction.menuItemText=Show Deletion Status"
|
||||||
|
})
|
||||||
|
public ShowCaseDeletionStatusAction(CaseNodeData caseNodeData) {
|
||||||
|
super(Bundle.ShowCaseDeletionStatusAction_menuItemText());
|
||||||
|
this.caseNodeData = caseNodeData;
|
||||||
|
setEnabled(false); // RJCTODO: Enable when implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
// RJCTODO: Implement
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShowCaseDeletionStatusAction clone() throws CloneNotSupportedException {
|
||||||
|
throw new CloneNotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user