Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/#204 consolidate search and multiselect #301

Merged
merged 68 commits into from
Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
756d02c
compare stix bundle versions when user upgrades layer version on import
clemiller Apr 22, 2021
c4d9b50
option to include revoked/deprecated objects when parsing a bundle; c…
clemiller Apr 22, 2021
01ab316
build changelog between two versions
clemiller Apr 23, 2021
f95e593
include sub-techniques in stix bundle comparison
clemiller Apr 26, 2021
e9f84c4
added sidebar adjacent to matrices
clemiller Apr 28, 2021
41d423e
layer upgrade sidebar component
clemiller Apr 28, 2021
20d01a4
show changelog sections in sidebar
clemiller Apr 30, 2021
6b2ee5d
Moved new sidebar from inside app.component to inside matrix (data-ta…
iguannalin May 5, 2021
e18a8f3
Styled new mat-drawer to show inside matrix tab, rather than overlay …
iguannalin May 5, 2021
85909cd
Moved mat-drawer-container to wrap matrix in data-table.component, ad…
iguannalin May 6, 2021
e77c625
Moved matrices class to wrap mat-drawer-container, to have the gray b…
iguannalin May 6, 2021
9cbc6f0
Added get, set for private _sidebarOpened variable in Data Service, a…
iguannalin May 7, 2021
222d9dc
Updated usage of sidebarOpened from the data service--in the data tab…
iguannalin May 17, 2021
92733c1
Updated usage of sidebarOpened in the data table component search ico…
iguannalin May 17, 2021
88d543b
Revert "Updated usage of sidebarOpened in the data table component se…
iguannalin May 17, 2021
672ecdb
Adding sidebarContentType to data service, to change the content of t…
iguannalin May 18, 2021
004b12a
Adding viewModel (optional Input) to sidebar called from datatable, t…
iguannalin May 18, 2021
8d3e8bf
Updated functionality of what search icon in toolbar does when clicke…
iguannalin May 18, 2021
13cb570
Added optional ? when looking for field in the search all techniques …
iguannalin May 18, 2021
8e35a26
moved sidebar control to viewmodel
clemiller May 19, 2021
1a463d5
Merge branch 'feature/#204-consolidate-search-and-multiselect' into f…
iguannalin May 19, 2021
7c000b9
Merge pull request #297 from mitre-attack/feature/#181-layer-upgrade-…
iguannalin May 19, 2021
f4b727f
Merging moving sidebar options from Data Service to View Model, and u…
iguannalin May 19, 2021
1b7796c
Legend bar should still appear on top of sidebar
iguannalin May 26, 2021
91bade5
Added settings icon, and styled search bar inside sidebar
iguannalin May 28, 2021
624e612
Added settings icon, and styled search bar inside sidebar
iguannalin May 28, 2021
1849f18
Removed multi-select from sidebar component
iguannalin Jun 2, 2021
154f994
Combined search and multi-select as accordion expansion panels in sid…
iguannalin Jun 2, 2021
2332e9f
Not sure why these didn't get pushed in the techniques-search.compone…
iguannalin Jun 2, 2021
137e0ac
Added a previousQuery variable to prevent users from seeing nothing i…
iguannalin Jun 2, 2021
b3e4d78
Added length of results to panel header
iguannalin Jun 3, 2021
b6e9a54
Modified filter and sort method in techniques search component to fil…
iguannalin Jun 3, 2021
0e97ea7
Added selectAllStix/deselectAllStic methods
iguannalin Jun 7, 2021
7adec59
Adjusted styling of sidebar contents, added MatCard and MatDivider mo…
iguannalin Jun 7, 2021
4e6a26e
Removed Multiselect component
iguannalin Jun 7, 2021
06b9bfe
Changed highlightedTechnique in ViewModel to a Set<string> of techniq…
iguannalin Jun 9, 2021
05c9e91
Adjusted style in techniques search component results table for consi…
iguannalin Jun 9, 2021
b8aa97a
Adjusted style in techniques search component results table for consi…
iguannalin Jun 9, 2021
76b9682
Added seenIDs set to remove duplicate sdos in dataService, since the …
iguannalin Jun 9, 2021
85daf2e
Updated CHANGELOG.md and Help component
iguannalin Jun 9, 2021
9e7686f
Merge branch 'develop' into feature/#204-consolidate-search-and-multi…
iguannalin Jun 9, 2021
48b64d1
Updated CHANGELOG.md date to TBD, and removed TODO as it's working as…
iguannalin Jun 9, 2021
c69d74b
Remove unused icons
iguannalin Jun 10, 2021
5cad3a2
Fixed typo
iguannalin Jun 11, 2021
e6ed890
Removed layer-upgrade component from this PR (this is part of issue#181)
iguannalin Jun 11, 2021
4e29984
Removed layerUpgrade from sidebar (this is part of issue#181)
iguannalin Jun 11, 2021
7096103
Removed versions observer from Tabs component (this is part of issue#…
iguannalin Jun 11, 2021
a28c48b
Removed layerupgrade from app module (this is part of issue#181)
iguannalin Jun 11, 2021
e720551
Removed dataService as parameter in app component constructor (this i…
iguannalin Jun 11, 2021
2d29815
Removed includeAll parameters in function call and version changelog …
iguannalin Jun 11, 2021
45c4017
Added close button to techniques search component
iguannalin Jun 11, 2021
61fa1d1
Added close button to techniques search component
iguannalin Jun 11, 2021
a6d149a
Renamed techniques-search component to search-and-multiselect component
iguannalin Jun 11, 2021
7e24509
Updated style in search-and-multiselect.component, set viewEncapsulat…
iguannalin Jun 11, 2021
9b148fa
Deleted unused spec file
iguannalin Jun 11, 2021
2f7de8c
Combined select & deselect functions to be repurposed for non-techniq…
iguannalin Jun 11, 2021
75e8639
Combined select & deselect functions to be repurposed for non-techniq…
iguannalin Jun 11, 2021
069d2ce
Changed Search Techniques to Search in query bar
iguannalin Jun 11, 2021
e7ded44
Removed dropdown class from search icon in toolbar
iguannalin Jun 11, 2021
fc2056b
Added in-code documentation for filterAndSort()
iguannalin Jun 11, 2021
dcbb2aa
If duplicate seen, should skip and continue rather than break from fo…
iguannalin Jun 11, 2021
9bed4e5
Reoorganized get data methods
iguannalin Jun 11, 2021
ee526fc
Updated isStix parameter to isTechnique in mouseEnter()
iguannalin Jun 11, 2021
c359dc9
Combined duplicative functions into one getResults() function; code c…
iguannalin Jun 16, 2021
bad0c8a
Code cleanup
iguannalin Jun 16, 2021
671cdec
Added debounce, and updated getResults function to always check user …
iguannalin Jun 16, 2021
65b08a1
Close and clear out search and multiselect in sidebar when switching …
iguannalin Jun 17, 2021
b19f767
update docs to better describe the combined interface
isaisabel Jun 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# v4.4 - changes staged on develop
- Added combined techniques search and multiselect feature in sidebar. See issue [#204](https://github.com/mitre-attack/attack-navigator/issues/204).

# v4.3 - 29 April 2021
## New Features
- Added aggregate scores. Aggregate scores are computed using the score of the technique and all sub-techniques using an "aggregate function" -- min, max, average, or sum. The aggregate score is used to determine the color of the technique in place of the technique's score. Aggregate scores are an optional feature and can be enabled in the "matrix configuration" dropdown. See issue [#269](https://github.com/mitre-attack/attack-navigator/issues/269).
Expand Down
13 changes: 1 addition & 12 deletions nav-app/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,2 @@
<!--The content below is only a placeholder and can be replaced.-->
<!-- <div *ngIf="techniques && tactics"> -->
<tabs>
<!-- <tab [tabTitle]="'grid'">
<DataTable></DataTable>
</tab> -->
</tabs>
<tabs></tabs>
<span style="font-size: 7pt">MITRE ATT&CK&reg; Navigator v{{nav_version}}</span>

<!-- </div> -->
<!-- <div *ngIf="!techniques && !tactics">
loading...
</div> -->
3 changes: 1 addition & 2 deletions nav-app/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, ViewChild, DoCheck, HostListener } from '@angular/core';
import { TabsComponent } from './tabs/tabs.component';
import { ConfigService } from './config.service';
import * as globals from "./globals";
import { DataService } from './data.service';

@Component({
selector: 'app-root',
Expand Down Expand Up @@ -30,6 +31,4 @@ export class AppComponent {
return false;
}
}


}
15 changes: 11 additions & 4 deletions nav-app/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDialogModule } from '@angular/material/dialog';
import { MatMenuModule } from '@angular/material/menu';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatSidenavModule } from '@angular/material/sidenav';

import { ColorPickerModule } from 'ngx-color-picker';
import { HttpClientModule } from '@angular/common/http';

Expand All @@ -27,11 +29,13 @@ import { MatrixSideComponent } from './matrix/matrix-side/matrix-side.component'
import { MatrixFlatComponent } from './matrix//matrix-flat/matrix-flat.component';
import { MatrixMiniComponent } from './matrix//matrix-mini/matrix-mini.component';
import { TooltipComponent } from './matrix/technique-cell/tooltip/tooltip.component';
import { MultiselectComponent } from './multiselect/multiselect.component';
import { TechniquesSearchComponent } from './techniques-search/techniques-search.component';
import { SearchAndMultiselectComponent } from './search-and-multiselect/search-and-multiselect.component';
import { ContextmenuComponent } from './matrix/technique-cell/contextmenu/contextmenu.component';
import { TacticCellComponent } from './matrix/tactic-cell/tactic-cell.component';
import { VersionUpgradeComponent } from './version-upgrade/version-upgrade.component';
import { SidebarComponent } from './sidebar/sidebar.component';
import { MatCardModule } from "@angular/material/card";
import { MatDividerModule } from "@angular/material/divider";


@NgModule({
Expand All @@ -46,11 +50,11 @@ import { VersionUpgradeComponent } from './version-upgrade/version-upgrade.compo
MatrixFlatComponent,
MatrixMiniComponent,
TooltipComponent,
MultiselectComponent,
TechniquesSearchComponent,
SearchAndMultiselectComponent,
ContextmenuComponent,
TacticCellComponent,
VersionUpgradeComponent,
SidebarComponent
],
imports: [
BrowserModule,
Expand All @@ -68,6 +72,9 @@ import { VersionUpgradeComponent } from './version-upgrade/version-upgrade.compo
MatExpansionModule,
MatDialogModule,
ColorPickerModule,
MatSidenavModule,
MatCardModule,
MatDividerModule
],
exports: [
MatSelectModule,
Expand Down
33 changes: 20 additions & 13 deletions nav-app/src/app/data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,20 @@ export class DataService {
*/
parseBundle(domain: Domain, stixBundles: any[]): void {
let platforms = new Set<String>();
let seenIDs = new Set<String>();
for (let bundle of stixBundles) {
let techniqueSDOs = [];
let matrixSDOs = [];
let idToTechniqueSDO = new Map<string, any>();
let idToTacticSDO = new Map<string, any>();
for (let sdo of bundle.objects) { //iterate through stix domain objects in the bundle
// ignore deprecated and revoked objects in the bundle
if (sdo.x_mitre_deprecated || sdo.revoked) continue;
// ignore deprecated and revoked objects in the bundle?
if (sdo.x_mitre_deprecated || sdo.revoked) continue;

// filter out duplicates
if (!seenIDs.has(sdo.id)) seenIDs.add(sdo.id)
else continue;

// parse according to type
switch(sdo.type) {
case "intrusion-set":
Expand Down Expand Up @@ -133,16 +139,18 @@ export class DataService {
}
domain.techniques.push(new Technique(techniqueSDO, subtechniques, this));
}

//create matrices, which also creates tactics and filters techniques
for (let matrixSDO of matrixSDOs) {
domain.matrices.push(new Matrix(matrixSDO, idToTacticSDO, domain.techniques, this));
}

// parse platforms
for (let technique of domain.techniques) {
for (let platform of technique.platforms) {
platforms.add(platform)
if (technique.platforms) {
for (let platform of technique.platforms) {
platforms.add(platform)
}
}
}
for (let subtechnique of domain.subtechniques) {
Expand Down Expand Up @@ -302,9 +310,9 @@ export class DataService {
}
}

/**
/**
* Common attributes for STIX objects
*/
*/
export abstract class BaseStix {
public readonly id: string; // STIX ID
public readonly attackID: string; // ATT&CK ID
Expand Down Expand Up @@ -376,15 +384,14 @@ export class Technique extends BaseStix {
this.platforms = stixSDO.x_mitre_platforms;
if (stixSDO.x_mitre_data_sources !== undefined)
this.datasources = stixSDO.x_mitre_data_sources.toString();
else
else
this.datasources = "";
this.tactics = stixSDO.kill_chain_phases.map((phase) => phase.phase_name);

this.subtechniques = subtechniques;
for (let subtechnique of this.subtechniques) {
subtechnique.parent = this;
}

}

/**
Expand Down Expand Up @@ -472,7 +479,7 @@ export class Mitigation extends BaseStix {
let rels = this.dataService.getDomain(domainID).relationships.mitigates;
if (rels.has(this.id)) {
return rels.get(this.id);
}
}
else return [];
}
/**
Expand Down Expand Up @@ -522,10 +529,10 @@ export class Domain {
public relationships: any = {
// subtechnique subtechnique-of technique
// ID of technique to [] of subtechnique IDs
subtechniques_of: new Map<string, string[]>(),
subtechniques_of: new Map<string, string[]>(),
// group uses technique
// ID of group to [] of technique IDs
group_uses: new Map<string, string[]>(),
group_uses: new Map<string, string[]>(),
// group uses technique
// ID of group to [] of technique IDs
software_uses: new Map<string, string[]>(),
Expand Down
61 changes: 25 additions & 36 deletions nav-app/src/app/datatable/data-table.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,33 +40,14 @@
<!-- Search -->
<div *ngIf="configService.getFeature('search')" class="control-row-item">

<div class="control-row-button dropdown noselect"
(click)="currentDropdown = currentDropdown !== 'search' ? 'search' : null;"
<div class="control-row-button noselect"
(click)="(viewModel.sidebarOpened = (viewModel.sidebarContentType !== 'search') ? true : !viewModel.sidebarOpened) && (viewModel.sidebarContentType = 'search')"
matTooltipPosition="below"
matTooltip="search">
<img src="assets/icons/ic_search_black_24px.svg"/>
</div>

<div class="dropdown-container search" *ngIf="currentDropdown === 'search'" #dropdown [class.left]="checkalign(dropdown)">
<app-techniques-search [viewModel]="viewModel"></app-techniques-search>
</div>
</div>


<!-- Multi-select -->
<div *ngIf="configService.getFeature('multiselect')" class="control-row-item">
<div class="control-row-button dropdown noselect"
(click)="currentDropdown = currentDropdown !== 'multiselect' ? 'multiselect' : null;"
matTooltipPosition="below"
matTooltip="multi-select">
<img src="assets/icons/ic_playlist_add_black_24px.svg"/>
</div>
<div class="dropdown-container multiselect" *ngIf="currentDropdown === 'multiselect'" #dropdown [class.left]="checkalign(dropdown)">
<app-multiselect [viewModel]="viewModel"></app-multiselect>
</div>
</div>


<!-- deselect all -->
<div *ngIf="configService.getFeature('deselect_all')" class="control-row-item">
<div class="control-row-button noselect"
Expand Down Expand Up @@ -535,26 +516,34 @@
88 888 88 8oooo88 888 888 88o 888 88 888
o88o 8 o88o o88o o888o o888o o888o 88o8 o888o o88o o888o
-->

<div class="matrices" oncontextmenu="return false">
<div class="matrices">
<div oncontextmenu="return false">
<div class="spinner" *ngIf="!dataService.getDomain(viewModel.domainID).dataLoaded">
<mat-progress-spinner mode="indeterminate"></mat-progress-spinner>
</div>
<div class="matrices-columns">
<div class="matrix-column" *ngFor="let matrix of dataService.getDomain(viewModel.domainID).matrices">
<div *ngIf="dataService.getDomain(viewModel.domainID).matrices.length > 1" class="matrix-name">{{matrix.name}}</div>
<div *ngIf="viewModel.layout.layout == 'side'">
<matrix-side [matrix]="matrix" [viewModel]="viewModel" (selectionChanged)="onTechniqueSelect()"></matrix-side>
</div>
<div *ngIf="viewModel.layout.layout == 'flat'">
<matrix-flat [matrix]="matrix" [viewModel]="viewModel" (selectionChanged)="onTechniqueSelect()"></matrix-flat>
</div>
<div *ngIf="viewModel.layout.layout == 'mini'">
<matrix-mini [matrix]="matrix" [viewModel]="viewModel" (selectionChanged)="onTechniqueSelect()"></matrix-mini>
<mat-drawer-container autosize>
<mat-drawer-content>
<div class="matrices-columns">
<div class="matrix-column" *ngFor="let matrix of dataService.getDomain(viewModel.domainID).matrices">
<div *ngIf="dataService.getDomain(viewModel.domainID).matrices.length > 1" class="matrix-name">{{matrix.name}}</div>
<div *ngIf="viewModel.layout.layout == 'side'">
<matrix-side [matrix]="matrix" [viewModel]="viewModel" (selectionChanged)="onTechniqueSelect()"></matrix-side>
</div>
<div *ngIf="viewModel.layout.layout == 'flat'">
<matrix-flat [matrix]="matrix" [viewModel]="viewModel" (selectionChanged)="onTechniqueSelect()"></matrix-flat>
</div>
<div *ngIf="viewModel.layout.layout == 'mini'">
<matrix-mini [matrix]="matrix" [viewModel]="viewModel" (selectionChanged)="onTechniqueSelect()"></matrix-mini>
</div>
</div>
</div>
</div>
</div>
</mat-drawer-content>
<mat-drawer mode="side" position="end" #sidebar [opened]="viewModel.sidebarOpened">
<sidebar [viewModel]="viewModel"></sidebar>
</mat-drawer>
</mat-drawer-container>
</div>
</div>


<!--
Expand Down
2 changes: 1 addition & 1 deletion nav-app/src/app/datatable/data-table.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ $panel-light: lighten($panel-dark, 8%);
}

.legendBar {
z-index: 999;
position: fixed;
bottom: 0;
right: 0;
Expand Down Expand Up @@ -472,4 +473,3 @@ $panel-light: lighten($panel-dark, 8%);
}
}
}

19 changes: 9 additions & 10 deletions nav-app/src/app/datatable/data-table.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ declare var tinycolor: any; //use tinycolor2

import * as FileSaver from 'file-saver';
import { ColorPickerModule } from 'ngx-color-picker';
import { TechniquesSearchComponent } from '../techniques-search/techniques-search.component';
import { SearchAndMultiselectComponent } from '../search-and-multiselect/search-and-multiselect.component';
import { TmplAstVariable } from '@angular/compiler';

@Component({
Expand All @@ -37,7 +37,6 @@ export class DataTableComponent implements AfterViewInit {

currentDropdown: string = ""; //current dropdown menu


//////////////////////////////////////////////////////////
// Stringifies the current view model into a json string//
// stores the string as a blob //
Expand All @@ -50,7 +49,7 @@ export class DataTableComponent implements AfterViewInit {
let filename = this.viewModel.name.replace(/ /g, "_") + ".json";
// FileSaver.saveAs(blob, this.viewModel.name.replace(/ /g, "_") + ".json");
this.saveBlob(blob, filename);

}

saveBlob(blob, filename){
Expand All @@ -75,8 +74,8 @@ export class DataTableComponent implements AfterViewInit {
var workbook = new Excel.Workbook();
let domain = this.dataService.getDomain(this.viewModel.domainID);
for (let matrix of domain.matrices) {
var worksheet = workbook.addWorksheet(matrix.name + " (v" + domain.getVersion() + ")");
var worksheet = workbook.addWorksheet(matrix.name + " (v" + domain.getVersion() + ")");

// create tactic columns
let columns = this.viewModel.filterTactics(matrix.tactics, matrix).map(tactic => { return {header: this.getDisplayName(tactic), key: tactic.name} });
worksheet.columns = columns;
Expand Down Expand Up @@ -234,10 +233,10 @@ export class DataTableComponent implements AfterViewInit {
}
}

constructor(public dataService: DataService,
private tabs: TabsComponent,
private sanitizer: DomSanitizer,
private viewModelsService: ViewModelsService,
constructor(public dataService: DataService,
private tabs: TabsComponent,
private sanitizer: DomSanitizer,
private viewModelsService: ViewModelsService,
public configService: ConfigService) { }

/**
Expand Down Expand Up @@ -273,7 +272,7 @@ export class DataTableComponent implements AfterViewInit {
* @param addToSelection add to the technique selection (shift key) or replace selection?
*/
onTechniqueSelect(technique, addToSelection, eventX, eventY): void {

if (!this.viewModel.isCurrentlyEditing()) {
if (["comment", "score", "colorpicker"].includes(this.currentDropdown)) this.currentDropdown = ""; //remove technique control dropdowns, because everything was deselected
return;
Expand Down
Loading