This is an automated email from the ASF dual-hosted git repository.
scottyaslan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 7945234f5a NIFI-13670: Improve sensitive value editing. (#9191)
7945234f5a is described below
commit 7945234f5a7e2eb7a7214ac893c0bbce14cb69c8
Author: Matt Gilman <[email protected]>
AuthorDate: Mon Aug 26 13:56:02 2024 -0400
NIFI-13670: Improve sensitive value editing. (#9191)
* NIFI-13670: Improve sensitive value editing.
- Do not present the user with the masked value.
- Do not use the masked value when determining if a value has changed.
- Do not include the masked value in the payload if the value hasn't
changed.
- Updates to ParameterItem model to more easily track changes.
* NIFI-13670: Not setting valueRemoved when deleting a parameter.
* NIFI-13670: Marking field as dirty following removal of sensitive value
set text.
---
.../parameter-context-listing.effects.ts | 18 +-
.../edit-parameter-context.component.ts | 5 +-
.../parameter-table/parameter-table.component.html | 78 ++++----
.../parameter-table/parameter-table.component.ts | 219 +++++++++++++++------
.../apps/nifi/src/app/state/shared/index.ts | 1 +
.../edit-parameter-dialog.component.html | 7 +-
.../edit-parameter-dialog.component.ts | 84 ++++++--
.../editors/nf-editor/nf-editor.component.html | 2 +-
.../editors/nf-editor/nf-editor.component.ts | 23 ++-
.../libs/shared/src/assets/styles/_app.scss | 4 +-
10 files changed, 310 insertions(+), 131 deletions(-)
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts
index 6da70b863d..4f5daaf489 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/state/parameter-context-listing/parameter-context-listing.effects.ts
@@ -113,7 +113,7 @@ export class ParameterContextListingEffects {
dialogReference.componentInstance.createNewParameter = (
existingParameters: string[]
- ): Observable<Parameter> => {
+ ): Observable<EditParameterResponse> => {
const dialogRequest: EditParameterRequest = {
existingParameters };
const newParameterDialogReference =
this.dialog.open(EditParameterDialog, {
...MEDIUM_DIALOG,
@@ -128,13 +128,15 @@ export class ParameterContextListingEffects {
newParameterDialogReference.close();
return {
- ...dialogResponse.parameter
+ ...dialogResponse
};
})
);
};
- dialogReference.componentInstance.editParameter =
(parameter: Parameter): Observable<Parameter> => {
+ dialogReference.componentInstance.editParameter = (
+ parameter: Parameter
+ ): Observable<EditParameterResponse> => {
const dialogRequest: EditParameterRequest = {
parameter: {
...parameter
@@ -153,7 +155,7 @@ export class ParameterContextListingEffects {
editParameterDialogReference.close();
return {
- ...dialogResponse.parameter
+ ...dialogResponse
};
})
);
@@ -317,7 +319,7 @@ export class ParameterContextListingEffects {
editDialogReference.componentInstance.createNewParameter =
(
existingParameters: string[]
- ): Observable<Parameter> => {
+ ): Observable<EditParameterResponse> => {
const dialogRequest: EditParameterRequest = {
existingParameters };
const newParameterDialogReference =
this.dialog.open(EditParameterDialog, {
...MEDIUM_DIALOG,
@@ -332,7 +334,7 @@ export class ParameterContextListingEffects {
newParameterDialogReference.close();
return {
- ...dialogResponse.parameter
+ ...dialogResponse
};
})
);
@@ -340,7 +342,7 @@ export class ParameterContextListingEffects {
editDialogReference.componentInstance.editParameter = (
parameter: Parameter
- ): Observable<Parameter> => {
+ ): Observable<EditParameterResponse> => {
const dialogRequest: EditParameterRequest = {
parameter: {
...parameter
@@ -359,7 +361,7 @@ export class ParameterContextListingEffects {
editParameterDialogReference.close();
return {
- ...dialogResponse.parameter
+ ...dialogResponse
};
})
);
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/edit-parameter-context/edit-parameter-context.component.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/edit-parameter-context/edit-parameter-context.component.ts
index 328e35154f..fe3944b7bc 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/edit-parameter-context/edit-parameter-context.component.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/edit-parameter-context/edit-parameter-context.component.ts
@@ -31,6 +31,7 @@ import { NifiSpinnerDirective } from
'../../../../../ui/common/spinner/nifi-spin
import { Client } from '../../../../../service/client.service';
import { ParameterTable } from '../parameter-table/parameter-table.component';
import {
+ EditParameterResponse,
Parameter,
ParameterContextEntity,
ParameterContextUpdateRequestEntity,
@@ -73,8 +74,8 @@ import { NiFiCommon, TextTip, NifiTooltipDirective } from
'@nifi/shared';
styleUrls: ['./edit-parameter-context.component.scss']
})
export class EditParameterContext extends TabbedDialog {
- @Input() createNewParameter!: (existingParameters: string[]) =>
Observable<Parameter>;
- @Input() editParameter!: (parameter: Parameter) => Observable<Parameter>;
+ @Input() createNewParameter!: (existingParameters: string[]) =>
Observable<EditParameterResponse>;
+ @Input() editParameter!: (parameter: Parameter) =>
Observable<EditParameterResponse>;
@Input() updateRequest!: Observable<ParameterContextUpdateRequestEntity |
null>;
@Input() availableParameterContexts$!:
Observable<ParameterContextEntity[]>;
@Input() saving$!: Observable<boolean>;
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-table/parameter-table.component.html
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-table/parameter-table.component.html
index 0c9b92358d..40aab1b589 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-table/parameter-table.component.html
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-table/parameter-table.component.html
@@ -41,15 +41,15 @@
<div class="flex justify-between items-center">
<div
class="whitespace-nowrap overflow-hidden
text-ellipsis leading-normal"
- [title]="item.entity.parameter.name">
- {{ item.entity.parameter.name }}
+
[title]="item.originalEntity.parameter.name">
+ {{ item.originalEntity.parameter.name }}
</div>
@if (hasDescription(item)) {
<i
class="fa fa-info-circle primary-color"
nifiTooltip
[tooltipComponentType]="TextTip"
-
[tooltipInputData]="item.entity.parameter.description"
+
[tooltipInputData]="getDescription(item)"
[delayClose]="false"></i>
}
@if (canOverride(item)) {
@@ -68,42 +68,46 @@
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef>Value</th>
<td mat-cell *matCellDef="let item">
- @if (isNull(item.entity.parameter.value)) {
- <div class="unset surface-color">No value
set</div>
- } @else {
- <ng-container
- *ngTemplateOutlet="
- isSensitiveParameter(item) ? sensitive
: nonSensitive;
- context: { $implicit:
item.entity.parameter.value }
- "></ng-container>
- <ng-template #sensitive>
- <div class="sensitive
surface-color">Sensitive value set</div>
- </ng-template>
- <ng-template #nonSensitive let-value>
+ <ng-container
+ *ngTemplateOutlet="renderValue; context: {
$implicit: getValue(item) }"></ng-container>
+ <ng-template #renderValue let-parameterValue>
+ @if (isNull(parameterValue)) {
+ <div class="unset surface-color">No value
set</div>
+ } @else {
<ng-container
*ngTemplateOutlet="
- isEmptyString(value) ? blank :
nonBlank;
- context: { $implicit: value }
+ isSensitiveParameter(item) ?
sensitive : nonSensitive;
+ context: { $implicit:
parameterValue }
"></ng-container>
- </ng-template>
- <ng-template #blank>
- <div class="empty surface-color">Empty
string set</div>
- </ng-template>
- <ng-template #nonBlank let-value>
- <div class="flex justify-between
items-center">
- <div class="whitespace-nowrap
overflow-hidden text-ellipsis">
- {{ value }}
+ <ng-template #sensitive>
+ <div class="sensitive
surface-color">Sensitive value set</div>
+ </ng-template>
+ <ng-template #nonSensitive let-value>
+ <ng-container
+ *ngTemplateOutlet="
+ isEmptyString(value) ? blank :
nonBlank;
+ context: { $implicit: value }
+ "></ng-container>
+ </ng-template>
+ <ng-template #blank>
+ <div class="empty surface-color">Empty
string set</div>
+ </ng-template>
+ <ng-template #nonBlank let-value>
+ <div class="flex justify-between
items-center">
+ <div class="whitespace-nowrap
overflow-hidden text-ellipsis">
+ {{ value }}
+ </div>
+ @if (hasExtraWhitespace(value)) {
+ <div
+ class="fa fa-info-circle
primary-color"
+ nifiTooltip
+
[tooltipComponentType]="TextTip"
+ tooltipInputData="The
specified value contains leading and/or trailing whitespace character(s). This
could produce unexpected results if it was not intentional."></div>
+ }
</div>
- @if (hasExtraWhitespace(value)) {
- <div
- class="fa fa-info-circle
primary-color"
- nifiTooltip
-
[tooltipComponentType]="TextTip"
- tooltipInputData="The
specified value contains leading and/or trailing whitespace character(s). This
could produce unexpected results if it was not intentional."></div>
- }
- </div>
- </ng-template>
- }
+ </ng-template>
+ }
+ </ng-template>
</td>
</ng-container>
@@ -171,7 +175,7 @@
<div>Parameter</div>
<div class="accent-color font-medium">
@if (selectedItem) {
- <span>{{ selectedItem.entity.parameter.name }}</span>
+ <span>{{ selectedItem.originalEntity.parameter.name
}}</span>
} @else {
<span class="unset surface-color">None</span>
}
@@ -191,7 +195,7 @@
@if (selectedItem) {
<parameter-references
[parameterReferences]="
-
selectedItem.entity.parameter.referencingComponents
+
selectedItem.originalEntity.parameter.referencingComponents
"></parameter-references>
}
</div>
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-table/parameter-table.component.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-table/parameter-table.component.ts
index 70f10fbb30..1d1c5fe01a 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-table/parameter-table.component.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/parameter-contexts/ui/parameter-context-listing/parameter-table/parameter-table.component.ts
@@ -23,7 +23,7 @@ import { MatTableDataSource, MatTableModule } from
'@angular/material/table';
import { AsyncPipe, NgTemplateOutlet } from '@angular/common';
import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
import { RouterLink } from '@angular/router';
-import { Parameter, ParameterEntity } from '../../../../../state/shared';
+import { EditParameterResponse, Parameter, ParameterEntity } from
'../../../../../state/shared';
import { NifiTooltipDirective, NiFiCommon, TextTip } from '@nifi/shared';
import { Observable, take } from 'rxjs';
import { ParameterReferences } from
'../../../../../ui/common/parameter-references/parameter-references.component';
@@ -37,7 +37,8 @@ export interface ParameterItem {
deleted: boolean;
dirty: boolean;
added: boolean;
- entity: ParameterEntity;
+ originalEntity: ParameterEntity; // either new or existing from server
+ updatedEntity?: ParameterEntity;
}
@Component({
@@ -70,8 +71,8 @@ export interface ParameterItem {
]
})
export class ParameterTable implements AfterViewInit, ControlValueAccessor {
- @Input() createNewParameter!: (existingParameters: string[]) =>
Observable<Parameter>;
- @Input() editParameter!: (parameter: Parameter) => Observable<Parameter>;
+ @Input() createNewParameter!: (existingParameters: string[]) =>
Observable<EditParameterResponse>;
+ @Input() editParameter!: (parameter: Parameter) =>
Observable<EditParameterResponse>;
@Input() canAddParameters = true;
protected readonly TextTip = TextTip;
@@ -128,10 +129,11 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
deleted: false,
added: false,
dirty: false,
- entity: {
+ originalEntity: {
...entity,
parameter: {
- ...entity.parameter
+ ...entity.parameter,
+ value: entity.parameter.value === undefined ? null :
entity.parameter.value
}
}
};
@@ -161,7 +163,10 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
let retVal = 0;
switch (sort.active) {
case 'name':
- retVal =
this.nifiCommon.compareString(a.entity.parameter.name, b.entity.parameter.name);
+ retVal = this.nifiCommon.compareString(
+ a.originalEntity.parameter.name,
+ b.originalEntity.parameter.name
+ );
break;
default:
return 0;
@@ -176,25 +181,27 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
// unmarked for deletion if the user chooses to enter the same name
const existingParameters: string[] = this.dataSource.data
.filter((item) => !item.deleted)
- .filter((item) => !item.entity.parameter.inherited)
- .map((item) => item.entity.parameter.name);
+ .filter((item) => !item.originalEntity.parameter.inherited)
+ .map((item) => item.originalEntity.parameter.name);
this.createNewParameter(existingParameters)
.pipe(take(1))
- .subscribe((parameter) => {
+ .subscribe((response: EditParameterResponse) => {
+ const parameter: Parameter = response.parameter;
+
const currentParameterItems: ParameterItem[] =
this.dataSource.data;
// identify if a parameter with the same name already exists
(must have been marked
// for deletion already)
const item: ParameterItem | undefined =
currentParameterItems.find(
- (item) => item.entity.parameter.name === parameter.name
+ (item) => item.originalEntity.parameter.name ===
parameter.name
);
if (item) {
// if the item is added that means it hasn't been saved
yet. in this case, we
// can simply update the existing parameter. if the item
has been saved, and the
// sensitivity has changed, the user must apply the
changes first.
- if (!item.added && item.entity.parameter.sensitive !==
parameter.sensitive) {
+ if (!item.added && item.originalEntity.parameter.sensitive
!== parameter.sensitive) {
this.store.dispatch(
showOkDialog({
title: 'Parameter Exists',
@@ -208,15 +215,21 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
// update the existing item
item.deleted = false;
item.dirty = true;
- item.entity.parameter = {
- ...parameter
- };
+
+ // since the item is either new or the sensitivity is the
same, accept the sensitivity
+ // from the response to be set on the entities
+ item.originalEntity.parameter.sensitive =
parameter.sensitive;
+ if (item.updatedEntity) {
+ item.updatedEntity.parameter.sensitive =
parameter.sensitive;
+ }
+
+ this.applyParameterEdit(item, response);
} else {
const newItem: ParameterItem = {
deleted: false,
added: true,
dirty: true,
- entity: {
+ originalEntity: {
canWrite: true,
parameter: {
...parameter
@@ -232,11 +245,36 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
}
hasDescription(item: ParameterItem): boolean {
- return !this.nifiCommon.isBlank(item.entity.parameter.description);
+ return !this.nifiCommon.isBlank(this.getDescription(item));
+ }
+
+ getDescription(item: ParameterItem): string {
+ if (item.updatedEntity) {
+ return item.updatedEntity.parameter.description;
+ } else {
+ return item.originalEntity.parameter.description;
+ }
}
isSensitiveParameter(item: ParameterItem): boolean {
- return item.entity.parameter.sensitive;
+ return item.originalEntity.parameter.sensitive;
+ }
+
+ getValue(item: ParameterItem): string | null {
+ if (item.updatedEntity) {
+ if (item.updatedEntity.parameter.valueRemoved) {
+ return null;
+ } else {
+ // if there is an updated value use that, otherwise the
original
+ if (item.updatedEntity.parameter.value !== null) {
+ return item.updatedEntity.parameter.value;
+ } else {
+ return item.originalEntity.parameter.value;
+ }
+ }
+ } else {
+ return item.originalEntity.parameter.value;
+ }
}
isNull(value: string): boolean {
@@ -253,35 +291,37 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
canGoToParameter(item: ParameterItem): boolean {
return (
- item.entity.parameter.inherited === true &&
- item.entity.parameter.parameterContext?.permissions.canRead == true
+ item.originalEntity.parameter.inherited === true &&
+
item.originalEntity.parameter.parameterContext?.permissions.canRead == true
);
}
getParameterLink(item: ParameterItem): string[] {
- if (item.entity.parameter.parameterContext) {
+ if (item.originalEntity.parameter.parameterContext) {
// TODO - support routing directly to a parameter
- return ['/parameter-contexts',
item.entity.parameter.parameterContext.id, 'edit'];
+ return ['/parameter-contexts',
item.originalEntity.parameter.parameterContext.id, 'edit'];
}
return [];
}
canOverride(item: ParameterItem): boolean {
- return item.entity.parameter.inherited === true;
+ return item.originalEntity.parameter.inherited === true;
}
overrideParameter(item: ParameterItem): void {
const overriddenParameter: Parameter = {
- ...item.entity.parameter,
+ ...item.originalEntity.parameter,
value: null
};
this.editParameter(overriddenParameter)
.pipe(take(1))
- .subscribe((parameter) => {
+ .subscribe((response) => {
item.dirty = true;
- item.entity.parameter = {
- ...parameter
+ item.updatedEntity = {
+ parameter: {
+ ...response.parameter
+ }
};
this.handleChanged();
@@ -289,46 +329,93 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
}
canEdit(item: ParameterItem): boolean {
- const canWrite: boolean = item.entity.canWrite == true;
- const provided: boolean = item.entity.parameter.provided == true;
- const inherited: boolean = item.entity.parameter.inherited == true;
+ const canWrite: boolean = item.originalEntity.canWrite == true;
+ const provided: boolean = item.originalEntity.parameter.provided ==
true;
+ const inherited: boolean = item.originalEntity.parameter.inherited ==
true;
return canWrite && !provided && !inherited;
}
editClicked(item: ParameterItem): void {
- this.editParameter(item.entity.parameter)
+ const parameterToEdit: Parameter = {
+ name: item.originalEntity.parameter.name,
+ sensitive: item.originalEntity.parameter.sensitive,
+ description: this.getDescription(item),
+ value: this.getValue(item)
+ };
+
+ this.editParameter(parameterToEdit)
.pipe(take(1))
- .subscribe((parameter) => {
- const valueChanged: boolean = item.entity.parameter.value !=
parameter.value;
- const descriptionChanged: boolean =
item.entity.parameter.description != parameter.description;
- const valueRemovedChanged: boolean =
item.entity.parameter.valueRemoved != parameter.valueRemoved;
-
- if (valueChanged || descriptionChanged || valueRemovedChanged)
{
- item.entity.parameter.value = parameter.value;
- item.entity.parameter.description = parameter.description;
- item.entity.parameter.valueRemoved =
parameter.valueRemoved;
- item.dirty = true;
+ .subscribe((response) => {
+ this.applyParameterEdit(item, response);
+ });
+ }
- if (valueChanged) {
- item.entity.parameter.referencedAssets = undefined;
- }
+ private applyParameterEdit(item: ParameterItem, response:
EditParameterResponse) {
+ const parameter: Parameter = response.parameter;
- this.handleChanged();
+ // initialize the updated entity if this is the first time this has
been edited
+ if (!item.updatedEntity) {
+ item.updatedEntity = {
+ parameter: {
+ ...item.originalEntity.parameter,
+ value: null
}
- });
+ };
+ }
+
+ let hasChanged: boolean = response.valueChanged;
+
+ if (response.valueChanged) {
+ item.updatedEntity.parameter.value = parameter.value;
+
+ // a value has been specified so record it in the updated entity
+ if (parameter.value !== null) {
+ item.updatedEntity.parameter.valueRemoved = undefined;
+ item.updatedEntity.parameter.referencedAssets = undefined;
+ } else {
+ // the value is null, this means that the value should be
unchanged
+ // or that the value has been removed. if removed we should
+ // clear our the value.
+ if (parameter.valueRemoved === true) {
+ item.updatedEntity.parameter.value = null;
+ item.updatedEntity.parameter.valueRemoved = true;
+ item.updatedEntity.parameter.referencedAssets = undefined;
+ }
+ }
+ }
+
+ if (item.updatedEntity.parameter.description !==
parameter.description) {
+ hasChanged = true;
+ item.updatedEntity.parameter.description = parameter.description;
+ }
+
+ // if any aspect of the parameter has changed, mark it dirty and
trigger handle changed
+ if (hasChanged) {
+ item.dirty = true;
+ this.handleChanged();
+ }
}
canDelete(item: ParameterItem): boolean {
- const canWrite: boolean = item.entity.canWrite == true;
- const provided: boolean = item.entity.parameter.provided == true;
- const inherited: boolean = item.entity.parameter.inherited == true;
+ const canWrite: boolean = item.originalEntity.canWrite == true;
+ const provided: boolean = item.originalEntity.parameter.provided ==
true;
+ const inherited: boolean = item.originalEntity.parameter.inherited ==
true;
return canWrite && !provided && !inherited;
}
deleteClicked(item: ParameterItem): void {
if (!item.deleted) {
- item.entity.parameter.value = null;
- item.entity.parameter.valueRemoved = true;
+ if (!item.updatedEntity) {
+ item.updatedEntity = {
+ parameter: {
+ ...item.originalEntity.parameter
+ }
+ };
+ }
+
+ item.updatedEntity.parameter.value = null;
+ item.updatedEntity.parameter.referencedAssets = undefined;
+
item.deleted = true;
item.dirty = true;
this.selectParameter(null);
@@ -360,20 +447,34 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
.filter((item) => !(item.added && item.deleted))
.map((item) => {
if (item.deleted) {
+ // item is deleted
+ return {
+ parameter: {
+ name: item.originalEntity.parameter.name
+ }
+ };
+ } else if (item.updatedEntity) {
+ // item has been edited
return {
parameter: {
- name: item.entity.parameter.name
+ name: item.originalEntity.parameter.name,
+ sensitive: item.originalEntity.parameter.sensitive,
+ description:
item.updatedEntity.parameter.description,
+ value: item.updatedEntity.parameter.value,
+ valueRemoved:
item.updatedEntity.parameter.valueRemoved,
+ referencedAssets:
item.updatedEntity.parameter.referencedAssets
}
};
} else {
+ // item is added (but not subsequently edited)
return {
parameter: {
- name: item.entity.parameter.name,
- sensitive: item.entity.parameter.sensitive,
- description: item.entity.parameter.description,
- value: item.entity.parameter.value,
- valueRemoved: item.entity.parameter.valueRemoved,
- referencedAssets:
item.entity.parameter.referencedAssets
+ name: item.originalEntity.parameter.name,
+ sensitive: item.originalEntity.parameter.sensitive,
+ description:
item.originalEntity.parameter.description,
+ value: item.originalEntity.parameter.value,
+ valueRemoved:
item.originalEntity.parameter.valueRemoved,
+ referencedAssets:
item.originalEntity.parameter.referencedAssets
}
};
}
@@ -386,7 +487,7 @@ export class ParameterTable implements AfterViewInit,
ControlValueAccessor {
isSelected(item: ParameterItem): boolean {
if (this.selectedItem) {
- return item.entity.parameter.name ==
this.selectedItem.entity.parameter.name;
+ return item.originalEntity.parameter.name ==
this.selectedItem.originalEntity.parameter.name;
}
return false;
}
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/state/shared/index.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/state/shared/index.ts
index 6b5522572f..17b9126cca 100644
--- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/state/shared/index.ts
+++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/state/shared/index.ts
@@ -50,6 +50,7 @@ export interface EditParameterRequest {
export interface EditParameterResponse {
parameter: Parameter;
+ valueChanged: boolean;
}
export interface AdvancedUiParams {
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/edit-parameter-dialog/edit-parameter-dialog.component.html
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/edit-parameter-dialog/edit-parameter-dialog.component.html
index c731da34e2..a828469ee9 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/edit-parameter-dialog/edit-parameter-dialog.component.html
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/edit-parameter-dialog/edit-parameter-dialog.component.html
@@ -37,7 +37,12 @@
[tooltipComponentType]="TextTip"
tooltipInputData="Parameter values do not support
Expression Language or embedded parameter references."></i>
</mat-label>
- <textarea matInput formControlName="value"
type="text"></textarea>
+ <textarea
+ matInput
+ formControlName="value"
+ type="text"
+ [class.sensitive]="showSensitiveHelperText"
+ (keydown)="clearSensitiveHelperText()"></textarea>
</mat-form-field>
</div>
<div class="-mt-4 mb-4">
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/edit-parameter-dialog/edit-parameter-dialog.component.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/edit-parameter-dialog/edit-parameter-dialog.component.ts
index 171879375f..6a48555751 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/edit-parameter-dialog/edit-parameter-dialog.component.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/edit-parameter-dialog/edit-parameter-dialog.component.ts
@@ -17,7 +17,7 @@
import { Component, EventEmitter, Inject, Input, Output } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
-import { EditParameterRequest, EditParameterResponse, Parameter,
ReferencedAsset } from '../../../state/shared';
+import { EditParameterRequest, EditParameterResponse, Parameter } from
'../../../state/shared';
import { MatButtonModule } from '@angular/material/button';
import {
AbstractControl,
@@ -67,6 +67,8 @@ export class EditParameterDialog extends CloseOnEscapeDialog {
sensitive: FormControl;
editParameterForm: FormGroup;
isNew: boolean;
+ showSensitiveHelperText: boolean = false;
+ valueInputTriggered: boolean = false;
private originalParameter: Parameter | undefined = undefined;
@@ -81,10 +83,14 @@ export class EditParameterDialog extends
CloseOnEscapeDialog {
const parameter: Parameter | undefined = request.parameter;
this.originalParameter = parameter;
+ let value: string | null;
+
const validators: any[] = [Validators.required];
if (request.existingParameters) {
this.isNew = true;
+ value = parameter ? parameter.value : null;
+
// since there were existing parameters in the request, add the
existing parameters validator because
// parameters names must be unique
validators.push(this.existingParameterValidator(request.existingParameters));
@@ -100,20 +106,25 @@ export class EditParameterDialog extends
CloseOnEscapeDialog {
} else {
this.isNew = false;
+ value = parameter ? parameter.value : null;
+
+ const sensitive = parameter ? parameter.sensitive : false;
+ if (sensitive && value !== null) {
+ value = 'Sensitive value set';
+ this.showSensitiveHelperText = true;
+ }
+
// without existingParameters, we are editing an existing
parameter. in this case the name and sensitivity cannot be modified
this.name = new FormControl(
{ value: parameter ? parameter.name : '', disabled: true },
Validators.required
);
- this.sensitive = new FormControl(
- { value: parameter ? parameter.sensitive : false, disabled:
true },
- Validators.required
- );
+ this.sensitive = new FormControl({ value: sensitive, disabled:
true }, Validators.required);
}
this.editParameterForm = this.formBuilder.group({
name: this.name,
- value: new FormControl(parameter ? parameter.value : null),
+ value: new FormControl(value),
empty: new FormControl(parameter ? parameter.value == '' : false),
sensitive: this.sensitive,
description: new FormControl(parameter ? parameter.description :
'')
@@ -146,12 +157,23 @@ export class EditParameterDialog extends
CloseOnEscapeDialog {
return this.name.hasError('existingParameter') ? 'A parameter with
this name already exists.' : '';
}
+ clearSensitiveHelperText(): void {
+ if (this.showSensitiveHelperText) {
+ this.editParameterForm.get('value')?.setValue('');
+ this.showSensitiveHelperText = false;
+ }
+
+ this.valueInputTriggered = true;
+ }
+
setEmptyStringChanged(): void {
const emptyStringChecked: AbstractControl | null =
this.editParameterForm.get('empty');
if (emptyStringChecked) {
if (emptyStringChecked.value) {
this.editParameterForm.get('value')?.setValue('');
this.editParameterForm.get('value')?.disable();
+
+ this.valueInputTriggered = true;
} else {
this.editParameterForm.get('value')?.enable();
}
@@ -162,24 +184,50 @@ export class EditParameterDialog extends
CloseOnEscapeDialog {
this.cancel.next();
}
+ private valueChanged(enteredValue: string | null): boolean {
+ let valueChanged = true;
+ if (this.originalParameter) {
+ if (this.originalParameter.sensitive) {
+ valueChanged = this.valueInputTriggered;
+ } else {
+ valueChanged = enteredValue !== this.originalParameter.value;
+ }
+ }
+ return valueChanged;
+ }
+
okClicked(): void {
- const value: string = this.editParameterForm.get('value')?.value;
+ const value: string | null =
this.editParameterForm.get('value')?.value;
const empty: boolean = this.editParameterForm.get('empty')?.value;
- let referencedAssets: ReferencedAsset[] | undefined = undefined;
- if (this.originalParameter) {
- referencedAssets = this.originalParameter.referencedAssets;
+ const parameter: Parameter = {
+ name: this.editParameterForm.get('name')?.value,
+ value: null,
+ sensitive: this.editParameterForm.get('sensitive')?.value,
+ description: this.editParameterForm.get('description')?.value
+ };
+
+ // update the parameter value
+ let valueChanged = this.valueChanged(value);
+ if (valueChanged) {
+ parameter.value = value;
}
- this.editParameter.next({
- parameter: {
- name: this.editParameterForm.get('name')?.value,
- value: value === '' && !empty ? null : value,
- valueRemoved: value === '' && !empty,
- sensitive: this.editParameterForm.get('sensitive')?.value,
- description: this.editParameterForm.get('description')?.value,
- referencedAssets
+ // indicate if the value has been removed
+ const valueRemoved = value === '' && !empty;
+ if (valueRemoved) {
+ valueChanged = true;
+ parameter.value = null;
+
+ // if this is a new parameter there is no need to indicate that
the value is removed
+ if (!this.isNew) {
+ parameter.valueRemoved = true;
}
+ }
+
+ this.editParameter.next({
+ parameter,
+ valueChanged
});
}
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/property-table/editors/nf-editor/nf-editor.component.html
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/property-table/editors/nf-editor/nf-editor.component.html
index b46575b993..be1026dfc9 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/property-table/editors/nf-editor/nf-editor.component.html
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/property-table/editors/nf-editor/nf-editor.component.html
@@ -47,7 +47,7 @@
</ng-template>
</div>
<div class="flex flex-col gap-y-0.5 flex-1">
- <div class="nf-editor flex-1" [class.blank]="blank">
+ <div class="nf-editor flex-1" [class.blank]="blank"
[class.sensitive]="showSensitiveHelperText">
<ngx-codemirror
[options]="getOptions()"
formControlName="value"
diff --git
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/property-table/editors/nf-editor/nf-editor.component.ts
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/property-table/editors/nf-editor/nf-editor.component.ts
index 1a396e2a3f..36dd4e7dfa 100644
---
a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/property-table/editors/nf-editor/nf-editor.component.ts
+++
b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/property-table/editors/nf-editor/nf-editor.component.ts
@@ -55,7 +55,13 @@ import { Editor } from 'codemirror';
})
export class NfEditor implements OnDestroy {
@Input() set item(item: PropertyItem) {
- this.nfEditorForm.get('value')?.setValue(item.value);
+ if (item.descriptor.sensitive && item.value !== null) {
+ this.nfEditorForm.get('value')?.setValue('Sensitive value set');
+ this.showSensitiveHelperText = true;
+ } else {
+ this.nfEditorForm.get('value')?.setValue(item.value);
+ }
+
if (item.descriptor.required) {
this.nfEditorForm.get('value')?.addValidators(Validators.required);
} else {
@@ -67,7 +73,6 @@ export class NfEditor implements OnDestroy {
this.setEmptyStringChanged();
this.supportsEl = item.descriptor.supportsEl;
- this.sensitive = item.descriptor.sensitive;
this.mode = this.supportsEl ? this.nfel.getLanguageId() :
this.nfpr.getLanguageId();
this.itemSet = true;
@@ -93,7 +98,7 @@ export class NfEditor implements OnDestroy {
getParametersSet = false;
nfEditorForm: FormGroup;
- sensitive = false;
+ showSensitiveHelperText = false;
supportsEl = false;
supportsParameters = false;
blank = false;
@@ -124,6 +129,18 @@ export class NfEditor implements OnDestroy {
this.editor.execCommand('selectAll');
}
+ if (this.showSensitiveHelperText) {
+ const clearSensitiveHelperText = () => {
+ if (this.showSensitiveHelperText) {
+ this.nfEditorForm.get('value')?.setValue('');
+ this.nfEditorForm.get('value')?.markAsDirty();
+ this.showSensitiveHelperText = false;
+ }
+ };
+
+ this.editor.on('keydown', clearSensitiveHelperText);
+ }
+
// disabling of the input through the form isn't supported until
codemirror
// has loaded so we must disable again if the value is an empty string
if (this.nfEditorForm.get('setEmptyString')?.value) {
diff --git
a/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_app.scss
b/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_app.scss
index 5e6c914bde..886458fcaf 100644
--- a/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_app.scss
+++ b/nifi-frontend/src/main/frontend/libs/shared/src/assets/styles/_app.scss
@@ -56,8 +56,8 @@
.unset,
.sensitive {
font-weight: normal !important;
- font-style: italic;
- opacity: 0.8;
+ font-style: italic !important;
+ opacity: 0.8 !important;
}
.context-logo {