Autopsy 4.22.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
Persona.java
Go to the documentation of this file.
1/*
2 * Central Repository
3 *
4 * Copyright 2020 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.centralrepository.datamodel;
20
21import java.sql.ResultSet;
22import java.sql.SQLException;
23import java.time.Instant;
24import java.util.ArrayList;
25import java.util.Collection;
26import java.util.Collections;
27import java.util.List;
28import java.util.Objects;
29import java.util.UUID;
30import org.apache.commons.lang3.StringUtils;
31import org.openide.util.NbBundle;
32
39public class Persona {
40
44 public enum Confidence {
45 LOW(1, "Low confidence"),
46 MODERATE(2, "Moderate confidence"),
47 HIGH(3, "High confidence");
48
49 private final String name;
50 private final int level_id;
51
52 Confidence(int level, String name) {
53 this.name = name;
54 this.level_id = level;
55
56 }
57
58 @Override
59 public String toString() {
60 return name;
61 }
62
63 public int getLevelId() {
64 return this.level_id;
65 }
66
67 static Confidence fromId(int value) {
68 for (Confidence confidence : Confidence.values()) {
69 if (confidence.getLevelId() == value) {
70 return confidence;
71 }
72 }
73 return Confidence.LOW;
74 }
75
76 }
77
81 public enum PersonaStatus {
82
83 UNKNOWN(1, "Unknown"),
84 ACTIVE(2, "Active"),
85 MERGED(3, "Merged"),
86 SPLIT(4, "Split"),
87 DELETED(5, "Deleted");
88
89 private final String description;
90 private final int status_id;
91
93 this.status_id = status;
94 this.description = description;
95 }
96
97 @Override
98 public String toString() {
99 return description;
100 }
101
102 public int getStatusId() {
103 return this.status_id;
104 }
105
106 static PersonaStatus fromId(int value) {
107 for (PersonaStatus status : PersonaStatus.values()) {
108 if (status.getStatusId() == value) {
109 return status;
110 }
111 }
112 return PersonaStatus.UNKNOWN;
113 }
114 }
115
116 // primary key in the Personas table in CR database
117 private final long id;
118 private final String uuidStr;
119 private final String name;
120 private final String comment;
121 private final long createdDate;
122 private final long modifiedDate;
123 private final PersonaStatus status;
125
126 @NbBundle.Messages("Persona.defaultName=Unnamed")
127 public static String getDefaultName() {
128 return Bundle.Persona_defaultName();
129 }
130
131 public long getId() {
132 return id;
133 }
134
135 public String getUuidStr() {
136 return uuidStr;
137 }
138
139 public String getName() {
140 return name;
141 }
142
143 public String getComment() {
144 return comment;
145 }
146
147 public long getCreatedDate() {
148 return createdDate;
149 }
150
151 public long getModifiedDate() {
152 return modifiedDate;
153 }
154
156 return status;
157 }
158
160 return examiner;
161 }
162
163 Persona(long id, String uuidStr, String name, String comment, long created_date, long modified_date, PersonaStatus status, CentralRepoExaminer examiner) {
164 this.id = id;
165 this.uuidStr = uuidStr;
166 this.name = name;
167 this.comment = comment;
168 this.createdDate = created_date;
169 this.modifiedDate = modified_date;
170 this.status = status;
171 this.examiner = examiner;
172 }
173
174 @Override
175 public int hashCode() {
176 int hash = 7;
177 hash = 67 * hash + (int) (this.id ^ (this.id >>> 32));
178 hash = 67 * hash + Objects.hashCode(this.uuidStr);
179 return hash;
180 }
181
182 @Override
183 public boolean equals(Object obj) {
184 if (this == obj) {
185 return true;
186 }
187 if (obj == null) {
188 return false;
189 }
190 if (getClass() != obj.getClass()) {
191 return false;
192 }
193 final Persona other = (Persona) obj;
194 if (this.id != other.getId()) {
195 return false;
196 }
197 return this.uuidStr.equalsIgnoreCase(other.getUuidStr());
198 }
199
216 public static Persona createPersonaForAccount(String personaName, String comment, PersonaStatus status, CentralRepoAccount account, String justification, Persona.Confidence confidence) throws CentralRepoException {
217 Persona persona = createPersona(personaName, comment, status);
218 persona.addAccount(account, justification, confidence);
219 return persona;
220 }
221
235 private static Persona createPersona(String name, String comment, PersonaStatus status) throws CentralRepoException {
236 // generate a UUID for the persona
237 String uuidStr = UUID.randomUUID().toString();
238 CentralRepoExaminer examiner = getCRInstance().getOrInsertExaminer(System.getProperty("user.name"));
239
240 Instant instant = Instant.now();
241 Long timeStampMillis = instant.toEpochMilli();
242
243 String insertPersonaSQL = "INSERT INTO personas (uuid, comment, name, created_date, modified_date, status_id, examiner_id ) " //NON-NLS
244 + " VALUES (?, ?, ?, ?, ?, ?, ?)";
245 List<Object> params = new ArrayList<>();
246 params.add(uuidStr);
247 params.add(StringUtils.isBlank(comment) ? "" : comment);
248 params.add(StringUtils.isBlank(name) ? getDefaultName() : name);
249 params.add(timeStampMillis);
250 params.add(timeStampMillis);
251 params.add(status.getStatusId());
252 params.add(examiner.getId());
253
254 getCRInstance().executeCommand(insertPersonaSQL, params);
256 }
257
265 public void setComment(String comment) throws CentralRepoException {
266 String updateSQL = "UPDATE personas SET comment = ? WHERE id = ?";
268 if (cr != null) {
269 List<Object> params = new ArrayList<>();
270 params.add(StringUtils.isBlank(comment) ? "" : comment);
271 params.add(id);
272
273 getCRInstance().executeCommand(updateSQL, params);
274 }
275 }
276
284 public void setName(String name) throws CentralRepoException {
285 String updateSQL = "UPDATE personas SET name = ? WHERE id = ?";
287 if (cr != null) {
288 List<Object> params = new ArrayList<>();
289 params.add(StringUtils.isBlank(name) ? getDefaultName() : name);
290 params.add(id);
291
292 getCRInstance().executeCommand(updateSQL, params);
293 }
294 }
295
309 public PersonaAccount addAccount(CentralRepoAccount account, String justification, Persona.Confidence confidence) throws CentralRepoException {
310 return PersonaAccount.addPersonaAccount(this, account, justification, confidence);
311 }
312
322 PersonaAccount.removePersonaAccount(account.getId());
323 }
324
335 public void modifyAccount(PersonaAccount account, Confidence confidence, String justification) throws CentralRepoException {
336 PersonaAccount.modifyPersonaAccount(account.getId(), confidence, justification);
337 }
338
342 public void delete() throws CentralRepoException {
343 String deleteSQL = "UPDATE personas SET status_id = ? WHERE id = ?";
345 if (cr != null) {
346 List<Object> params = new ArrayList<>();
347 params.add(PersonaStatus.DELETED.getStatusId());
348 params.add(id);
349
350 getCRInstance().executeCommand(deleteSQL, params);
351 }
352 }
353
358
359 private final Collection<Persona> personaList = new ArrayList<>();
360
361 @Override
362 public void process(ResultSet rs) throws SQLException {
363
364 while (rs.next()) {
366 rs.getInt("examiner_id"),
367 rs.getString("login_name"));
368
369 PersonaStatus status = PersonaStatus.fromId(rs.getInt("status_id"));
370 Persona persona = new Persona(
371 rs.getInt("id"),
372 rs.getString("uuid"),
373 rs.getString("name"),
374 rs.getString("comment"),
375 Long.parseLong(rs.getString("created_date")),
376 Long.parseLong(rs.getString("modified_date")),
377 status,
379 );
380
381 personaList.add(persona);
382 }
383 }
384
385 Collection<Persona> getPersonas() {
386 return Collections.unmodifiableCollection(personaList);
387 }
388 };
389
390 // Partial query string to select from personas table,
391 // just supply the where clause.
392 private static final String PERSONA_QUERY
393 = "SELECT p.id, p.uuid, p.name, p.comment, p.created_date, p.modified_date, p.status_id, p.examiner_id, e.login_name, e.display_name "
394 + "FROM personas as p "
395 + "INNER JOIN examiners as e ON e.id = p.examiner_id ";
396
409 private static Persona getPersonaByUUID(String uuid) throws CentralRepoException {
410
411 String queryClause
413 + "WHERE p.uuid = ?";
414
415 List<Object> params = new ArrayList<>();
416 params.add(uuid);
417
418 PersonaQueryCallback queryCallback = new PersonaQueryCallback();
419 getCRInstance().executeQuery(queryClause, params, queryCallback);
420
421 Collection<Persona> personas = queryCallback.getPersonas();
422
423 return personas.isEmpty() ? null : personas.iterator().next();
424 }
425
438 public static Collection<Persona> getPersonaByName(String partialName) throws CentralRepoException {
439
440 String queryClause = PERSONA_QUERY
441 + "WHERE p.status_id != ? "
442 + " AND LOWER(p.name) LIKE LOWER(?) ESCAPE '!'";
443
444 List<Object> params = new ArrayList<>();
445 params.add(PersonaStatus.DELETED.getStatusId());
446 params.add("%" + getLikeEscaped(partialName) + "%"); // partial substring search
447
448 PersonaQueryCallback queryCallback = new PersonaQueryCallback();
449 getCRInstance().executeQuery(queryClause, params, queryCallback);
450
451 return queryCallback.getPersonas();
452 }
453
466 private static String getLikeEscaped(String initial) {
467 if (initial == null) {
468 return null;
469 }
470
471 return initial
472 .replace("!", "!!")
473 .replace("%", "!%")
474 .replace("_", "!_");
475 }
476
489 public static Collection<Persona> getPersonaByAccountIdentifierLike(String partialName) throws CentralRepoException {
490 String queryClause = "SELECT p.id, p.uuid, p.name, p.comment, p.created_date, p.modified_date, p.status_id, p.examiner_id, e.login_name\n"
491 + "FROM personas p\n"
492 + "LEFT JOIN examiners e ON e.id = p.examiner_id\n"
493 + "WHERE p.status_id <> ?\n"
494 + "AND p.id IN (\n"
495 + " SELECT pa.persona_id\n"
496 + " FROM persona_accounts pa\n"
497 + " INNER JOIN accounts a ON a.id = pa.account_id\n"
498 + " WHERE LOWER(a.account_unique_identifier) LIKE LOWER(?) ESCAPE '!'\n"
499 + ")";
500
501 PersonaQueryCallback queryCallback = new PersonaQueryCallback();
502
503 List<Object> params = new ArrayList<>();
504 params.add(PersonaStatus.DELETED.getStatusId());
505 params.add("%" + getLikeEscaped(partialName) + "%"); // partial substring search
506
507 getCRInstance().executeQuery(queryClause, params, queryCallback);
508 return queryCallback.getPersonas();
509 }
510
522 public PersonaAlias addAlias(String alias, String justification, Persona.Confidence confidence) throws CentralRepoException {
523 return PersonaAlias.addPersonaAlias(this, alias, justification, confidence);
524 }
525
535 PersonaAlias.removePersonaAlias(alias);
536 }
537
548 public void modifyAlias(PersonaAlias key, Confidence confidence, String justification) throws CentralRepoException {
549 PersonaAlias.modifyPersonaAlias(key, confidence, justification);
550 }
551
559 public Collection<PersonaAlias> getAliases() throws CentralRepoException {
560 return PersonaAlias.getPersonaAliases(this.getId());
561 }
562
575 public PersonaMetadata addMetadata(String name, String value, String justification, Persona.Confidence confidence) throws CentralRepoException {
576 return PersonaMetadata.addPersonaMetadata(this.getId(), name, value, justification, confidence);
577 }
578
588 PersonaMetadata.removePersonaMetadata(metadata);
589 }
590
601 public void modifyMetadata(PersonaMetadata key, Confidence confidence, String justification) throws CentralRepoException {
602 PersonaMetadata.modifyPersonaMetadata(key, confidence, justification);
603 }
604
612 public Collection<PersonaMetadata> getMetadata() throws CentralRepoException {
613 return PersonaMetadata.getPersonaMetadata(this.getId());
614 }
615
624 public Collection<PersonaAccount> getPersonaAccounts() throws CentralRepoException {
625 return PersonaAccount.getPersonaAccountsForPersona(this.getId());
626 }
627
633
634 Collection<CorrelationCase> correlationCases = new ArrayList<>();
635
636 @Override
637 public void process(ResultSet resultSet) throws CentralRepoException, SQLException {
638
639 while (resultSet.next()) {
640 // get Case for case_id
641 CorrelationCase correlationCase = getCRInstance().getCaseById(resultSet.getInt("case_id"));
642 correlationCases.add(correlationCase);
643 }
644 }
645
646 Collection<CorrelationCase> getCases() {
647 return Collections.unmodifiableCollection(correlationCases);
648 }
649 };
650
659 public Collection<CorrelationCase> getCases() throws CentralRepoException {
660
661 Collection<CorrelationCase> casesForPersona = new ArrayList<>();
662
663 // get all accounts for this persona
664 Collection<CentralRepoAccount> accounts = PersonaAccount.getAccountsForPersona(this.getId());
665 for (CentralRepoAccount account : accounts) {
666 int corrTypeId = account.getAccountType().getCorrelationTypeId();
668
669 String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(correlationType);
670 String querySql = "SELECT DISTINCT case_id FROM " + tableName
671 + " WHERE account_id = ?"; // param 1
672
673 List<Object> params = new ArrayList<>();
674 params.add(account.getId());
675
677 getCRInstance().executeQuery(querySql, params, queryCallback);
678
679 // Add any cases that aren't already on the list.
680 for (CorrelationCase corrCase : queryCallback.getCases()) {
681 if (!casesForPersona.stream().anyMatch(p -> p.getCaseUUID().equalsIgnoreCase(corrCase.getCaseUUID()))) {
682 casesForPersona.add(corrCase);
683 }
684 }
685 }
686
687 return casesForPersona;
688 }
689
695
696 Collection<CorrelationDataSource> correlationDataSources = new ArrayList<>();
697
698 @Override
699 public void process(ResultSet resultSet) throws CentralRepoException, SQLException {
700
701 while (resultSet.next()) {
702 // get Case for case_id
703
704 CorrelationCase correlationCase = getCRInstance().getCaseById(resultSet.getInt("case_id"));
705 CorrelationDataSource correlationDatasource = getCRInstance().getDataSourceById(correlationCase, resultSet.getInt("data_source_id"));
706
707 // Add data source to list if not already on it.
708 if (!correlationDataSources.stream().anyMatch(p -> Objects.equals(p.getDataSourceObjectID(), correlationDatasource.getDataSourceObjectID()))) {
709 correlationDataSources.add(correlationDatasource);
710 }
711 }
712 }
713
714 Collection<CorrelationDataSource> getDataSources() {
715 return Collections.unmodifiableCollection(correlationDataSources);
716 }
717 };
718
727 public Collection<CorrelationDataSource> getDataSources() throws CentralRepoException {
728 Collection<CorrelationDataSource> correlationDataSources = new ArrayList<>();
729
730 Collection<CentralRepoAccount> accounts = PersonaAccount.getAccountsForPersona(this.getId());
731 for (CentralRepoAccount account : accounts) {
732 int corrTypeId = account.getAccountType().getCorrelationTypeId();
734
735 String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(correlationType);
736 String querySql = "SELECT case_id, data_source_id FROM " + tableName
737 + " WHERE account_id = ?"; // param 1
738
739 List<Object> params = new ArrayList<>();
740 params.add(account.getId());
741
743 getCRInstance().executeQuery(querySql, params, queryCallback);
744
745 // Add any data sources that aren't already on the list.
746 for (CorrelationDataSource correlationDatasource : queryCallback.getDataSources()) {
747 if (!correlationDataSources.stream().anyMatch(p -> Objects.equals(p.getDataSourceObjectID(), correlationDatasource.getDataSourceObjectID()))) {
748 correlationDataSources.add(correlationDatasource);
749 }
750 }
751 }
752
753 return correlationDataSources;
754 }
755
760
761 Collection<Persona> personasList = new ArrayList<>();
762
763 @Override
764 public void process(ResultSet resultSet) throws CentralRepoException, SQLException {
765
766 while (resultSet.next()) {
767
768 // examiner that created the persona
769 CentralRepoExaminer personaExaminer = new CentralRepoExaminer(
770 resultSet.getInt("persona_examiner_id"),
771 resultSet.getString("persona_examiner_login_name"));
772
773 // create persona
774 PersonaStatus status = PersonaStatus.fromId(resultSet.getInt("status_id"));
775 Persona persona = new Persona(
776 resultSet.getInt("persona_id"),
777 resultSet.getString("uuid"),
778 resultSet.getString("name"),
779 resultSet.getString("comment"),
780 Long.parseLong(resultSet.getString("created_date")),
781 Long.parseLong(resultSet.getString("modified_date")),
782 status,
783 personaExaminer
784 );
785
786 personasList.add(persona);
787 }
788 }
789
790 Collection<Persona> getPersonasList() {
791 return Collections.unmodifiableCollection(personasList);
792 }
793 };
794
806
807 int corrTypeId = crAccountType.getCorrelationTypeId();
809
810 String instanceTableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(correlationType);
811 return "SELECT " + instanceTableName + ".account_id, case_id, data_source_id, "
812 + " personas.id as persona_id, personas.uuid, personas.name, personas.comment, personas.created_date, personas.modified_date, personas.status_id, "
813 + " personas.examiner_id as persona_examiner_id, persona_examiner.login_name as persona_examiner_login_name, persona_examiner.display_name as persona_examiner_display_name "
814 + " FROM " + instanceTableName
815 + " JOIN persona_accounts as pa on pa.account_id = " + instanceTableName + ".account_id"
816 + " JOIN personas as personas on personas.id = pa.persona_id"
817 + " JOIN examiners as persona_examiner ON persona_examiner.id = personas.examiner_id ";
818
819 }
820
830 public static Collection<Persona> getPersonasForCase(CorrelationCase correlationCase) throws CentralRepoException {
831 Collection<Persona> personaList = new ArrayList<>();
832
834 for (CentralRepoAccount.CentralRepoAccountType crAccountType : accountTypes) {
835
836 String querySql = getPersonaFromInstanceTableQueryTemplate(crAccountType)
837 + " WHERE case_id = ?" // param 1
838 + " AND personas.status_id != ?"; // param 2
839
840 List<Object> params = new ArrayList<>();
841 params.add(correlationCase.getID());
842 params.add(Persona.PersonaStatus.DELETED.getStatusId());
843
845 getCRInstance().executeQuery(querySql, params, queryCallback);
846
847 // Add persona that aren't already on the list.
848 for (Persona persona : queryCallback.getPersonasList()) {
849 if (!personaList.stream().anyMatch(p -> Objects.equals(p.getUuidStr(), persona.getUuidStr()))) {
850 personaList.add(persona);
851 }
852 }
853
854 }
855 return personaList;
856 }
857
867 public static Collection<Persona> getPersonasForDataSource(CorrelationDataSource dataSource) throws CentralRepoException {
868 Collection<Persona> personaList = new ArrayList<>();
869
871 for (CentralRepoAccount.CentralRepoAccountType crAccountType : accountTypes) {
872
873 String querySql = getPersonaFromInstanceTableQueryTemplate(crAccountType)
874 + " WHERE data_source_id = ?"
875 + " AND personas.status_id != ?";
876
877 List<Object> params = new ArrayList<>();
878 params.add(dataSource.getID());
879 params.add(Persona.PersonaStatus.DELETED.getStatusId());
880
882 getCRInstance().executeQuery(querySql, params, queryCallback);
883
884 // Add persona that aren't already on the list.
885 for (Persona persona : queryCallback.getPersonasList()) {
886 if (!personaList.stream().anyMatch(p -> Objects.equals(p.getUuidStr(), persona.getUuidStr()))) {
887 personaList.add(persona);
888 }
889 }
890
891 }
892 return personaList;
893 }
894
905
906 if (instance == null) {
907 throw new CentralRepoException("Failed to get instance of CentralRespository, CR was null");
908 }
909
910 return instance;
911 }
912}
static String correlationTypeToInstanceTableName(CorrelationAttributeInstance.Type type)
static Collection< PersonaAlias > getPersonaAliases(long personaId)
static Collection< Persona > getPersonaByAccountIdentifierLike(String partialName)
Definition Persona.java:489
void modifyAccount(PersonaAccount account, Confidence confidence, String justification)
Definition Persona.java:335
static Collection< Persona > getPersonaByName(String partialName)
Definition Persona.java:438
static Persona createPersona(String name, String comment, PersonaStatus status)
Definition Persona.java:235
Collection< CorrelationDataSource > getDataSources()
Definition Persona.java:727
void modifyMetadata(PersonaMetadata key, Confidence confidence, String justification)
Definition Persona.java:601
static Collection< Persona > getPersonasForCase(CorrelationCase correlationCase)
Definition Persona.java:830
PersonaAccount addAccount(CentralRepoAccount account, String justification, Persona.Confidence confidence)
Definition Persona.java:309
static Persona createPersonaForAccount(String personaName, String comment, PersonaStatus status, CentralRepoAccount account, String justification, Persona.Confidence confidence)
Definition Persona.java:216
PersonaMetadata addMetadata(String name, String value, String justification, Persona.Confidence confidence)
Definition Persona.java:575
static String getPersonaFromInstanceTableQueryTemplate(CentralRepoAccount.CentralRepoAccountType crAccountType)
Definition Persona.java:805
PersonaAlias addAlias(String alias, String justification, Persona.Confidence confidence)
Definition Persona.java:522
static Collection< Persona > getPersonasForDataSource(CorrelationDataSource dataSource)
Definition Persona.java:867
void modifyAlias(PersonaAlias key, Confidence confidence, String justification)
Definition Persona.java:548
CentralRepoExaminer getOrInsertExaminer(String examinerLoginName)
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
CorrelationDataSource getDataSourceById(CorrelationCase correlationCase, int dataSourceId)
void executeQuery(String sql, List< Object > params, CentralRepositoryDbQueryCallback queryCallback)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.