Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<ht-table #table name="filesAttackTable" dataType="files-attack" [columnLabels]="columnLabels" [dataSource]="dataSource"
[tableColumns]="tableColumns" [isFilterable]="isFilterable" [isPageable]="true" [isCmdTask]="cmdTask"
[isCmdLabel]="customLabel" [isCmdPreproAttack]="cmdPrepro" [isCmdFiles]="formData.files" [isSelectable]="true"
[isCmdLabel]="customLabel" [isCmdPreproAttack]="cmdPrepro" [isCmdFiles]="formData.files"
[isCmdPreproFiles]="formData.otherFiles ?? []" [isSelectable]="true"
[showExport]="false" [isDetailPage]="true" (checkboxChanged)="onCheckboxChanged($event)"
(selectedFilterColumnChanged)="selectedFilterColumn = $event" (backendSqlFilter)="handleBackendSqlFilter($event)" />
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,11 @@
<ng-container>
<!-- CMD Preprocessor -->
@if (isCmdPreproAttack) {
<mat-checkbox (click)="$event.stopPropagation()" (change)="toggleAttack($event, row, 'CMD_PREPRO')" />
<mat-checkbox
(click)="$event.stopPropagation()"
(change)="toggleAttack($event, row, 'CMD_PREPRO')"
[checked]="isPreproSelected(row)"
/>
}
</ng-container>
</td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ export class HTTableComponent<T extends BaseModel> implements OnInit, AfterViewI
/** Flag to enable or disable cmd preprocessor attack checkbox. */
@Input() isCmdPreproAttack = false;

@Input() isCmdPreproFiles: number[] = [];

/** Flag to add dual label text. */
@Input() isCmdLabel: string;

Expand Down Expand Up @@ -680,6 +682,10 @@ export class HTTableComponent<T extends BaseModel> implements OnInit, AfterViewI
}
}

isPreproSelected(row: T): boolean {
return this.isCmdPreproFiles.includes(row.id);
}

/**
* Checks if all rows are selected.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/app/tasks/new-tasks/new-tasks.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ <h2 class="text-sm font-medium text-muted-foreground uppercase tracking-wide">Ta
[fileType]="FileType.OTHER"
[formData]="getFormData()"
(updateFormEvent)="onUpdateForm($event)"
[cmdPrepro]="false"
[cmdPrepro]="isPreprocessor()"
></app-files-attack-table>
</mat-expansion-panel>
</mat-accordion>
Expand Down
106 changes: 106 additions & 0 deletions src/app/tasks/new-tasks/new-tasks.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Params, Router } from '@angular/router';

import { UiSettings } from '@models/config-ui.schema';
import { FileType } from '@models/file.model';
import { JPretask } from '@models/pretask.model';
import { ResponseWrapper } from '@models/response.model';
import { JTask } from '@models/task.model';
Expand Down Expand Up @@ -426,6 +427,60 @@ describe('NewTasksComponent', () => {
expect(routerSpy.navigate).toHaveBeenCalledWith(['tasks/show-tasks']);
});

it('should merge the preprocessor files into the task files', async () => {
await initComponent(fixture);

component.form.patchValue({
taskName: 'My Task',
hashlistId: 1,
attackCmd: '-a 0 #HL# dict.txt',
priority: 0,
crackerBinaryId: 10,
files: [10]
});
component['onUpdateForm']({
type: 'CMD_PREPRO',
attackCmd: '--prince keyspace.txt',
files: [],
otherFiles: [10, 30]
});
component.form.updateValueAndValidity();

await component['onSubmit']();

const payload = globalServiceSpy.create.calls.mostRecent().args[1] as { files: number[] };
expect(payload.files).toEqual([10, 30]);
});

it('should drop the preprocessor files when the preprocessor is set to none', async () => {
await initComponent(fixture);

component.form.patchValue({
taskName: 'My Task',
hashlistId: 1,
attackCmd: '-a 0 #HL# dict.txt',
priority: 0,
crackerBinaryId: 10,
preprocessorId: 1,
files: [10]
});
component['onUpdateForm']({
type: 'CMD_PREPRO',
attackCmd: '--prince keyspace.txt',
files: [],
otherFiles: [30]
});

component.form.controls.preprocessorId.setValue(0);
component.form.updateValueAndValidity();

await component['onSubmit']();

const payload = globalServiceSpy.create.calls.mostRecent().args[1] as { files: number[] };
expect(payload.files).toEqual([10]);
expect(component.form.controls.preprocessorCommand.value).toBe('');
});

it('should mark form as touched when invalid and not submit', async () => {
await initComponent(fixture);

Expand Down Expand Up @@ -900,6 +955,41 @@ describe('NewTasksComponent', () => {
});
});

describe('Preprocessor file selection', () => {
function cmdPreproByFileType(): Record<number, unknown> {
const tables = Array.from(fixture.nativeElement.querySelectorAll('app-files-attack-table')) as Record<
string,
unknown
>[];

return Object.fromEntries(tables.map((table) => [table['fileType'] as number, table['cmdPrepro']]));
}

it('should offer the preprocessor checkbox for wordlists and other files when a preprocessor is set', async () => {
await initComponent(fixture);

component.form.controls.preprocessorId.setValue(5, { emitEvent: false });
fixture.detectChanges();

const cmdPrepro = cmdPreproByFileType();
expect(cmdPrepro[FileType.WORDLIST]).toBe(true);
expect(cmdPrepro[FileType.OTHER]).toBe(true);
expect(cmdPrepro[FileType.RULES]).toBe(false);
});

it('should hide the preprocessor checkbox on every file table when no preprocessor is set', async () => {
await initComponent(fixture);

component.form.controls.preprocessorId.setValue(0, { emitEvent: false });
fixture.detectChanges();

const cmdPrepro = cmdPreproByFileType();
expect(cmdPrepro[FileType.WORDLIST]).toBe(false);
expect(cmdPrepro[FileType.OTHER]).toBe(false);
expect(cmdPrepro[FileType.RULES]).toBe(false);
});
});

describe('onUpdateForm', () => {
it('should update attackCmd and files when event type is CMD', async () => {
await initComponent(fixture);
Expand Down Expand Up @@ -927,6 +1017,22 @@ describe('NewTasksComponent', () => {

expect(component.form.controls.preprocessorCommand.value).toBe('--prince-elem-cnt-min=1');
});

it('should keep the preprocessor files out of the task files when event type is not CMD', async () => {
await initComponent(fixture);

component.form.controls.files.setValue([10]);

component['onUpdateForm']({
type: 'CMD_PREPRO',
attackCmd: '--prince keyspace.txt',
files: [],
otherFiles: [30]
});

expect(component.form.controls.preprocessorCommand.value).toBe('--prince keyspace.txt');
expect(component.form.controls.files.value).toEqual([10]);
});
});

describe('openHelpDialog', () => {
Expand Down
9 changes: 9 additions & 0 deletions src/app/tasks/new-tasks/new-tasks.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ export class NewTasksComponent implements OnInit {
copyFiles: FileId[];
editedIndex: number;

private preprocessorFiles: FileId[] = [];

// Tooltips
tasktip: TaskTooltipsLevel;

Expand Down Expand Up @@ -174,6 +176,10 @@ export class NewTasksComponent implements OnInit {
});

this.form.controls.preprocessorId.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((newValue) => {
if (newValue === 0) {
this.preprocessorFiles = [];
this.form.controls.preprocessorCommand.setValue('', { emitEvent: false });
}
this.handleChangePreprocessor(newValue);
});
}
Expand Down Expand Up @@ -279,6 +285,7 @@ export class NewTasksComponent implements OnInit {
return {
attackCmd: this.form.controls.attackCmd.value,
files: this.form.controls.files.value,
otherFiles: this.preprocessorFiles,
preprocessorCommand: this.form.controls.preprocessorCommand.value
};
}
Expand All @@ -303,6 +310,7 @@ export class NewTasksComponent implements OnInit {
files: event.files
});
} else {
this.preprocessorFiles = event.otherFiles;
this.form.patchValue({
preprocessorCommand: event.attackCmd
});
Expand Down Expand Up @@ -408,6 +416,7 @@ export class NewTasksComponent implements OnInit {

const payload = { ...this.form.value };
delete payload.crackerBinaryTypeId;
payload.files = [...new Set([...(payload.files ?? []), ...this.preprocessorFiles])];

this.gs.create(SERV.TASKS, payload).subscribe({
next: () => {
Expand Down
Loading