Add ability to get host results from a person

This commit is contained in:
apriestman 2021-11-04 10:33:45 -04:00
parent 71318cf71a
commit 0843206ade
4 changed files with 159 additions and 5 deletions

View File

@ -137,7 +137,7 @@ class FileSystemColumnUtils {
getColumnKey(Bundle.FileSystemColumnUtils_imageColumns_devID())
);
// Not used yet - Note that Hosts aren't content and will not be combined with other types, so we include the name here
// Note that Hosts aren't content and will not be combined with other types, so we include the name here
private static final List<ColumnKey> HOST_COLUMNS = Arrays.asList(
NAME_COLUMN
);
@ -230,6 +230,15 @@ class FileSystemColumnUtils {
return colKeys;
}
/**
* Get the column keys for a Host.
*
* @return The column keys.
*/
static List<ColumnKey> getColumnKeysForHost() {
return Arrays.asList(NAME_COLUMN);
}
/**
* Get the cell values for a given content object.
*

View File

@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.mainui.datamodel;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@ -33,6 +32,7 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.Person;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
@ -93,6 +93,45 @@ public class FileSystemDAO {
return fetchContentForTable(cacheKey, contentForTable, parentName);
}
private BaseSearchResultsDTO fetchHostsForTable(SearchParams<FileSystemPersonSearchParam> cacheKey) throws NoCurrentCaseException, TskCoreException {
SleuthkitCase skCase = Case.getCurrentCaseThrows().getSleuthkitCase();
Long objectId = cacheKey.getParamData().getPersonObjectId();
List<Host> hostsForTable = new ArrayList<>();
String parentName = "";
if (objectId != null) {
Optional<Person> person = skCase.getPersonManager().getPerson(objectId);
if (person.isPresent()) {
parentName = person.get().getName();
hostsForTable.addAll(skCase.getPersonManager().getHostsForPerson(person.get()));
} else {
throw new TskCoreException("Error loading person with ID " + objectId);
}
} else {
hostsForTable.addAll(skCase.getPersonManager().getHostsWithoutPersons());
}
Stream<Host> pagedHostsStream = hostsForTable.stream()
.sorted(Comparator.comparing((host) -> host.getHostId()))
.skip(cacheKey.getStartItem());
if (cacheKey.getMaxResultsCount() != null) {
pagedHostsStream = pagedHostsStream.limit(cacheKey.getMaxResultsCount());
}
List<Host> pagedHosts = pagedHostsStream.collect(Collectors.toList());
List<ColumnKey> columnKeys = FileSystemColumnUtils.getColumnKeysForHost();
List<RowDTO> rows = new ArrayList<>();
for (Host host : pagedHosts) {
List<Object> cellValues = FileSystemColumnUtils.getCellValuesForHost(host);
rows.add(new BaseRowDTO(cellValues, FILE_SYSTEM_TYPE_ID, host.getHostId()));
}
return new BaseSearchResultsDTO(FILE_SYSTEM_TYPE_ID, parentName, columnKeys, rows, cacheKey.getStartItem(), hostsForTable.size());
}
private BaseSearchResultsDTO fetchContentForTable(SearchParams<?> cacheKey, List<Content> contentForTable,
String parentName) throws NoCurrentCaseException, TskCoreException {
@ -116,7 +155,7 @@ public class FileSystemDAO {
* @param contentObjects The content objects.
* @param searchParams The search parameters including the paging.
*
* @return The list of paged artifacts.
* @return The list of paged content.
*/
private List<Content> getPaged(List<? extends Content> contentObjects, SearchParams<?> searchParams) {
Stream<? extends Content> pagedArtsStream = contentObjects.stream()
@ -149,4 +188,14 @@ public class FileSystemDAO {
return searchParamsCache.get(searchParams, () -> fetchContentForTableFromHost(searchParams));
}
public BaseSearchResultsDTO getHostsForTable(FileSystemPersonSearchParam objectKey, long startItem, Long maxCount, boolean hardRefresh) throws ExecutionException, IllegalArgumentException {
SearchParams<FileSystemPersonSearchParam> searchParams = new SearchParams<>(objectKey, startItem, maxCount);
if (hardRefresh) {
searchParamsCache.invalidate(searchParams);
}
return searchParamsCache.get(searchParams, () -> fetchHostsForTable(searchParams));
}
}

View File

@ -0,0 +1,66 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 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.mainui.datamodel;
import java.util.Objects;
/**
* Key for person object in order to retrieve data from DAO.
*/
public class FileSystemPersonSearchParam {
private final Long personObjectId;
/**
* Create search param.
*
* @param personObjectId May be null to fetch hosts not associated with a Person
*/
public FileSystemPersonSearchParam(Long personObjectId) {
this.personObjectId = personObjectId;
}
public Long getPersonObjectId() {
return personObjectId;
}
@Override
public int hashCode() {
int hash = 7;
hash = 67 * hash + Objects.hashCode(this.personObjectId);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final FileSystemPersonSearchParam other = (FileSystemPersonSearchParam) obj;
if (!Objects.equals(this.personObjectId, other.personObjectId)) {
return false;
}
return true;
}
}

View File

@ -46,8 +46,8 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DataArtifact;
import org.sleuthkit.datamodel.DataSource;
import org.sleuthkit.datamodel.FileSystem;
import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.Host;
import org.sleuthkit.datamodel.Person;
import org.sleuthkit.datamodel.Pool;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.Score;
@ -114,6 +114,12 @@ public class TableSearchTest extends NbTestCase {
private static final String SOURCE_NAME_COLUMN = "Source Name";
private static final String SOURCE_FILE_PATH_COLUMN = "Source File Path";
// File system test
private static final String PERSON_NAME = "Person1";
private static final String PERSON_HOST_NAME1 = "Host for Person A";
private static final String PERSON_HOST_NAME2 = "Host for Person B";
/////////////////////////////////////////////////
// Data to be used across the test methods.
// These are initialized in setUpCaseDatabase().
@ -160,6 +166,8 @@ public class TableSearchTest extends NbTestCase {
Image fsTestImageB = null; // Another image
Volume fsTestVolumeB1 = null; // Another volume
Pool fsTestPoolB = null; // A pool
Person person1 = null; // A person
Host personHost1 = null; // A host belonging to the above person
// Tags test
TagName knownTag1 = null;
@ -435,6 +443,12 @@ public class TableSearchTest extends NbTestCase {
trans.commit();
trans = null;
// Create a person associated with two hosts
person1 = db.getPersonManager().newPerson(PERSON_NAME);
personHost1 = db.getHostManager().newHost(PERSON_HOST_NAME1);
Host personHost2 = db.getHostManager().newHost(PERSON_HOST_NAME2);
db.getPersonManager().addHostsToPerson(person1, Arrays.asList(personHost1, personHost2));
// Add tags ----
knownTag1 = tagsManager.addTagName("Tag 1", TAG_DESCRIPTION, TagName.HTML_COLOR.RED, TskData.FileKnown.KNOWN);
@ -987,9 +1001,25 @@ public class TableSearchTest extends NbTestCase {
try {
FileSystemDAO fileSystemDAO = MainDAO.getInstance().getFileSystemDAO();
// There are 4 hosts not associated with a person
FileSystemPersonSearchParam personParam = new FileSystemPersonSearchParam(null);
BaseSearchResultsDTO results = fileSystemDAO.getHostsForTable(personParam, 0, null, false);
assertEquals(4, results.getTotalResultsCount());
assertEquals(4, results.getItems().size());
// Person1 is associated with two hosts
personParam = new FileSystemPersonSearchParam(person1.getPersonId());
results = fileSystemDAO.getHostsForTable(personParam, 0, null, false);
assertEquals(2, results.getTotalResultsCount());
assertEquals(2, results.getItems().size());
// Check that the name of the first host is present
RowDTO row = results.getItems().get(0);
assertTrue(row.getCellValues().contains(PERSON_HOST_NAME1));
// HostA is associated with two images
FileSystemHostSearchParam hostParam = new FileSystemHostSearchParam(fsTestHostA.getHostId());
BaseSearchResultsDTO results = fileSystemDAO.getContentForTable(hostParam, 0, null, false);
results = fileSystemDAO.getContentForTable(hostParam, 0, null, false);
assertEquals(2, results.getTotalResultsCount());
assertEquals(2, results.getItems().size());