From 418ee88cd5bda27384a87965b50deb651e8ec4e1 Mon Sep 17 00:00:00 2001 From: Borys Date: Tue, 17 Feb 2026 09:20:38 -0500 Subject: [PATCH 01/24] editable fields config Signed-off-by: Borys --- .../validation/schemas/policies.dto.ts | 8 + .../src/database-modules/database-server.ts | 1 + common/src/entity/policy.ts | 3 + .../editible-fields-dialog.component.html | 118 +++++++++++ .../editible-fields-dialog.component.scss | 101 ++++++++++ .../editible-fields-dialog.component.ts | 190 ++++++++++++++++++ .../policy-configuration.component.html | 5 + .../policy-configuration.component.ts | 19 ++ .../policy-engine/policy-engine.module.ts | 4 +- .../policy-models/policy/policy.model.ts | 3 + interfaces/src/helpers/index.ts | 3 +- .../src/helpers/policy-editable-field.ts | 30 +++ 12 files changed, 483 insertions(+), 2 deletions(-) create mode 100644 frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html create mode 100644 frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.scss create mode 100644 frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.ts create mode 100644 interfaces/src/helpers/policy-editable-field.ts diff --git a/api-gateway/src/middlewares/validation/schemas/policies.dto.ts b/api-gateway/src/middlewares/validation/schemas/policies.dto.ts index 9167292076..4936708fc6 100644 --- a/api-gateway/src/middlewares/validation/schemas/policies.dto.ts +++ b/api-gateway/src/middlewares/validation/schemas/policies.dto.ts @@ -247,6 +247,14 @@ export class PolicyDTO { @IsBoolean() originalChanged?: boolean; + @ApiProperty({ + type: 'string', + required: false + }) + + @IsOptional() + editableParametersSettings?: string; + @ApiProperty({ type: 'object', additionalProperties: true, diff --git a/common/src/database-modules/database-server.ts b/common/src/database-modules/database-server.ts index 3a2d86830d..cbc059dbe4 100644 --- a/common/src/database-modules/database-server.ts +++ b/common/src/database-modules/database-server.ts @@ -4860,6 +4860,7 @@ export class DatabaseServer extends AbstractDatabaseServer { model.policyGroups = data.policyGroups; model.categories = data.categories; model.projectSchema = data.projectSchema; + model.editableParametersSettings = data.editableParametersSettings; return await new DataBaseHelper(Policy).save(model); } diff --git a/common/src/entity/policy.ts b/common/src/entity/policy.ts index 5271174097..1ef6cf6c93 100644 --- a/common/src/entity/policy.ts +++ b/common/src/entity/policy.ts @@ -297,6 +297,9 @@ export class Policy extends BaseEntity { @Property({ nullable: true }) originalMessageId?: string; + @Property({ nullable: true }) + editableParametersSettings?: string; + /** * File id of the original policy zip (publish flow). */ diff --git a/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html b/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html new file mode 100644 index 0000000000..db1e5608c0 --- /dev/null +++ b/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html @@ -0,0 +1,118 @@ +
+
+
+
+
+
+
+ + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + + + +
+
+
+
+
+ +
+ +
\ No newline at end of file diff --git a/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.scss b/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.scss new file mode 100644 index 0000000000..c805b1489a --- /dev/null +++ b/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.scss @@ -0,0 +1,101 @@ +.context { + position: relative; + overflow-y: auto; + padding: 14px 0 20px 0; + display: flex; + flex-direction: row; + height: 100%; + font-family: Inter, serif; + font-style: normal; +} + +form { + width: 100%; + + .guardian-input-container { + margin-bottom: 24px; + } + + .guardian-textarea-container { + margin-bottom: 24px; + } +} + +.action-buttons { + display: flex; + justify-content: flex-end; + user-select: none; + + &>div { + margin-left: 15px; + margin-right: 0px; + } +} + +.close-icon-color { + fill: #848FA9; + color: #848FA9; +} + +.ddl { + width: 210px; +} + +.field { + display: inline-block; + width: auto; + vertical-align: top; + width: 210px; +} + +.fields-grid { + display:grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap:16px; + align-items:end; +} +.delete-field { + grid-column: 5; + justify-self:end; + position: relative; + top: -3px; +} +.label-field{ grid-column: 1; } +.description-field{ + grid-column: 2 / 5; + min-width: 0; + width: 100%; +} +.default-field{ grid-column: 1; } +.required-field{ + grid-column: 2 / 5; + display:flex; + align-items:center; + gap:10px; + padding-bottom:10px; +} + +.group-container { + background-color: #F9FAFC; + border-radius: 8px; + border: 1px solid #E1E7EF; + opacity: 1; + gap: 16px; + padding: 16px; + margin-bottom: 24px; +} + +.guardian-icon-button { + width: 24px; + height: 24px; +} + +.add-button, +.dialog-button button { + height: 40px; + padding: 5px 24px; +} + +.add-button { + margin-bottom: 24px; +} \ No newline at end of file diff --git a/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.ts b/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.ts new file mode 100644 index 0000000000..4e0e5b3941 --- /dev/null +++ b/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.ts @@ -0,0 +1,190 @@ +import { Component, OnInit } from '@angular/core'; +import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; +import { SelectItem } from 'primeng/api/public_api'; +import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; +import { PolicyBlock, PolicyItem, PolicyTemplate } from '../../structures'; +import { RegisteredService } from '../../services/registered.service'; +import { PolicyEngineService } from 'src/app/services/policy-engine.service'; +import { Subject, takeUntil } from 'rxjs'; +import { PolicyEditableField } from '@guardian/interfaces'; + +type PolicyEditableFieldForm = { + blockTag: FormControl; + property: FormControl; + visible: FormControl; + appliesTo: FormControl; + defaultLabel: FormControl; + required: FormControl; + blocks: FormControl; + properties: FormControl; + roles: FormControl; + targets: FormControl; + label: FormControl; + shortDescription: FormControl; +}; + +type PolicyForm = { + fields: FormArray>; +}; + +@Component({ + selector: 'app-editible-fields-dialog', + templateUrl: './editible-fields-dialog.component.html', + styleUrls: ['./editible-fields-dialog.component.scss'], +}) +export class EditibleFieldsDialog implements OnInit { + form: FormGroup; + policyTemplate: PolicyTemplate; + customProperties!: any[]; + blockInfo: any; + selectedBlock: any; + private _destroy$ = new Subject(); + + blockItems: PolicyItem[] = []; + propertyItems: SelectItem[] = []; + + loading = true; + + policyEditibleFields: PolicyEditableField[] = []; + + constructor( + public ref: DynamicDialogRef, + public config: DynamicDialogConfig, + private fb: FormBuilder, + private registeredService: RegisteredService, + private policyEngineService: PolicyEngineService, + ) { + this.blockItems = this.config.data.blockItems; + this.propertyItems = this.config.data.propertyItems; + + this.policyTemplate = this.config.data.policy; + + this.form = this.fb.group({ + fields: this.fb.array(this.policyEditibleFields.map(m => this.createFieldGroup(m))), + }); + } + + ngOnInit() { + this.loading = false; + this.policyEngineService.getBlockInformation() + .pipe(takeUntil(this._destroy$)) + .subscribe(blockInfo => { + this.blockInfo = blockInfo; + this.registeredService.registerConfig(blockInfo); + }); + } + + get blockOptions(): SelectItem[] { + return this.policyTemplate.allBlocks.map(block => ({ + label: block.tag, + value: block.id + })); + } + + get fieldGroups(): FormGroup[] { + return this.form.controls.fields.controls as FormGroup[]; + } + + onBlockChange(selected: any, index: number): void { + const fg = this.fields.at(index) as FormGroup; + + fg.controls.blockTag.setValue(selected?.tag ?? selected); + + let customProperties: any[] = []; + let selectedBlock: PolicyBlock = null as any; + this.policyTemplate.allBlocks.forEach(block => { + if (block.id === selected.id) { + selectedBlock = block; + const props = this.registeredService.getCustomProperties(block.blockType); + if(props && props.length > 0) { + customProperties = [...props]; + } + } + }); + + fg.controls.properties.setValue(customProperties); + fg.controls.property.setValue(''); + } + + createFieldGroup(m?: Partial): FormGroup { + return this.fb.group({ + blockTag: this.fb.control(m?.blockTag ?? '', { nonNullable: true, validators: [Validators.required] }), + property: this.fb.control(m?.property ?? '', { nonNullable: true, validators: [Validators.required] }), + visible: this.fb.control(m?.visible ?? [], { nonNullable: true, validators: [Validators.required] }), + appliesTo: this.fb.control(m?.appliesTo ?? [], { nonNullable: true, validators: [Validators.required] }), + label: this.fb.control(m?.label ?? '', { nonNullable: true, validators: [Validators.required] }), + defaultLabel: this.fb.control(m?.defaultLabel ?? null), + required: this.fb.control(m?.required ?? false, { nonNullable: true }), + blocks: this.fb.control(m?.blocks ?? [], { nonNullable: true }), + properties: this.fb.control(m?.properties ?? [], { nonNullable: true }), + roles: this.fb.control(m?.roles ?? [], { nonNullable: true }), + targets: this.fb.control(m?.targets ?? [], { nonNullable: true }), + shortDescription: this.fb.control(m?.shortDescription ?? '', { nonNullable: true }), + }); + } + + addField(): void { + const g = this.createFieldGroup({ + blocks: this.policyTemplate.allBlocks, + roles: this.policyTemplate.policyRoles, + }); + + this.fields.push(g); + } + + removeField(index: number): void { + this.fields.removeAt(index); + } + + get fieldsArray(): FormArray { + return this.form.get('fields') as FormArray; + } + + get fields(): FormArray { + return this.form.get('fields') as FormArray; + } + + + onClose(): void { + this._destroy$.next(); + } + + buildPayload(): { fields: PolicyEditableField[] } { + const fields = (this.form.getRawValue().fields ?? []) as PolicyEditableField[]; + return { fields }; + } + + async submit(): Promise { + //console.log('submit', this.form.getRawValue()); + // if (this.form.invalid) { + // this.form.markAllAsTouched(); + // return; + // } + + const payload = this.buildPayload(); + console.log('before submit payload'); + const res = JSON.stringify(payload.fields.map(f => ({ + blockTag: f.blockTag, + property: f.property, + visible: f.visible ?? [], + appliesTo: f.appliesTo ?? [], + label: f.label, + defaultLabel: f.defaultLabel, + required: !!f.required, + shortDescription: f.shortDescription, + }))); + + const root = this.policyTemplate.getJSON(); + root.editableParametersSettings = res; + if (root) { + this.loading = true; + this.policyEngineService.update(this.policyTemplate.id, root).pipe(takeUntil(this._destroy$)).subscribe((policy: any) => { + if (policy) { + console.log('updated policy', policy); + this.ref.close(res); + } + }); + } + } + +} diff --git a/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.html b/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.html index 3027b1ea6a..8fade0cc0d 100644 --- a/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.html +++ b/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.html @@ -332,6 +332,11 @@
+ +
+ + Editible Fields +
{ + console.log(options); + }); + } + public onSchemas() { switch (this.rootType) { case 'Policy': { diff --git a/frontend/src/app/modules/policy-engine/policy-engine.module.ts b/frontend/src/app/modules/policy-engine/policy-engine.module.ts index 2f8a9752ea..0cf9e29667 100644 --- a/frontend/src/app/modules/policy-engine/policy-engine.module.ts +++ b/frontend/src/app/modules/policy-engine/policy-engine.module.ts @@ -177,6 +177,7 @@ import { FieldLinkDialog } from './dialogs/field-link-dialog/field-link-dialog.c import { ChangeBlockSettingsDialog } from './dialogs/change-block-settings-dialog/change-block-settings-dialog.component'; import { ApproveUpdateVcDocumentDialogComponent } from './dialogs/approve-update-vc-document-dialog/approve-update-vc-document-dialog.component' import { AddDocumentDialog } from './dialogs/add-document-dialog/add-document-dialog.component'; +import { EditibleFieldsDialog } from './dialogs/editible-fields-dialog/editible-fields-dialog.component'; @NgModule({ declarations: [ @@ -310,7 +311,8 @@ import { AddDocumentDialog } from './dialogs/add-document-dialog/add-document-di FieldLinkDialog, AddDocumentDialog, ChangeBlockSettingsDialog, - ApproveUpdateVcDocumentDialogComponent + ApproveUpdateVcDocumentDialogComponent, + EditibleFieldsDialog, ], imports: [ CommonModule, diff --git a/frontend/src/app/modules/policy-engine/structures/policy-models/policy/policy.model.ts b/frontend/src/app/modules/policy-engine/structures/policy-models/policy/policy.model.ts index df89368ac6..a14b502207 100644 --- a/frontend/src/app/modules/policy-engine/structures/policy-models/policy/policy.model.ts +++ b/frontend/src/app/modules/policy-engine/structures/policy-models/policy/policy.model.ts @@ -37,6 +37,7 @@ export class PolicyTemplate { public readonly version!: string; public readonly previousVersion!: string; public readonly tests!: any; + public readonly editableParametersSettings: string; private _policyTag!: string; private _name!: string; @@ -99,6 +100,7 @@ export class PolicyTemplate { this.version = policy.version; this.previousVersion = policy.previousVersion; this.tests = policy.tests; + this.editableParametersSettings = policy.editableParametersSettings; this.buildPolicy(policy); this.buildBlock(policy.config); @@ -648,6 +650,7 @@ export class PolicyTemplate { policyTokens: Array(), policyGroups: Array(), config: null, + editableParametersSettings: this.editableParametersSettings }; for (const role of this.policyRoles) { json.policyRoles.push(role.getJSON()); diff --git a/interfaces/src/helpers/index.ts b/interfaces/src/helpers/index.ts index 864db031b6..4abc364b60 100644 --- a/interfaces/src/helpers/index.ts +++ b/interfaces/src/helpers/index.ts @@ -9,4 +9,5 @@ export * from './generate-document.js'; export * from './sentinel-hub/index.js'; export * from './permissions-helper.js'; export * from './policy-helper.js'; -export * from './schema-json.js'; \ No newline at end of file +export * from './schema-json.js'; +export * from './policy-editable-field.js'; diff --git a/interfaces/src/helpers/policy-editable-field.ts b/interfaces/src/helpers/policy-editable-field.ts new file mode 100644 index 0000000000..54a99cc34f --- /dev/null +++ b/interfaces/src/helpers/policy-editable-field.ts @@ -0,0 +1,30 @@ +export class PolicyEditableField { + public blockTag: string = ''; + public property: string = ''; + public visible: string[] = []; + public appliesTo: string[] = []; + public defaultLabel: any = null; + public required: boolean = false; + public blocks: any[] = []; + public properties: any[] = []; + public roles: any[] = []; + public targets: any[] = []; + public label: string = ''; + public shortDescription: string = ''; + + constructor(blocks: any[]) { + } + + toJson(): { blockTag: string; property: string; visible: string[]; appliesTo: string[]; label: string, defaultLabel: string; required: boolean; shortDescription: string } { + return { + blockTag: this.blockTag, + property: this.property, + visible: this.visible, + appliesTo: this.appliesTo, + label: this.label, + defaultLabel: this.defaultLabel, + required: this.required, + shortDescription: this.shortDescription, + } + } +} \ No newline at end of file From 524a15d60e2797218e992e2bd7520f8c46c2e9ae Mon Sep 17 00:00:00 2001 From: envision-ci-agent Date: Tue, 17 Feb 2026 14:33:21 +0000 Subject: [PATCH 02/24] [skip ci] Add swagger.yaml --- swagger.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/swagger.yaml b/swagger.yaml index 007871fe6c..be37be04ff 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -18682,6 +18682,8 @@ components: example: 1.0.0 originalChanged: type: string + editableParametersSettings: + type: string config: type: object additionalProperties: true From 0e8291f0461cb1360ae5861ddae44524271f765b Mon Sep 17 00:00:00 2001 From: Borys Date: Sat, 21 Feb 2026 23:05:06 -0500 Subject: [PATCH 03/24] fix: editable fields dialog Signed-off-by: Borys --- api-gateway/src/api/service/policy.ts | 3 +- .../validation/schemas/policies.dto.ts | 12 +- common/src/entity/policy.ts | 4 +- .../editible-fields-dialog.component.html | 29 ++- .../editible-fields-dialog.component.ts | 165 +++++++++--------- .../policy-configuration.component.ts | 6 +- .../policy-models/policy/policy.model.ts | 13 +- .../src/helpers/policy-editable-field.ts | 45 +++-- 8 files changed, 153 insertions(+), 124 deletions(-) diff --git a/api-gateway/src/api/service/policy.ts b/api-gateway/src/api/service/policy.ts index b44ecb6fa9..27b28ae0d1 100644 --- a/api-gateway/src/api/service/policy.ts +++ b/api-gateway/src/api/service/policy.ts @@ -712,7 +712,8 @@ export class PolicyApi { model.policyGroups = policy.policyGroups; model.categories = policy.categories; model.projectSchema = policy.projectSchema; - + model.editableParametersSettings = policy.editableParametersSettings; + const invalidedCacheTags = [`${PREFIXES.POLICIES}${policyId}/navigation`, `${PREFIXES.POLICIES}${policyId}/groups`, `${PREFIXES.SCHEMES}schema-with-sub-schemas`]; await this.cacheService.invalidate(getCacheKey([req.url, ...invalidedCacheTags], user)); diff --git a/api-gateway/src/middlewares/validation/schemas/policies.dto.ts b/api-gateway/src/middlewares/validation/schemas/policies.dto.ts index 4936708fc6..c922c24937 100644 --- a/api-gateway/src/middlewares/validation/schemas/policies.dto.ts +++ b/api-gateway/src/middlewares/validation/schemas/policies.dto.ts @@ -1,6 +1,6 @@ import { ApiExtraModels, ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import {ArrayNotEmpty, IsArray, IsBoolean, IsIn, IsNumber, IsObject, IsOptional, IsString, ValidateNested} from 'class-validator'; -import { PolicyAvailability, PolicyStatus, PolicyTestStatus } from '@guardian/interfaces'; +import { PolicyAvailability, PolicyEditableFieldDto, PolicyStatus, PolicyTestStatus } from '@guardian/interfaces'; import { Examples } from '../examples.js'; import { ValidationErrorsDTO } from './blocks.js'; import {Type} from 'class-transformer'; @@ -247,13 +247,13 @@ export class PolicyDTO { @IsBoolean() originalChanged?: boolean; - @ApiProperty({ - type: 'string', - required: false + @ApiProperty({ + type: () => PolicyEditableFieldDto, + isArray: true }) - @IsOptional() - editableParametersSettings?: string; + @IsArray() + editableParametersSettings?: PolicyEditableFieldDto[]; @ApiProperty({ type: 'object', diff --git a/common/src/entity/policy.ts b/common/src/entity/policy.ts index 1ef6cf6c93..47e7492650 100644 --- a/common/src/entity/policy.ts +++ b/common/src/entity/policy.ts @@ -1,5 +1,5 @@ import { BaseEntity } from '../models/index.js'; -import { GenerateUUIDv4, LocationType, PolicyAvailability, PolicyCategoryExport, PolicyStatus } from '@guardian/interfaces'; +import { GenerateUUIDv4, LocationType, PolicyAvailability, PolicyCategoryExport, PolicyEditableFieldDto, PolicyStatus } from '@guardian/interfaces'; import { AfterCreate, AfterDelete, AfterUpdate, BeforeCreate, BeforeUpdate, Entity, OnLoad, Property, Unique } from '@mikro-orm/core'; import { DataBaseHelper } from '../helpers/index.js'; import { ObjectId } from '@mikro-orm/mongodb'; @@ -298,7 +298,7 @@ export class Policy extends BaseEntity { originalMessageId?: string; @Property({ nullable: true }) - editableParametersSettings?: string; + editableParametersSettings?: any[]; /** * File id of the original policy zip (publish flow). diff --git a/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html b/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html index db1e5608c0..cecdde60e7 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html +++ b/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html @@ -2,62 +2,59 @@
-
+
+ [showClear]="false" + aria-required="true" + >
+ optionValue="_name" + filterBy="_name" + >
- + ; property: FormControl; visible: FormControl; - appliesTo: FormControl; + applyTo: FormControl; defaultLabel: FormControl; required: FormControl; label: FormControl; @@ -33,7 +33,7 @@ export class EditibleFieldsDialog implements OnInit { form: FormGroup; policyTemplate: PolicyTemplate; policyEditibleFields: PolicyEditableField[] = []; - additionalOptionsAppliesTo = [ + additionalOptionsApplyTo = [ { _name: 'All' }, { _name: 'Self' } ]; @@ -58,7 +58,7 @@ export class EditibleFieldsDialog implements OnInit { this.loading = false; if(this.policyTemplate.editableParametersSettings) { - this.policyEditibleFields = this.policyTemplate.editableParametersSettings?.map(ep => PolicyEditableFieldDto.fromDTO(ep)); + this.policyEditibleFields = this.policyTemplate.editableParametersSettings?.map(ep => PolicyEditableFieldDTO.fromDTO(ep)); } this.policyEngineService.getBlockInformation() @@ -68,14 +68,14 @@ export class EditibleFieldsDialog implements OnInit { this.loadData(); }); } - + loadData() { const fields = this.policyTemplate.editableParametersSettings; if(!fields?.length) { return; } - fields.forEach((field: PolicyEditableFieldDto) => { + fields.forEach((field: PolicyEditableFieldDTO) => { const block = this.policyTemplate.allBlocks.find(b => b.tag === field.blockTag); if(!block) { return; @@ -93,8 +93,8 @@ export class EditibleFieldsDialog implements OnInit { return this.form.get('fields') as FormArray; } - get appliesToOptions(): any[] { - return [...this.additionalOptionsAppliesTo, ...this.policyTemplate.policyRoles]; + get applyToOptions(): any[] { + return [...this.additionalOptionsApplyTo, ...this.policyTemplate.policyRoles]; } get fieldGroups(): FormGroup[] { @@ -105,6 +105,21 @@ export class EditibleFieldsDialog implements OnInit { return this.policyEditibleFields[index]?.properties ?? []; } + private setPath(properties:any[], result:any[], parent?:string) { + if(!properties) return; + + for(const prop of properties) { + prop.path = parent ? parent + '.' + prop.name : prop.name; + if(prop.properties) { + this.setPath(prop.properties, result, prop.path); + } + else { + result.push(prop); + } + } + return result; + } + onBlockChange(selected: any, index: number): void { const fg = this.fields.at(index) as FormGroup; fg.controls.blockTag.setValue(selected?.tag ?? selected); @@ -112,8 +127,9 @@ export class EditibleFieldsDialog implements OnInit { this.policyTemplate.allBlocks.forEach(block => { if (block.tag === selected) { const props = this.registeredService.getCustomProperties(block.blockType); - if(props && props.length > 0) { - this.policyEditibleFields[index].properties = props; + const propsWithPath = this.setPath(props, []); + if(propsWithPath && propsWithPath.length > 0) { + this.policyEditibleFields[index].properties = propsWithPath; } } }); @@ -122,9 +138,9 @@ export class EditibleFieldsDialog implements OnInit { createFieldGroup(m?: Partial): FormGroup { return this.fb.group({ blockTag: this.fb.control(m?.blockTag ?? '', { nonNullable: true, validators: [Validators.required] }), - property: this.fb.control(m?.property ?? '', { nonNullable: true, validators: [Validators.required] }), + property: this.fb.control(m?.propertyPath ?? '', { nonNullable: true, validators: [Validators.required] }), visible: this.fb.control(m?.visible ?? [], { nonNullable: true, validators: [Validators.required] }), - appliesTo: this.fb.control(m?.appliesTo ?? [], { nonNullable: true, validators: [Validators.required] }), + applyTo: this.fb.control(m?.applyTo ?? [], { nonNullable: true, validators: [Validators.required] }), label: this.fb.control(m?.label ?? '', { nonNullable: true, validators: [Validators.required] }), defaultLabel: this.fb.control(m?.defaultLabel ?? null), required: this.fb.control(m?.required ?? false, { nonNullable: true }), @@ -148,14 +164,19 @@ export class EditibleFieldsDialog implements OnInit { this.ref.close(); } - buildFields(): PolicyEditableFieldDto[] { + buildFields(): PolicyEditableFieldDTO[] { + const blocksByTag = new Map( + this.policyTemplate.allBlocks.map(b => [b.tag, b.blockType] as const) + ); + return this.form.getRawValue().fields ? this.form.getRawValue().fields.map(val => { - const field = new PolicyEditableFieldDto(); + const field = new PolicyEditableFieldDTO(); + field.blockType = blocksByTag.get(val.blockTag) ?? ''; field.blockTag = val.blockTag; - field.property = val.property; + field.propertyPath = val.property; field.visible = val.visible; - field.appliesTo = val.appliesTo; + field.applyTo = val.applyTo; field.label = val.label; field.defaultLabel = val.defaultLabel; field.required = val.required; diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html new file mode 100644 index 0000000000..15dbcb6e22 --- /dev/null +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html @@ -0,0 +1,45 @@ +
+
+
Policy Settings
+
+
+ +
+
+
+
+
+
+
+
+ + These settings will be used during policy execution. Please fill in all required fields where applicable. +
+
+
+
+
+ \ No newline at end of file diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.scss b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.scss new file mode 100644 index 0000000000..aab6107ebd --- /dev/null +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.scss @@ -0,0 +1,187 @@ +.context { + position: relative; + overflow-y: auto; + padding: 5px 3px 20px 3px; + display: flex; + flex-direction: column; + height: 100%; + + .filters { + display: flex; + flex-direction: column; + width: 100%; + + .filter-row { + height: 40px; + position: relative; + width: 100%; + display: flex; + flex-direction: row; + } + + .p-input-icon-right { + width: 100%; + } + + .search-policy-input { + width: 100%; + height: 40px; + border: 1px solid #e1e7ef; + border-radius: 8px; + padding-left: 16px; + position: relative; + + &:hover { + border-color: #2196F3; + } + + &:focus { + outline: 1px solid #2196F3; + } + } + + .guardian-button { + width: 150px; + min-width: 150px; + max-width: 150px; + margin-left: 12px; + padding: 6px 12px; + } + } + + .empty-grid { + margin-top: 16px; + display: flex; + flex-direction: column; + width: 100%; + overflow: auto; + height: 100%; + justify-content: center; + align-items: center; + color: #848FA9; + + .empty-grid-icon { + margin-bottom: 2px; + } + + .empty-grid-header { + font-weight: 500; + margin-bottom: 4px; + } + } + + .grid-container { + margin-top: 16px; + display: flex; + flex-direction: column; + width: 100%; + overflow: auto; + + .col-auto { + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .col-110 { + width: 100px; + min-width: 100px; + max-width: 100px; + + &.center { + justify-content: center; + display: flex; + } + } + + .grid-header { + display: flex; + flex-direction: row; + width: 100%; + height: 46px; + min-height: 46px; + max-height: 46px; + + &>div { + font-weight: 500; + padding: 12px 16px; + } + } + + .grid-body { + display: flex; + flex-direction: column; + width: 100%; + border: 1px solid #E1E7EF; + border-radius: 6px; + overflow: auto; + + .grid-row { + display: flex; + flex-direction: row; + width: 100%; + height: 50px; + min-height: 50px; + max-height: 50px; + border-bottom: 1px solid #E1E7EF; + cursor: pointer; + + &>div { + padding: 13px 16px; + } + + &:hover { + background: #f1f1f1; + } + } + } + } + + .checkbox-input { + width: 16px; + height: 16px; + cursor: pointer; + } + + .import-icon { + height: 24px; + display: flex; + align-items: center; + text-transform: capitalize; + + svg-icon { + margin-right: 8px; + } + } +} + +.dialog-body { + max-height: 75vh; + overflow-y: auto; +} + +.dropdown-type { + color: #848FA9; + padding: 0px 8px 0px 0px; +} + +.settings-warning { + background-color: #F7F7F7; + border: 1px solid #C5C2C2; + padding: 12px; + display: flex; + margin-bottom: 24px; + justify-content: center; + border-radius: 8px; + + span { + font-weight: 500; + font-size: 12px; + margin-left: 8px; + } +} + +.dialog-button button { + padding: 5px 24px; +} \ No newline at end of file diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.ts b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.ts new file mode 100644 index 0000000000..dda3c2073a --- /dev/null +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.ts @@ -0,0 +1,98 @@ +import { Component } from '@angular/core'; +import { UntypedFormControl } from '@angular/forms'; +import { PolicyEditableFieldDTO, UserPermissions } from '@guardian/interfaces'; +import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; +import { RegisteredService } from '../../services/registered.service'; +import { PolicyEngineService } from 'src/app/services/policy-engine.service'; +import { PolicyBlock } from '../../structures'; +import { Subject, takeUntil } from 'rxjs'; + +/** + * Policy parameters dialog. + */ +interface PolicyParameterItem { + block: PolicyBlock, + property: any, + config: PolicyEditableFieldDTO, +} + +@Component({ + selector: 'policy-parameters-dialog', + templateUrl: './policy-parameters-dialog.component.html', + styleUrls: ['./policy-parameters-dialog.component.scss'] +}) +export class PolicyParametersDialog { + public blockInfo: any; + public loading = false; + public policy: any; + public policyId: string; + public editableParameters: PolicyEditableFieldDTO[] = []; + + public user: UserPermissions = new UserPermissions(); + + public searchFilter = new UntypedFormControl(''); + public readonly: boolean = false; + private _destroy$ = new Subject(); + + public items: PolicyParameterItem[] = []; + + constructor( + public ref: DynamicDialogRef, + public config: DynamicDialogConfig, + private registeredService: RegisteredService, + private policyEngineService: PolicyEngineService + ) { + this.policy = this.config.data?.policy || {}; + this.policyId = this.policy.id; + } + + ngOnInit() { + this.policyEngineService.getBlockInformation() + .pipe(takeUntil(this._destroy$)) + .subscribe(blockInfo => { + this.registeredService.registerConfig(blockInfo); + this.blockInfo = blockInfo; + this.loadConfig(); + }); + + } + + loadConfig() { + this.policyEngineService.getParametersConfig(this.policy.id).subscribe((response: any) => { + this.editableParameters = response || []; + this.loadItems(); + }); + } + + loadItems() { + for(let i=0; i< this.editableParameters.length; i++) { + const field = this.editableParameters[i]; + const block = structuredClone(this.blockInfo[field.blockType]); + + const property = block.properties?.find((p: any) => p.name === field.propertyPath); + this.items.push({ + block, + property, + config: field + }); + } + } + + async onSubmit() { + this.policyEngineService.saveParameters( + this.policyId, + this.editableParameters + ).subscribe( + (response) => { + this.onClose(); + } + ); + } + + onSave() { + } + + public onClose(): void { + this.ref.close(null); + } +} \ No newline at end of file diff --git a/frontend/src/app/modules/policy-engine/policies/policies.component.ts b/frontend/src/app/modules/policy-engine/policies/policies.component.ts index 43ec6dc3d9..5b210d7a08 100644 --- a/frontend/src/app/modules/policy-engine/policies/policies.component.ts +++ b/frontend/src/app/modules/policy-engine/policies/policies.component.ts @@ -55,6 +55,7 @@ import { IndexedDbRegistryService } from 'src/app/services/indexed-db-registry.s import { DB_NAME, STORES_NAME } from 'src/app/constants'; import { ToastrService } from 'ngx-toastr'; import { UserPolicyDialog } from '../dialogs/user-policy-dialog/user-policy-dialog.component'; +import { PolicyParametersDialog } from '../dialogs/policy-parameters-dialog/policy-parameters-dialog.component'; class MenuButton { public readonly visible: boolean; @@ -619,7 +620,23 @@ export class PoliciesComponent implements OnInit { click: () => this.userPolicyManage(policy) }) ] - }, { + }, + { + tooltip: 'Parameters', + group: false, + visible: true, + color: 'primary-color', + buttons: [ + new MenuButton({ + visible: PolicyHelper.isPublishMode(policy) && this.user.POLICIES_POLICY_MANAGE, + disabled: false, + tooltip: 'Policy parameters', + icon: 'group', + color: 'primary-color', + click: () => this.policyParameters(policy) + }) + ] + },{ tooltip: 'Delete', group: false, visible: true, @@ -1877,6 +1894,19 @@ export class PoliciesComponent implements OnInit { dialogRef.onClose.pipe(takeUntil(this._destroy$)).subscribe(async (options) => { }); } + public policyParameters(policy?: any) { + this.policySubMenu?.hide(); + const dialogRef = this.dialogService.open(PolicyParametersDialog, { + showHeader: false, + width: '90%', + styleClass: 'guardian-dialog', + data: { + policy + }, + }); + dialogRef.onClose.pipe(takeUntil(this._destroy$)).subscribe(async (options) => { }); + } + public onSelectAllItems(event: any) { if (event.checked) { this.selectedItems = [...this.selectedItems, ...this.policiesList.filter((item: any) => (item.status === PolicyStatus.DRAFT || diff --git a/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.html b/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.html index e75ce435a5..39025b49eb 100644 --- a/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.html +++ b/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.html @@ -333,9 +333,9 @@
-
- - Editible Fields +
+ + Parameters
diff --git a/frontend/src/app/modules/policy-engine/policy-engine.module.ts b/frontend/src/app/modules/policy-engine/policy-engine.module.ts index 0cf9e29667..d5a04d5483 100644 --- a/frontend/src/app/modules/policy-engine/policy-engine.module.ts +++ b/frontend/src/app/modules/policy-engine/policy-engine.module.ts @@ -178,6 +178,8 @@ import { ChangeBlockSettingsDialog } from './dialogs/change-block-settings-dialo import { ApproveUpdateVcDocumentDialogComponent } from './dialogs/approve-update-vc-document-dialog/approve-update-vc-document-dialog.component' import { AddDocumentDialog } from './dialogs/add-document-dialog/add-document-dialog.component'; import { EditibleFieldsDialog } from './dialogs/editible-fields-dialog/editible-fields-dialog.component'; +import { PolicyParametersDialog } from './dialogs/policy-parameters-dialog/policy-parameters-dialog.component'; +import { PolicyParameterPropertyComponent } from 'src/app/components/policy-parameter-property/policy-parameter-property.component'; @NgModule({ declarations: [ @@ -313,6 +315,8 @@ import { EditibleFieldsDialog } from './dialogs/editible-fields-dialog/editible- ChangeBlockSettingsDialog, ApproveUpdateVcDocumentDialogComponent, EditibleFieldsDialog, + PolicyParametersDialog, + PolicyParameterPropertyComponent ], imports: [ CommonModule, diff --git a/frontend/src/app/modules/policy-engine/structures/policy-models/policy/policy.model.ts b/frontend/src/app/modules/policy-engine/structures/policy-models/policy/policy.model.ts index 1c644c2e6c..122b6399e7 100644 --- a/frontend/src/app/modules/policy-engine/structures/policy-models/policy/policy.model.ts +++ b/frontend/src/app/modules/policy-engine/structures/policy-models/policy/policy.model.ts @@ -1,4 +1,4 @@ -import { BlockType, GenerateUUIDv4, GroupRelationshipType, PolicyEditableFieldDto, PolicyStatus, Schema, Token, } from '@guardian/interfaces'; +import { BlockType, GenerateUUIDv4, GroupRelationshipType, PolicyEditableFieldDTO, PolicyStatus, Schema, Token, } from '@guardian/interfaces'; import { PolicyRole } from './policy-role.model'; import { PolicyGroup } from './policy-group.model'; import { PolicyToken } from './policy-token.model'; @@ -38,7 +38,7 @@ export class PolicyTemplate { public readonly previousVersion!: string; public readonly tests!: any; - private _editableParametersSettings?: PolicyEditableFieldDto[]; + private _editableParametersSettings?: PolicyEditableFieldDTO[]; private _policyTag!: string; private _name!: string; private _description!: string; @@ -122,11 +122,11 @@ export class PolicyTemplate { this.isTest = this.isDraft || this.isDryRun; } - public get editableParametersSettings(): PolicyEditableFieldDto[] | undefined { + public get editableParametersSettings(): PolicyEditableFieldDTO[] | undefined { return this._editableParametersSettings; } - public set editableParametersSettings(value: PolicyEditableFieldDto[] | undefined) { + public set editableParametersSettings(value: PolicyEditableFieldDTO[] | undefined) { this._editableParametersSettings = value; } diff --git a/frontend/src/app/services/policy-engine.service.ts b/frontend/src/app/services/policy-engine.service.ts index 13a2e79fc5..9ecebe593e 100644 --- a/frontend/src/app/services/policy-engine.service.ts +++ b/frontend/src/app/services/policy-engine.service.ts @@ -622,4 +622,12 @@ export class PolicyEngineService { public getAllVersionVcDocuments(policyId?: string, documentId?: string): Observable { return this.http.get(`${this.url}/${policyId}/get-all-version-vc-documents/${documentId}`); } + + public saveParameters(policyId: string, data: any): Observable { + return this.http.post(`${this.url}/${policyId}/parameters/`, data); + } + + public getParametersConfig(policyId: string): Observable { + return this.http.get(`${this.url}/${policyId}/parameters/config`); + } } diff --git a/guardian-service/src/policy-engine/policy-engine.service.ts b/guardian-service/src/policy-engine/policy-engine.service.ts index 105bcfa100..d540357a65 100644 --- a/guardian-service/src/policy-engine/policy-engine.service.ts +++ b/guardian-service/src/policy-engine/policy-engine.service.ts @@ -27,6 +27,7 @@ import { PolicyDiscussion, PolicyImportExport, PolicyMessage, + PolicyParameters, RecordImportExport, RunFunctionAsync, Schema as SchemaCollection, @@ -55,7 +56,8 @@ import { PolicyActionType, PolicyActionStatus, IgnoreRule, - SchemaStatus + SchemaStatus, + PolicyEditableFieldDTO } from '@guardian/interfaces'; import { AccountId, PrivateKey } from '@hiero-ledger/sdk'; import { NatsConnection } from 'nats'; @@ -4536,6 +4538,51 @@ export class PolicyEngineService { return new MessageError(error); } }) + + this.channel.getMessages(PolicyEngineEvents.SAVE_POLICY_PARAMETERS_VALUES, + async (msg: { owner: IOwner, userDID: string, policyId: string, config: PolicyEditableFieldDTO[] }) => { + try { + let result; + const { userDID, policyId, config } = msg; + + const found = await DatabaseServer.getPolicyParameters(userDID, policyId); + + if(found) { + found.config = config; + result = await DatabaseServer.updatePolicyParameters(found); + } else { + const parameters = new PolicyParameters(); + parameters.userDID = userDID; + parameters.policyId = policyId; + parameters.config = config; + parameters.properties = {}; + parameters.updated = false; + + result = await DatabaseServer.createPolicyParameters(parameters); + } + + //flag update + + return new MessageResponse(result); + } catch (error) { + await logger.error(error, ['GUARDIAN_SERVICE'], msg?.owner.id); + return new MessageError(error); + } + }) + + this.channel.getMessages(PolicyEngineEvents.GET_POLICY_PARAMETERS_VALUES, + async (msg: { owner: IOwner, userDID: string, policyId: string }) => { + try { + const { userDID, policyId } = msg; + + const result = await DatabaseServer.getPolicyParameters(userDID, policyId); + + return new MessageResponse(result); + } catch (error) { + await logger.error(error, ['GUARDIAN_SERVICE'], msg?.owner.id); + return new MessageError(error); + } + }) //#endregion } } diff --git a/guardian-service/src/policy-engine/policy-engine.ts b/guardian-service/src/policy-engine/policy-engine.ts index 53296b0317..fff2b34aa8 100644 --- a/guardian-service/src/policy-engine/policy-engine.ts +++ b/guardian-service/src/policy-engine/policy-engine.ts @@ -1359,6 +1359,8 @@ export class PolicyEngine extends NatsService { if (model.originalHash) { const policyComponents = await PolicyImportExport.loadPolicyComponents(model); currentHash = PolicyImportExport.getPolicyHash(policyComponents); + console.log('original hash:', model.originalHash); + console.log('current hash:', currentHash); } const message = new PolicyMessage(MessageType.InstancePolicy, MessageAction.PublishPolicy); diff --git a/interfaces/src/helpers/policy-editable-field.ts b/interfaces/src/helpers/policy-editable-field.ts index 72207225b3..a624db5cc6 100644 --- a/interfaces/src/helpers/policy-editable-field.ts +++ b/interfaces/src/helpers/policy-editable-field.ts @@ -1,26 +1,30 @@ -export class PolicyEditableFieldDto { +export class PolicyEditableFieldDTO { constructor() { } + public blockType: string; public blockTag: string; - public property: string; + public propertyPath: string; public visible: string[]; - public appliesTo: string[]; + public applyTo: string[]; public label: string; public defaultLabel: any; public required: boolean; public shortDescription: string; - public static fromDTO(dto: PolicyEditableFieldDto): PolicyEditableField { + public value?: any; + + public static fromDTO(dto: PolicyEditableFieldDTO): PolicyEditableField { return Object.assign(new PolicyEditableField(), dto); } } export class PolicyEditableField { + public blockType: string = ''; public blockTag: string = ''; - public property: string = ''; + public propertyPath: string = ''; public visible: string[] = []; - public appliesTo: string[] = []; + public applyTo: string[] = []; public defaultLabel: any = null; public required: boolean = false; public blocks: any[] = []; @@ -33,12 +37,13 @@ export class PolicyEditableField { constructor() { } - toDTO(): PolicyEditableFieldDto { - const dto = new PolicyEditableFieldDto(); + toDTO(): PolicyEditableFieldDTO { + const dto = new PolicyEditableFieldDTO(); + dto.blockType = this.blockType; dto.blockTag = this.blockTag; - dto.property = this.property; + dto.propertyPath = this.propertyPath; dto.visible = this.visible; - dto.appliesTo = this.appliesTo; + dto.applyTo = this.applyTo; dto.label = this.label; dto.defaultLabel = this.defaultLabel; dto.required = this.required; diff --git a/interfaces/src/type/messages/policy-engine-events.ts b/interfaces/src/type/messages/policy-engine-events.ts index 8e67b7425e..ac7a25ffea 100644 --- a/interfaces/src/type/messages/policy-engine-events.ts +++ b/interfaces/src/type/messages/policy-engine-events.ts @@ -109,5 +109,9 @@ export enum PolicyEngineEvents { GET_POLICY_REPOSITORY_DOCUMENTS = 'policy-engine-policy-repository-documents', GET_POLICY_REPOSITORY_SCHEMAS = 'policy-engine-policy-repository-schemas', CREATE_NEW_VERSION_VC_DOCUMENT = 'policy-engine-create-new-version-vc-document', - GET_All_NEW_VERSION_VC_DOCUMENTS = 'policy-engine-get-all-new-version-vc-documents' + GET_All_NEW_VERSION_VC_DOCUMENTS = 'policy-engine-get-all-new-version-vc-documents', + + SAVE_POLICY_PARAMETERS_VALUES = 'policy-engine-save-policy-parameters-values', + GET_POLICY_PARAMETERS_VALUES = 'policy-engine-get-policy-parameters-values' + } diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index ed68315240..e3b201e346 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -6,7 +6,7 @@ import { AnyBlockType, IPolicyBlock, IPolicyDocument, ISerializedBlock, } from ' import { PolicyComponentsUtils } from '../../policy-components-utils.js'; import { IPolicyEvent, PolicyLink } from '../../interfaces/policy-event.js'; import { PolicyInputEventType, PolicyOutputEventType } from '../../interfaces/policy-event-type.js'; -import { DatabaseServer, Policy } from '@guardian/common'; +import { DatabaseServer, Policy, PolicyParameters } from '@guardian/common'; import deepEqual from 'deep-equal'; import { PolicyUser } from '../../policy-user.js'; import { ComponentsService } from '../components-service.js'; @@ -930,6 +930,61 @@ export function BasicBlock(options: Partial) { this.policyId, this.uuid, did, name, value, true ); } + + + setPropValue(properties:any, path:string, value:any) { + const keys = path.split('.'); + const last = keys.pop(); + for (const key of keys) { + if(!(properties[key] && typeof properties[key] === 'object')) { + properties[key] = {}; + } + } + properties[last] = value; + } + + public async getOption(user:any) { + const row = await DatabaseServer.getPolicyParameters(this.policyId , user.did ); + + let properties; + if(!row || row.updated || !row.properties) { + properties = {}; + const policyRows = await this.databaseServer.find(PolicyParameters, { policyId: this.policyId }); + + for (const item of policyRows) { + for (const config of item.config) { + if( + config.applyTo.includes('All') || + config.applyTo.includes(user.role) || + (config.applyTo.includes('Self') && item.userDID === user.did) + ) { + if(!properties[config.blockTag]) { + properties[config.blockTag] = {}; + } + this.setPropValue(properties[config.blockTag], config.propertyPath, config.value); + } + } + } + if(row) { + row.properties = properties; + this.databaseServer.update(PolicyParameters, { + policyId: row.policyId, + userDID: row.userDID + }, row); + } else { + this.databaseServer.save(PolicyParameters, { + policyId: this.policyId, + userDID: user.did, + config: null, + properties + }) + } + } else { + properties = row.properties; + } + + return Object.assign({}, this.options, properties[this.tag]); + } }; }; } diff --git a/policy-service/src/policy-engine/policy-engine.interface.ts b/policy-service/src/policy-engine/policy-engine.interface.ts index f4c4691f92..8e4e1fba81 100644 --- a/policy-service/src/policy-engine/policy-engine.interface.ts +++ b/policy-service/src/policy-engine/policy-engine.interface.ts @@ -475,6 +475,8 @@ export interface IPolicyBlock { value: T, user?: PolicyUser | string ): Promise; + + getOption(user: PolicyUser | null): any; } /** From 6067f0a399b89ece51d92641f0666a1027b75e26 Mon Sep 17 00:00:00 2001 From: envision-ci-agent Date: Wed, 25 Feb 2026 23:43:30 +0000 Subject: [PATCH 05/24] [skip ci] Add swagger.yaml --- swagger.yaml | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/swagger.yaml b/swagger.yaml index 0222180638..0157d841c3 100644 --- a/swagger.yaml +++ b/swagger.yaml @@ -8842,6 +8842,80 @@ paths: summary: Get all version VC documents. tags: - policies + /policies/{policyId}/parameters: + post: + description: Save policy config with values to the PolicyParameters tale + operationId: PolicyApi_savePolicyParametersValues + parameters: + - name: policyId + required: true + in: path + schema: + type: string + requestBody: + required: true + description: Policy parameters. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PolicyEditableFieldDTO' + responses: + '200': + description: Successful operation. + '401': + description: Unauthorized. + '403': + description: Forbidden. + '500': + description: Internal server error. + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerErrorDTO' + security: + - bearer: [] + summary: Save policy config with values + tags: + - policies + /policies/{policyId}/parameters/config: + get: + description: Get policy parameters. + operationId: PolicyApi_getPolicyParametersConfig + parameters: + - name: policyId + required: true + in: path + schema: + type: string + requestBody: + required: true + description: Policy parameters. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PolicyEditableFieldDTO' + responses: + '200': + description: Successful operation. + '401': + description: Unauthorized. + '403': + description: Forbidden. + '500': + description: Internal server error. + content: + application/json: + schema: + $ref: '#/components/schemas/InternalServerErrorDTO' + security: + - bearer: [] + summary: Get policy parameters. + tags: + - policies /schema/{schemaId}: get: description: >- @@ -18604,6 +18678,9 @@ components: - progress - resultId - result + PolicyEditableFieldDTO: + type: object + properties: {} IgnoreRuleDTO: type: object properties: @@ -18683,7 +18760,9 @@ components: originalChanged: type: string editableParametersSettings: - type: string + type: array + items: + $ref: '#/components/schemas/PolicyEditableFieldDTO' config: type: object additionalProperties: true @@ -18805,6 +18884,7 @@ components: - codeVersion - createDate - version + - editableParametersSettings - config - userRole - userRoles @@ -20794,6 +20874,28 @@ components: - id - name - type + PolicyParametersDTO: + type: object + properties: + userId: + type: string + example: '000000000000000000000001' + policyId: + type: string + example: 00000000-0000-0000-0000-000000000000 + config: + type: array + items: + $ref: '#/components/schemas/PolicyEditableFieldDTO' + updated: + type: boolean + example: true + propValue: + type: string + example: Prop Value + required: + - userId + - policyId VersionSchemaDTO: type: object properties: From e2d3480e31edf16c60195e9438d1ffa6699b6432 Mon Sep 17 00:00:00 2001 From: Borys Date: Thu, 26 Feb 2026 22:30:10 -0500 Subject: [PATCH 06/24] Policy parameters: array fields Signed-off-by: Borys --- .../policy-parameter-property.component.html | 156 +++++++++------ .../policy-parameter-property.component.scss | 45 +++++ .../policy-parameter-property.component.ts | 180 ++++-------------- ...y-parameters-config-dialog.component.html} | 78 ++++---- ...y-parameters-config-dialog.component.scss} | 0 ...icy-parameters-config-dialog.component.ts} | 23 ++- .../policy-parameters-dialog.component.ts | 26 ++- .../policies/policies.component.ts | 8 +- .../policy-configuration.component.ts | 4 +- .../policy-engine/policy-engine.module.ts | 6 +- .../policy-viewer.component.html | 6 + .../policy-viewer.component.scss | 4 + .../policy-viewer/policy-viewer.component.ts | 14 ++ frontend/src/assets/images/icons/settings.svg | 5 + 14 files changed, 282 insertions(+), 273 deletions(-) rename frontend/src/app/modules/policy-engine/dialogs/{editible-fields-dialog/editible-fields-dialog.component.html => policy-parameters-config-dialog/policy-parameters-config-dialog.component.html} (61%) rename frontend/src/app/modules/policy-engine/dialogs/{editible-fields-dialog/editible-fields-dialog.component.scss => policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss} (100%) rename frontend/src/app/modules/policy-engine/dialogs/{editible-fields-dialog/editible-fields-dialog.component.ts => policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts} (91%) create mode 100644 frontend/src/assets/images/icons/settings.svg diff --git a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html index b07c0192ff..d17bc5b10f 100644 --- a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html +++ b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html @@ -1,87 +1,72 @@ - +
- - {{ config.shortDescription }} - - +
- - -
- - {{ config.shortDescription }} - - + (blur)="onSave()"/> +
- +
- - {{ config.shortDescription }} -
- - -
+
-
- +
- - {{ config.shortDescription }} - - - +
- +
- + {{ config.shortDescription }}
@@ -107,3 +92,48 @@
+ + +
+ + {{ config.shortDescription }} + +
+ +
+
+
+ +
+
+ +
+ +
+
+
+
+
\ No newline at end of file diff --git a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.scss b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.scss index 750f3eb379..373438030b 100644 --- a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.scss +++ b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.scss @@ -33,4 +33,49 @@ font-weight: 500; font-size: 12px; margin-bottom: 5px; +} + +.element-array { + display: flex; + flex-direction: column; + gap: 16px; + margin-top: 16px; + + .add-button { + height: 28px; + padding: 6px 16px; + } +} + +.element-array-group { + align-items: center; + display: flex; + gap: 16px; + + > :not(:last-child) { + flex: 1; + } + + .element-container { + padding: 0; + border: none; + padding-left: 0; + padding-right: 0; + margin-bottom: 0; + } + + .element-array-delete { + position: relative; + top: 10px; + } + + .property-label { + font-weight: 500; + font-size: 12px; + } +} + +.ghost-color { + fill: #AAB7C4; + color: #AAB7C4; } \ No newline at end of file diff --git a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.ts b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.ts index 3f7a2aa4c7..0c7791a25c 100644 --- a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.ts +++ b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.ts @@ -2,7 +2,6 @@ import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges, ViewEnca import { PolicyEditableFieldDTO } from '@guardian/interfaces'; import { DialogService } from 'primeng/dynamicdialog'; import { CodeEditorDialogComponent } from 'src/app/modules/policy-engine/dialogs/code-editor-dialog/code-editor-dialog.component'; -import { RegisteredService } from 'src/app/modules/policy-engine/services/registered.service'; import { PolicyBlock } from 'src/app/modules/policy-engine/structures'; /** @@ -23,16 +22,25 @@ export class PolicyParameterPropertyComponent implements OnInit { @Input('config') config: PolicyEditableFieldDTO; @Input('offset') offset!: number; @Output('update') update = new EventEmitter(); + @Input('isArrayElement') isArrayElement?: boolean; rootPath: string; pathValue: string; - + get value(): any { - return this.config.value; + if(this.isArrayElement) { + return (this.config as any)[this.property?.name]; + } else { + return this.config.value; + } } set value(v: any) { - this.config.value = v; + if(this.isArrayElement) { + (this.config as any)[this.property?.name] = v; + } else { + this.config.value = v; + } } pathOptions = [ @@ -47,30 +55,41 @@ export class PolicyParameterPropertyComponent implements OnInit { { label: 'Attributes', value: 'option.', title: 'option.' } ]; - groupCollapse: boolean = false; - itemCollapse: any = {}; needUpdate: boolean = true; allBlocks: any[] = []; childrenBlocks: any[] = []; loaded: boolean = false; - + constructor( - private registeredService: RegisteredService, private dialog: DialogService, ) { } - ngOnInit(): void { + addItems() { + this.needUpdate = true; + const item: any = {}; + for (const p of this.property?.items?.properties) { + item[p.name] = ''; + } + + this.value.push(item); + this.update.emit(); + } + + removeItems(i: number) { this.needUpdate = true; + this.value.splice(i, 1); + this.update.emit(); } - ngOnChanges(changes: SimpleChanges) { - if(this.currentBlock) { - this.load(this.currentBlock); - setTimeout(() => { - this.loaded = true; - }, 0); + ngOnInit(): void { + this.needUpdate = true; + + if (this.property?.type === 'Array') { + if (!Array.isArray(this.config.value)) { + this.config.value = []; + } } } @@ -79,78 +98,6 @@ export class PolicyParameterPropertyComponent implements OnInit { this.onSave(); } - load(block: PolicyBlock) { - const moduleVariables = block.moduleVariables; - if (this.property) { - if (this.property.type === 'Array') { - if (!Array.isArray(this.config.value)) { - this.config.value = []; - } - } else if (this.property.type === 'Path') { - if (this.value) { - for (const item of this.pathOptions) { - if (this.value.startsWith(item.value)) { - this.rootPath = item.value; - this.pathValue = this.value.substring(item.value.length); - } - } - } else { - this.rootPath = ''; - this.pathValue = ''; - } - } - else if ( - this.property.type === 'Select' || - this.property.type === 'MultipleSelect' - ) { - this.allBlocks = []; - if (moduleVariables?.module?.allBlocks) { - this.allBlocks = moduleVariables.module.allBlocks.map( - (item) => { - return { - name: item.localTag, - icon: this.registeredService.getIcon( - item.blockType - ), - value: item.tag, - parent: item?.parent?.id, - }; - } - ); - } - // this.childrenBlocks = this.allBlocks.filter( - // (item) => item.parent === this.data?.id - // ); - // this.schemas = moduleVariables?.schemas || []; - // this.roles = - // moduleVariables?.roles?.filter( - // (item: any) => - // !['OWNER', 'NO_ROLE', 'ANY_ROLE'].includes( - // item.value - // ) - // ) || []; - } - // else if (this.property.type === 'Schemas') { - // this.schemas = moduleVariables?.schemas || []; - // } - // if ( - // this.property.type !== 'Group' && - // this.property.type !== 'Array' - // ) { - // if ( - // (this.property.default !== undefined) && - // (!this.data.hasOwnProperty(this.property.name)) - // ) { - // this.data[this.property.name] = this.property.default; - // } - // } - } - } - - customPropCollapse(property: any) { - return this.collapse; - } - onSave() { this.needUpdate = true; this.update.emit(); @@ -177,63 +124,4 @@ export class PolicyParameterPropertyComponent implements OnInit { } }) } - - onHide() { - this.groupCollapse = !this.groupCollapse; - } - - onHideItem(i: any) { - this.itemCollapse[i] = !this.itemCollapse[i]; - } - - addItems() { - this.needUpdate = true; - const item: any = {}; - for (const p of this.property.items.properties) { - if (p.default) { - item[p.name] = p.default; - } - } - this.value.push(item); - this.update.emit(); - } - - removeItems(i: number) { - this.needUpdate = true; - this.value.splice(i, 1); - this.update.emit(); - } - - getArrayItemText(config: any, item: any): string { - if (this.needUpdate) { - let text = config.value; - if (text && text.indexOf('@') !== -1) { - for (const prop of config.properties) { - text = text.replaceAll( - '@' + prop.name, - item[prop.name] || '' - ); - } - } - config.__value = text; - } - return config.__value; - } - - visible(expression: string) { - return true; - // return ( - // !expression || - // new Function(...Object.keys(this.config), 'return ' + expression)( - // ...Object.values(this.config) - // ) - // ); - } - - getSelectedItemsDisplay(selectedItems: any[]): string { - if (!selectedItems || selectedItems.length === 0) { - return 'No blocks selected'; - } - return selectedItems.map(selected => selected.name).join(', '); - } } diff --git a/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html similarity index 61% rename from frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html rename to frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html index 6a3fdb1bc3..31d2f721a3 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/editible-fields-dialog/editible-fields-dialog.component.html +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html @@ -5,49 +5,53 @@
- - +
- - - +
- - - +
- - - +
{ }); } + public openParametersSettings() { + const dialogRef = this.dialogService.open(PolicyParametersDialog, { + showHeader: false, + width: '90%', + styleClass: 'guardian-dialog', + data: { + policyId: this.policyId + }, + }); + + dialogRef.onClose.subscribe(async (result) => { }); + } + public onPage(event: any): void { if (this.pageSize != event.pageSize) { this.pageIndex = 0; diff --git a/frontend/src/assets/images/icons/settings.svg b/frontend/src/assets/images/icons/settings.svg new file mode 100644 index 0000000000..f6e22409cf --- /dev/null +++ b/frontend/src/assets/images/icons/settings.svg @@ -0,0 +1,5 @@ + + + + + From 0f718766e3c5cb7341c2b998145d19ebccf6e01c Mon Sep 17 00:00:00 2001 From: Borys Date: Thu, 26 Feb 2026 22:39:54 -0500 Subject: [PATCH 07/24] basic block fixes Signed-off-by: Borys --- .../src/policy-engine/helpers/decorators/basic-block.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index e3b201e346..02b0d7587b 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -944,10 +944,9 @@ export function BasicBlock(options: Partial) { } public async getOption(user:any) { - const row = await DatabaseServer.getPolicyParameters(this.policyId , user.did ); - + const row = await DatabaseServer.getPolicyParameters(user.did, this.policyId); let properties; - if(!row || row.updated || !row.properties) { + if(!row || row.updated || !row.properties || Object.keys(row.properties).length === 0) { properties = {}; const policyRows = await this.databaseServer.find(PolicyParameters, { policyId: this.policyId }); @@ -969,13 +968,14 @@ export function BasicBlock(options: Partial) { row.properties = properties; this.databaseServer.update(PolicyParameters, { policyId: row.policyId, - userDID: row.userDID + userDID: row.userDID, }, row); } else { this.databaseServer.save(PolicyParameters, { policyId: this.policyId, userDID: user.did, config: null, + updated: false, properties }) } From da8caf17dfad673e83a07081ae57b9d7eb9d67be Mon Sep 17 00:00:00 2001 From: Borys Date: Fri, 27 Feb 2026 09:27:55 -0500 Subject: [PATCH 08/24] updated blocks with editable parameters Signed-off-by: Borys --- .../src/database-modules/database-server.ts | 11 +++ ...licy-parameters-config-dialog.component.ts | 2 +- .../policy-engine/policy-engine.service.ts | 4 +- .../src/policy-engine/blocks/action-block.ts | 46 ++++++----- .../policy-engine/blocks/aggregate-block.ts | 31 +++++--- .../blocks/button-block-addon.ts | 17 +++- .../src/policy-engine/blocks/button-block.ts | 7 +- .../policy-engine/blocks/calculate-block.ts | 45 +++++++---- .../blocks/calculate-math-addon.ts | 12 ++- .../blocks/calculate-math-variables.ts | 60 ++++++++------ .../policy-engine/blocks/container-block.ts | 4 +- .../blocks/create-token-block.ts | 26 ++++--- .../blocks/custom-logic-block.ts | 34 +++++--- .../blocks/document-validator-block.ts | 30 +++---- .../blocks/documents-source-addon.ts | 51 ++++++------ .../policy-engine/blocks/documents-source.ts | 10 ++- .../blocks/dropdown-block-addon.ts | 16 ++-- .../blocks/external-data-block.ts | 7 +- .../blocks/external-topic-block.ts | 6 +- .../blocks/extract-data-block.ts | 9 ++- .../blocks/filters-addon-block.ts | 78 ++++++++++--------- .../blocks/global-events-reader-block.ts | 25 ++++-- .../blocks/global-events-writer-block.ts | 19 ++++- .../src/policy-engine/blocks/group-manager.ts | 15 ++-- .../src/policy-engine/blocks/history-addon.ts | 6 +- .../blocks/http-request-block.ts | 10 ++- .../blocks/http-request-ui-addon.ts | 23 ++++-- .../src/policy-engine/blocks/impact-addon.ts | 22 ++++-- .../policy-engine/blocks/information-block.ts | 4 +- .../blocks/integration-button-block.ts | 24 +++--- .../src/policy-engine/blocks/math-block.ts | 39 ++++++---- .../src/policy-engine/blocks/mint-block.ts | 36 +++++---- .../src/policy-engine/blocks/module.ts | 8 +- .../policy-engine/blocks/multi-sign-block.ts | 28 ++++--- .../blocks/notification.block.ts | 55 ++++++++----- .../src/policy-engine/blocks/policy-roles.ts | 8 +- .../policy-engine/blocks/reassigning.block.ts | 9 ++- .../src/policy-engine/blocks/report-block.ts | 12 ++- .../policy-engine/blocks/report-item-block.ts | 26 ++++--- .../blocks/request-vc-document-block-addon.ts | 27 ++++--- .../blocks/request-vc-document-block.ts | 24 +++--- .../policy-engine/blocks/retirement-block.ts | 25 +++--- .../policy-engine/blocks/revocation-block.ts | 8 +- .../src/policy-engine/blocks/revoke-block.ts | 3 +- .../blocks/selective-attributes-addon.ts | 4 +- .../blocks/send-to-guardian-block.ts | 76 ++++++++++-------- .../blocks/set-relationships-block.ts | 26 ++++--- .../src/policy-engine/blocks/split-block.ts | 30 ++++--- .../src/policy-engine/blocks/step-block.ts | 18 +++-- .../src/policy-engine/blocks/switch-block.ts | 4 +- .../src/policy-engine/blocks/timer-block.ts | 16 ++-- .../blocks/token-action-block.ts | 18 +++-- .../blocks/token-confirmation-block.ts | 34 ++++---- .../blocks/transformation-button-block.ts | 47 ++++++----- .../blocks/transformation-ui-addon.ts | 6 +- .../blocks/upload-vc-document-block.ts | 5 +- .../helpers/decorators/basic-block.ts | 15 +++- .../policy-engine/interfaces/block-about.ts | 2 + .../policy-engine/policy-engine.interface.ts | 2 +- 59 files changed, 782 insertions(+), 483 deletions(-) diff --git a/common/src/database-modules/database-server.ts b/common/src/database-modules/database-server.ts index ddd58c29af..8b3cddc2c9 100644 --- a/common/src/database-modules/database-server.ts +++ b/common/src/database-modules/database-server.ts @@ -967,6 +967,17 @@ export class DatabaseServer extends AbstractDatabaseServer { return await new DataBaseHelper(PolicyParameters).save(item); } + /** + * Set flag updated true + * @param parameters + * @param policyId + */ + public static async setPolicyParametersUpdated( + parameters: PolicyParameters[], + ): Promise { + return await new DataBaseHelper(PolicyParameters).updateMany(parameters); + } + /** * Update Policy Parameters * @param label diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts index f0d2d87c46..9b553016e9 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts @@ -126,7 +126,7 @@ export class PolicyParametersConfigDialog implements OnInit { this.policyTemplate.allBlocks.forEach(block => { if (block.tag === selected) { const props = this.registeredService.getCustomProperties(block.blockType); - const propsWithPath = this.setPath(props, []); + const propsWithPath = this.setPath(props.filter((prop: any) => prop.editable), []); if(propsWithPath && propsWithPath.length > 0) { this.policyEditableFields[index].properties = propsWithPath; } diff --git a/guardian-service/src/policy-engine/policy-engine.service.ts b/guardian-service/src/policy-engine/policy-engine.service.ts index d540357a65..ea39ee2131 100644 --- a/guardian-service/src/policy-engine/policy-engine.service.ts +++ b/guardian-service/src/policy-engine/policy-engine.service.ts @@ -4561,7 +4561,9 @@ export class PolicyEngineService { result = await DatabaseServer.createPolicyParameters(parameters); } - //flag update + const allPolicyParameters = await DatabaseServer.getPolicyParametersByPolicyId(policyId); + allPolicyParameters.forEach(parameter => parameter.updated = true); + await DatabaseServer.setPolicyParametersUpdated(allPolicyParameters); return new MessageResponse(result); } catch (error) { diff --git a/policy-service/src/policy-engine/blocks/action-block.ts b/policy-service/src/policy-engine/blocks/action-block.ts index 7cecdeddc1..4675037766 100644 --- a/policy-service/src/policy-engine/blocks/action-block.ts +++ b/policy-service/src/policy-engine/blocks/action-block.ts @@ -46,6 +46,8 @@ export class InterfaceDocumentActionBlock { async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -54,29 +56,29 @@ export class InterfaceDocumentActionBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - type: ref.options.type, - uiMetaData: ref.options.uiMetaData, - user: ref.options.user + type: options.type, + uiMetaData: options.uiMetaData, + user: options.user } - if (ref.options.type === 'selector') { - data.field = ref.options.field; + if (options.type === 'selector') { + data.field = options.field; } - if (ref.options.type === 'dropdown') { + if (options.type === 'dropdown') { const documents: any[] = await ref.getSources(user, null); - data.name = ref.options.name; - data.value = ref.options.value; - data.field = ref.options.field; + data.name = options.name; + data.value = options.value; + data.field = options.field; data.options = documents.map((e) => { return { - name: findOptions(e, ref.options.name), - value: findOptions(e, ref.options.value), + name: findOptions(e, options.name), + value: findOptions(e, options.value), } }); } - if (ref.options.type === 'transformation') { + if (options.type === 'transformation') { const children = []; for (const child of (ref.children as any[])) { if (child.blockClassName === 'UIAddon') { @@ -103,11 +105,13 @@ export class InterfaceDocumentActionBlock { async setData(user: PolicyUser, document: IPolicyDocument, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const state: IPolicyEventState = { data: document }; let result: any = null; - if (ref.options.type === 'selector') { - const option = this.findOptions(document, ref.options.field, ref.options.uiMetaData.options); + if (options.type === 'selector') { + const option = this.findOptions(document, options.field, options.uiMetaData.options); if (option) { const newUser = option.user === UserType.CURRENT ? user @@ -117,23 +121,23 @@ export class InterfaceDocumentActionBlock { } } - if (ref.options.type === 'dropdown') { + if (options.type === 'dropdown') { const newUser = await PolicyUtils.getDocumentOwner(ref, document, user.userId); await ref.triggerEvents(PolicyOutputEventType.DropdownEvent, newUser, state, actionStatus); await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, newUser, state, actionStatus); } - if (ref.options.type === 'download') { + if (options.type === 'download') { const sensorDid = document.document.credentialSubject[0].id; const userDID = document.owner; - const schemaObject = await PolicyUtils.loadSchemaByID(ref, ref.options.schema); + const schemaObject = await PolicyUtils.loadSchemaByID(ref, options.schema); const schema = new Schema(schemaObject); const sensorKey = await PolicyUtils.getAccountKey(ref, userDID, KeyType.KEY, sensorDid, user.userId); const key = await PolicyActionsUtils.downloadPrivateDocument(ref, userDID, sensorDid, user.userId); result = { - fileName: ref.options.filename || `${sensorDid}.config.json`, + fileName: options.filename || `${sensorDid}.config.json`, body: { - 'url': ref.options.targetUrl || process.env.MRV_ADDRESS, + 'url': options.targetUrl || process.env.MRV_ADDRESS, 'topic': ref.policyInstance?.topicId, 'hederaAccountId': key.hederaAccountId, 'hederaAccountKey': key.hederaAccountKey, @@ -154,13 +158,13 @@ export class InterfaceDocumentActionBlock { } } - if (ref.options.type === 'transformation') { + if (options.type === 'transformation') { // actionStatus.saveResult(state); await ref.triggerEvents(PolicyOutputEventType.RunEvent, user, state, actionStatus); } PolicyComponentsUtils.ExternalEventFn(new ExternalEvent(ExternalEventType.Set, ref, user, { - action: ref.options.type, + action: options.type, documents: ExternalDocuments(document) })); ref.backup(); diff --git a/policy-service/src/policy-engine/blocks/aggregate-block.ts b/policy-service/src/policy-engine/blocks/aggregate-block.ts index 0c906d44eb..4af8179e99 100644 --- a/policy-service/src/policy-engine/blocks/aggregate-block.ts +++ b/policy-service/src/policy-engine/blocks/aggregate-block.ts @@ -10,6 +10,7 @@ import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-abo import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfaces/external-event.js'; import { LocationType } from '@guardian/interfaces'; import { RecordActionStep } from '../record-action-step.js'; +import { PolicyUser } from '../policy-user.js'; /** * Aggregate block @@ -40,12 +41,14 @@ import { RecordActionStep } from '../record-action-step.js'; label: 'Disable user grouping', title: 'Disable user grouping', type: PropertyType.Checkbox, - default: false + default: false, + editable: true }, { name: 'groupByFields', label: 'Group By Fields', title: 'Group By Fields', type: PropertyType.Array, + editable: false, items: { label: 'Field Path', value: '@fieldPath', @@ -53,7 +56,8 @@ import { RecordActionStep } from '../record-action-step.js'; name: 'fieldPath', label: 'Field Path', title: 'Field Path', - type: PropertyType.Path + type: PropertyType.Path, + editable: true }] } }] @@ -118,7 +122,10 @@ export class AggregateBlock { }) public async tickCron(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const { aggregateType, groupByFields, disableUserGrouping } = ref.options; + + const options = ref.getOptions(event.user); + + const { aggregateType, groupByFields, disableUserGrouping } = options; if (aggregateType !== 'period') { return; } @@ -179,9 +186,10 @@ export class AggregateBlock { */ private async sendCronDocuments(ref: AnyBlockType, userId: string, documents: AggregateVC[], actionStatus: RecordActionStep) { documents = await this.removeDocuments(ref, documents); - if (documents.length || ref.options.emptyData) { + const user = await PolicyUtils.getPolicyUserById(ref, userId); + const options = ref.getOptions(user); + if (documents.length || options.emptyData) { const state: IPolicyEventState = { data: documents }; - const user = await PolicyUtils.getPolicyUserById(ref, userId); await ref.triggerEvents(PolicyOutputEventType.RunEvent, user, state, actionStatus); await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, user, state, actionStatus); PolicyComponentsUtils.ExternalEventFn( @@ -247,8 +255,10 @@ export class AggregateBlock { @ActionCallback({ output: [PolicyOutputEventType.RunEvent, PolicyOutputEventType.RefreshEvent] }) - private async tickAggregate(ref: AnyBlockType, document: any, userId: string | null, actionStatus: RecordActionStep) { - const { expressions, condition, disableUserGrouping, groupByFields } = ref.options; + private async tickAggregate(ref: AnyBlockType, document: any, userId: string | null, actionStatus: RecordActionStep, user?: PolicyUser) { + let options = ref.getOptions(user); + + const { expressions, condition, disableUserGrouping, groupByFields } = options; const groupByUser = !disableUserGrouping; const filters: any = {}; @@ -340,20 +350,21 @@ export class AggregateBlock { */ async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const { aggregateType } = ref.options; + const options = ref.getOptions(event.user); + const { aggregateType } = options; const docs: IPolicyDocument | IPolicyDocument[] = event.data.data; if (Array.isArray(docs)) { for (const doc of docs) { await this.saveDocuments(ref, doc); if (aggregateType === 'cumulative') { - await this.tickAggregate(ref, doc, event?.user?.userId, event.actionStatus); + await this.tickAggregate(ref, doc, event?.user?.userId, event.actionStatus, event.user); } } } else { await this.saveDocuments(ref, docs); if (aggregateType === 'cumulative') { - await this.tickAggregate(ref, docs, event?.user?.userId, event.actionStatus); + await this.tickAggregate(ref, docs, event?.user?.userId, event.actionStatus, event.user); } } diff --git a/policy-service/src/policy-engine/blocks/button-block-addon.ts b/policy-service/src/policy-engine/blocks/button-block-addon.ts index 170eb8c0f4..3df67e8324 100644 --- a/policy-service/src/policy-engine/blocks/button-block-addon.ts +++ b/policy-service/src/policy-engine/blocks/button-block-addon.ts @@ -38,12 +38,14 @@ import { LocationType } from '@guardian/interfaces'; title: 'Button Name', type: PropertyType.Input, required: true, + editable: true }, { name: 'uiClass', label: 'UI Class', title: 'UI Class', type: PropertyType.Input, + editable: true }, { name: 'dialog', @@ -51,13 +53,15 @@ import { LocationType } from '@guardian/interfaces'; title: 'Dialog', type: PropertyType.Checkbox, default: false, + editable: true }, { name: 'hideWhenDiscontinued', label: 'Hide when discontinued', title: 'Hide when discontinued', type: PropertyType.Checkbox, - default: false + default: false, + editable: true }, { name: 'dialogOptions', @@ -71,12 +75,14 @@ import { LocationType } from '@guardian/interfaces'; title: 'Dialog Title', type: PropertyType.Input, required: true, + editable: true }, { name: 'dialogDescription', label: 'Dialog Description', title: 'Dialog Description', type: PropertyType.Input, + editable: true }, { name: 'dialogResultFieldPath', @@ -85,6 +91,7 @@ import { LocationType } from '@guardian/interfaces'; type: PropertyType.Path, required: true, default: 'option.comment', + editable: true }, ], visible: 'dialog === true', @@ -100,6 +107,7 @@ export class ButtonBlockAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -108,7 +116,7 @@ export class ButtonBlockAddon { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - ...ref.options, + ...options, }; return data; } @@ -128,6 +136,7 @@ export class ButtonBlockAddon { actionStatus ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const parent = PolicyComponentsUtils.GetBlockRef( ref.parent ); @@ -136,10 +145,10 @@ export class ButtonBlockAddon { ref.tag, blockData.documentId, (document: any) => { - if (ref.options.dialog) { + if (options.dialog) { document = setOptions( document, - ref.options.dialogOptions.dialogResultFieldPath, + options.dialogOptions.dialogResultFieldPath, blockData.dialogResult ); } diff --git a/policy-service/src/policy-engine/blocks/button-block.ts b/policy-service/src/policy-engine/blocks/button-block.ts index d9ed05e469..04dea3fe61 100644 --- a/policy-service/src/policy-engine/blocks/button-block.ts +++ b/policy-service/src/policy-engine/blocks/button-block.ts @@ -36,6 +36,7 @@ export class ButtonBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -44,9 +45,9 @@ export class ButtonBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - type: ref.options.type, - uiMetaData: ref.options.uiMetaData, - user: ref.options.user, + type: options.type, + uiMetaData: options.uiMetaData, + user: options.user, userId: user ? user.userId : null, userDid: user ? user.did : null, diff --git a/policy-service/src/policy-engine/blocks/calculate-block.ts b/policy-service/src/policy-engine/blocks/calculate-block.ts index 8e3768996b..914c2d0b40 100644 --- a/policy-service/src/policy-engine/blocks/calculate-block.ts +++ b/policy-service/src/policy-engine/blocks/calculate-block.ts @@ -51,7 +51,8 @@ interface IMetadata { name: 'unsigned', label: 'Unsigned VC', title: 'Unsigned document', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }] }, variables: [ @@ -71,9 +72,12 @@ export class CalculateContainerBlock { documents: IVC | IVC[], ref: IPolicyCalculateBlock, parents: IPolicyDocument | IPolicyDocument[], - userId: string | null + userId: string | null, + user?: PolicyUser ): Promise { - const fields = ref.options.inputFields; + let options = ref.getOptions(user); + + const fields = options.inputFields; let scope = {}; let docOwner: PolicyUser; if (Array.isArray(parents)) { @@ -101,8 +105,8 @@ export class CalculateContainerBlock { scope = await addon.run(scope, docOwner); } const newJson: any = {}; - if (ref.options.outputFields) { - for (const field of ref.options.outputFields) { + if (options.outputFields) { + for (const field of options.outputFields) { if (scope[field.value]) { newJson[field.name] = scope[field.value]; } @@ -122,11 +126,14 @@ export class CalculateContainerBlock { documents: IPolicyDocument | IPolicyDocument[], ref: IPolicyCalculateBlock, userId: string | null, - actionStatus: RecordActionStep + actionStatus: RecordActionStep, + user?: PolicyUser ): Promise { const context = await ref.debugContext({ documents }); const contextDocuments = context.documents as IPolicyDocument | IPolicyDocument[]; + let options = ref.getOptions(user); + const isArray = Array.isArray(contextDocuments); if (!contextDocuments || (isArray && !contextDocuments.length)) { throw new BlockActionError('Invalid VC', ref.blockType, ref.uuid); @@ -147,12 +154,12 @@ export class CalculateContainerBlock { } // --> - const newJson = await this.calculate(json, ref, contextDocuments, userId); - if (ref.options.unsigned) { + const newJson = await this.calculate(json, ref, contextDocuments, userId, user); + if (options.unsigned) { return await this.createUnsignedDocument(newJson, ref, actionStatus?.id); } else { - const metadata = await this.aggregateMetadata(contextDocuments, ref, userId); - return await this.createDocument(newJson, metadata, ref, userId, actionStatus?.id); + const metadata = await this.aggregateMetadata(contextDocuments, ref, userId, user); + return await this.createDocument(newJson, metadata, ref, userId, actionStatus?.id, user); } } @@ -165,11 +172,14 @@ export class CalculateContainerBlock { private async aggregateMetadata( documents: IPolicyDocument | IPolicyDocument[], ref: IPolicyCalculateBlock, - userId: string | null + userId: string | null, + user?: PolicyUser ): Promise { const isArray = Array.isArray(documents); const firstDocument = isArray ? documents[0] : documents; const relationships = []; + let options = ref.getOptions(user); + let accounts: any = {}; let tokens: any = {}; let id: string; @@ -226,6 +236,7 @@ export class CalculateContainerBlock { ref: IPolicyCalculateBlock, userId: string | null, actionStatusId: string, + user?: PolicyUser ): Promise { const { owner, @@ -238,8 +249,9 @@ export class CalculateContainerBlock { } = metadata; // <-- new vc const VCHelper = new VcHelper(); + let options = ref.getOptions(user); - const outputSchema = await PolicyUtils.loadSchemaByID(ref, ref.options.outputSchema); + const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const vcSubject: any = { ...SchemaHelper.getContext(outputSchema), ...json @@ -311,20 +323,21 @@ export class CalculateContainerBlock { @CatchErrors() public async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); + let options = ref.getOptions(event.user); - if (ref.options.inputDocuments === 'separate') { + if (options.inputDocuments === 'separate') { if (Array.isArray(event.data.data)) { const result: IPolicyDocument[] = []; for (const doc of event.data.data) { - const newVC = await this.process(doc, ref, event?.user?.userId, event.actionStatus); + const newVC = await this.process(doc, ref, event?.user?.userId, event.actionStatus, event.user); result.push(newVC) } event.data.data = result; } else { - event.data.data = await this.process(event.data.data, ref, event?.user?.userId, event.actionStatus); + event.data.data = await this.process(event.data.data, ref, event?.user?.userId, event.actionStatus, event.user); } } else { - event.data.data = await this.process(event.data.data, ref, event?.user?.userId, event.actionStatus); + event.data.data = await this.process(event.data.data, ref, event?.user?.userId, event.actionStatus, event.user); } // event.actionStatus.saveResult(event.data); diff --git a/policy-service/src/policy-engine/blocks/calculate-math-addon.ts b/policy-service/src/policy-engine/blocks/calculate-math-addon.ts index 9009634a3a..0620fde195 100644 --- a/policy-service/src/policy-engine/blocks/calculate-math-addon.ts +++ b/policy-service/src/policy-engine/blocks/calculate-math-addon.ts @@ -33,8 +33,10 @@ export class CalculateMathAddon { */ public async run(scope: any, user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - if (ref.options.equations) { - for (const equation of ref.options.equations) { + const options = ref.getOptions(user); + + if (options.equations) { + for (const equation of options.equations) { scope[equation.variable] = ref.evaluate(equation.formula, scope); } } @@ -50,8 +52,10 @@ export class CalculateMathAddon { */ public getVariables(variables: any): any { const ref = PolicyComponentsUtils.GetBlockRef(this); - if (ref.options.equations) { - for (const equation of ref.options.equations) { + const options = ref.getOptions(); + + if (options.equations) { + for (const equation of options.equations) { variables[equation.variable] = equation.formula; } } diff --git a/policy-service/src/policy-engine/blocks/calculate-math-variables.ts b/policy-service/src/policy-engine/blocks/calculate-math-variables.ts index 2c69dc64a5..2ef62f832c 100644 --- a/policy-service/src/policy-engine/blocks/calculate-math-variables.ts +++ b/policy-service/src/policy-engine/blocks/calculate-math-variables.ts @@ -29,32 +29,38 @@ import { LocationType } from '@guardian/interfaces'; name: 'sourceSchema', label: 'Source schema', title: 'Source schema', - type: PropertyType.Schemas + type: PropertyType.Schemas, + editable: false }, { name: 'onlyOwnDocuments', label: 'Owned by User', title: 'Owned by User', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }, { name: 'onlyOwnByGroupDocuments', label: 'Owned by Group', title: 'Owned by Group', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }, { name: 'onlyAssignDocuments', label: 'Assigned to User', title: 'Assigned to User', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }, { name: 'onlyAssignByGroupDocuments', label: 'Assigned to Group', title: 'Assigned to Group', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }, { name: 'selectors', label: 'Selectors', title: 'Selectors', type: PropertyType.Array, + editable: true, items: { label: 'Selector', value: '@sourceField @selectorType @comparisonValue', @@ -62,12 +68,14 @@ import { LocationType } from '@guardian/interfaces'; name: 'sourceField', label: 'Source field', title: 'Source field', - type: PropertyType.Path + type: PropertyType.Path, + editable: true }, { name: 'selectorType', label: 'Selector type', title: 'Selector type', type: PropertyType.Select, + editable: true, items: [{ label: 'Equal', value: 'equal' @@ -86,12 +94,14 @@ import { LocationType } from '@guardian/interfaces'; name: 'comparisonValue', label: 'Comparison value', title: 'Comparison value', - type: PropertyType.Input + type: PropertyType.Input, + editable: true }, { name: 'comparisonValueType', label: 'Comparison value type', title: 'Comparison value type', type: PropertyType.Select, + editable: true, items: [{ label: 'Constanta', value: 'const' @@ -107,6 +117,7 @@ import { LocationType } from '@guardian/interfaces'; label: 'Variables', title: 'Variables', type: PropertyType.Array, + editable: true, items: { label: 'Variable', value: 'var @variableName = @variablePath', @@ -114,12 +125,14 @@ import { LocationType } from '@guardian/interfaces'; name: 'variableName', label: 'Variable name', title: 'Variable name', - type: PropertyType.Input + type: PropertyType.Input, + editable: true }, { name: 'variablePath', label: 'Variable Path', title: 'Variable Path', - type: PropertyType.Path + type: PropertyType.Path, + editable: true }] } }] @@ -145,25 +158,26 @@ export class CalculateMathVariables { */ public async run(scope: any, user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - + const options = ref.getOptions(user); + const filters: any = {}; - if (ref.options.onlyOwnDocuments) { + if (options.onlyOwnDocuments) { filters.owner = user.did; } - if (ref.options.onlyOwnByGroupDocuments) { + if (options.onlyOwnByGroupDocuments) { filters.group = user.group; } - if (ref.options.onlyAssignDocuments) { + if (options.onlyAssignDocuments) { filters.assignedTo = user.did; } - if (ref.options.onlyAssignByGroupDocuments) { + if (options.onlyAssignByGroupDocuments) { filters.assignedToGroup = user.group; } - if (ref.options.sourceSchema) { - filters.schema = ref.options.sourceSchema; + if (options.sourceSchema) { + filters.schema = options.sourceSchema; } - if (Array.isArray(ref.options.selectors)) { - for (const selector of ref.options.selectors) { + if (Array.isArray(options.selectors)) { + for (const selector of options.selectors) { const expr = filters[selector.sourceField] || {}; switch (selector.selectorType) { case 'equal': @@ -205,7 +219,7 @@ export class CalculateMathVariables { const data = await ref.databaseServer.getVcDocument(filters); if (data) { - for (const variable of ref.options.variables) { + for (const variable of options.variables) { scope[variable.variableName] = PolicyUtils.getObjectValue(data, variable.variablePath); } } @@ -221,10 +235,12 @@ export class CalculateMathVariables { * Get variables * @param variables */ - public getVariables(variables: any): any { + public options(variables: any): any { const ref = PolicyComponentsUtils.GetBlockRef(this); - if (ref.options.variables) { - for (const variable of ref.options.variables) { + const options = ref.getOptions(); + + if (options.variables) { + for (const variable of options.variables) { variables[variable.variableName] = variable.variablePath; } } diff --git a/policy-service/src/policy-engine/blocks/container-block.ts b/policy-service/src/policy-engine/blocks/container-block.ts index 05ea531c4e..373c10f9f0 100644 --- a/policy-service/src/policy-engine/blocks/container-block.ts +++ b/policy-service/src/policy-engine/blocks/container-block.ts @@ -36,6 +36,8 @@ export class InterfaceContainerBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + return { id: ref.uuid, blockType: ref.blockType, @@ -44,7 +46,7 @@ export class InterfaceContainerBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - uiMetaData: ref.options?.uiMetaData + uiMetaData: options?.uiMetaData }; } } diff --git a/policy-service/src/policy-engine/blocks/create-token-block.ts b/policy-service/src/policy-engine/blocks/create-token-block.ts index 9f238f06f3..5fd3b29101 100644 --- a/policy-service/src/policy-engine/blocks/create-token-block.ts +++ b/policy-service/src/policy-engine/blocks/create-token-block.ts @@ -117,7 +117,9 @@ export class CreateTokenBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - if (ref.options.autorun) { + const options = ref.getOptions(user); + + if (options.autorun) { throw new BlockActionError( `Block is autorunable and doesn't return any data`, ref.blockType, @@ -126,7 +128,7 @@ export class CreateTokenBlock { } const tokenTemplate = this._prepareTokenTemplate( ref, - PolicyUtils.getTokenTemplate(ref, ref.options.template), + PolicyUtils.getTokenTemplate(ref, options.template), Object.assign({}, this.state?.[user.id]?.data?.data, { index: this.state.tokenNumber, }) @@ -141,7 +143,7 @@ export class CreateTokenBlock { ), active: ref.isBlockActive(user), data: tokenTemplate, - ...ref.options, + ...options, }; } @@ -162,6 +164,8 @@ export class CreateTokenBlock { ); } + const options = ref.getOptions(user); + const policyOwnerCred = await PolicyUtils.getUserCredentials(ref, ref.policyOwner, userId); if (!docs) { @@ -209,13 +213,13 @@ export class CreateTokenBlock { if (!doc.tokens) { doc.tokens = {}; } - doc.tokens[ref.options.template] = createdToken.tokenId; + doc.tokens[options.template] = createdToken.tokenId; } } else { if (!docs.tokens) { docs.tokens = {}; } - docs.tokens[ref.options.template] = createdToken.tokenId; + docs.tokens[options.template] = createdToken.tokenId; } delete this.state[user.id]; @@ -261,7 +265,9 @@ export class CreateTokenBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); ref.log(`setData`); - if (ref.options.autorun) { + const options = ref.getOptions(user); + + if (options.autorun) { throw new BlockActionError( `Block is autorunable and doesn't produce anything`, ref.blockType, @@ -285,7 +291,7 @@ export class CreateTokenBlock { template, this._prepareTokenTemplate( ref, - PolicyUtils.getTokenTemplate(ref, ref.options.template), + PolicyUtils.getTokenTemplate(ref, options.template), Object.assign({}, this.state?.[user.id]?.data?.data, { index: this.state.tokenNumber, }) @@ -322,6 +328,8 @@ export class CreateTokenBlock { const user = event.user; const eventData = event.data; + let options = ref.getOptions(user); + if (!this.state.tokenNumber) { this.state.tokenNumber = 0; } @@ -329,13 +337,13 @@ export class CreateTokenBlock { this.state.tokenNumber++; await ref.saveState(); - if (ref.options.autorun) { + if (options.autorun) { await this._createToken( user, ref, this._prepareTokenTemplate( ref, - PolicyUtils.getTokenTemplate(ref, ref.options.template), + PolicyUtils.getTokenTemplate(ref, options.template), Object.assign({}, eventData.data, { index: this.state.tokenNumber, }) diff --git a/policy-service/src/policy-engine/blocks/custom-logic-block.ts b/policy-service/src/policy-engine/blocks/custom-logic-block.ts index 4616b14a4b..a47dbea150 100644 --- a/policy-service/src/policy-engine/blocks/custom-logic-block.ts +++ b/policy-service/src/policy-engine/blocks/custom-logic-block.ts @@ -59,19 +59,22 @@ interface IMetadata { name: 'unsigned', label: 'Unsigned VC', title: 'Unsigned document', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }, { name: 'passOriginal', label: 'Pass original', title: 'Pass original document', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }, { name: 'selectedScriptLanguage', label: 'Script Language', title: 'Select script language', type: PropertyType.Select, + editable: true, items: [ { label: 'JavaScript', @@ -113,6 +116,7 @@ export class CustomLogicBlock { @CatchErrors() public async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); + try { const triggerEvents = async (documents: IPolicyDocument | IPolicyDocument[]) => { if (!documents) { @@ -174,6 +178,8 @@ export class CustomLogicBlock { return new Promise(async (resolve, reject) => { try { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + let documents: IPolicyDocument[]; if (Array.isArray(state.data)) { documents = state.data; @@ -182,7 +188,7 @@ export class CustomLogicBlock { } let metadata: IMetadata; - if (ref.options.unsigned) { + if (options.unsigned) { metadata = null; } else { if (!documents || !documents.length) { @@ -205,13 +211,13 @@ export class CustomLogicBlock { return; } const processing = async (json: any): Promise => { - if (ref.options.passOriginal) { + if (options.passOriginal) { return json; } - if (ref.options.unsigned) { + if (options.unsigned) { return await this.createUnsignedDocument(json, ref, actionStatus?.id); } else { - return await this.createDocument(json, metadata, ref, userId, actionStatus?.id); + return await this.createDocument(json, metadata, ref, userId, actionStatus?.id, user); } } if (Array.isArray(result)) { @@ -245,7 +251,7 @@ export class CustomLogicBlock { } } - const files = Array.isArray(ref.options.artifacts) ? ref.options.artifacts : []; + const files = Array.isArray(options.artifacts) ? options.artifacts : []; const execCodeArtifacts = files.filter((file: any) => file.type === ArtifactType.EXECUTABLE_CODE); let execCode = ''; for (const execCodeArtifact of execCodeArtifacts) { // todo for python??? @@ -273,8 +279,8 @@ export class CustomLogicBlock { collectTablesPack(context.documents, tablesPack); - const expression = ref.options.expression || ''; - if (ref.options.selectedScriptLanguage === ScriptLanguageOption.PYTHON) { + const expression = options.expression || ''; + if (options.selectedScriptLanguage === ScriptLanguageOption.PYTHON) { const worker = new Worker( path.join(path.dirname(filename), '..', 'helpers', 'workers', 'custom-logic-python-worker.js'), { @@ -359,6 +365,7 @@ export class CustomLogicBlock { const owner = await PolicyUtils.getDocumentOwner(ref, firstDocument, userId); const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, firstDocument, userId); const relationships = []; + const options = ref.getOptions(user); let accounts: any = {}; let tokens: any = {}; let id: string; @@ -400,7 +407,7 @@ export class CustomLogicBlock { } let issuer: string; - switch (ref.options.documentSigner) { + switch (options.documentSigner) { case 'owner': issuer = owner.did; break; @@ -427,6 +434,7 @@ export class CustomLogicBlock { ref: IPolicyCalculateBlock, userId: string | null, actionStatusId: string, + user?: PolicyUser ): Promise { const { owner, @@ -442,7 +450,9 @@ export class CustomLogicBlock { // <-- new vc const VCHelper = new VcHelper(); - const outputSchema = await PolicyUtils.loadSchemaByID(ref, ref.options.outputSchema); + let options = ref.getOptions(user); + + const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const vcSubject: any = { ...SchemaHelper.getContext(outputSchema), ...json @@ -467,7 +477,7 @@ export class CustomLogicBlock { const newId = await PolicyActionsUtils.generateId({ ref, - type: ref.options.idType, + type: options.idType, user: owner, relayerAccount, userId diff --git a/policy-service/src/policy-engine/blocks/document-validator-block.ts b/policy-service/src/policy-engine/blocks/document-validator-block.ts index 91623a7323..cc530b4e29 100644 --- a/policy-service/src/policy-engine/blocks/document-validator-block.ts +++ b/policy-service/src/policy-engine/blocks/document-validator-block.ts @@ -71,7 +71,9 @@ export class DocumentValidatorBlock { const documentRef = PolicyUtils.getDocumentRef(document); - if (ref.options.documentType === 'related-vc-document') { + const options = ref.getOptions(event.user); + + if (options.documentType === 'related-vc-document') { if (documentRef) { document = await ref.databaseServer.getVcDocument({ 'policyId': { $eq: ref.policyId }, @@ -82,7 +84,7 @@ export class DocumentValidatorBlock { } } - if (ref.options.documentType === 'related-vp-document') { + if (options.documentType === 'related-vp-document') { if (documentRef) { document = await ref.databaseServer.getVpDocument({ 'policyId': ref.policyId, @@ -99,19 +101,19 @@ export class DocumentValidatorBlock { const documentType = PolicyUtils.getDocumentType(document); - if (ref.options.documentType === 'vc-document') { + if (options.documentType === 'vc-document') { if (documentType !== 'VerifiableCredential') { return `Invalid document type`; } - } else if (ref.options.documentType === 'vp-document') { + } else if (options.documentType === 'vp-document') { if (documentType !== 'VerifiablePresentation') { return `Invalid document type`; } - } else if (ref.options.documentType === 'related-vc-document') { + } else if (options.documentType === 'related-vc-document') { if (documentType !== 'VerifiableCredential') { return `Invalid document type`; } - } else if (ref.options.documentType === 'related-vp-document') { + } else if (options.documentType === 'related-vp-document') { if (documentType !== 'VerifiablePresentation') { return `Invalid document type`; } @@ -120,36 +122,36 @@ export class DocumentValidatorBlock { const userDID = event?.user?.did; const userGroup = event?.user?.group; - if (ref.options.checkOwnerDocument) { + if (options.checkOwnerDocument) { if (document.owner !== userDID) { return `Invalid owner`; } } - if (ref.options.checkOwnerByGroupDocument) { + if (options.checkOwnerByGroupDocument) { if (document.group !== userGroup) { return `Invalid group`; } } - if (ref.options.checkAssignDocument) { + if (options.checkAssignDocument) { if (document.assignedTo !== userDID) { return `Invalid assigned user`; } } - if (ref.options.checkAssignByGroupDocument) { + if (options.checkAssignByGroupDocument) { if (document.assignedToGroup !== userGroup) { return `Invalid assigned group`; } } - if (ref.options.schema) { - const schema = await PolicyUtils.loadSchemaByID(ref, ref.options.schema); + if (options.schema) { + const schema = await PolicyUtils.loadSchemaByID(ref, options.schema); if (!PolicyUtils.checkDocumentSchema(ref, document, schema)) { return `Invalid document schema`; } } - if (ref.options.conditions) { - for (const filter of ref.options.conditions) { + if (options.conditions) { + for (const filter of options.conditions) { if (!PolicyUtils.checkDocumentField(document, filter)) { return `Invalid document`; } diff --git a/policy-service/src/policy-engine/blocks/documents-source-addon.ts b/policy-service/src/policy-engine/blocks/documents-source-addon.ts index 1d88fa0c37..6f2509664d 100644 --- a/policy-service/src/policy-engine/blocks/documents-source-addon.ts +++ b/policy-service/src/policy-engine/blocks/documents-source-addon.ts @@ -87,35 +87,36 @@ export class DocumentsSourceAddon { otherOptions?: any ) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const filters: any = {}; - if (!Array.isArray(ref.options.filters)) { + if (!Array.isArray(options.filters)) { throw new BlockActionError('filters option must be an array', ref.blockType, ref.uuid); } - if (ref.options.onlyOwnDocuments) { + if (options.onlyOwnDocuments) { filters.owner = user.did; } - if (ref.options.onlyOwnByGroupDocuments) { + if (options.onlyOwnByGroupDocuments) { filters.group = user.group; } - if (ref.options.onlyAssignDocuments) { + if (options.onlyAssignDocuments) { filters.assignedTo = user.did; } - if (ref.options.onlyAssignByGroupDocuments) { + if (options.onlyAssignByGroupDocuments) { filters.assignedToGroup = user.group; } - if (ref.options.hidePreviousVersions) { + if (options.hidePreviousVersions) { filters.edited = { $ne: true }; } - if (ref.options.schema) { - filters.schema = ref.options.schema; + if (options.schema) { + filters.schema = options.schema; } filters.initId = { $exists: false } - for (const filter of ref.options.filters) { + for (const filter of options.filters) { const expr = filters[filter.field] || {}; const query = PolicyUtils.parseQuery(filter.type, filter.value); @@ -150,17 +151,17 @@ export class DocumentsSourceAddon { } else { otherOptions.orderBy.createDate = stateData.orderDirection; } - } else if (ref.options.orderDirection) { + } else if (options.orderDirection) { otherOptions.orderBy = {}; - if (ref.options.orderField) { - otherOptions.orderBy[ref.options.orderField] = ref.options.orderDirection; + if (options.orderField) { + otherOptions.orderBy[options.orderField] = options.orderDirection; } else { - otherOptions.orderBy.createDate = ref.options.orderDirection; + otherOptions.orderBy.createDate = options.orderDirection; } } let data: IPolicyDocument[] | number; - switch (ref.options.dataType) { + switch (options.dataType) { case 'vc-documents': filters.policyId = ref.policyId; data = await ref.databaseServer.getVcDocuments(filters, otherOptions, countResult) as number | IPolicyDocument[]; @@ -203,7 +204,7 @@ export class DocumentsSourceAddon { data = await PolicyUtils.getAllStandardRegistryAccounts(ref, countResult, user.userId); break; default: - throw new BlockActionError(`dataType "${ref.options.dataType}" is unknown`, ref.blockType, ref.uuid) + throw new BlockActionError(`dataType "${options.dataType}" is unknown`, ref.blockType, ref.uuid) } if (!countResult) { @@ -236,33 +237,33 @@ export class DocumentsSourceAddon { */ async getFromSourceFilters(user: PolicyUser, globalFilters: any) { const ref = PolicyComponentsUtils.GetBlockRef(this); - + const options = ref.getOptions(user); const filters: any = []; - if (!Array.isArray(ref.options.filters)) { + if (!Array.isArray(options.filters)) { throw new BlockActionError('filters option must be an array', ref.blockType, ref.uuid); } - if (ref.options.onlyOwnDocuments) { + if (options.onlyOwnDocuments) { filters.push({ $eq: [user.did, '$owner'] }); } - if (ref.options.onlyOwnByGroupDocuments) { + if (options.onlyOwnByGroupDocuments) { filters.push({ $eq: [user.group, '$group'] }); } - if (ref.options.onlyAssignDocuments) { + if (options.onlyAssignDocuments) { filters.push({ $eq: [user.did, '$assignedTo'] }); } - if (ref.options.onlyAssignByGroupDocuments) { + if (options.onlyAssignByGroupDocuments) { filters.push({ $eq: [user.group, '$assignedToGroup'] }); } - if (ref.options.hidePreviousVersions) { + if (options.hidePreviousVersions) { filters.push({ $ne: [true, '$assignedToGroup'] }); } - if (ref.options.schema) { - filters.push({ $eq: [ref.options.schema, '$schema'] }); + if (options.schema) { + filters.push({ $eq: [options.schema, '$schema'] }); } - for (const filter of ref.options.filters) { + for (const filter of options.filters) { const queryType = filter.type as QueryType; const queryValue = PolicyUtils.getQueryValue(queryType, filter.value); const queryExpression = PolicyUtils.getQueryExpression(queryType, queryValue); diff --git a/policy-service/src/policy-engine/blocks/documents-source.ts b/policy-service/src/policy-engine/blocks/documents-source.ts index 67b6e97005..bd326caa4b 100644 --- a/policy-service/src/policy-engine/blocks/documents-source.ts +++ b/policy-service/src/policy-engine/blocks/documents-source.ts @@ -64,7 +64,8 @@ export class InterfaceDocumentsSource { async onAddonEvent(user: PolicyUser, tag: string, documentId: string, handler: (document: any) => Promise, actionStatus) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const fields = ref.options?.uiMetaData?.fields?.filter((field) => + const options = ref.getOptions(user); + const fields = options?.uiMetaData?.fields?.filter((field) => field?.bindBlocks?.includes(tag) ); @@ -72,7 +73,7 @@ export class InterfaceDocumentsSource { const savepointIds = saved.__savepointIds as string[] | undefined; const enableCommonSorting = - !!ref.options?.uiMetaData?.enableSorting + !!options?.uiMetaData?.enableSorting const sourceAddons = fields ?.filter((field) => field.bindGroup) @@ -147,6 +148,7 @@ export class InterfaceDocumentsSource { */ async getData(user: PolicyUser, uuid: string, queryParams: any): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); let ret: IPolicyGetData = { id: ref.uuid, @@ -228,7 +230,7 @@ export class InterfaceDocumentsSource { return addon.blockType === 'historyAddon'; }) as IPolicyAddonBlock; - const enableCommonSorting = ref.options.uiMetaData.enableSorting || (sortDirection && sortField) + const enableCommonSorting = options.uiMetaData.enableSorting || (sortDirection && sortField) let sortState = this.state[user.id] || {}; if (sortDirection && sortField) { @@ -328,7 +330,7 @@ export class InterfaceDocumentsSource { blocks: filters, commonAddons, }, - Object.assign(ref.options.uiMetaData, { + Object.assign(options.uiMetaData, { viewHistory: !!history, }), sortState diff --git a/policy-service/src/policy-engine/blocks/dropdown-block-addon.ts b/policy-service/src/policy-engine/blocks/dropdown-block-addon.ts index f9fba23a03..79e3fc1aff 100644 --- a/policy-service/src/policy-engine/blocks/dropdown-block-addon.ts +++ b/policy-service/src/policy-engine/blocks/dropdown-block-addon.ts @@ -40,6 +40,7 @@ import { LocationType } from '@guardian/interfaces'; title: 'Option Name', type: PropertyType.Path, required: true, + editable: true }, { name: 'optionValue', @@ -47,6 +48,7 @@ import { LocationType } from '@guardian/interfaces'; title: 'Option Value', type: PropertyType.Path, required: true, + editable: true }, { name: 'field', @@ -54,6 +56,7 @@ import { LocationType } from '@guardian/interfaces'; title: 'Field', type: PropertyType.Path, required: true, + editable: true }, ], }, @@ -66,7 +69,7 @@ export class DropdownBlockAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - + const options = ref.getOptions(user); const documents: any[] = await ref.getSources(user, null); const data: IPolicyGetData = { @@ -77,11 +80,11 @@ export class DropdownBlockAddon { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - ...ref.options, + ...options, documents: documents.map((e) => { return { - name: findOptions(e, ref.options.optionName), - optionValue: findOptions(e, ref.options.optionValue), + name: findOptions(e, options.optionName), + optionValue: findOptions(e, options.optionValue), value: e.id, }; }), @@ -104,6 +107,7 @@ export class DropdownBlockAddon { actionStatus ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const documents: any[] = await ref.getSources(user, null); const dropdownDocument = documents.find( // tslint:disable-next-line:no-shadowed-variable @@ -126,8 +130,8 @@ export class DropdownBlockAddon { (document: any) => { document = setOptions( document, - ref.options.field, - findOptions(dropdownDocument, ref.options.optionValue) + options.field, + findOptions(dropdownDocument, options.optionValue) ); return { data: document, diff --git a/policy-service/src/policy-engine/blocks/external-data-block.ts b/policy-service/src/policy-engine/blocks/external-data-block.ts index 7cae363f4a..4b7e2508ff 100644 --- a/policy-service/src/policy-engine/blocks/external-data-block.ts +++ b/policy-service/src/policy-engine/blocks/external-data-block.ts @@ -161,10 +161,11 @@ export class ExternalDataBlock { } const user: PolicyUser = await PolicyUtils.getDocumentOwner(ref, data, null); + const options = ref.getOptions(user); const documentRef = await this.getRelationships(ref, data.ref); const schema = await this.getSchema(); const vc = VcDocument.fromJsonTree(data.document); - const forceRelayerAccount = ref.options.forceRelayerAccount; + const forceRelayerAccount = options.forceRelayerAccount; const inheritRelayerAccount = PolicyComponentsUtils.IsInheritRelayerAccount(ref.policyId, forceRelayerAccount); //Relayer Account @@ -178,8 +179,8 @@ export class ExternalDataBlock { const tags = await PolicyUtils.getBlockTags(ref); PolicyUtils.setDocumentTags(doc, tags); - doc.type = ref.options.entityType; - doc.schema = ref.options.schema; + doc.type = options.entityType; + doc.schema = options.schema; doc.accounts = accounts; doc.relayerAccount = relayerAccount; doc.signature = (verify ? diff --git a/policy-service/src/policy-engine/blocks/external-topic-block.ts b/policy-service/src/policy-engine/blocks/external-topic-block.ts index 6a41c3a4c7..ceb94a225c 100644 --- a/policy-service/src/policy-engine/blocks/external-topic-block.ts +++ b/policy-service/src/policy-engine/blocks/external-topic-block.ts @@ -118,7 +118,8 @@ interface SchemaItem { name: 'schema', label: 'Schema', title: 'Schema', - type: PropertyType.Schemas + type: PropertyType.Schemas, + editable: false }] }, variables: [ @@ -715,6 +716,7 @@ export class ExternalTopicBlock { actionStatus: RecordActionStep ): Promise { const documentRef = await this.getRelationships(ref, user); + const options = ref.getOptions(user); if (message.type !== MessageType.VCDocument) { return; @@ -734,7 +736,7 @@ export class ExternalTopicBlock { const relayerAccount = await PolicyUtils.getRefRelayerAccount(ref, user.did, null, documentRef, user.userId); const result: IPolicyDocument = PolicyUtils.createPolicyDocument(ref, user, document); - result.schema = ref.options.schema; + result.schema = options.schema; result.relayerAccount = relayerAccount; if (documentRef) { PolicyUtils.setDocumentRef(result, documentRef); diff --git a/policy-service/src/policy-engine/blocks/extract-data-block.ts b/policy-service/src/policy-engine/blocks/extract-data-block.ts index 8513c4e3ae..a9e779105c 100644 --- a/policy-service/src/policy-engine/blocks/extract-data-block.ts +++ b/policy-service/src/policy-engine/blocks/extract-data-block.ts @@ -37,6 +37,7 @@ import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfac label: 'Action', title: 'Action', type: PropertyType.Select, + editable: true, items: [ { label: 'Get', @@ -52,7 +53,8 @@ import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfac name: 'schema', label: 'Schema', title: 'Schema', - type: PropertyType.Schemas + type: PropertyType.Schemas, + editable: false }] }, variables: [ @@ -254,8 +256,9 @@ export class ExtractDataBlock { @CatchErrors() async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); + let options = ref.getOptions(event.user); - if (ref.options.action === 'set') { + if (options.action === 'set') { await this.setAction(ref, event); } else { await this.getAction(ref, event); @@ -263,7 +266,7 @@ export class ExtractDataBlock { PolicyComponentsUtils.ExternalEventFn( new ExternalEvent(ExternalEventType.Run, ref, event?.user, { - action: ref.options.action, + action: options.action, documents: ExternalDocuments(event.data.data) }) ); diff --git a/policy-service/src/policy-engine/blocks/filters-addon-block.ts b/policy-service/src/policy-engine/blocks/filters-addon-block.ts index c7dd109eaf..bc6bc3df4f 100644 --- a/policy-service/src/policy-engine/blocks/filters-addon-block.ts +++ b/policy-service/src/policy-engine/blocks/filters-addon-block.ts @@ -53,20 +53,22 @@ export class FiltersAddonBlock { } } - private addQuery(filter: any, value: any) { + private addQuery(filter: any, value: any, user?: PolicyUser) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const query = PolicyUtils.parseQuery(ref.options.queryType || QueryType.eq, value); + const options = ref.getOptions(user); + const query = PolicyUtils.parseQuery(options.queryType || QueryType.eq, value); if (query && query.expression) { - filter[ref.options.field] = query.expression; + filter[options.field] = query.expression; } else { throw new BlockActionError(`Unknown filter type: ${filter.type}`, ref.blockType, ref.uuid); } } - private checkValues(blockState: any, value: any): boolean { + private checkValues(blockState: any, value: any, user: PolicyUser): boolean { if (Array.isArray(blockState.lastData)) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const query = PolicyUtils.parseQuery(ref.options.queryType || QueryType.eq, value); + const options = ref.getOptions(user); + const query = PolicyUtils.parseQuery(options.queryType || QueryType.eq, value); const itemValues = query.value; if (Array.isArray(itemValues)) { for (const itemValue of itemValues) { @@ -98,20 +100,21 @@ export class FiltersAddonBlock { public async getFilters(user: PolicyUser): Promise<{ [key: string]: string }> { const ref = PolicyComponentsUtils.GetBlockRef(this); const filters = ref.filters[user.id] || {}; + const options = ref.getOptions(user); - if (!filters[ref.options.field] && !ref.options.canBeEmpty) { + if (!filters[options.field] && !options.canBeEmpty) { let filterValue: any; - if (ref.options.type === 'dropdown') { + if (options.type === 'dropdown') { const data: any[] = await ref.getSources(user, null); - filterValue = findOptions(data[0], ref.options.optionValue); + filterValue = findOptions(data[0], options.optionValue); } - if (ref.options.type === 'datepicker') { + if (options.type === 'datepicker') { filterValue = ''; } - if (ref.options.type === 'input') { + if (options.type === 'input') { filterValue = ''; } @@ -122,11 +125,11 @@ export class FiltersAddonBlock { } else { filterValue = ''; } - if (ref.options.queryType === 'user_defined') { + if (options.queryType === 'user_defined') { filterValue = 'eq:' + filterValue; } - this.addQuery(filters, filterValue) + this.addQuery(filters, filterValue, user); } return filters; } @@ -137,6 +140,7 @@ export class FiltersAddonBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const block: IPolicyGetData = { id: ref.uuid, @@ -146,33 +150,33 @@ export class FiltersAddonBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - type: ref.options.type, - uiMetaData: ref.options.uiMetaData, - canBeEmpty: ref.options.canBeEmpty, - queryType: ref.options.queryType + type: options.type, + uiMetaData: options.uiMetaData, + canBeEmpty: options.canBeEmpty, + queryType: options.queryType }; const data: any[] = await ref.getSources(user, null); - if (ref.options.type === 'dropdown') { + if (options.type === 'dropdown') { const blockState = this.state[user.id] || {}; blockState.lastData = data.map((e) => { return { - name: findOptions(e, ref.options.optionName), - value: findOptions(e, ref.options.optionValue), + name: findOptions(e, options.optionName), + value: findOptions(e, options.optionValue), } }).filter((value, index, array) => { const i = array.findIndex(v => v.value === value.value); return i === index; }); block.data = blockState.lastData; - block.optionName = ref.options.optionName; - block.optionValue = ref.options.optionValue; + block.optionName = options.optionName; + block.optionValue = options.optionValue; block.filterValue = blockState.lastValue; this.state[user.id] = blockState; } - if (ref.options.type === 'datepicker' || ref.options.type === 'input') { + if (options.type === 'datepicker' || options.type === 'input') { const blockState = this.state[user.id] || {}; block.filterValue = blockState.lastValue; } @@ -194,6 +198,8 @@ export class FiltersAddonBlock { async setFiltersStrict(user: PolicyUser, data: any) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + this.previousState[user.id] = { ...this.state[user.id] }; const filter: any = {}; if (!data) { @@ -202,27 +208,27 @@ export class FiltersAddonBlock { const value = data.filterValue; const blockState = this.state[user.id] || {}; - if (ref.options.type === 'dropdown') { + if (options.type === 'dropdown') { if (!blockState.lastData) { await this.getData(user); } if (value) { this.addQuery(filter, value); - } else if (!ref.options.canBeEmpty) { + } else if (!options.canBeEmpty) { throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) } } - if (ref.options.type === 'datepicker') { + if (options.type === 'datepicker') { if (value) { this.addQuery(filter, value); - } else if (!ref.options.canBeEmpty) { + } else if (!options.canBeEmpty) { throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) } } - if (ref.options.type === 'input') { + if (options.type === 'input') { if (value) { this.addQuery(filter, value); - } else if (!ref.options.canBeEmpty) { + } else if (!options.canBeEmpty) { throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) } } @@ -234,6 +240,8 @@ export class FiltersAddonBlock { async setFilterState(user: PolicyUser, data: any): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + this.previousState[user.id] = { ...this.state[user.id] }; const filter: any = {}; if (!data) { @@ -242,27 +250,27 @@ export class FiltersAddonBlock { const value = data.filterValue; const blockState = this.state[user.id] || {}; - if (ref.options.type === 'dropdown') { + if (options.type === 'dropdown') { if (!blockState.lastData) { await this.getData(user); } - if (this.checkValues(blockState, value)) { + if (this.checkValues(blockState, value, user)) { this.addQuery(filter, value); - } else if (!ref.options.canBeEmpty) { + } else if (!options.canBeEmpty) { throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) } } - if (ref.options.type === 'datepicker') { + if (options.type === 'datepicker') { if (value) { this.addQuery(filter, value); - } else if (!ref.options.canBeEmpty) { + } else if (!options.canBeEmpty) { throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) } } - if (ref.options.type === 'input') { + if (options.type === 'input') { if (value) { this.addQuery(filter, value); - } else if (!ref.options.canBeEmpty) { + } else if (!options.canBeEmpty) { throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) } } diff --git a/policy-service/src/policy-engine/blocks/global-events-reader-block.ts b/policy-service/src/policy-engine/blocks/global-events-reader-block.ts index 6a879a4313..2d039ba8ff 100644 --- a/policy-service/src/policy-engine/blocks/global-events-reader-block.ts +++ b/policy-service/src/policy-engine/blocks/global-events-reader-block.ts @@ -99,6 +99,7 @@ type WorkerTopicMessageRaw = { title: 'Show button to move to next block with cached payload', type: PropertyType.Checkbox, default: false, + editable: true }, { name: 'eventTopics', @@ -113,7 +114,8 @@ type WorkerTopicMessageRaw = { name: 'topicId', label: 'Topic ID', title: 'Hedera topic id (0.0.x)', - type: PropertyType.Input + type: PropertyType.Input, + editable: true }, { name: 'active', @@ -121,6 +123,7 @@ type WorkerTopicMessageRaw = { title: 'Add this topic stream as active for new users', type: PropertyType.Checkbox, default: true, + editable: true } ] } @@ -130,6 +133,7 @@ type WorkerTopicMessageRaw = { label: 'Branches', title: 'Branch outputs', type: PropertyType.Array, + editable: true, items: { label: 'Branch', value: '@branchEvent', @@ -138,7 +142,8 @@ type WorkerTopicMessageRaw = { name: 'branchEvent', label: 'Branch event', title: 'Output event name', - type: PropertyType.Input + type: PropertyType.Input, + editable: true }, { name: 'documentType', @@ -147,12 +152,14 @@ type WorkerTopicMessageRaw = { type: PropertyType.Select, items: GLOBAL_DOCUMENT_TYPE_ITEMS, default: GLOBAL_DOCUMENT_TYPE_DEFAULT, + editable: true }, { name: 'schema', label: 'Schema', title: 'Local policy schema (validate VC before routing)', type: PropertyType.Schemas, + editable: false } ] } @@ -182,6 +189,8 @@ class GlobalEventsReaderBlock { user.userId ); + const options = ref.getOptions(user); + const existingTopicIds = new Set(); for (const stream of existingStreams) { @@ -191,7 +200,7 @@ class GlobalEventsReaderBlock { } } - const config = ref.options; + const config = options; const optionTopicIds = config.eventTopics ?? []; const defaultBranchDocumentTypeByBranch: Record = {}; @@ -903,7 +912,9 @@ class GlobalEventsReaderBlock { user: PolicyUser, stream: GlobalEventsReaderStream ): Promise { - const config = (ref.options || {}) as GlobalEventReaderConfig; + const options = ref.getOptions(user); + + const config = (options || {}) as GlobalEventReaderConfig; const branches = config.branches ?? []; if (!stream.globalTopicId) { @@ -1081,7 +1092,8 @@ class GlobalEventsReaderBlock { public async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const config = ref.options; + const options = ref.getOptions(user); + const config = options; if (ref.dryRun) { return { @@ -1242,6 +1254,7 @@ class GlobalEventsReaderBlock { actionStatus ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); if (ref.dryRun) { throw new BlockActionError('Block is disabled in dry run mode', ref.blockType, ref.uuid); @@ -1253,7 +1266,7 @@ class GlobalEventsReaderBlock { throw new BlockActionError('Invalid operation', ref.blockType, ref.uuid); } - const config = ref.options || {}; + const config = options || {}; const configuredTopicIdSet = new Set(this.extractConfiguredTopicIds(config)); const value: SetDataPayloadReader | { streams: [] } = data.value ?? { streams: [] }; diff --git a/policy-service/src/policy-engine/blocks/global-events-writer-block.ts b/policy-service/src/policy-engine/blocks/global-events-writer-block.ts index 6e8d783f0f..6d4f1bb5e4 100644 --- a/policy-service/src/policy-engine/blocks/global-events-writer-block.ts +++ b/policy-service/src/policy-engine/blocks/global-events-writer-block.ts @@ -50,12 +50,14 @@ interface SetDataPayload { title: 'Show button to move to next block with cached payload', type: PropertyType.Checkbox, default: false, + editable: true }, { name: 'topicIds', label: 'Global topics', title: 'One or more Hedera topics where notifications are published', type: PropertyType.Array, + editable: true, items: { label: 'Topic', value: '@topicId', @@ -65,6 +67,7 @@ interface SetDataPayload { label: 'Topic id', title: 'Hedera topic id', type: PropertyType.Input, + editable: true }, { name: 'active', @@ -72,6 +75,7 @@ interface SetDataPayload { title: 'Add this topic stream as active for new users', type: PropertyType.Checkbox, default: true, + editable: true }, { name: 'documentType', @@ -80,6 +84,7 @@ interface SetDataPayload { type: PropertyType.Select, items: GLOBAL_DOCUMENT_TYPE_ITEMS, default: GLOBAL_DOCUMENT_TYPE_DEFAULT, + editable: true }, ], }, @@ -98,6 +103,8 @@ export class GlobalEventsWriterBlock { user.userId, ); + const options = ref.getOptions(user); + const existingTopicIds = new Set(); for (const stream of existingStreams) { if (stream?.globalTopicId) { @@ -105,7 +112,7 @@ export class GlobalEventsWriterBlock { } } - const optionTopicIds = ref.options.topicIds ?? []; + const optionTopicIds = options.topicIds ?? []; for (const optionTopic of optionTopicIds) { const optionTopicId = optionTopic.topicId; @@ -478,7 +485,9 @@ export class GlobalEventsWriterBlock { */ public async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const config = ref.options || {} + const options = ref.getOptions(user); + + const config = options || {} if (ref.dryRun) { return { @@ -507,7 +516,7 @@ export class GlobalEventsWriterBlock { const streams = await ref.databaseServer.getGlobalEventsWriterStreamsByUser(ref.policyId, ref.uuid, user.userId); const defaultTopicIds: string[] = []; - const optionTopicIds = ref.options.topicIds ?? []; + const optionTopicIds = options.topicIds ?? []; for (const item of optionTopicIds) { defaultTopicIds.push(item.topicId); @@ -535,6 +544,8 @@ export class GlobalEventsWriterBlock { */ public async setData(user: PolicyUser, data: SetDataPayload, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const operation = data.operation; const streams = data.streams ?? []; @@ -610,7 +621,7 @@ export class GlobalEventsWriterBlock { } if (operation === 'Delete') { - const optionTopicIds = ref.options.topicIds ?? []; + const optionTopicIds = options.topicIds ?? []; const defaultTopicIds = new Set(); for (const item of optionTopicIds) { diff --git a/policy-service/src/policy-engine/blocks/group-manager.ts b/policy-service/src/policy-engine/blocks/group-manager.ts index 85d4545090..e4ad53152a 100644 --- a/policy-service/src/policy-engine/blocks/group-manager.ts +++ b/policy-service/src/policy-engine/blocks/group-manager.ts @@ -49,6 +49,8 @@ export class GroupManagerBlock { role: string ): Promise { const group = await ref.databaseServer.getUserInGroup(ref.policyId, user.did, groupId); + const options = ref.getOptions(user); + if (!group) { throw new Error(`Group not found`); } @@ -56,7 +58,7 @@ export class GroupManagerBlock { group.groupRelationshipType === GroupRelationshipType.Multiple && group.groupAccessType === GroupAccessType.Private ) { - if (ref.options.canInvite === 'all' || group.owner === user.did) { + if (options.canInvite === 'all' || group.owner === user.did) { const inviteId = await ref.databaseServer.createInviteToken(ref.policyId, group.uuid, user.did, role); return Buffer.from(JSON.stringify({ invitation: inviteId, @@ -92,6 +94,8 @@ export class GroupManagerBlock { if (user.did === did) { throw new Error(`Permission denied`); } + const options = ref.getOptions(user); + const member = await ref.databaseServer.getUserInGroup(ref.policyId, did, groupId); if (!member) { throw new Error(`Group not found`); @@ -100,13 +104,13 @@ export class GroupManagerBlock { member.groupRelationshipType === GroupRelationshipType.Multiple && member.groupAccessType === GroupAccessType.Private ) { - if (ref.options.canDelete === 'all' || member.owner === user.did) { + if (options.canDelete === 'all' || member.owner === user.did) { await ref.databaseServer.deleteGroup(member); } else { throw new Error(`Permission denied`); } } else if (member.groupAccessType === GroupAccessType.Global) { - if (ref.options.canDelete === 'all' || member.owner === user.did) { + if (options.canDelete === 'all' || member.owner === user.did) { await ref.databaseServer.deleteGroup(member); } else { throw new Error(`Permission denied`); @@ -152,6 +156,7 @@ export class GroupManagerBlock { */ private async groupMapping(ref: IPolicyInterfaceBlock, user: PolicyUser, group: PolicyRoles): Promise { const config = PolicyUtils.getGroupTemplate(ref, group.groupName); + const options = ref.getOptions(user); const members = (await ref.databaseServer.getAllMembersByGroup(group)).map(member => { return { did: member.did, @@ -161,8 +166,8 @@ export class GroupManagerBlock { current: member.did === user.did } }); - const canInvite = ref.options.canInvite === 'all' ? true : group.owner === user.did; - const canDelete = ref.options.canDelete === 'all' ? true : group.owner === user.did; + const canInvite = options.canInvite === 'all' ? true : group.owner === user.did; + const canDelete = options.canDelete === 'all' ? true : group.owner === user.did; return { id: group.uuid, role: group.role, diff --git a/policy-service/src/policy-engine/blocks/history-addon.ts b/policy-service/src/policy-engine/blocks/history-addon.ts index b21082055e..0e537d4df2 100644 --- a/policy-service/src/policy-engine/blocks/history-addon.ts +++ b/policy-service/src/policy-engine/blocks/history-addon.ts @@ -23,13 +23,15 @@ import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-abo label: 'Timeline Label Path', title: 'Timeline unit label path', type: PropertyType.Path, - default: '' + default: '', + editable: true }, { name: 'timelineDescriptionPath', label: 'Timeline Description Path', title: 'Timeline unit description', type: PropertyType.Path, - default: '' + default: '', + editable: true }] }, variables: [] diff --git a/policy-service/src/policy-engine/blocks/http-request-block.ts b/policy-service/src/policy-engine/blocks/http-request-block.ts index 835c2783f0..e4b90ba66c 100644 --- a/policy-service/src/policy-engine/blocks/http-request-block.ts +++ b/policy-service/src/policy-engine/blocks/http-request-block.ts @@ -144,6 +144,8 @@ export class HttpRequestBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); event.data.data = event.data.data || {}; + let options = ref.getOptions(event.user); + const variablesObj: any = { did: event?.user?.did, username: event?.user.username @@ -156,11 +158,11 @@ export class HttpRequestBlock { variablesObj.document = inputObject = (event?.data?.data as IPolicyDocument)?.document; } - const method = ref.options.method; - const url = this.replaceVariablesInString(ref.options.url, variablesObj); + const method = options.method; + const url = this.replaceVariablesInString(options.url, variablesObj); const headers = {}; - if (Array.isArray(ref.options.headers)) { - for (const header of ref.options.headers) { + if (Array.isArray(options.headers)) { + for (const header of options.headers) { headers[header.name] = this.replaceVariablesInString(header.value, variablesObj) } } diff --git a/policy-service/src/policy-engine/blocks/http-request-ui-addon.ts b/policy-service/src/policy-engine/blocks/http-request-ui-addon.ts index 97486eb2b4..4653f36150 100644 --- a/policy-service/src/policy-engine/blocks/http-request-ui-addon.ts +++ b/policy-service/src/policy-engine/blocks/http-request-ui-addon.ts @@ -28,6 +28,7 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; label: 'Method', title: 'Method', type: PropertyType.Select, + editable: true, items: [ { label: 'Get', @@ -50,13 +51,15 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; label: 'URL', title: 'URL', type: PropertyType.Input, - required: true + required: true, + editable: true }, { name: 'authentication', label: 'Authentication', title: 'Authentication', type: PropertyType.Select, + editable: true, items: [ { label: 'No Auth', @@ -75,7 +78,8 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; title: 'Authentication ClientId', type: PropertyType.Input, visible: 'authentication === "bearerToken"', - default: '' + default: '', + editable: true }, { name: 'authenticationURL', @@ -83,7 +87,8 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; title: 'Authentication Url', type: PropertyType.Input, visible: 'authentication === "bearerToken"', - default: '' + default: '', + editable: true }, { name: 'authenticationScopes', @@ -91,13 +96,15 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; title: 'Authentication Scopes', type: PropertyType.Input, visible: 'authentication === "bearerToken"', - default: '' + default: '', + editable: true }, { name: 'headers', label: 'Headers', title: 'Headers', type: PropertyType.Array, + editable: true, items: { label: 'Header', value: '', @@ -106,13 +113,15 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; name: 'name', label: 'Header name', title: 'Header name', - type: PropertyType.Input + type: PropertyType.Input, + editable: true }, { name: 'value', label: 'Header value', title: 'Header value', - type: PropertyType.Input + type: PropertyType.Input, + editable: true } ] } @@ -129,7 +138,7 @@ export class HttpRequestUIAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = PolicyComponentsUtils.GetBlockUniqueOptionsObject(this); + const options = ref.getOptions(user); return { id: ref.uuid, blockType: ref.blockType, diff --git a/policy-service/src/policy-engine/blocks/impact-addon.ts b/policy-service/src/policy-engine/blocks/impact-addon.ts index 5448ee9a41..0ee28894ad 100644 --- a/policy-service/src/policy-engine/blocks/impact-addon.ts +++ b/policy-service/src/policy-engine/blocks/impact-addon.ts @@ -30,6 +30,7 @@ import { BlockActionError } from '../errors/index.js'; label: 'Impact type', title: 'Impact type', type: PropertyType.Select, + editable: true, items: [{ label: 'Primary Impacts', value: 'Primary Impacts' @@ -43,22 +44,26 @@ import { BlockActionError } from '../errors/index.js'; name: 'label', label: 'Label', title: 'Label', + editable: true, type: PropertyType.Input }, { name: 'description', label: 'Description', title: 'Description', + editable: true, type: PropertyType.Input }, { name: 'amount', label: 'Amount (Formula)', title: 'Amount (Formula)', required: true, + editable: true, type: PropertyType.Input }, { name: 'unit', label: 'Unit', title: 'Unit', + editable: true, type: PropertyType.Input }] }, @@ -99,23 +104,24 @@ export class TokenOperationAddon { userId: string | null ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const policySchema = await this.getSchema(); - const amount = PolicyUtils.aggregate(ref.options.amount, documents); + const amount = PolicyUtils.aggregate(options.amount, documents); const vcHelper = new VcHelper(); const vcSubject: any = { ...SchemaHelper.getContext(policySchema), - impactType: ref.options.impactType === 'Primary Impacts' ? 'Primary Impacts' : 'Secondary Impacts', + impactType: options.impactType === 'Primary Impacts' ? 'Primary Impacts' : 'Secondary Impacts', date: (new Date()).toISOString(), amount: amount.toString(), } - if (ref.options.unit) { - vcSubject.unit = ref.options.unit; + if (options.unit) { + vcSubject.unit = options.unit; } - if (ref.options.label) { - vcSubject.label = ref.options.label; + if (options.label) { + vcSubject.label = options.label; } - if (ref.options.description) { - vcSubject.description = ref.options.description; + if (options.description) { + vcSubject.description = options.description; } const didDocument = await root.loadDidDocument(ref, userId); const uuid = await ref.components.generateUUID(); diff --git a/policy-service/src/policy-engine/blocks/information-block.ts b/policy-service/src/policy-engine/blocks/information-block.ts index 9b1c5dccd1..3b36349af5 100644 --- a/policy-service/src/policy-engine/blocks/information-block.ts +++ b/policy-service/src/policy-engine/blocks/information-block.ts @@ -36,6 +36,8 @@ export class InformationBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + return { id: ref.uuid, blockType: ref.blockType, @@ -44,7 +46,7 @@ export class InformationBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - uiMetaData: ref.options?.uiMetaData + uiMetaData: options?.uiMetaData }; } } diff --git a/policy-service/src/policy-engine/blocks/integration-button-block.ts b/policy-service/src/policy-engine/blocks/integration-button-block.ts index 484fd643d9..19c3320df6 100644 --- a/policy-service/src/policy-engine/blocks/integration-button-block.ts +++ b/policy-service/src/policy-engine/blocks/integration-button-block.ts @@ -9,7 +9,6 @@ import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfac import { generateConfigForIntegrationBlock, VcHelper, IntegrationServiceFactory, HederaDidDocument, VcDocumentDefinition, VcDocument } from '@guardian/common'; import { PolicyUtils } from '../helpers/utils.js'; import { FilterQuery } from '@mikro-orm/core'; - /** * Document action clock with UI */ @@ -27,6 +26,8 @@ export class IntegrationButtonBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -35,10 +36,10 @@ export class IntegrationButtonBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - integrationType: ref.options.integrationType || '', - requestName: ref.options.requestName || '', - buttonName: ref.options.buttonName, - hideWhenDiscontinued: !!ref.options.hideWhenDiscontinued, + integrationType: options.integrationType || '', + requestName: options.requestName || '', + buttonName: options.buttonName, + hideWhenDiscontinued: !!options.hideWhenDiscontinued, } return data; } @@ -59,11 +60,12 @@ export class IntegrationButtonBlock { tag: any }, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const requestNameSplited = ref.options.requestName.split('_'); + const options = ref.getOptions(user); + const requestNameSplited = options.requestName.split('_'); const params = {}; - Object.entries(ref.options.requestParams).forEach(([key, value]: [string, string]) => { + Object.entries(options.requestParams).forEach(([key, value]: [string, string]) => { if (key.startsWith('path_')) { const keyName = key.split('path_')[1]; @@ -82,14 +84,14 @@ export class IntegrationButtonBlock { const methodName = requestNameSplited[requestNameSplited.length - 1]; const dataForRequest = IntegrationServiceFactory.getDataForRequest( - ref.options.integrationType, - IntegrationServiceFactory.getAvailableMethods(ref.options.integrationType)[methodName], + options.integrationType, + IntegrationServiceFactory.getAvailableMethods(options.integrationType)[methodName], params ); const dataForRequestStr = JSON.stringify(dataForRequest); - if (ref.options.getFromCache) { + if (options.getFromCache) { const cachedData = await ref.databaseServer.getVcDocument({ 'option.requestParams': dataForRequestStr, policyId: ref.policyId, @@ -111,7 +113,7 @@ export class IntegrationButtonBlock { } } - const integrationService = IntegrationServiceFactory.create(ref.options.integrationType); + const integrationService = IntegrationServiceFactory.create(options.integrationType); const { data: responseFromRequest, diff --git a/policy-service/src/policy-engine/blocks/math-block.ts b/policy-service/src/policy-engine/blocks/math-block.ts index 53b8cbecde..4e6ff2fd4b 100644 --- a/policy-service/src/policy-engine/blocks/math-block.ts +++ b/policy-service/src/policy-engine/blocks/math-block.ts @@ -54,17 +54,20 @@ interface IMetadata { name: 'inputSchema', label: 'Input Schema', title: 'Input Schema', - type: PropertyType.Schemas + type: PropertyType.Schemas, + editable: false }, { name: 'outputSchema', label: 'Output Schema', title: 'Output Schema', - type: PropertyType.Schemas + type: PropertyType.Schemas, + editable: false }, { name: 'unsigned', label: 'Unsigned VC', title: 'Unsigned document', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }] }, variables: [ @@ -110,11 +113,12 @@ export class MathBlock { documents: DocumentMap, user: PolicyUser ): Promise { - const outputSchema = await PolicyUtils.loadSchemaByID(ref, ref.options.outputSchema); + const options = ref.getOptions(user); + const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const schema = new Schema(outputSchema); // Artifacts - const files = Array.isArray(ref.options.artifacts) ? ref.options.artifacts : []; + const files = Array.isArray(options.artifacts) ? options.artifacts : []; const artifacts = []; const jsonArtifacts = files.filter((file: any) => file.type === ArtifactType.JSON); for (const jsonArtifact of jsonArtifacts) { @@ -124,12 +128,12 @@ export class MathBlock { // Run const result = await this.createWorker({ - expression: ref.options.expression, + expression: options.expression, documents: documents.toJson(), artifacts, user, schema, - copy: !ref.options.outputSchema || ref.options.outputSchema === ref.options.inputSchema + copy: !options.outputSchema || options.outputSchema === options.inputSchema }) return result; @@ -154,12 +158,15 @@ export class MathBlock { private async process( documents: IPolicyDocument, ref: IPolicyCalculateBlock, - userId: string | null + userId: string | null, + user?: PolicyUser ): Promise { if (!documents) { throw new BlockActionError('Invalid VC', ref.blockType, ref.uuid); } + let options = ref.getOptions(user); + const sources: IPolicyDocument[] = await PolicyUtils.findRelationships(ref, documents); const context = await ref.debugContext({ documents, sources }); @@ -173,11 +180,11 @@ export class MathBlock { map.addRelationships(contextRelationships.map((d) => this.getCredentialSubject(d))); const newJson = await this.calculate(ref, map, docOwner); - if (ref.options.unsigned) { + if (options.unsigned) { return await this.createUnsignedDocument(newJson, ref); } else { const metadata = await this.aggregateMetadata(contextDocument, ref, userId); - return await this.createDocument(newJson, metadata, ref, userId); + return await this.createDocument(newJson, metadata, ref, userId, user); } } @@ -199,6 +206,7 @@ export class MathBlock { let tokens: any = {}; let id: string; let reference: string; + if (isArray) { const credentialSubject = documents[0].document?.credentialSubject; if (credentialSubject) { @@ -249,7 +257,8 @@ export class MathBlock { json: any, metadata: IMetadata, ref: IPolicyCalculateBlock, - userId: string | null + userId: string | null, + user?: PolicyUser ): Promise { const { owner, @@ -263,7 +272,9 @@ export class MathBlock { // <-- new vc const VCHelper = new VcHelper(); - const outputSchema = await PolicyUtils.loadSchemaByID(ref, ref.options.outputSchema); + let options = ref.getOptions(user); + + const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const vcSubject: any = { ...SchemaHelper.getContext(outputSchema), @@ -339,12 +350,12 @@ export class MathBlock { if (Array.isArray(event.data.data)) { const result: IPolicyDocument[] = []; for (const doc of event.data.data) { - const newVC = await this.process(doc, ref, event?.user?.userId); + const newVC = await this.process(doc, ref, event?.user?.userId, event.user); result.push(newVC) } event.data.data = result; } else { - event.data.data = await this.process(event.data.data, ref, event?.user?.userId); + event.data.data = await this.process(event.data.data, ref, event?.user?.userId, event.user); } ref.triggerEvents(PolicyOutputEventType.RunEvent, event.user, event.data, event.actionStatus); diff --git a/policy-service/src/policy-engine/blocks/mint-block.ts b/policy-service/src/policy-engine/blocks/mint-block.ts index 444a80d043..eaac4f1caa 100644 --- a/policy-service/src/policy-engine/blocks/mint-block.ts +++ b/policy-service/src/policy-engine/blocks/mint-block.ts @@ -52,15 +52,16 @@ export class MintBlock { * @param docs * @private */ - private async getToken(ref: AnyBlockType, docs: IPolicyDocument[]): Promise { + private async getToken(ref: AnyBlockType, docs: IPolicyDocument[], user?: PolicyUser): Promise { let token: TokenCollection; - if (ref.options.useTemplate) { + const options = ref.getOptions(user); + if (options.useTemplate) { if (docs[0].tokens) { - const tokenId = docs[0].tokens[ref.options.template]; + const tokenId = docs[0].tokens[options.template]; token = await ref.databaseServer.getToken(tokenId, ref.dryRun); } } else { - token = await ref.databaseServer.getToken(ref.options.tokenId); + token = await ref.databaseServer.getToken(options.tokenId); } if (!token) { throw new BlockActionError('Bad token id', ref.blockType, ref.uuid); @@ -74,11 +75,12 @@ export class MintBlock { * @param docs * @private */ - private getObjects(ref: AnyBlockType, docs: IPolicyDocument[]): any { + private getObjects(ref: AnyBlockType, docs: IPolicyDocument[], user?: PolicyUser): any { const vcs: VcDocument[] = []; const messages: string[] = []; const topics: string[] = []; - const field = ref.options.accountId || 'default'; + const options = ref.getOptions(user); + const field = options.accountId || 'default'; const accounts: string[] = []; for (const doc of docs) { if (doc.signature === DocumentSignature.INVALID) { @@ -130,15 +132,17 @@ export class MintBlock { docs: IPolicyDocument[], accounts: string[], relayerAccount: string, - userId: string | null + userId: string | null, + user?: PolicyUser ): string { let targetAccount: string; - if (ref.options.accountType !== 'custom-value') { + const options = ref.getOptions(user); + if (options.accountType !== 'custom-value') { const firstAccounts = accounts[0]; if (accounts.find(a => a !== firstAccounts)) { ref.error(`More than one account found! Transfer made on the first (${firstAccounts})`); } - if (ref.options.accountId) { + if (options.accountId) { targetAccount = firstAccounts; } else { targetAccount = relayerAccount; @@ -147,7 +151,7 @@ export class MintBlock { throw new BlockActionError('Token recipient is not set', ref.blockType, ref.uuid); } } else { - targetAccount = ref.options.accountIdValue; + targetAccount = options.accountIdValue; } return targetAccount; } @@ -288,11 +292,11 @@ export class MintBlock { actionStatus: RecordActionStep ): Promise<[IPolicyDocument, number]> { const ref = PolicyComponentsUtils.GetBlockRef(this); - + const options = ref.getOptions(user); const tags = await PolicyUtils.getBlockTags(ref); const uuid: string = await ref.components.generateUUID(); - const amount = PolicyUtils.aggregate(ref.options.rule, documents); + const amount = PolicyUtils.aggregate(options.rule, documents); if (Number.isNaN(amount) || !Number.isFinite(amount) || amount < 0) { throw new BlockActionError(`Invalid token value: ${amount}`, ref.blockType, ref.uuid); } @@ -390,7 +394,7 @@ export class MintBlock { const savedVp = await ref.databaseServer.saveVP(vpDocument); // #endregion - const transactionMemo = `${vpMessageId} ${MessageMemo.parseMemo(true, ref.options.memo, savedVp)}`.trimEnd(); + const transactionMemo = `${vpMessageId} ${MessageMemo.parseMemo(true, options.memo, savedVp)}`.trimEnd(); await MintService.mint({ ref, token, @@ -507,13 +511,13 @@ export class MintBlock { additionalDocs: IPolicyDocument[], userId: string | null ) { - const token = await this.getToken(ref, docs); - const { vcs, messages, topics, accounts } = this.getObjects(ref, docs); + const token = await this.getToken(ref, docs, user); + const { vcs, messages, topics, accounts } = this.getObjects(ref, docs, event.user); const additionalMessages = this.getAdditionalMessages(additionalDocs); const topicId = topics[0]; const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, docs[0], userId); - const targetAccount = this.getAccount(ref, docs, accounts, relayerAccount, userId); + const targetAccount = this.getAccount(ref, docs, accounts, relayerAccount, userId, event.user); const [vp, amount] = await this.mintProcessing( token, diff --git a/policy-service/src/policy-engine/blocks/module.ts b/policy-service/src/policy-engine/blocks/module.ts index 043250334e..4381ee173b 100644 --- a/policy-service/src/policy-engine/blocks/module.ts +++ b/policy-service/src/policy-engine/blocks/module.ts @@ -100,11 +100,13 @@ export class ModuleBlock { */ private _getVariable(name: any, type: string): any { const ref = PolicyComponentsUtils.GetBlockRef(this); - if (Array.isArray(ref.options.variables)) { - for (const variable of ref.options.variables) { + const options = ref.getOptions(); + + if (Array.isArray(options.variables)) { + for (const variable of options.variables) { if (type) { if (name === variable.name && variable.type === type) { - return ref.options[variable.name]; + return options[variable.name]; } } else { if (name === variable.name) { diff --git a/policy-service/src/policy-engine/blocks/multi-sign-block.ts b/policy-service/src/policy-engine/blocks/multi-sign-block.ts index 6f1b561dca..a9a2a270c6 100644 --- a/policy-service/src/policy-engine/blocks/multi-sign-block.ts +++ b/policy-service/src/policy-engine/blocks/multi-sign-block.ts @@ -50,7 +50,8 @@ enum DocumentStatus { label: 'Threshold (%)', title: 'Number of signatures required to move to the next step, as a percentage of the total number of users in the group.', type: PropertyType.Input, - default: '50' + default: '50', + editable: true }] }, variables: [] @@ -108,6 +109,8 @@ export class MultiSignBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -116,9 +119,9 @@ export class MultiSignBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - type: ref.options.type, - uiMetaData: ref.options.uiMetaData, - user: ref.options.user + type: options.type, + uiMetaData: options.uiMetaData, + user: options.user } return data; } @@ -130,6 +133,8 @@ export class MultiSignBlock { */ async setData(user: PolicyUser, blockData: any, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const { status, document } = blockData; const documentId = document.id; const sourceDoc = await ref.databaseServer.getVcDocument(documentId); @@ -183,7 +188,7 @@ export class MultiSignBlock { ); const users = await ref.databaseServer.getAllUsersByRole(ref.policyId, user.group, user.role); - await this.updateThreshold(users, sourceDoc, documentId, user, user.userId, actionStatus); + await this.updateThreshold(users, sourceDoc, documentId, user, user.userId, actionStatus, user); await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, user, null, actionStatus); @@ -207,9 +212,12 @@ export class MultiSignBlock { documentId: string, currentUser: PolicyUser, userId: string | null, - actionStatus: RecordActionStep + actionStatus: RecordActionStep, + user?: PolicyUser ) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const data = await ref.databaseServer.getMultiSignDocuments(ref.uuid, documentId, currentUser.group); let signed = 0; @@ -222,7 +230,7 @@ export class MultiSignBlock { } } - const signedThreshold = Math.ceil(users.length * ref.options.threshold / 100); + const signedThreshold = Math.ceil(users.length * options.threshold / 100); const declinedThreshold = Math.round(users.length - signedThreshold + 1); if (signed >= signedThreshold) { @@ -314,6 +322,8 @@ export class MultiSignBlock { */ private async getDocumentStatus(document: IPolicyDocument, user: PolicyUser) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const confirmationDocument = await ref.databaseServer.getMultiSignStatus(ref.uuid, document.id); const data: any[] = await ref.databaseServer.getMultiSignDocuments(ref.uuid, document.id, user.group); const users = await ref.databaseServer.getAllUsersByRole(ref.policyId, user.group, user.role); @@ -338,7 +348,7 @@ export class MultiSignBlock { confirmationStatus = confirmationDocument.status; } - const threshold = ref.options.threshold; + const threshold = options.threshold; const total = users.length; const signedThreshold = Math.ceil(users.length * threshold / 100); const declinedThreshold = Math.round(users.length - signedThreshold + 1); @@ -371,7 +381,7 @@ export class MultiSignBlock { for (const document of documents) { const documentId = document.documentId; const vc = await ref.databaseServer.getVcDocument(documentId); - await this.updateThreshold(users, vc, documentId, event.target, event?.user?.userId, event.actionStatus); + await this.updateThreshold(users, vc, documentId, event.target, event?.user?.userId, event.actionStatus, event.user); } await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, null, null, event.actionStatus); PolicyComponentsUtils.ExternalEventFn(new ExternalEvent(ExternalEventType.DeleteMember, ref, event.target, null)); diff --git a/policy-service/src/policy-engine/blocks/notification.block.ts b/policy-service/src/policy-engine/blocks/notification.block.ts index 2fe80d67a0..c1d6194452 100644 --- a/policy-service/src/policy-engine/blocks/notification.block.ts +++ b/policy-service/src/policy-engine/blocks/notification.block.ts @@ -28,6 +28,7 @@ import { NotificationType, UserOption, } from '@guardian/interfaces'; +import { PolicyUser } from '@policy-engine/policy-user.js'; /** * Notification block @@ -52,6 +53,7 @@ import { title: 'Title', type: PropertyType.Input, required: true, + editable: true }, { name: 'message', @@ -59,12 +61,14 @@ import { title: 'Message', type: PropertyType.Input, required: true, + editable: true }, { name: 'type', label: 'Type', title: 'Type', type: PropertyType.Select, + editable: true, items: [ { label: 'Info', @@ -90,12 +94,14 @@ import { label: 'Link notification to policy', title: 'Link notification to policy', type: PropertyType.Checkbox, + editable: true }, { name: 'user', label: 'User', title: 'User', type: PropertyType.Select, + editable: true, items: [ { label: 'All', @@ -136,6 +142,7 @@ import { items: SelectItemType.Roles, visible: 'user === "ROLE"', required: true, + editable: true }, { name: 'grouped', @@ -143,6 +150,7 @@ import { title: 'Only for current user group', type: PropertyType.Checkbox, visible: 'user === "ROLE"', + editable: true }, ], }, @@ -154,10 +162,13 @@ export class NotificationBlock { * @returns Function */ private getNotificationFunction( - ref: any + ref: any, + user: PolicyUser ): (title: string, message: string, userId: string) => void { let fn; - switch (ref.options.type) { + const options = ref.getOptions(user); + + switch (options.type) { case NotificationType.INFO: fn = NotificationHelper.info; break; @@ -175,7 +186,7 @@ export class NotificationBlock { } let notify = fn; - if (ref.options.link) { + if (options.link) { notify = async (title: string, message: string, userId: string) => await fn( title, @@ -199,9 +210,11 @@ export class NotificationBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); - const notify = this.getNotificationFunction(ref); + const options = ref.getOptions(event.user); + + const notify = this.getNotificationFunction(ref, event.user); - switch (ref.options.user) { + switch (options.user) { case UserOption.ALL: { if (!ref.dryRun) { const policyUsers = @@ -213,8 +226,8 @@ export class NotificationBlock { ); for (const user of users) { await notify( - ref.options.title, - ref.options.message, + options.title, + options.message, user.id ); } @@ -224,8 +237,8 @@ export class NotificationBlock { if (event.user.did !== ref.policyOwner && !ref.dryRun) { const user = await PolicyUtils.getUser(ref, event.user.did, event?.user?.userId); await notify( - ref.options.title, - ref.options.message, + options.title, + options.message, user.id ); break; @@ -237,7 +250,7 @@ export class NotificationBlock { case UserOption.ALL: case UserOption.POLICY_OWNER: { const owner = await new Users().getUserById(ref.policyOwner, event?.user?.userId); - await notify(ref.options.title, ref.options.message, owner.id); + await notify(options.title, options.message, owner.id); break; } case UserOption.DOCUMENT_OWNER: { @@ -250,8 +263,8 @@ export class NotificationBlock { ); if (user.did === ref.policyOwner || !ref.dryRun) { await notify( - ref.options.title, - ref.options.message, + options.title, + options.message, user.id ); } @@ -267,8 +280,8 @@ export class NotificationBlock { ); if (user.did === ref.policyOwner || !ref.dryRun) { await notify( - ref.options.title, - ref.options.message, + options.title, + options.message, user.id ); } @@ -283,8 +296,8 @@ export class NotificationBlock { const owner = await PolicyUtils.getUser(ref, role.owner, event?.user?.userId); if (owner.did === ref.policyOwner || !ref.dryRun) { await notify( - ref.options.title, - ref.options.message, + options.title, + options.message, owner.id ); } @@ -292,15 +305,15 @@ export class NotificationBlock { break; } case UserOption.ROLE: { - let policyUsers = ref.options.grouped + let policyUsers = options.grouped ? await ref.databaseServer.getAllUsersByRole( ref.policyId, event.user.group, - ref.options.role + options.role ) : await ref.databaseServer.getUsersByRole( ref.policyId, - ref.options.role + options.role ); policyUsers = ref.dryRun ? policyUsers.filter((pu) => pu.did === ref.policyOwner) @@ -310,8 +323,8 @@ export class NotificationBlock { ); for (const user of users) { await notify( - ref.options.title, - ref.options.message, + options.title, + options.message, user.id ); } diff --git a/policy-service/src/policy-engine/blocks/policy-roles.ts b/policy-service/src/policy-engine/blocks/policy-roles.ts index cece849afd..54a0eeae70 100644 --- a/policy-service/src/policy-engine/blocks/policy-roles.ts +++ b/policy-service/src/policy-engine/blocks/policy-roles.ts @@ -371,8 +371,10 @@ export class PolicyRolesBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const roles: string[] = Array.isArray(ref.options.roles) ? ref.options.roles : []; - const groups: string[] = Array.isArray(ref.options.groups) ? ref.options.groups : []; + const options = ref.getOptions(user); + + const roles: string[] = Array.isArray(options.roles) ? options.roles : []; + const groups: string[] = Array.isArray(options.groups) ? options.groups : []; const policyGroups = PolicyUtils.getGroupTemplates(ref); const groupMap = {}; for (const item of policyGroups) { @@ -395,7 +397,7 @@ export class PolicyRolesBlock { groups, groupMap, isMultipleGroups: policyGroups.length > 0, - uiMetaData: ref.options.uiMetaData + uiMetaData: options.uiMetaData } } diff --git a/policy-service/src/policy-engine/blocks/reassigning.block.ts b/policy-service/src/policy-engine/blocks/reassigning.block.ts index 076ae67785..b4154e15ad 100644 --- a/policy-service/src/policy-engine/blocks/reassigning.block.ts +++ b/policy-service/src/policy-engine/blocks/reassigning.block.ts @@ -64,16 +64,17 @@ export class ReassigningBlock { actor: PolicyUser }> { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const owner: PolicyUser = await PolicyUtils.getDocumentOwner(ref, document, userId); const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, document, user.userId); let groupContext: any; let issuer: string; - if (ref.options.issuer === 'owner') { + if (options.issuer === 'owner') { const cred = await PolicyUtils.getUserCredentials(ref, document.owner, userId); issuer = cred.did; groupContext = await PolicyUtils.getGroupContext(ref, owner); - } else if (ref.options.issuer === 'policyOwner') { + } else if (options.issuer === 'policyOwner') { const cred = await PolicyUtils.getUserCredentials(ref, ref.policyOwner, userId); issuer = cred.did; groupContext = null; @@ -84,9 +85,9 @@ export class ReassigningBlock { } let actor: PolicyUser; - if (ref.options.actor === 'owner') { + if (options.actor === 'owner') { actor = await PolicyUtils.getDocumentOwner(ref, document, userId); - } else if (ref.options.actor === 'issuer') { + } else if (options.actor === 'issuer') { actor = await PolicyUtils.getPolicyUser(ref, issuer, document.group, userId); } else { actor = user; diff --git a/policy-service/src/policy-engine/blocks/report-block.ts b/policy-service/src/policy-engine/blocks/report-block.ts index 7ce4f2816f..d65815407d 100644 --- a/policy-service/src/policy-engine/blocks/report-block.ts +++ b/policy-service/src/policy-engine/blocks/report-block.ts @@ -37,11 +37,13 @@ import { FilterObject } from '@mikro-orm/core'; label: 'UI', title: 'UI Properties', type: PropertyType.Group, + editable: true, properties: [{ name: 'vpSectionHeader', label: 'VP section header', title: 'VP section header', - type: PropertyType.Input + type: PropertyType.Input, + editable: true } ] }] @@ -434,6 +436,8 @@ export class ReportBlock { */ async getData(user: PolicyUser, uuid: string): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + try { const blockState = this.state[user.id] || {}; if (!blockState.lastValue) { @@ -446,7 +450,7 @@ export class ReportBlock { user.location === LocationType.REMOTE ), hash: null, - uiMetaData: ref.options.uiMetaData, + uiMetaData: options.uiMetaData, data: null }; } @@ -505,7 +509,7 @@ export class ReportBlock { for (const reportItem of reportItems) { const [documentsNotFound] = await reportItem.run( documents, - variables + variables, ); if (documentsNotFound) { break; @@ -528,7 +532,7 @@ export class ReportBlock { user.location === LocationType.REMOTE ), hash, - uiMetaData: ref.options.uiMetaData, + uiMetaData: options.uiMetaData, data: report }; } catch (error) { diff --git a/policy-service/src/policy-engine/blocks/report-item-block.ts b/policy-service/src/policy-engine/blocks/report-item-block.ts index 6c37347054..5e5dc7c498 100644 --- a/policy-service/src/policy-engine/blocks/report-item-block.ts +++ b/policy-service/src/policy-engine/blocks/report-item-block.ts @@ -58,20 +58,22 @@ export class ReportItemBlock { */ public async run( resultFields: IReportItem[], - variables: any + variables: any, ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const icon = ref.options.icon; - const title = ref.options.title; - const description = ref.options.description; - const visible = ref.options.visible; - const iconType = ref.options.iconType; - const multiple = ref.options.multiple; - const dynamicFilters = ref.options.dynamicFilters; + const options = ref.getOptions(); + + const icon = options.icon; + const title = options.title; + const description = options.description; + const visible = options.visible; + const iconType = options.iconType; + const multiple = options.multiple; + const dynamicFilters = options.dynamicFilters; const filtersToVc: any = {}; - if (ref.options.filters) { - for (const filter of ref.options.filters) { + if (options.filters) { + for (const filter of options.filters) { let expr: any; if (filter.typeValue === 'value') { expr = filter.value; @@ -149,8 +151,8 @@ export class ReportItemBlock { item.document = vcDocument; } - if (ref.options.variables) { - for (const variable of ref.options.variables) { + if (options.variables) { + for (const variable of options.variables) { const findOptionsResult = findOptions(vcDocument, variable.value); if (multiple) { variables[variable.name] = variables[variable.name] || [] diff --git a/policy-service/src/policy-engine/blocks/request-vc-document-block-addon.ts b/policy-service/src/policy-engine/blocks/request-vc-document-block-addon.ts index 7dd1e71290..6fb78251f0 100644 --- a/policy-service/src/policy-engine/blocks/request-vc-document-block-addon.ts +++ b/policy-service/src/policy-engine/blocks/request-vc-document-block-addon.ts @@ -140,6 +140,8 @@ export class RequestVcDocumentBlockAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); + const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -148,7 +150,7 @@ export class RequestVcDocumentBlockAddon { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - ...ref.options, + ...options, schema: { ...this._schema, fields: [], conditions: [] }, }; return data; @@ -185,6 +187,7 @@ export class RequestVcDocumentBlockAddon { ); } const document = _data.document; + const options = ref.getOptions(user); const disposeTables = await hydrateTablesInObject( document, @@ -198,7 +201,8 @@ export class RequestVcDocumentBlockAddon { const presetCheck = await this.checkPreset( ref, document, - documentRef + documentRef, + user ); if (!presetCheck.valid) { throw new BlockActionError( @@ -211,8 +215,8 @@ export class RequestVcDocumentBlockAddon { SchemaHelper.updateObjectContext(this._schema, document); const _vcHelper = new VcHelper(); - const idType = ref.options.idType; - const forceRelayerAccount = ref.options.forceRelayerAccount; + const idType = options.idType; + const forceRelayerAccount = options.forceRelayerAccount; const inheritRelayerAccount = PolicyComponentsUtils.IsInheritRelayerAccount(ref.policyId, forceRelayerAccount); //Relayer Account @@ -273,7 +277,7 @@ export class RequestVcDocumentBlockAddon { PolicyUtils.setDocumentTags(item, tags); const accounts = PolicyUtils.getHederaAccounts(vc, relayerAccount, this._schema); - const schemaIRI = ref.options.schema; + const schemaIRI = options.schema; item.type = schemaIRI; item.schema = schemaIRI; item.accounts = accounts; @@ -303,14 +307,17 @@ export class RequestVcDocumentBlockAddon { private async checkPreset( ref: AnyBlockType, document: any, - documentRef: VcDocumentCollection + documentRef: VcDocumentCollection, + user?: PolicyUser ): Promise { + const options = ref.getOptions(user); + if ( - ref.options.presetFields && - ref.options.presetFields.length && - ref.options.presetSchema + options.presetFields && + options.presetFields.length && + options.presetSchema ) { - const readonly = ref.options.presetFields.filter( + const readonly = options.presetFields.filter( (item: any) => item.readonly && item.value ); if (!readonly.length || !document || !documentRef) { diff --git a/policy-service/src/policy-engine/blocks/request-vc-document-block.ts b/policy-service/src/policy-engine/blocks/request-vc-document-block.ts index b7499a7e31..a1ab34ea86 100644 --- a/policy-service/src/policy-engine/blocks/request-vc-document-block.ts +++ b/policy-service/src/policy-engine/blocks/request-vc-document-block.ts @@ -193,13 +193,14 @@ export class RequestVcDocumentBlock { private async setBlockData(user: PolicyUser, data: IPolicyDocument, actionStatus: RecordActionStep) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); try { //Prepare data const document = await this.prepareDocument(data); const draft = data.draft; const draftId = data.draftId; - const editType = ref.options.editType; - const forceRelayerAccount = ref.options.forceRelayerAccount; + const editType = options.editType; + const forceRelayerAccount = options.forceRelayerAccount; const inheritRelayerAccount = PolicyComponentsUtils.IsInheritRelayerAccount(ref.policyId, forceRelayerAccount); const documentRef = await this.getRelationships(ref, data.ref); @@ -220,7 +221,7 @@ export class RequestVcDocumentBlock { } //Validate preset - const presetCheck = await this.checkPreset(ref, document, documentRef) + const presetCheck = await this.checkPreset(ref, document, documentRef, user); if (!presetCheck.valid) { throw new BlockActionError( JSON.stringify(presetCheck.error), @@ -325,14 +326,17 @@ export class RequestVcDocumentBlock { private async checkPreset( ref: AnyBlockType, document: any, - documentRef: VcDocumentCollection + documentRef: VcDocumentCollection, + user?: PolicyUser ): Promise { + const options = ref.getOptions(user); + if ( - ref.options.presetFields && - ref.options.presetFields.length && - ref.options.presetSchema + options.presetFields && + options.presetFields.length && + options.presetSchema ) { - const readonly = ref.options.presetFields.filter( + const readonly = options.presetFields.filter( (item: any) => item.readonly && item.value ); if (!readonly.length || !document || !documentRef) { @@ -398,11 +402,11 @@ export class RequestVcDocumentBlock { actionStatusId: string, ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - + const options = ref.getOptions(user); SchemaHelper.updateObjectContext(this._schema, document); const _vcHelper = new VcHelper(); - const idType = ref.options.idType; + const idType = options.idType; const credentialSubject = document; credentialSubject.policyId = ref.policyId; diff --git a/policy-service/src/policy-engine/blocks/retirement-block.ts b/policy-service/src/policy-engine/blocks/retirement-block.ts index b20406f59b..56fe88841c 100644 --- a/policy-service/src/policy-engine/blocks/retirement-block.ts +++ b/policy-service/src/policy-engine/blocks/retirement-block.ts @@ -121,6 +121,7 @@ export class RetirementBlock { actionStatus: RecordActionStep ): Promise<[IPolicyDocument, number]> { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const tags = await PolicyUtils.getBlockTags(ref); @@ -134,7 +135,7 @@ export class RetirementBlock { let tokenValue: number = 0; let tokenAmount: string = '0'; if (token.tokenType === TokenType.NON_FUNGIBLE) { - const exprOpt = ref.options.serialNumbersExpression; + const exprOpt = options.serialNumbersExpression; if (!exprOpt || !String(exprOpt).trim()) { throw new Error('For NON_FUNGIBLE tokens, Serial numbers is required'); } @@ -186,14 +187,14 @@ export class RetirementBlock { } } else if (token.tokenType === TokenType.FUNGIBLE) { - const ruleOpt = ref.options.rule + const ruleOpt = options.rule const hasRule = ruleOpt !== null && ruleOpt !== undefined && (typeof ruleOpt !== 'string' || ruleOpt.trim() !== ''); if (!hasRule) { throw new Error('For FUNGIBLE tokens, Rule is required'); } - const amount = PolicyUtils.aggregate(ref.options.rule, documents); + const amount = PolicyUtils.aggregate(options.rule, documents); [tokenValue, tokenAmount] = PolicyUtils.tokenAmount(token, amount); } @@ -290,15 +291,17 @@ export class RetirementBlock { * @param docs * @private */ - private async getToken(ref: AnyBlockType, docs: IPolicyDocument[]): Promise { + private async getToken(ref: AnyBlockType, docs: IPolicyDocument[], user?: PolicyUser): Promise { let token: TokenCollection; - if (ref.options.useTemplate) { + const options = ref.getOptions(user); + + if (options.useTemplate) { if (docs[0].tokens) { - const tokenId = docs[0].tokens[ref.options.template]; + const tokenId = docs[0].tokens[options.template]; token = await ref.databaseServer.getToken(tokenId, ref.dryRun); } } else { - token = await ref.databaseServer.getToken(ref.options.tokenId); + token = await ref.databaseServer.getToken(options.tokenId); } if (!token) { throw new BlockActionError('Bad token id', ref.blockType, ref.uuid); @@ -322,12 +325,14 @@ export class RetirementBlock { async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); + let options = ref.getOptions(event.user); + const docs = PolicyUtils.getArray(event.data.data); if (!docs.length && docs[0]) { throw new BlockActionError('Bad VC', ref.blockType, ref.uuid); } - const token = await this.getToken(ref, docs); + const token = await this.getToken(ref, docs, event.user); if (!token) { throw new BlockActionError('Bad token id', ref.blockType, ref.uuid); } @@ -340,7 +345,7 @@ export class RetirementBlock { const vcs: VcDocument[] = []; const vsMessages: string[] = []; const topicIds: string[] = []; - const field = ref.options.accountId || 'default'; + const field = options.accountId || 'default'; const accounts: string[] = []; for (const doc of docs) { if (doc.signature === DocumentSignature.INVALID) { @@ -368,7 +373,7 @@ export class RetirementBlock { const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, docs[0], event?.user?.userId); let targetAccount: string; - if (ref.options.accountId) { + if (options.accountId) { targetAccount = firstAccounts; } else { targetAccount = relayerAccount; diff --git a/policy-service/src/policy-engine/blocks/revocation-block.ts b/policy-service/src/policy-engine/blocks/revocation-block.ts index 6bc542a9ab..21a5f59a6a 100644 --- a/policy-service/src/policy-engine/blocks/revocation-block.ts +++ b/policy-service/src/policy-engine/blocks/revocation-block.ts @@ -40,6 +40,7 @@ export const RevokedStatus = 'Revoked'; title: 'Update previous document status', type: PropertyType.Checkbox, default: false, + editable: true }, { name: 'prevDocStatus', @@ -47,6 +48,7 @@ export const RevokedStatus = 'Revoked'; title: 'Status value', type: PropertyType.Input, default: '', + editable: true }, ], }, @@ -133,6 +135,8 @@ export class RevocationBlock { async runAction(event: IPolicyEvent): Promise { const userId = event?.user?.userId; const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(event.user); + const data = event.data.data; const doc = Array.isArray(data) ? data[0] : data; @@ -197,11 +201,11 @@ export class RevocationBlock { } } - if (ref.options.updatePrevDoc && doc.relationships) { + if (options.updatePrevDoc && doc.relationships) { const prevDocs = await this.findDocumentByMessageIds(doc.relationships); const prevDocument = prevDocs[prevDocs.length - 1]; if (prevDocument) { - prevDocument.option.status = ref.options.prevDocStatus; + prevDocument.option.status = options.prevDocStatus; await PolicyUtils.updateVC(ref, prevDocument, userId); await PolicyUtils.saveDocumentState(ref, prevDocument); } diff --git a/policy-service/src/policy-engine/blocks/revoke-block.ts b/policy-service/src/policy-engine/blocks/revoke-block.ts index 591f83c1fd..28ab78a09e 100644 --- a/policy-service/src/policy-engine/blocks/revoke-block.ts +++ b/policy-service/src/policy-engine/blocks/revoke-block.ts @@ -118,7 +118,8 @@ export class RevokeBlock { async runAction(event: IPolicyEvent): Promise { const userId = event?.user?.userId; const ref = PolicyComponentsUtils.GetBlockRef(this); - const uiMetaData = ref.options.uiMetaData; + const options = ref.getOptions(event.user); + const uiMetaData = options.uiMetaData; const data = event.data.data; const doc = Array.isArray(data) ? data[0] : data; diff --git a/policy-service/src/policy-engine/blocks/selective-attributes-addon.ts b/policy-service/src/policy-engine/blocks/selective-attributes-addon.ts index c3f18f45c9..216da80604 100644 --- a/policy-service/src/policy-engine/blocks/selective-attributes-addon.ts +++ b/policy-service/src/policy-engine/blocks/selective-attributes-addon.ts @@ -23,6 +23,7 @@ import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-abo label: 'Attributes To Select', title: 'Attributes To Select', type: PropertyType.Array, + editable: true, items: { label: 'Attribute Path', value: '@attributePath', @@ -30,7 +31,8 @@ import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-abo name: 'attributePath', label: 'Attribute Path', title: 'Attribute Path', - type: PropertyType.Input + type: PropertyType.Input, + editable: true }] } }] diff --git a/policy-service/src/policy-engine/blocks/send-to-guardian-block.ts b/policy-service/src/policy-engine/blocks/send-to-guardian-block.ts index 0e673b20b6..a4450ad788 100644 --- a/policy-service/src/policy-engine/blocks/send-to-guardian-block.ts +++ b/policy-service/src/policy-engine/blocks/send-to-guardian-block.ts @@ -12,6 +12,7 @@ import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfac import { DocumentType } from '../interfaces/document.type.js'; import { FilterQuery } from '@mikro-orm/core'; import { PolicyActionsUtils } from '../policy-actions/utils.js'; +import { PolicyUser } from '@policy-engine/policy-user.js'; /** * Document Operations @@ -172,8 +173,11 @@ export class SendToGuardianBlock { document: IPolicyDocument, operation: Operation, ref: AnyBlockType, - userId: string | null + userId: string | null, + user?: PolicyUser ): Promise { + const options = ref.getOptions(user); + let old = await this.getVCRecord(document, operation, ref); if (old) { if (!document.draft) { @@ -190,7 +194,7 @@ export class SendToGuardianBlock { delete document._id; old = await PolicyUtils.saveVC(ref, document, userId); } - if (!ref.options.skipSaveState) { + if (!options.skipSaveState) { await PolicyUtils.saveDocumentState(ref, old); } return old; @@ -363,14 +367,17 @@ export class SendToGuardianBlock { private async sendByType( document: IPolicyDocument, ref: AnyBlockType, - userId: string | null + userId: string | null, + user?: PolicyUser ): Promise { + const options = ref.getOptions(user); + document.documentFields = Array.from( PolicyComponentsUtils.getDocumentCacheFields(ref.policyId) ); - switch (ref.options.dataType) { + switch (options.dataType) { case 'vc-documents': { - return await this.updateVCRecord(document, Operation.auto, ref, userId); + return await this.updateVCRecord(document, Operation.auto, ref, userId, user); } case 'did-documents': { return await this.updateDIDRecord(document, Operation.auto, ref); @@ -379,7 +386,7 @@ export class SendToGuardianBlock { return await this.updateApprovalRecord(document, Operation.auto, ref); } default: - throw new BlockActionError(`dataType "${ref.options.dataType}" is unknown`, ref.blockType, ref.uuid) + throw new BlockActionError(`dataType "${options.dataType}" is unknown`, ref.blockType, ref.uuid) } } @@ -393,7 +400,8 @@ export class SendToGuardianBlock { document: IPolicyDocument, type: DocumentType, ref: AnyBlockType, - userId: string | null + userId: string | null, + user?: PolicyUser ): Promise { const operation: Operation = Operation.auto; document.documentFields = Array.from( @@ -404,7 +412,7 @@ export class SendToGuardianBlock { if (type === DocumentType.DID) { return await this.updateDIDRecord(document, operation, ref); } else if (type === DocumentType.VerifiableCredential) { - return await this.updateVCRecord(document, operation, ref, userId); + return await this.updateVCRecord(document, operation, ref, userId, user); } else if (type === DocumentType.VerifiablePresentation) { return await this.updateVPRecord(document, operation, ref); } @@ -446,17 +454,20 @@ export class SendToGuardianBlock { document: IPolicyDocument, message: Message, ref: AnyBlockType, - userId: string | null + userId: string | null, + user?: PolicyUser ): Promise { try { - const memo = MessageMemo.parseMemo(true, ref.options.memo, document); + const options = ref.getOptions(user); + + const memo = MessageMemo.parseMemo(true, options.memo, document); message.setMemo(memo); - const topicOwner = this.getTopicOwner(ref, document, ref.options.topicOwner); + const topicOwner = this.getTopicOwner(ref, document, options.topicOwner); const relayerAccount = document.owner === topicOwner ? document.relayerAccount : null; const topic = await PolicyActionsUtils.getOrCreateTopic({ ref, - name: ref.options.topic, + name: options.topic, owner: topicOwner, relayerAccount, memoObj: document, @@ -491,8 +502,10 @@ export class SendToGuardianBlock { private async documentSender( document: IPolicyDocument, userId: string | null, + user?: PolicyUser ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const type = PolicyUtils.getDocumentType(document); const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, document, userId); const owner = await PolicyUtils.getUserByIssuer(ref, document, userId); @@ -545,13 +558,13 @@ export class SendToGuardianBlock { document.tag = ref.tag; document.relayerAccount = relayerAccount; document.option = Object.assign({}, document.option); - if (ref.options.options) { - for (const option of ref.options.options) { + if (options.options) { + for (const option of options.options) { document.option[option.name] = option.value; } } - if (ref.options.entityType) { - document.type = ref.options.entityType; + if (options.entityType) { + document.type = options.entityType; } // @@ -559,31 +572,31 @@ export class SendToGuardianBlock { // const hash = docObject.toCredentialHash(); const messageHash = message.toHash(); - if (ref.options.dataType) { - if (ref.options.dataType === 'hedera') { - document = await this.sendToHedera(document, message, ref, userId); + if (options.dataType) { + if (options.dataType === 'hedera') { + document = await this.sendToHedera(document, message, ref, userId, user); document.messageHash = messageHash; document = await this.updateMessage(document, type, ref, userId); } else { document.hash = hash; - document = await this.sendByType(document, ref, userId); + document = await this.sendByType(document, ref, userId, user); } - } else if (ref.options.dataSource === 'auto' || !ref.options.dataSource) { + } else if (options.dataSource === 'auto' || !options.dataSource) { if (document.messageHash !== messageHash) { - document = await this.sendToHedera(document, message, ref, userId); + document = await this.sendToHedera(document, message, ref, userId, user); document.messageHash = messageHash; } document.hash = hash; - document = await this.sendToDatabase(document, type, ref, userId); - } else if (ref.options.dataSource === 'database') { + document = await this.sendToDatabase(document, type, ref, userId, user); + } else if (options.dataSource === 'database') { document.hash = hash; - document = await this.sendToDatabase(document, type, ref, userId); - } else if (ref.options.dataSource === 'hedera') { - document = await this.sendToHedera(document, message, ref, userId); + document = await this.sendToDatabase(document, type, ref, userId, user); + } else if (options.dataSource === 'hedera') { + document = await this.sendToHedera(document, message, ref, userId, user); document.messageHash = messageHash; document = await this.updateMessage(document, type, ref, userId); } else { - throw new BlockActionError(`dataSource "${ref.options.dataSource}" is unknown`, ref.blockType, ref.uuid); + throw new BlockActionError(`dataSource "${options.dataSource}" is unknown`, ref.blockType, ref.uuid); } return document; } @@ -621,6 +634,7 @@ export class SendToGuardianBlock { @CatchErrors() async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(event.user); ref.log(`runAction`); const tags = await PolicyUtils.getBlockTags(ref); @@ -630,13 +644,13 @@ export class SendToGuardianBlock { const newDocs = []; for (const doc of docs) { PolicyUtils.setDocumentTags(doc, tags); - const newDoc = await this.documentSender(doc, event?.user?.userId); + const newDoc = await this.documentSender(doc, event?.user?.userId, event.user); newDocs.push(newDoc); } event.data.data = newDocs; } else { PolicyUtils.setDocumentTags(docs, tags); - event.data.data = await this.documentSender(docs, event?.user?.userId); + event.data.data = await this.documentSender(docs, event?.user?.userId, event.user); } const olds: IPolicyDocument | IPolicyDocument[] = event.data.old; @@ -653,7 +667,7 @@ export class SendToGuardianBlock { await ref.triggerEvents(PolicyOutputEventType.ReleaseEvent, event.user, null, event.actionStatus); await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, event.user, event.data, event.actionStatus); PolicyComponentsUtils.ExternalEventFn(new ExternalEvent(ExternalEventType.Run, ref, event.user, { - type: (ref.options.dataSource || ref.options.dataType), + type: (options.dataSource || options.dataType), documents: ExternalDocuments(event.data?.data), })); diff --git a/policy-service/src/policy-engine/blocks/set-relationships-block.ts b/policy-service/src/policy-engine/blocks/set-relationships-block.ts index 930b759a82..cc44c717d8 100644 --- a/policy-service/src/policy-engine/blocks/set-relationships-block.ts +++ b/policy-service/src/policy-engine/blocks/set-relationships-block.ts @@ -32,19 +32,22 @@ import { LocationType } from '@guardian/interfaces'; label: 'Include Accounts', title: 'Include Related Documents Accounts', type: PropertyType.Checkbox, - default: false + default: false, + editable: true }, { name: 'includeTokens', label: 'Include Tokens', title: 'Include Related Documents Tokens', type: PropertyType.Checkbox, - default: false + default: false, + editable: true }, { name: 'changeOwner', label: 'Change Owner', title: 'Change Document Owner', type: PropertyType.Checkbox, - default: false + default: false, + editable: true }] }, variables: [] @@ -59,6 +62,7 @@ export class SetRelationshipsBlock { }) async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(event.user); const data: IPolicyDocument[] = await ref.getSources(event.user); const owner = data[0] && data[0].owner || null; const group = data[0] && data[0].group || null; @@ -81,20 +85,20 @@ export class SetRelationshipsBlock { doc.relationships = doc.relationships ? doc.relationships.concat(relationships) : relationships; - if (ref.options.includeAccounts) { + if (options.includeAccounts) { doc.accounts = doc.accounts ? Object.assign(doc.accounts, accounts) : accounts; } - if (ref.options.includeTokens) { + if (options.includeTokens) { doc.tokens = doc.tokens ? Object.assign(doc.tokens, tokens) : tokens; } - if (owner && ref.options.changeOwner) { + if (owner && options.changeOwner) { doc.owner = owner; } - if (group && ref.options.changeOwner) { + if (group && options.changeOwner) { doc.group = group; } } @@ -102,24 +106,24 @@ export class SetRelationshipsBlock { documents.relationships = documents.relationships ? documents.relationships.concat(relationships) : relationships; - if (ref.options.includeAccounts) { + if (options.includeAccounts) { documents.accounts = Object.assign( {}, documents.accounts, accounts ); } - if (ref.options.includeTokens) { + if (options.includeTokens) { documents.tokens = Object.assign( {}, documents.tokens, tokens ); } - if (owner && ref.options.changeOwner) { + if (owner && options.changeOwner) { documents.owner = owner; } - if (group && ref.options.changeOwner) { + if (group && options.changeOwner) { documents.group = group; } } diff --git a/policy-service/src/policy-engine/blocks/split-block.ts b/policy-service/src/policy-engine/blocks/split-block.ts index 845ed9de72..118faea272 100644 --- a/policy-service/src/policy-engine/blocks/split-block.ts +++ b/policy-service/src/policy-engine/blocks/split-block.ts @@ -45,12 +45,14 @@ import { RecordActionStep } from '../record-action-step.js'; name: 'threshold', label: 'Threshold', title: 'Threshold', - type: PropertyType.Input + type: PropertyType.Input, + editable: true }, { name: 'sourceField', label: 'Source field', title: 'Source field', - type: PropertyType.Path + type: PropertyType.Path, + editable: true }] }, variables: [] @@ -88,9 +90,10 @@ export class SplitBlock { * @param ref * @param doc */ - private async calcDocValue(ref: IPolicyBlock, doc: IPolicyDocument): Promise { + private async calcDocValue(ref: IPolicyBlock, doc: IPolicyDocument, user?: PolicyUser): Promise { try { - const value = PolicyUtils.getObjectValue(doc, ref.options.sourceField); + const options = ref.getOptions(user); + const value = PolicyUtils.getObjectValue(doc, options.sourceField); return parseFloat(value); } catch (error) { return 0; @@ -120,9 +123,11 @@ export class SplitBlock { threshold: number, userId: string | null, actionStatusId: string, + user?: PolicyUser ): Promise { let clone = PolicyUtils.cloneVC(ref, document); - PolicyUtils.setObjectValue(clone, ref.options.sourceField, newValue); + const options = ref.getOptions(user); + PolicyUtils.setObjectValue(clone, options.sourceField, newValue); let vc = VcDocument.fromJsonTree(clone.document); if (document.messageId) { const evidenceSchema = await this.getSchema(); @@ -132,7 +137,7 @@ export class SplitBlock { vc.addEvidence({ type: ['SourceDocument'], messageId: document.messageId, - sourceField: ref.options.sourceField, + sourceField: options.sourceField, sourceValue, threshold, chunkNumber, @@ -174,8 +179,9 @@ export class SplitBlock { userId: string | null, actionStatusId: string ) { - const threshold = parseFloat(ref.options.threshold); - const value = await this.calcDocValue(ref, document); + const options = ref.getOptions(user); + const threshold = parseFloat(options.threshold); + const value = await this.calcDocValue(ref, document, user); let sum = 0; for (const item of residue) { @@ -192,7 +198,7 @@ export class SplitBlock { if (value < needed) { const maxChunks = 1; const newDoc = await this.createNewDoc( - ref, root, document, value, maxChunks, maxChunks, value, threshold, userId, actionStatusId + ref, root, document, value, maxChunks, maxChunks, value, threshold, userId, actionStatusId, user ); residue.push(ref.databaseServer.createResidue( ref.policyId, @@ -207,7 +213,7 @@ export class SplitBlock { const maxChunks = (count > 0 ? count : 0) + (end > 0 ? 1 : 0) + 1; const newDoc1 = await this.createNewDoc( - ref, root, document, needed, 1, maxChunks, value, threshold, userId, actionStatusId + ref, root, document, needed, 1, maxChunks, value, threshold, userId, actionStatusId, user ); residue.push(ref.databaseServer.createResidue( ref.policyId, @@ -222,7 +228,7 @@ export class SplitBlock { if (count > 0) { for (let i = 0; i < count; i++) { const newDocN = await this.createNewDoc( - ref, root, document, threshold, i + 2, maxChunks, value, threshold, userId, actionStatusId + ref, root, document, threshold, i + 2, maxChunks, value, threshold, userId, actionStatusId, user ); result.push([ref.databaseServer.createResidue( ref.policyId, @@ -235,7 +241,7 @@ export class SplitBlock { } if (end > 0) { const newDocL = await this.createNewDoc( - ref, root, document, end, maxChunks, maxChunks, value, threshold, userId, actionStatusId + ref, root, document, end, maxChunks, maxChunks, value, threshold, userId, actionStatusId, user ); residue.push(ref.databaseServer.createResidue( ref.policyId, diff --git a/policy-service/src/policy-engine/blocks/step-block.ts b/policy-service/src/policy-engine/blocks/step-block.ts index 301f688243..89abe5f821 100644 --- a/policy-service/src/policy-engine/blocks/step-block.ts +++ b/policy-service/src/policy-engine/blocks/step-block.ts @@ -35,23 +35,27 @@ import { RecordActionStep } from '../record-action-step.js'; name: 'cyclic', label: 'Cyclic', title: 'Restart the block when the final step is reached?', - type: PropertyType.Checkbox + type: PropertyType.Checkbox, + editable: true }, { name: 'finalBlocks', label: 'Final steps', title: 'Final steps', type: PropertyType.MultipleSelect, - items: SelectItemType.Children + items: SelectItemType.Children, + editable: true }, { name: 'uiMetaData', label: 'UI', title: 'UI Properties', type: PropertyType.Group, + editable: true, properties: [{ name: 'title', label: 'Title', title: 'Title', - type: PropertyType.Input + type: PropertyType.Input, + editable: true }] }] }, @@ -75,6 +79,7 @@ export class InterfaceStepBlock { this.state = {} const ref = PolicyComponentsUtils.GetBlockRef(this); + this.endIndexes[ref.children.length - 1] = true; if (ref.options?.finalBlocks && Array.isArray(ref.options.finalBlocks)) { for (const finalBlock of ref.options.finalBlocks) { @@ -95,6 +100,7 @@ export class InterfaceStepBlock { }) async changeStep(user: PolicyUser, data: any, target: IPolicyBlock, actionStatus: RecordActionStep) { const ref = PolicyComponentsUtils.GetBlockRef(this); + let blockState: any; if (!this.state.hasOwnProperty(user.id)) { blockState = {}; @@ -133,8 +139,9 @@ export class InterfaceStepBlock { }) async releaseChild(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(event.user); const index = ref.children.findIndex(c => c.uuid === event.sourceId); - if ((ref.options.cyclic && index !== -1) && (this.endIndexes[index])) { + if ((options.cyclic && index !== -1) && (this.endIndexes[index])) { const user = event.user; if (user) { let blockState: any; @@ -159,6 +166,7 @@ export class InterfaceStepBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); let blockState: any; if (!this.state.hasOwnProperty(user.id)) { blockState = {}; @@ -177,7 +185,7 @@ export class InterfaceStepBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - uiMetaData: ref.options?.uiMetaData, + uiMetaData: options?.uiMetaData, index: blockState.index }; } diff --git a/policy-service/src/policy-engine/blocks/switch-block.ts b/policy-service/src/policy-engine/blocks/switch-block.ts index fe1daa4719..cb9f7a034c 100644 --- a/policy-service/src/policy-engine/blocks/switch-block.ts +++ b/policy-service/src/policy-engine/blocks/switch-block.ts @@ -97,7 +97,7 @@ export class SwitchBlock { }) async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - + const options = ref.getOptions(event.user); ref.log(`switch: ${event.user?.id}`); const docs: IPolicyDocument | IPolicyDocument[] = event.data.data; @@ -117,7 +117,7 @@ export class SwitchBlock { const scope = this.getScope(docs); - const { conditions, executionFlow } = ref.options; + const { conditions, executionFlow } = options; const tags: string[] = []; for (const condition of conditions) { const type = condition.type as string; diff --git a/policy-service/src/policy-engine/blocks/timer-block.ts b/policy-service/src/policy-engine/blocks/timer-block.ts index 4eba7fc81c..cbd9c48ec8 100644 --- a/policy-service/src/policy-engine/blocks/timer-block.ts +++ b/policy-service/src/policy-engine/blocks/timer-block.ts @@ -115,15 +115,17 @@ export class TimerBlock { * @private */ private startCron(ref: AnyBlockType) { + const options = ref.getOptions(); + try { - let sd = moment(ref.options.startDate).utc(); + let sd = moment(options.startDate).utc(); if (sd.isValid()) { sd = moment().utc(); } this.endTime = Infinity; - if (ref.options.endDate) { - const ed = moment(ref.options.endDate).utc(); + if (options.endDate) { + const ed = moment(options.endDate).utc(); if (ed.isValid()) { this.endTime = ed.toDate().getTime(); } @@ -136,7 +138,7 @@ export class TimerBlock { let mask: string = ''; this.interval = 0; - switch (ref.options.period) { + switch (options.period) { case 'yearly': { mask = `${sd.minute()} ${sd.hour()} ${sd.date()} ${sd.month() + 1} *`; break; @@ -158,14 +160,14 @@ export class TimerBlock { break; } case 'custom': { - mask = ref.options.periodMask; - this.interval = ref.options.periodInterval; + mask = options.periodMask; + this.interval = options.periodInterval; break; } default: throw new Error('Bad period') } - ref.log(`start scheduler: ${mask}, ${ref.options.startDate}, ${ref.options.endDate}, ${ref.options.periodInterval}`); + ref.log(`start scheduler: ${mask}, ${options.startDate}, ${options.endDate}, ${options.periodInterval}`); if (this.interval > 1) { this.tickCount = 0; this.job = new CronJob(mask, () => { diff --git a/policy-service/src/policy-engine/blocks/token-action-block.ts b/policy-service/src/policy-engine/blocks/token-action-block.ts index 5530c1fc20..0e9fbf2cd5 100644 --- a/policy-service/src/policy-engine/blocks/token-action-block.ts +++ b/policy-service/src/policy-engine/blocks/token-action-block.ts @@ -90,6 +90,7 @@ export class TokenActionBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); return { id: ref.uuid, blockType: ref.blockType, @@ -98,7 +99,7 @@ export class TokenActionBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - uiMetaData: ref.options?.uiMetaData + uiMetaData: options?.uiMetaData }; } @@ -118,17 +119,18 @@ export class TokenActionBlock { async runAction(event: IPolicyEvent) { const userId = event?.user?.userId; const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(event.user); ref.log(`runAction`); - const field = ref.options.accountId; + const field = options.accountId; const documents = event?.data?.data; const doc = Array.isArray(documents) ? documents[0] : documents; let token: Token | null; - if (!ref.options.useTemplate) { - token = await ref.databaseServer.getToken(ref.options.tokenId); + if (!options.useTemplate) { + token = await ref.databaseServer.getToken(options.tokenId); } - if (ref.options.useTemplate && doc && doc.tokens) { - token = await ref.databaseServer.getToken(doc.tokens[ref.options.template], ref.dryRun); + if (options.useTemplate && doc && doc.tokens) { + token = await ref.databaseServer.getToken(doc.tokens[options.template], ref.dryRun); } if (!token) { throw new BlockActionError('Bad token id', ref.blockType, ref.uuid); @@ -146,7 +148,7 @@ export class TokenActionBlock { throw new BlockActionError('Hedera Account not found.', ref.blockType, ref.uuid); } - switch (ref.options.action) { + switch (options.action) { case 'associate': { await PolicyActionsUtils.associateToken({ ref, @@ -207,7 +209,7 @@ export class TokenActionBlock { await ref.triggerEvents(PolicyOutputEventType.ReleaseEvent, event.user, null, event.actionStatus); await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, event.user, event.data, event.actionStatus); PolicyComponentsUtils.ExternalEventFn(new ExternalEvent(ExternalEventType.Run, ref, event.user, { - action: ref.options.action + action: options.action })); ref.backup(); diff --git a/policy-service/src/policy-engine/blocks/token-confirmation-block.ts b/policy-service/src/policy-engine/blocks/token-confirmation-block.ts index 644ebaa3e1..f22803d12b 100644 --- a/policy-service/src/policy-engine/blocks/token-confirmation-block.ts +++ b/policy-service/src/policy-engine/blocks/token-confirmation-block.ts @@ -79,10 +79,11 @@ export class TokenConfirmationBlock { /** * Get Schema */ - async getToken(): Promise { + async getToken(user?: PolicyUser): Promise { if (!this.token) { const ref = PolicyComponentsUtils.GetBlockRef(this); - this.token = await ref.databaseServer.getToken(ref.options.tokenId); + const options = ref.getOptions(user); + this.token = await ref.databaseServer.getToken(options.tokenId); } return this.token; } @@ -93,8 +94,9 @@ export class TokenConfirmationBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const blockState: any = this.state[user?.id] || {}; - const token = await this.getToken(); + const token = await this.getToken(user); const block: IPolicyGetData = { id: ref.uuid, blockType: 'tokenConfirmationBlock', @@ -103,7 +105,7 @@ export class TokenConfirmationBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - action: ref.options.action, + action: options.action, accountId: blockState.accountId, tokenName: token.tokenName, tokenSymbol: token.tokenSymbol, @@ -133,7 +135,7 @@ export class TokenConfirmationBlock { } if (data.action === 'confirm') { - await this.confirm(ref, data, blockState, user.userId); + await this.confirm(ref, data, blockState, user.userId, user); } return { @@ -145,6 +147,7 @@ export class TokenConfirmationBlock { action: 'confirm' | 'skip' }, actionStatus: RecordActionStep) { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); ref.log(`setData`); if (!data) { @@ -160,7 +163,7 @@ export class TokenConfirmationBlock { await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, blockState.user, blockState.data, actionStatus); PolicyComponentsUtils.ExternalEventFn(new ExternalEvent(ExternalEventType.Set, ref, blockState.user, { userAction: data.action, - action: ref.options.action + action: options.action })); } @@ -205,31 +208,34 @@ export class TokenConfirmationBlock { hederaAccountKey: string }, state: any, - userId: string | null) { + userId: string | null, + user?: PolicyUser) { const account = { id: userId, hederaAccountId: state.accountId, hederaAccountKey: data.hederaAccountKey } + const options = ref.getOptions(user); + if (!account.hederaAccountKey) { throw new BlockActionError(`Key value is unknown`, ref.blockType, ref.uuid) } let token: any; - if (ref.options.useTemplate) { + if (options.useTemplate) { if (state.tokenId) { token = await ref.databaseServer.getToken(state.tokenId, ref.dryRun); } } else { - token = await this.getToken(); + token = await this.getToken(user); } if (!token) { throw new BlockActionError('Bad token id', ref.blockType, ref.uuid); } - switch (ref.options.action) { + switch (options.action) { case 'associate': { await PolicyUtils.associate(ref, token, account, userId); break; @@ -260,15 +266,17 @@ export class TokenConfirmationBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); ref.log(`runAction`); - const field = ref.options.accountId; + const options = ref.getOptions(event.user); + + const field = options.accountId; if (event) { const documents = event.data?.data; const id = event.user?.id; const userId = event?.user?.userId; const doc = Array.isArray(documents) ? documents[0] : documents; let tokenId: string; - if (ref.options.useTemplate && doc && doc.tokens) { - tokenId = doc.tokens[ref.options.template]; + if (options.useTemplate && doc && doc.tokens) { + tokenId = doc.tokens[options.template]; } let relayerAccount: string = null; diff --git a/policy-service/src/policy-engine/blocks/transformation-button-block.ts b/policy-service/src/policy-engine/blocks/transformation-button-block.ts index a9a93923c9..eab590b60f 100644 --- a/policy-service/src/policy-engine/blocks/transformation-button-block.ts +++ b/policy-service/src/policy-engine/blocks/transformation-button-block.ts @@ -30,25 +30,28 @@ import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfac defaultEvent: false, properties: [ { - 'name': 'buttonName', - 'label': 'Button name', - 'title': 'Button name', - 'type': PropertyType.Input, - 'default': '' + name: 'buttonName', + label: 'Button name', + title: 'Button name', + type: PropertyType.Input, + default: '', + editable: true }, { - 'name': 'url', - 'label': 'Url', - 'title': 'Url', - 'type': PropertyType.Input, - 'default': '' + name: 'url', + label: 'Url', + title: 'Url', + type: PropertyType.Input, + default: '', + editable: true }, { - 'name': 'hideWhenDiscontinued', - 'label': 'Hide when discontinued', - 'title': 'Hide when discontinued', - 'type': PropertyType.Checkbox, - 'default': false + name: 'hideWhenDiscontinued', + label: 'Hide when discontinued', + title: 'Hide when discontinued', + type: PropertyType.Checkbox, + default: false, + editable: true }, ] }, @@ -63,6 +66,7 @@ export class TransformationButtonBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -71,11 +75,11 @@ export class TransformationButtonBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - type: ref.options.type, - uiMetaData: ref.options.uiMetaData, - user: ref.options.user, - buttonName: ref.options.buttonName, - hideWhenDiscontinued: !!ref.options.hideWhenDiscontinued, + type: options.type, + uiMetaData: options.uiMetaData, + user: options.user, + buttonName: options.buttonName, + hideWhenDiscontinued: !!options.hideWhenDiscontinued, } return data; } @@ -96,6 +100,7 @@ export class TransformationButtonBlock { tag: any }, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); const data: IPolicyDocument = blockData.document; const state: IPolicyEventState = { data }; const eventData = await ref.triggerEventSync(PolicyInputEventType.GetDataEvent, user, state, actionStatus); @@ -107,7 +112,7 @@ export class TransformationButtonBlock { return { data: eventData, - url: ref.options?.url ?? '' + url: options?.url ?? '' }; } } diff --git a/policy-service/src/policy-engine/blocks/transformation-ui-addon.ts b/policy-service/src/policy-engine/blocks/transformation-ui-addon.ts index 3971f85db1..d7679aa32a 100644 --- a/policy-service/src/policy-engine/blocks/transformation-ui-addon.ts +++ b/policy-service/src/policy-engine/blocks/transformation-ui-addon.ts @@ -27,7 +27,8 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; name: 'expression', label: 'Expression', title: 'Expression', - type: PropertyType.Code + type: PropertyType.Code, + editable: true } ] }, @@ -41,7 +42,8 @@ export class TransformationUIAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = PolicyComponentsUtils.GetBlockUniqueOptionsObject(this); + const options = ref.getOptions(user); + return { id: ref.uuid, blockType: ref.blockType, diff --git a/policy-service/src/policy-engine/blocks/upload-vc-document-block.ts b/policy-service/src/policy-engine/blocks/upload-vc-document-block.ts index e727e7dacd..83f3a87cda 100644 --- a/policy-service/src/policy-engine/blocks/upload-vc-document-block.ts +++ b/policy-service/src/policy-engine/blocks/upload-vc-document-block.ts @@ -161,6 +161,7 @@ export class UploadVcDocumentBlock { }) async setData(user: PolicyUser, data: any, _, actionStatus: RecordActionStep): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); + const options = ref.getOptions(user); if (!user.did) { throw new BlockActionError('User have no any did', ref.blockType, ref.uuid); @@ -193,8 +194,8 @@ export class UploadVcDocumentBlock { const tags = await PolicyUtils.getBlockTags(ref); PolicyUtils.setDocumentTags(doc, tags); - doc.type = ref.options.entityType; - doc.schema = ref.options.schema; + doc.type = options.entityType; + doc.schema = options.schema; doc.signature = DocumentSignature.VERIFIED; retArray.push(doc); diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index 02b0d7587b..c8e3db80a8 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -943,7 +943,10 @@ export function BasicBlock(options: Partial) { properties[last] = value; } - public async getOption(user:any) { + public async getOptions(user?: any) { + if(!user) { + return this.options; + } const row = await DatabaseServer.getPolicyParameters(user.did, this.policyId); let properties; if(!row || row.updated || !row.properties || Object.keys(row.properties).length === 0) { @@ -977,13 +980,17 @@ export function BasicBlock(options: Partial) { config: null, updated: false, properties - }) + }); } } else { properties = row.properties; } - - return Object.assign({}, this.options, properties[this.tag]); + + if(properties && properties[this.tag]) { + return Object.assign({}, this.options, properties[this.tag]); + } else { + return this.options; + } } }; }; diff --git a/policy-service/src/policy-engine/interfaces/block-about.ts b/policy-service/src/policy-engine/interfaces/block-about.ts index 6754ff194d..2893d135b3 100644 --- a/policy-service/src/policy-engine/interfaces/block-about.ts +++ b/policy-service/src/policy-engine/interfaces/block-about.ts @@ -77,6 +77,8 @@ export interface BlockProperties { * Visible expression */ visible?: string; + + editable?: boolean; } /** diff --git a/policy-service/src/policy-engine/policy-engine.interface.ts b/policy-service/src/policy-engine/policy-engine.interface.ts index 8e4e1fba81..4dbac66ee1 100644 --- a/policy-service/src/policy-engine/policy-engine.interface.ts +++ b/policy-service/src/policy-engine/policy-engine.interface.ts @@ -476,7 +476,7 @@ export interface IPolicyBlock { user?: PolicyUser | string ): Promise; - getOption(user: PolicyUser | null): any; + getOptions(user?: PolicyUser | null): any; } /** From 2908680a8f62907184f863f22ae0ccc34bb919a1 Mon Sep 17 00:00:00 2001 From: Borys Date: Fri, 27 Feb 2026 10:57:09 -0500 Subject: [PATCH 09/24] basic block fix Signed-off-by: Borys --- .../src/policy-engine/helpers/decorators/basic-block.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index c8e3db80a8..0bc0149f17 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -954,7 +954,7 @@ export function BasicBlock(options: Partial) { const policyRows = await this.databaseServer.find(PolicyParameters, { policyId: this.policyId }); for (const item of policyRows) { - for (const config of item.config) { + for (const config of item.config ?? []) { if( config.applyTo.includes('All') || config.applyTo.includes(user.role) || @@ -977,7 +977,7 @@ export function BasicBlock(options: Partial) { this.databaseServer.save(PolicyParameters, { policyId: this.policyId, userDID: user.did, - config: null, + config: [], updated: false, properties }); @@ -985,7 +985,7 @@ export function BasicBlock(options: Partial) { } else { properties = row.properties; } - + if(properties && properties[this.tag]) { return Object.assign({}, this.options, properties[this.tag]); } else { From 27fd77208b3f62a3a72c2903707e67a0a94df7bd Mon Sep 17 00:00:00 2001 From: Borys Date: Fri, 27 Feb 2026 13:15:11 -0500 Subject: [PATCH 10/24] fixed basic block options Signed-off-by: Borys --- api-gateway/src/api/service/policy.ts | 16 +--------- api-gateway/src/helpers/policy-engine.ts | 2 +- .../policy-configuration.component.ts | 2 +- .../policy-engine/policy-engine.service.ts | 11 +++++-- .../src/policy-engine/blocks/action-block.ts | 4 +-- .../policy-engine/blocks/aggregate-block.ts | 8 ++--- .../blocks/button-block-addon.ts | 4 +-- .../src/policy-engine/blocks/button-block.ts | 2 +- .../policy-engine/blocks/calculate-block.ts | 10 +++--- .../blocks/calculate-math-addon.ts | 9 +++--- .../blocks/calculate-math-variables.ts | 9 +++--- .../policy-engine/blocks/container-block.ts | 4 +-- .../blocks/create-token-block.ts | 8 ++--- .../blocks/custom-logic-block.ts | 6 ++-- .../blocks/document-validator-block.ts | 2 +- .../blocks/documents-source-addon.ts | 4 +-- .../policy-engine/blocks/documents-source.ts | 4 +-- .../blocks/dropdown-block-addon.ts | 4 +-- .../blocks/external-data-block.ts | 2 +- .../blocks/external-topic-block.ts | 2 +- .../blocks/extract-data-block.ts | 2 +- .../blocks/filters-addon-block.ts | 20 ++++++------ .../blocks/global-events-reader-block.ts | 8 ++--- .../blocks/global-events-writer-block.ts | 6 ++-- .../src/policy-engine/blocks/group-manager.ts | 6 ++-- .../blocks/http-request-block.ts | 2 +- .../blocks/http-request-ui-addon.ts | 2 +- .../src/policy-engine/blocks/impact-addon.ts | 2 +- .../policy-engine/blocks/information-block.ts | 4 +-- .../blocks/integration-button-block.ts | 4 +-- .../src/policy-engine/blocks/math-block.ts | 6 ++-- .../src/policy-engine/blocks/mint-block.ts | 18 +++++------ .../src/policy-engine/blocks/module.ts | 7 ++-- .../policy-engine/blocks/multi-sign-block.ts | 21 +++++------- .../blocks/notification.block.ts | 10 +++--- .../src/policy-engine/blocks/policy-roles.ts | 4 +-- .../policy-engine/blocks/reassigning.block.ts | 2 +- .../src/policy-engine/blocks/report-block.ts | 2 +- .../policy-engine/blocks/report-item-block.ts | 2 +- .../blocks/request-vc-document-block-addon.ts | 6 ++-- .../blocks/request-vc-document-block.ts | 6 ++-- .../policy-engine/blocks/retirement-block.ts | 8 ++--- .../policy-engine/blocks/revocation-block.ts | 2 +- .../src/policy-engine/blocks/revoke-block.ts | 2 +- .../blocks/send-to-guardian-block.ts | 10 +++--- .../blocks/set-relationships-block.ts | 2 +- .../src/policy-engine/blocks/split-block.ts | 6 ++-- .../src/policy-engine/blocks/step-block.ts | 4 +-- .../src/policy-engine/blocks/switch-block.ts | 2 +- .../src/policy-engine/blocks/timer-block.ts | 16 ++++------ .../blocks/token-action-block.ts | 4 +-- .../blocks/token-confirmation-block.ts | 10 +++--- .../blocks/transformation-button-block.ts | 6 ++-- .../blocks/transformation-ui-addon.ts | 4 +-- .../blocks/upload-vc-document-block.ts | 2 +- .../helpers/decorators/basic-block.ts | 4 +-- .../src/policy-engine/helpers/utils.ts | 32 +++++++++++++++++++ .../policy-engine/policy-engine.interface.ts | 2 +- 58 files changed, 192 insertions(+), 177 deletions(-) diff --git a/api-gateway/src/api/service/policy.ts b/api-gateway/src/api/service/policy.ts index 0c6ddc3679..12e66b5eb6 100644 --- a/api-gateway/src/api/service/policy.ts +++ b/api-gateway/src/api/service/policy.ts @@ -4865,22 +4865,8 @@ export class PolicyApi { @Param('policyId') policyId: string, ): Promise { try { - let config; const engineService = new PolicyEngine(); - const parameters: PolicyParametersDTO = await engineService.getPolicyParametersConfig(new EntityOwner(user), user.did, policyId ); - - if(parameters) { - config = parameters.config; - } else { - const policy = await engineService.getPolicy({ - filters: policyId, - userDid: user.did, - }, new EntityOwner(user)); - - config = policy.editableParametersSettings; - } - - return config; + return await engineService.getPolicyParametersConfig(new EntityOwner(user), user.did, policyId ); } catch (error) { await InternalException(error, this.logger, user.id); } diff --git a/api-gateway/src/helpers/policy-engine.ts b/api-gateway/src/helpers/policy-engine.ts index 30771f3680..52ce929f87 100644 --- a/api-gateway/src/helpers/policy-engine.ts +++ b/api-gateway/src/helpers/policy-engine.ts @@ -1641,7 +1641,7 @@ export class PolicyEngine extends NatsService { owner: IOwner, userDID: string, policyId: string, - ): Promise { + ): Promise { return await this.sendMessage(PolicyEngineEvents.GET_POLICY_PARAMETERS_VALUES, { owner, userDID, policyId }); } } diff --git a/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.ts b/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.ts index 31fc059358..cbdd04bf41 100644 --- a/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.ts +++ b/frontend/src/app/modules/policy-engine/policy-configuration/policy-configuration/policy-configuration.component.ts @@ -1714,7 +1714,7 @@ export class PolicyConfigurationComponent implements OnInit { const dialogRef = this.dialogService.open(PolicyParametersConfigDialog, { width: '1024px', styleClass: 'custom-dialog', - header: 'Editible Fields', + header: 'Policy Parameters', closable: true, data: { policy: this.policyTemplate, diff --git a/guardian-service/src/policy-engine/policy-engine.service.ts b/guardian-service/src/policy-engine/policy-engine.service.ts index ea39ee2131..5301ecaed7 100644 --- a/guardian-service/src/policy-engine/policy-engine.service.ts +++ b/guardian-service/src/policy-engine/policy-engine.service.ts @@ -4546,7 +4546,6 @@ export class PolicyEngineService { const { userDID, policyId, config } = msg; const found = await DatabaseServer.getPolicyParameters(userDID, policyId); - if(found) { found.config = config; result = await DatabaseServer.updatePolicyParameters(found); @@ -4577,7 +4576,15 @@ export class PolicyEngineService { try { const { userDID, policyId } = msg; - const result = await DatabaseServer.getPolicyParameters(userDID, policyId); + let result; + const parameters = await DatabaseServer.getPolicyParameters(userDID, policyId); + if(parameters && parameters.config?.length) { + result = parameters.config; + } + else { + const foundPolicy = await DatabaseServer.getPolicyById(policyId); + result = foundPolicy?.editableParametersSettings; + } return new MessageResponse(result); } catch (error) { diff --git a/policy-service/src/policy-engine/blocks/action-block.ts b/policy-service/src/policy-engine/blocks/action-block.ts index 4675037766..d512a117e7 100644 --- a/policy-service/src/policy-engine/blocks/action-block.ts +++ b/policy-service/src/policy-engine/blocks/action-block.ts @@ -46,7 +46,7 @@ export class InterfaceDocumentActionBlock { async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, @@ -105,7 +105,7 @@ export class InterfaceDocumentActionBlock { async setData(user: PolicyUser, document: IPolicyDocument, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const state: IPolicyEventState = { data: document }; diff --git a/policy-service/src/policy-engine/blocks/aggregate-block.ts b/policy-service/src/policy-engine/blocks/aggregate-block.ts index 4af8179e99..27f10730be 100644 --- a/policy-service/src/policy-engine/blocks/aggregate-block.ts +++ b/policy-service/src/policy-engine/blocks/aggregate-block.ts @@ -123,7 +123,7 @@ export class AggregateBlock { public async tickCron(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const { aggregateType, groupByFields, disableUserGrouping } = options; if (aggregateType !== 'period') { @@ -187,7 +187,7 @@ export class AggregateBlock { private async sendCronDocuments(ref: AnyBlockType, userId: string, documents: AggregateVC[], actionStatus: RecordActionStep) { documents = await this.removeDocuments(ref, documents); const user = await PolicyUtils.getPolicyUserById(ref, userId); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (documents.length || options.emptyData) { const state: IPolicyEventState = { data: documents }; await ref.triggerEvents(PolicyOutputEventType.RunEvent, user, state, actionStatus); @@ -256,7 +256,7 @@ export class AggregateBlock { output: [PolicyOutputEventType.RunEvent, PolicyOutputEventType.RefreshEvent] }) private async tickAggregate(ref: AnyBlockType, document: any, userId: string | null, actionStatus: RecordActionStep, user?: PolicyUser) { - let options = ref.getOptions(user); + let options = await ref.getOptions(user); const { expressions, condition, disableUserGrouping, groupByFields } = options; const groupByUser = !disableUserGrouping; @@ -350,7 +350,7 @@ export class AggregateBlock { */ async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const { aggregateType } = options; const docs: IPolicyDocument | IPolicyDocument[] = event.data.data; diff --git a/policy-service/src/policy-engine/blocks/button-block-addon.ts b/policy-service/src/policy-engine/blocks/button-block-addon.ts index 3df67e8324..d8395294eb 100644 --- a/policy-service/src/policy-engine/blocks/button-block-addon.ts +++ b/policy-service/src/policy-engine/blocks/button-block-addon.ts @@ -107,7 +107,7 @@ export class ButtonBlockAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -136,7 +136,7 @@ export class ButtonBlockAddon { actionStatus ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const parent = PolicyComponentsUtils.GetBlockRef( ref.parent ); diff --git a/policy-service/src/policy-engine/blocks/button-block.ts b/policy-service/src/policy-engine/blocks/button-block.ts index 04dea3fe61..f5f4afa66a 100644 --- a/policy-service/src/policy-engine/blocks/button-block.ts +++ b/policy-service/src/policy-engine/blocks/button-block.ts @@ -36,7 +36,7 @@ export class ButtonBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, diff --git a/policy-service/src/policy-engine/blocks/calculate-block.ts b/policy-service/src/policy-engine/blocks/calculate-block.ts index 914c2d0b40..f7118be5c0 100644 --- a/policy-service/src/policy-engine/blocks/calculate-block.ts +++ b/policy-service/src/policy-engine/blocks/calculate-block.ts @@ -75,7 +75,7 @@ export class CalculateContainerBlock { userId: string | null, user?: PolicyUser ): Promise { - let options = ref.getOptions(user); + let options = await ref.getOptions(user); const fields = options.inputFields; let scope = {}; @@ -132,7 +132,7 @@ export class CalculateContainerBlock { const context = await ref.debugContext({ documents }); const contextDocuments = context.documents as IPolicyDocument | IPolicyDocument[]; - let options = ref.getOptions(user); + let options = await ref.getOptions(user); const isArray = Array.isArray(contextDocuments); if (!contextDocuments || (isArray && !contextDocuments.length)) { @@ -178,7 +178,7 @@ export class CalculateContainerBlock { const isArray = Array.isArray(documents); const firstDocument = isArray ? documents[0] : documents; const relationships = []; - let options = ref.getOptions(user); + let options = await ref.getOptions(user); let accounts: any = {}; let tokens: any = {}; @@ -249,7 +249,7 @@ export class CalculateContainerBlock { } = metadata; // <-- new vc const VCHelper = new VcHelper(); - let options = ref.getOptions(user); + let options = await ref.getOptions(user); const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const vcSubject: any = { @@ -323,7 +323,7 @@ export class CalculateContainerBlock { @CatchErrors() public async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - let options = ref.getOptions(event.user); + let options = await ref.getOptions(event.user); if (options.inputDocuments === 'separate') { if (Array.isArray(event.data.data)) { diff --git a/policy-service/src/policy-engine/blocks/calculate-math-addon.ts b/policy-service/src/policy-engine/blocks/calculate-math-addon.ts index 0620fde195..b5eccdd541 100644 --- a/policy-service/src/policy-engine/blocks/calculate-math-addon.ts +++ b/policy-service/src/policy-engine/blocks/calculate-math-addon.ts @@ -33,7 +33,7 @@ export class CalculateMathAddon { */ public async run(scope: any, user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (options.equations) { for (const equation of options.equations) { @@ -52,10 +52,9 @@ export class CalculateMathAddon { */ public getVariables(variables: any): any { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(); - - if (options.equations) { - for (const equation of options.equations) { + + if (ref.options.equations) { + for (const equation of ref.options.equations) { variables[equation.variable] = equation.formula; } } diff --git a/policy-service/src/policy-engine/blocks/calculate-math-variables.ts b/policy-service/src/policy-engine/blocks/calculate-math-variables.ts index 2ef62f832c..a20dadbb9b 100644 --- a/policy-service/src/policy-engine/blocks/calculate-math-variables.ts +++ b/policy-service/src/policy-engine/blocks/calculate-math-variables.ts @@ -117,7 +117,7 @@ import { LocationType } from '@guardian/interfaces'; label: 'Variables', title: 'Variables', type: PropertyType.Array, - editable: true, + editable: false, items: { label: 'Variable', value: 'var @variableName = @variablePath', @@ -158,7 +158,7 @@ export class CalculateMathVariables { */ public async run(scope: any, user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const filters: any = {}; if (options.onlyOwnDocuments) { @@ -237,10 +237,9 @@ export class CalculateMathVariables { */ public options(variables: any): any { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(); - if (options.variables) { - for (const variable of options.variables) { + if (ref.options.variables) { + for (const variable of ref.options.variables) { variables[variable.variableName] = variable.variablePath; } } diff --git a/policy-service/src/policy-engine/blocks/container-block.ts b/policy-service/src/policy-engine/blocks/container-block.ts index 373c10f9f0..5c6f9775e9 100644 --- a/policy-service/src/policy-engine/blocks/container-block.ts +++ b/policy-service/src/policy-engine/blocks/container-block.ts @@ -36,8 +36,8 @@ export class InterfaceContainerBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); - + const options = await ref.getOptions(user); + return { id: ref.uuid, blockType: ref.blockType, diff --git a/policy-service/src/policy-engine/blocks/create-token-block.ts b/policy-service/src/policy-engine/blocks/create-token-block.ts index 5fd3b29101..4e4261bcfe 100644 --- a/policy-service/src/policy-engine/blocks/create-token-block.ts +++ b/policy-service/src/policy-engine/blocks/create-token-block.ts @@ -117,7 +117,7 @@ export class CreateTokenBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (options.autorun) { throw new BlockActionError( @@ -164,7 +164,7 @@ export class CreateTokenBlock { ); } - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const policyOwnerCred = await PolicyUtils.getUserCredentials(ref, ref.policyOwner, userId); @@ -265,7 +265,7 @@ export class CreateTokenBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); ref.log(`setData`); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (options.autorun) { throw new BlockActionError( @@ -328,7 +328,7 @@ export class CreateTokenBlock { const user = event.user; const eventData = event.data; - let options = ref.getOptions(user); + let options = await ref.getOptions(user); if (!this.state.tokenNumber) { this.state.tokenNumber = 0; diff --git a/policy-service/src/policy-engine/blocks/custom-logic-block.ts b/policy-service/src/policy-engine/blocks/custom-logic-block.ts index a47dbea150..857ee7a8bc 100644 --- a/policy-service/src/policy-engine/blocks/custom-logic-block.ts +++ b/policy-service/src/policy-engine/blocks/custom-logic-block.ts @@ -178,7 +178,7 @@ export class CustomLogicBlock { return new Promise(async (resolve, reject) => { try { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); let documents: IPolicyDocument[]; if (Array.isArray(state.data)) { @@ -365,7 +365,7 @@ export class CustomLogicBlock { const owner = await PolicyUtils.getDocumentOwner(ref, firstDocument, userId); const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, firstDocument, userId); const relationships = []; - const options = ref.getOptions(user); + const options = await ref.getOptions(user); let accounts: any = {}; let tokens: any = {}; let id: string; @@ -450,7 +450,7 @@ export class CustomLogicBlock { // <-- new vc const VCHelper = new VcHelper(); - let options = ref.getOptions(user); + let options = await ref.getOptions(user); const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const vcSubject: any = { diff --git a/policy-service/src/policy-engine/blocks/document-validator-block.ts b/policy-service/src/policy-engine/blocks/document-validator-block.ts index cc530b4e29..fb0aeced20 100644 --- a/policy-service/src/policy-engine/blocks/document-validator-block.ts +++ b/policy-service/src/policy-engine/blocks/document-validator-block.ts @@ -71,7 +71,7 @@ export class DocumentValidatorBlock { const documentRef = PolicyUtils.getDocumentRef(document); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); if (options.documentType === 'related-vc-document') { if (documentRef) { diff --git a/policy-service/src/policy-engine/blocks/documents-source-addon.ts b/policy-service/src/policy-engine/blocks/documents-source-addon.ts index 6f2509664d..ab9d8ee8d5 100644 --- a/policy-service/src/policy-engine/blocks/documents-source-addon.ts +++ b/policy-service/src/policy-engine/blocks/documents-source-addon.ts @@ -87,7 +87,7 @@ export class DocumentsSourceAddon { otherOptions?: any ) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const filters: any = {}; if (!Array.isArray(options.filters)) { @@ -237,7 +237,7 @@ export class DocumentsSourceAddon { */ async getFromSourceFilters(user: PolicyUser, globalFilters: any) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const filters: any = []; if (!Array.isArray(options.filters)) { throw new BlockActionError('filters option must be an array', ref.blockType, ref.uuid); diff --git a/policy-service/src/policy-engine/blocks/documents-source.ts b/policy-service/src/policy-engine/blocks/documents-source.ts index bd326caa4b..9b9b566f8d 100644 --- a/policy-service/src/policy-engine/blocks/documents-source.ts +++ b/policy-service/src/policy-engine/blocks/documents-source.ts @@ -64,7 +64,7 @@ export class InterfaceDocumentsSource { async onAddonEvent(user: PolicyUser, tag: string, documentId: string, handler: (document: any) => Promise, actionStatus) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const fields = options?.uiMetaData?.fields?.filter((field) => field?.bindBlocks?.includes(tag) ); @@ -148,7 +148,7 @@ export class InterfaceDocumentsSource { */ async getData(user: PolicyUser, uuid: string, queryParams: any): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); let ret: IPolicyGetData = { id: ref.uuid, diff --git a/policy-service/src/policy-engine/blocks/dropdown-block-addon.ts b/policy-service/src/policy-engine/blocks/dropdown-block-addon.ts index 79e3fc1aff..6abe89bc01 100644 --- a/policy-service/src/policy-engine/blocks/dropdown-block-addon.ts +++ b/policy-service/src/policy-engine/blocks/dropdown-block-addon.ts @@ -69,7 +69,7 @@ export class DropdownBlockAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const documents: any[] = await ref.getSources(user, null); const data: IPolicyGetData = { @@ -107,7 +107,7 @@ export class DropdownBlockAddon { actionStatus ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const documents: any[] = await ref.getSources(user, null); const dropdownDocument = documents.find( // tslint:disable-next-line:no-shadowed-variable diff --git a/policy-service/src/policy-engine/blocks/external-data-block.ts b/policy-service/src/policy-engine/blocks/external-data-block.ts index 4b7e2508ff..325defb6ca 100644 --- a/policy-service/src/policy-engine/blocks/external-data-block.ts +++ b/policy-service/src/policy-engine/blocks/external-data-block.ts @@ -161,7 +161,7 @@ export class ExternalDataBlock { } const user: PolicyUser = await PolicyUtils.getDocumentOwner(ref, data, null); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const documentRef = await this.getRelationships(ref, data.ref); const schema = await this.getSchema(); const vc = VcDocument.fromJsonTree(data.document); diff --git a/policy-service/src/policy-engine/blocks/external-topic-block.ts b/policy-service/src/policy-engine/blocks/external-topic-block.ts index ceb94a225c..4b71fc2e13 100644 --- a/policy-service/src/policy-engine/blocks/external-topic-block.ts +++ b/policy-service/src/policy-engine/blocks/external-topic-block.ts @@ -716,7 +716,7 @@ export class ExternalTopicBlock { actionStatus: RecordActionStep ): Promise { const documentRef = await this.getRelationships(ref, user); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (message.type !== MessageType.VCDocument) { return; diff --git a/policy-service/src/policy-engine/blocks/extract-data-block.ts b/policy-service/src/policy-engine/blocks/extract-data-block.ts index a9e779105c..d956d16877 100644 --- a/policy-service/src/policy-engine/blocks/extract-data-block.ts +++ b/policy-service/src/policy-engine/blocks/extract-data-block.ts @@ -256,7 +256,7 @@ export class ExtractDataBlock { @CatchErrors() async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - let options = ref.getOptions(event.user); + let options = await ref.getOptions(event.user); if (options.action === 'set') { await this.setAction(ref, event); diff --git a/policy-service/src/policy-engine/blocks/filters-addon-block.ts b/policy-service/src/policy-engine/blocks/filters-addon-block.ts index bc6bc3df4f..22ac3c23fb 100644 --- a/policy-service/src/policy-engine/blocks/filters-addon-block.ts +++ b/policy-service/src/policy-engine/blocks/filters-addon-block.ts @@ -53,9 +53,9 @@ export class FiltersAddonBlock { } } - private addQuery(filter: any, value: any, user?: PolicyUser) { + private async addQuery(filter: any, value: any, user?: PolicyUser) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const query = PolicyUtils.parseQuery(options.queryType || QueryType.eq, value); if (query && query.expression) { filter[options.field] = query.expression; @@ -64,10 +64,10 @@ export class FiltersAddonBlock { } } - private checkValues(blockState: any, value: any, user: PolicyUser): boolean { + private async checkValues(blockState: any, value: any, user: PolicyUser): Promise { if (Array.isArray(blockState.lastData)) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const query = PolicyUtils.parseQuery(options.queryType || QueryType.eq, value); const itemValues = query.value; if (Array.isArray(itemValues)) { @@ -100,7 +100,7 @@ export class FiltersAddonBlock { public async getFilters(user: PolicyUser): Promise<{ [key: string]: string }> { const ref = PolicyComponentsUtils.GetBlockRef(this); const filters = ref.filters[user.id] || {}; - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (!filters[options.field] && !options.canBeEmpty) { @@ -129,7 +129,7 @@ export class FiltersAddonBlock { filterValue = 'eq:' + filterValue; } - this.addQuery(filters, filterValue, user); + await this.addQuery(filters, filterValue, user); } return filters; } @@ -140,7 +140,7 @@ export class FiltersAddonBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const block: IPolicyGetData = { id: ref.uuid, @@ -198,7 +198,7 @@ export class FiltersAddonBlock { async setFiltersStrict(user: PolicyUser, data: any) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); this.previousState[user.id] = { ...this.state[user.id] }; const filter: any = {}; @@ -240,7 +240,7 @@ export class FiltersAddonBlock { async setFilterState(user: PolicyUser, data: any): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); this.previousState[user.id] = { ...this.state[user.id] }; const filter: any = {}; @@ -254,7 +254,7 @@ export class FiltersAddonBlock { if (!blockState.lastData) { await this.getData(user); } - if (this.checkValues(blockState, value, user)) { + if (await this.checkValues(blockState, value, user)) { this.addQuery(filter, value); } else if (!options.canBeEmpty) { throw new BlockActionError(`filter value is unknown`, ref.blockType, ref.uuid) diff --git a/policy-service/src/policy-engine/blocks/global-events-reader-block.ts b/policy-service/src/policy-engine/blocks/global-events-reader-block.ts index 2d039ba8ff..a72bd19ecf 100644 --- a/policy-service/src/policy-engine/blocks/global-events-reader-block.ts +++ b/policy-service/src/policy-engine/blocks/global-events-reader-block.ts @@ -189,7 +189,7 @@ class GlobalEventsReaderBlock { user.userId ); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const existingTopicIds = new Set(); @@ -912,7 +912,7 @@ class GlobalEventsReaderBlock { user: PolicyUser, stream: GlobalEventsReaderStream ): Promise { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const config = (options || {}) as GlobalEventReaderConfig; const branches = config.branches ?? []; @@ -1092,7 +1092,7 @@ class GlobalEventsReaderBlock { public async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const config = options; if (ref.dryRun) { @@ -1254,7 +1254,7 @@ class GlobalEventsReaderBlock { actionStatus ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (ref.dryRun) { throw new BlockActionError('Block is disabled in dry run mode', ref.blockType, ref.uuid); diff --git a/policy-service/src/policy-engine/blocks/global-events-writer-block.ts b/policy-service/src/policy-engine/blocks/global-events-writer-block.ts index 6d4f1bb5e4..1e8e5de1a4 100644 --- a/policy-service/src/policy-engine/blocks/global-events-writer-block.ts +++ b/policy-service/src/policy-engine/blocks/global-events-writer-block.ts @@ -103,7 +103,7 @@ export class GlobalEventsWriterBlock { user.userId, ); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const existingTopicIds = new Set(); for (const stream of existingStreams) { @@ -485,7 +485,7 @@ export class GlobalEventsWriterBlock { */ public async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const config = options || {} @@ -544,7 +544,7 @@ export class GlobalEventsWriterBlock { */ public async setData(user: PolicyUser, data: SetDataPayload, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const operation = data.operation; const streams = data.streams ?? []; diff --git a/policy-service/src/policy-engine/blocks/group-manager.ts b/policy-service/src/policy-engine/blocks/group-manager.ts index e4ad53152a..e8d401d542 100644 --- a/policy-service/src/policy-engine/blocks/group-manager.ts +++ b/policy-service/src/policy-engine/blocks/group-manager.ts @@ -49,7 +49,7 @@ export class GroupManagerBlock { role: string ): Promise { const group = await ref.databaseServer.getUserInGroup(ref.policyId, user.did, groupId); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (!group) { throw new Error(`Group not found`); @@ -94,7 +94,7 @@ export class GroupManagerBlock { if (user.did === did) { throw new Error(`Permission denied`); } - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const member = await ref.databaseServer.getUserInGroup(ref.policyId, did, groupId); if (!member) { @@ -156,7 +156,7 @@ export class GroupManagerBlock { */ private async groupMapping(ref: IPolicyInterfaceBlock, user: PolicyUser, group: PolicyRoles): Promise { const config = PolicyUtils.getGroupTemplate(ref, group.groupName); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const members = (await ref.databaseServer.getAllMembersByGroup(group)).map(member => { return { did: member.did, diff --git a/policy-service/src/policy-engine/blocks/http-request-block.ts b/policy-service/src/policy-engine/blocks/http-request-block.ts index e4b90ba66c..1807262fe8 100644 --- a/policy-service/src/policy-engine/blocks/http-request-block.ts +++ b/policy-service/src/policy-engine/blocks/http-request-block.ts @@ -144,7 +144,7 @@ export class HttpRequestBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); event.data.data = event.data.data || {}; - let options = ref.getOptions(event.user); + let options = await ref.getOptions(event.user); const variablesObj: any = { did: event?.user?.did, diff --git a/policy-service/src/policy-engine/blocks/http-request-ui-addon.ts b/policy-service/src/policy-engine/blocks/http-request-ui-addon.ts index 4653f36150..8a2da3bd7a 100644 --- a/policy-service/src/policy-engine/blocks/http-request-ui-addon.ts +++ b/policy-service/src/policy-engine/blocks/http-request-ui-addon.ts @@ -138,7 +138,7 @@ export class HttpRequestUIAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); return { id: ref.uuid, blockType: ref.blockType, diff --git a/policy-service/src/policy-engine/blocks/impact-addon.ts b/policy-service/src/policy-engine/blocks/impact-addon.ts index 0ee28894ad..52438d0186 100644 --- a/policy-service/src/policy-engine/blocks/impact-addon.ts +++ b/policy-service/src/policy-engine/blocks/impact-addon.ts @@ -104,7 +104,7 @@ export class TokenOperationAddon { userId: string | null ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const policySchema = await this.getSchema(); const amount = PolicyUtils.aggregate(options.amount, documents); const vcHelper = new VcHelper(); diff --git a/policy-service/src/policy-engine/blocks/information-block.ts b/policy-service/src/policy-engine/blocks/information-block.ts index 3b36349af5..1391ae6058 100644 --- a/policy-service/src/policy-engine/blocks/information-block.ts +++ b/policy-service/src/policy-engine/blocks/information-block.ts @@ -36,8 +36,8 @@ export class InformationBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); - + const options = await ref.getOptions(user); + return { id: ref.uuid, blockType: ref.blockType, diff --git a/policy-service/src/policy-engine/blocks/integration-button-block.ts b/policy-service/src/policy-engine/blocks/integration-button-block.ts index 19c3320df6..53a3edd174 100644 --- a/policy-service/src/policy-engine/blocks/integration-button-block.ts +++ b/policy-service/src/policy-engine/blocks/integration-button-block.ts @@ -26,7 +26,7 @@ export class IntegrationButtonBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, @@ -60,7 +60,7 @@ export class IntegrationButtonBlock { tag: any }, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const requestNameSplited = options.requestName.split('_'); const params = {}; diff --git a/policy-service/src/policy-engine/blocks/math-block.ts b/policy-service/src/policy-engine/blocks/math-block.ts index 4e6ff2fd4b..3110d045b7 100644 --- a/policy-service/src/policy-engine/blocks/math-block.ts +++ b/policy-service/src/policy-engine/blocks/math-block.ts @@ -113,7 +113,7 @@ export class MathBlock { documents: DocumentMap, user: PolicyUser ): Promise { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const schema = new Schema(outputSchema); @@ -165,7 +165,7 @@ export class MathBlock { throw new BlockActionError('Invalid VC', ref.blockType, ref.uuid); } - let options = ref.getOptions(user); + let options = await ref.getOptions(user); const sources: IPolicyDocument[] = await PolicyUtils.findRelationships(ref, documents); @@ -272,7 +272,7 @@ export class MathBlock { // <-- new vc const VCHelper = new VcHelper(); - let options = ref.getOptions(user); + let options = await ref.getOptions(user); const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); diff --git a/policy-service/src/policy-engine/blocks/mint-block.ts b/policy-service/src/policy-engine/blocks/mint-block.ts index eaac4f1caa..295d8b86be 100644 --- a/policy-service/src/policy-engine/blocks/mint-block.ts +++ b/policy-service/src/policy-engine/blocks/mint-block.ts @@ -54,7 +54,7 @@ export class MintBlock { */ private async getToken(ref: AnyBlockType, docs: IPolicyDocument[], user?: PolicyUser): Promise { let token: TokenCollection; - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (options.useTemplate) { if (docs[0].tokens) { const tokenId = docs[0].tokens[options.template]; @@ -75,11 +75,11 @@ export class MintBlock { * @param docs * @private */ - private getObjects(ref: AnyBlockType, docs: IPolicyDocument[], user?: PolicyUser): any { + private async getObjects(ref: AnyBlockType, docs: IPolicyDocument[], user?: PolicyUser): Promise { const vcs: VcDocument[] = []; const messages: string[] = []; const topics: string[] = []; - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const field = options.accountId || 'default'; const accounts: string[] = []; for (const doc of docs) { @@ -127,16 +127,16 @@ export class MintBlock { * @param userId * @private */ - private getAccount( + private async getAccount( ref: AnyBlockType, docs: IPolicyDocument[], accounts: string[], relayerAccount: string, userId: string | null, user?: PolicyUser - ): string { + ): Promise { let targetAccount: string; - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (options.accountType !== 'custom-value') { const firstAccounts = accounts[0]; if (accounts.find(a => a !== firstAccounts)) { @@ -292,7 +292,7 @@ export class MintBlock { actionStatus: RecordActionStep ): Promise<[IPolicyDocument, number]> { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const tags = await PolicyUtils.getBlockTags(ref); const uuid: string = await ref.components.generateUUID(); @@ -512,12 +512,12 @@ export class MintBlock { userId: string | null ) { const token = await this.getToken(ref, docs, user); - const { vcs, messages, topics, accounts } = this.getObjects(ref, docs, event.user); + const { vcs, messages, topics, accounts } = await this.getObjects(ref, docs, event.user); const additionalMessages = this.getAdditionalMessages(additionalDocs); const topicId = topics[0]; const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, docs[0], userId); - const targetAccount = this.getAccount(ref, docs, accounts, relayerAccount, userId, event.user); + const targetAccount = await this.getAccount(ref, docs, accounts, relayerAccount, userId, event.user); const [vp, amount] = await this.mintProcessing( token, diff --git a/policy-service/src/policy-engine/blocks/module.ts b/policy-service/src/policy-engine/blocks/module.ts index 4381ee173b..e5fad1e55e 100644 --- a/policy-service/src/policy-engine/blocks/module.ts +++ b/policy-service/src/policy-engine/blocks/module.ts @@ -100,13 +100,12 @@ export class ModuleBlock { */ private _getVariable(name: any, type: string): any { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(); - if (Array.isArray(options.variables)) { - for (const variable of options.variables) { + if (Array.isArray(ref.options.variables)) { + for (const variable of ref.options.variables) { if (type) { if (name === variable.name && variable.type === type) { - return options[variable.name]; + return ref.options[variable.name]; } } else { if (name === variable.name) { diff --git a/policy-service/src/policy-engine/blocks/multi-sign-block.ts b/policy-service/src/policy-engine/blocks/multi-sign-block.ts index a9a2a270c6..b09027c668 100644 --- a/policy-service/src/policy-engine/blocks/multi-sign-block.ts +++ b/policy-service/src/policy-engine/blocks/multi-sign-block.ts @@ -51,7 +51,7 @@ enum DocumentStatus { title: 'Number of signatures required to move to the next step, as a percentage of the total number of users in the group.', type: PropertyType.Input, default: '50', - editable: true + editable: false }] }, variables: [] @@ -109,7 +109,6 @@ export class MultiSignBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, @@ -119,9 +118,9 @@ export class MultiSignBlock { ref.actionType === LocationType.REMOTE && user.location === LocationType.REMOTE ), - type: options.type, - uiMetaData: options.uiMetaData, - user: options.user + type: ref.options.type, + uiMetaData: ref.options.uiMetaData, + user: ref.options.user } return data; } @@ -133,7 +132,6 @@ export class MultiSignBlock { */ async setData(user: PolicyUser, blockData: any, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); const { status, document } = blockData; const documentId = document.id; @@ -188,7 +186,7 @@ export class MultiSignBlock { ); const users = await ref.databaseServer.getAllUsersByRole(ref.policyId, user.group, user.role); - await this.updateThreshold(users, sourceDoc, documentId, user, user.userId, actionStatus, user); + await this.updateThreshold(users, sourceDoc, documentId, user, user.userId, actionStatus); await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, user, null, actionStatus); @@ -213,10 +211,8 @@ export class MultiSignBlock { currentUser: PolicyUser, userId: string | null, actionStatus: RecordActionStep, - user?: PolicyUser ) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); const data = await ref.databaseServer.getMultiSignDocuments(ref.uuid, documentId, currentUser.group); @@ -230,7 +226,7 @@ export class MultiSignBlock { } } - const signedThreshold = Math.ceil(users.length * options.threshold / 100); + const signedThreshold = Math.ceil(users.length * ref.options.threshold / 100); const declinedThreshold = Math.round(users.length - signedThreshold + 1); if (signed >= signedThreshold) { @@ -322,7 +318,6 @@ export class MultiSignBlock { */ private async getDocumentStatus(document: IPolicyDocument, user: PolicyUser) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); const confirmationDocument = await ref.databaseServer.getMultiSignStatus(ref.uuid, document.id); const data: any[] = await ref.databaseServer.getMultiSignDocuments(ref.uuid, document.id, user.group); @@ -348,7 +343,7 @@ export class MultiSignBlock { confirmationStatus = confirmationDocument.status; } - const threshold = options.threshold; + const threshold = ref.options.threshold; const total = users.length; const signedThreshold = Math.ceil(users.length * threshold / 100); const declinedThreshold = Math.round(users.length - signedThreshold + 1); @@ -381,7 +376,7 @@ export class MultiSignBlock { for (const document of documents) { const documentId = document.documentId; const vc = await ref.databaseServer.getVcDocument(documentId); - await this.updateThreshold(users, vc, documentId, event.target, event?.user?.userId, event.actionStatus, event.user); + await this.updateThreshold(users, vc, documentId, event.target, event?.user?.userId, event.actionStatus); } await ref.triggerEvents(PolicyOutputEventType.RefreshEvent, null, null, event.actionStatus); PolicyComponentsUtils.ExternalEventFn(new ExternalEvent(ExternalEventType.DeleteMember, ref, event.target, null)); diff --git a/policy-service/src/policy-engine/blocks/notification.block.ts b/policy-service/src/policy-engine/blocks/notification.block.ts index c1d6194452..9516366c22 100644 --- a/policy-service/src/policy-engine/blocks/notification.block.ts +++ b/policy-service/src/policy-engine/blocks/notification.block.ts @@ -161,12 +161,12 @@ export class NotificationBlock { * @param ref Block ref * @returns Function */ - private getNotificationFunction( + private async getNotificationFunction( ref: any, user: PolicyUser - ): (title: string, message: string, userId: string) => void { + ): Promise<(title: string, message: string, userId: string) => void> { let fn; - const options = ref.getOptions(user); + const options = await ref.getOptions(user); switch (options.type) { case NotificationType.INFO: @@ -210,9 +210,9 @@ export class NotificationBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); - const notify = this.getNotificationFunction(ref, event.user); + const notify = await this.getNotificationFunction(ref, event.user); switch (options.user) { case UserOption.ALL: { diff --git a/policy-service/src/policy-engine/blocks/policy-roles.ts b/policy-service/src/policy-engine/blocks/policy-roles.ts index 54a0eeae70..60682a11ba 100644 --- a/policy-service/src/policy-engine/blocks/policy-roles.ts +++ b/policy-service/src/policy-engine/blocks/policy-roles.ts @@ -371,8 +371,8 @@ export class PolicyRolesBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); - + const options = await ref.getOptions(user); + const roles: string[] = Array.isArray(options.roles) ? options.roles : []; const groups: string[] = Array.isArray(options.groups) ? options.groups : []; const policyGroups = PolicyUtils.getGroupTemplates(ref); diff --git a/policy-service/src/policy-engine/blocks/reassigning.block.ts b/policy-service/src/policy-engine/blocks/reassigning.block.ts index b4154e15ad..48f9cb67e9 100644 --- a/policy-service/src/policy-engine/blocks/reassigning.block.ts +++ b/policy-service/src/policy-engine/blocks/reassigning.block.ts @@ -64,7 +64,7 @@ export class ReassigningBlock { actor: PolicyUser }> { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const owner: PolicyUser = await PolicyUtils.getDocumentOwner(ref, document, userId); const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, document, user.userId); diff --git a/policy-service/src/policy-engine/blocks/report-block.ts b/policy-service/src/policy-engine/blocks/report-block.ts index d65815407d..4bfc534d1a 100644 --- a/policy-service/src/policy-engine/blocks/report-block.ts +++ b/policy-service/src/policy-engine/blocks/report-block.ts @@ -436,7 +436,7 @@ export class ReportBlock { */ async getData(user: PolicyUser, uuid: string): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); try { const blockState = this.state[user.id] || {}; diff --git a/policy-service/src/policy-engine/blocks/report-item-block.ts b/policy-service/src/policy-engine/blocks/report-item-block.ts index 5e5dc7c498..ba0b356994 100644 --- a/policy-service/src/policy-engine/blocks/report-item-block.ts +++ b/policy-service/src/policy-engine/blocks/report-item-block.ts @@ -61,7 +61,7 @@ export class ReportItemBlock { variables: any, ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(); + const options = await ref.getOptions(); const icon = options.icon; const title = options.title; diff --git a/policy-service/src/policy-engine/blocks/request-vc-document-block-addon.ts b/policy-service/src/policy-engine/blocks/request-vc-document-block-addon.ts index 6fb78251f0..b3b10b9249 100644 --- a/policy-service/src/policy-engine/blocks/request-vc-document-block-addon.ts +++ b/policy-service/src/policy-engine/blocks/request-vc-document-block-addon.ts @@ -140,7 +140,7 @@ export class RequestVcDocumentBlockAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, @@ -187,7 +187,7 @@ export class RequestVcDocumentBlockAddon { ); } const document = _data.document; - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const disposeTables = await hydrateTablesInObject( document, @@ -310,7 +310,7 @@ export class RequestVcDocumentBlockAddon { documentRef: VcDocumentCollection, user?: PolicyUser ): Promise { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if ( options.presetFields && diff --git a/policy-service/src/policy-engine/blocks/request-vc-document-block.ts b/policy-service/src/policy-engine/blocks/request-vc-document-block.ts index a1ab34ea86..ef183ac64b 100644 --- a/policy-service/src/policy-engine/blocks/request-vc-document-block.ts +++ b/policy-service/src/policy-engine/blocks/request-vc-document-block.ts @@ -193,7 +193,7 @@ export class RequestVcDocumentBlock { private async setBlockData(user: PolicyUser, data: IPolicyDocument, actionStatus: RecordActionStep) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); try { //Prepare data const document = await this.prepareDocument(data); @@ -329,7 +329,7 @@ export class RequestVcDocumentBlock { documentRef: VcDocumentCollection, user?: PolicyUser ): Promise { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if ( options.presetFields && @@ -402,7 +402,7 @@ export class RequestVcDocumentBlock { actionStatusId: string, ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); SchemaHelper.updateObjectContext(this._schema, document); const _vcHelper = new VcHelper(); diff --git a/policy-service/src/policy-engine/blocks/retirement-block.ts b/policy-service/src/policy-engine/blocks/retirement-block.ts index 56fe88841c..f2b8909cad 100644 --- a/policy-service/src/policy-engine/blocks/retirement-block.ts +++ b/policy-service/src/policy-engine/blocks/retirement-block.ts @@ -121,7 +121,7 @@ export class RetirementBlock { actionStatus: RecordActionStep ): Promise<[IPolicyDocument, number]> { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const tags = await PolicyUtils.getBlockTags(ref); @@ -293,8 +293,8 @@ export class RetirementBlock { */ private async getToken(ref: AnyBlockType, docs: IPolicyDocument[], user?: PolicyUser): Promise { let token: TokenCollection; - const options = ref.getOptions(user); - + const options = await ref.getOptions(user); + if (options.useTemplate) { if (docs[0].tokens) { const tokenId = docs[0].tokens[options.template]; @@ -325,7 +325,7 @@ export class RetirementBlock { async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - let options = ref.getOptions(event.user); + let options = await ref.getOptions(event.user); const docs = PolicyUtils.getArray(event.data.data); if (!docs.length && docs[0]) { diff --git a/policy-service/src/policy-engine/blocks/revocation-block.ts b/policy-service/src/policy-engine/blocks/revocation-block.ts index 21a5f59a6a..edf581f906 100644 --- a/policy-service/src/policy-engine/blocks/revocation-block.ts +++ b/policy-service/src/policy-engine/blocks/revocation-block.ts @@ -135,7 +135,7 @@ export class RevocationBlock { async runAction(event: IPolicyEvent): Promise { const userId = event?.user?.userId; const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const data = event.data.data; const doc = Array.isArray(data) ? data[0] : data; diff --git a/policy-service/src/policy-engine/blocks/revoke-block.ts b/policy-service/src/policy-engine/blocks/revoke-block.ts index 28ab78a09e..4ff8c1bb7a 100644 --- a/policy-service/src/policy-engine/blocks/revoke-block.ts +++ b/policy-service/src/policy-engine/blocks/revoke-block.ts @@ -118,7 +118,7 @@ export class RevokeBlock { async runAction(event: IPolicyEvent): Promise { const userId = event?.user?.userId; const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const uiMetaData = options.uiMetaData; const data = event.data.data; const doc = Array.isArray(data) ? data[0] : data; diff --git a/policy-service/src/policy-engine/blocks/send-to-guardian-block.ts b/policy-service/src/policy-engine/blocks/send-to-guardian-block.ts index a4450ad788..24243cfc9d 100644 --- a/policy-service/src/policy-engine/blocks/send-to-guardian-block.ts +++ b/policy-service/src/policy-engine/blocks/send-to-guardian-block.ts @@ -176,7 +176,7 @@ export class SendToGuardianBlock { userId: string | null, user?: PolicyUser ): Promise { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); let old = await this.getVCRecord(document, operation, ref); if (old) { @@ -370,7 +370,7 @@ export class SendToGuardianBlock { userId: string | null, user?: PolicyUser ): Promise { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); document.documentFields = Array.from( PolicyComponentsUtils.getDocumentCacheFields(ref.policyId) @@ -458,7 +458,7 @@ export class SendToGuardianBlock { user?: PolicyUser ): Promise { try { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const memo = MessageMemo.parseMemo(true, options.memo, document); message.setMemo(memo); @@ -505,7 +505,7 @@ export class SendToGuardianBlock { user?: PolicyUser ): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const type = PolicyUtils.getDocumentType(document); const relayerAccount = await PolicyUtils.getDocumentRelayerAccount(ref, document, userId); const owner = await PolicyUtils.getUserByIssuer(ref, document, userId); @@ -634,7 +634,7 @@ export class SendToGuardianBlock { @CatchErrors() async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); ref.log(`runAction`); const tags = await PolicyUtils.getBlockTags(ref); diff --git a/policy-service/src/policy-engine/blocks/set-relationships-block.ts b/policy-service/src/policy-engine/blocks/set-relationships-block.ts index cc44c717d8..c2ee96d82a 100644 --- a/policy-service/src/policy-engine/blocks/set-relationships-block.ts +++ b/policy-service/src/policy-engine/blocks/set-relationships-block.ts @@ -62,7 +62,7 @@ export class SetRelationshipsBlock { }) async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const data: IPolicyDocument[] = await ref.getSources(event.user); const owner = data[0] && data[0].owner || null; const group = data[0] && data[0].group || null; diff --git a/policy-service/src/policy-engine/blocks/split-block.ts b/policy-service/src/policy-engine/blocks/split-block.ts index 118faea272..61a3678efd 100644 --- a/policy-service/src/policy-engine/blocks/split-block.ts +++ b/policy-service/src/policy-engine/blocks/split-block.ts @@ -92,7 +92,7 @@ export class SplitBlock { */ private async calcDocValue(ref: IPolicyBlock, doc: IPolicyDocument, user?: PolicyUser): Promise { try { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const value = PolicyUtils.getObjectValue(doc, options.sourceField); return parseFloat(value); } catch (error) { @@ -126,7 +126,7 @@ export class SplitBlock { user?: PolicyUser ): Promise { let clone = PolicyUtils.cloneVC(ref, document); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); PolicyUtils.setObjectValue(clone, options.sourceField, newValue); let vc = VcDocument.fromJsonTree(clone.document); if (document.messageId) { @@ -179,7 +179,7 @@ export class SplitBlock { userId: string | null, actionStatusId: string ) { - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const threshold = parseFloat(options.threshold); const value = await this.calcDocValue(ref, document, user); diff --git a/policy-service/src/policy-engine/blocks/step-block.ts b/policy-service/src/policy-engine/blocks/step-block.ts index 89abe5f821..39b9edf0b9 100644 --- a/policy-service/src/policy-engine/blocks/step-block.ts +++ b/policy-service/src/policy-engine/blocks/step-block.ts @@ -139,7 +139,7 @@ export class InterfaceStepBlock { }) async releaseChild(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const index = ref.children.findIndex(c => c.uuid === event.sourceId); if ((options.cyclic && index !== -1) && (this.endIndexes[index])) { const user = event.user; @@ -166,7 +166,7 @@ export class InterfaceStepBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); let blockState: any; if (!this.state.hasOwnProperty(user.id)) { blockState = {}; diff --git a/policy-service/src/policy-engine/blocks/switch-block.ts b/policy-service/src/policy-engine/blocks/switch-block.ts index cb9f7a034c..48dd004a07 100644 --- a/policy-service/src/policy-engine/blocks/switch-block.ts +++ b/policy-service/src/policy-engine/blocks/switch-block.ts @@ -97,7 +97,7 @@ export class SwitchBlock { }) async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); ref.log(`switch: ${event.user?.id}`); const docs: IPolicyDocument | IPolicyDocument[] = event.data.data; diff --git a/policy-service/src/policy-engine/blocks/timer-block.ts b/policy-service/src/policy-engine/blocks/timer-block.ts index cbd9c48ec8..4eba7fc81c 100644 --- a/policy-service/src/policy-engine/blocks/timer-block.ts +++ b/policy-service/src/policy-engine/blocks/timer-block.ts @@ -115,17 +115,15 @@ export class TimerBlock { * @private */ private startCron(ref: AnyBlockType) { - const options = ref.getOptions(); - try { - let sd = moment(options.startDate).utc(); + let sd = moment(ref.options.startDate).utc(); if (sd.isValid()) { sd = moment().utc(); } this.endTime = Infinity; - if (options.endDate) { - const ed = moment(options.endDate).utc(); + if (ref.options.endDate) { + const ed = moment(ref.options.endDate).utc(); if (ed.isValid()) { this.endTime = ed.toDate().getTime(); } @@ -138,7 +136,7 @@ export class TimerBlock { let mask: string = ''; this.interval = 0; - switch (options.period) { + switch (ref.options.period) { case 'yearly': { mask = `${sd.minute()} ${sd.hour()} ${sd.date()} ${sd.month() + 1} *`; break; @@ -160,14 +158,14 @@ export class TimerBlock { break; } case 'custom': { - mask = options.periodMask; - this.interval = options.periodInterval; + mask = ref.options.periodMask; + this.interval = ref.options.periodInterval; break; } default: throw new Error('Bad period') } - ref.log(`start scheduler: ${mask}, ${options.startDate}, ${options.endDate}, ${options.periodInterval}`); + ref.log(`start scheduler: ${mask}, ${ref.options.startDate}, ${ref.options.endDate}, ${ref.options.periodInterval}`); if (this.interval > 1) { this.tickCount = 0; this.job = new CronJob(mask, () => { diff --git a/policy-service/src/policy-engine/blocks/token-action-block.ts b/policy-service/src/policy-engine/blocks/token-action-block.ts index 0e9fbf2cd5..ccb220db2e 100644 --- a/policy-service/src/policy-engine/blocks/token-action-block.ts +++ b/policy-service/src/policy-engine/blocks/token-action-block.ts @@ -90,7 +90,7 @@ export class TokenActionBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); return { id: ref.uuid, blockType: ref.blockType, @@ -119,7 +119,7 @@ export class TokenActionBlock { async runAction(event: IPolicyEvent) { const userId = event?.user?.userId; const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); ref.log(`runAction`); const field = options.accountId; const documents = event?.data?.data; diff --git a/policy-service/src/policy-engine/blocks/token-confirmation-block.ts b/policy-service/src/policy-engine/blocks/token-confirmation-block.ts index f22803d12b..d911cb9cc1 100644 --- a/policy-service/src/policy-engine/blocks/token-confirmation-block.ts +++ b/policy-service/src/policy-engine/blocks/token-confirmation-block.ts @@ -82,7 +82,7 @@ export class TokenConfirmationBlock { async getToken(user?: PolicyUser): Promise { if (!this.token) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); this.token = await ref.databaseServer.getToken(options.tokenId); } return this.token; @@ -94,7 +94,7 @@ export class TokenConfirmationBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const blockState: any = this.state[user?.id] || {}; const token = await this.getToken(user); const block: IPolicyGetData = { @@ -147,7 +147,7 @@ export class TokenConfirmationBlock { action: 'confirm' | 'skip' }, actionStatus: RecordActionStep) { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); ref.log(`setData`); if (!data) { @@ -216,7 +216,7 @@ export class TokenConfirmationBlock { hederaAccountKey: data.hederaAccountKey } - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (!account.hederaAccountKey) { throw new BlockActionError(`Key value is unknown`, ref.blockType, ref.uuid) @@ -266,7 +266,7 @@ export class TokenConfirmationBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); ref.log(`runAction`); - const options = ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const field = options.accountId; if (event) { diff --git a/policy-service/src/policy-engine/blocks/transformation-button-block.ts b/policy-service/src/policy-engine/blocks/transformation-button-block.ts index eab590b60f..2aff9ce223 100644 --- a/policy-service/src/policy-engine/blocks/transformation-button-block.ts +++ b/policy-service/src/policy-engine/blocks/transformation-button-block.ts @@ -66,7 +66,7 @@ export class TransformationButtonBlock { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, @@ -100,7 +100,7 @@ export class TransformationButtonBlock { tag: any }, _, actionStatus): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); const data: IPolicyDocument = blockData.document; const state: IPolicyEventState = { data }; const eventData = await ref.triggerEventSync(PolicyInputEventType.GetDataEvent, user, state, actionStatus); @@ -112,7 +112,7 @@ export class TransformationButtonBlock { return { data: eventData, - url: options?.url ?? '' + url: options && options.url ? options.url : '' }; } } diff --git a/policy-service/src/policy-engine/blocks/transformation-ui-addon.ts b/policy-service/src/policy-engine/blocks/transformation-ui-addon.ts index d7679aa32a..bd4342b2f6 100644 --- a/policy-service/src/policy-engine/blocks/transformation-ui-addon.ts +++ b/policy-service/src/policy-engine/blocks/transformation-ui-addon.ts @@ -42,8 +42,8 @@ export class TransformationUIAddon { */ async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); - + const options = await ref.getOptions(user); + return { id: ref.uuid, blockType: ref.blockType, diff --git a/policy-service/src/policy-engine/blocks/upload-vc-document-block.ts b/policy-service/src/policy-engine/blocks/upload-vc-document-block.ts index 83f3a87cda..4ae5ff1143 100644 --- a/policy-service/src/policy-engine/blocks/upload-vc-document-block.ts +++ b/policy-service/src/policy-engine/blocks/upload-vc-document-block.ts @@ -161,7 +161,7 @@ export class UploadVcDocumentBlock { }) async setData(user: PolicyUser, data: any, _, actionStatus: RecordActionStep): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); - const options = ref.getOptions(user); + const options = await ref.getOptions(user); if (!user.did) { throw new BlockActionError('User have no any did', ref.blockType, ref.uuid); diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index 0bc0149f17..67fedc3352 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -12,6 +12,7 @@ import { PolicyUser } from '../../policy-user.js'; import { ComponentsService } from '../components-service.js'; import { IDebugContext } from '../../block-engine/block-result.js'; import { RecordActionStep } from '../../record-action-step.js'; +import { PolicyUtils } from '../utils.js'; /** * Basic block decorator @@ -952,7 +953,6 @@ export function BasicBlock(options: Partial) { if(!row || row.updated || !row.properties || Object.keys(row.properties).length === 0) { properties = {}; const policyRows = await this.databaseServer.find(PolicyParameters, { policyId: this.policyId }); - for (const item of policyRows) { for (const config of item.config ?? []) { if( @@ -987,7 +987,7 @@ export function BasicBlock(options: Partial) { } if(properties && properties[this.tag]) { - return Object.assign({}, this.options, properties[this.tag]); + return PolicyUtils.deepAssign({}, this.options, properties[this.tag]); } else { return this.options; } diff --git a/policy-service/src/policy-engine/helpers/utils.ts b/policy-service/src/policy-engine/helpers/utils.ts index 1f4c4b50d7..e24c7f9938 100644 --- a/policy-service/src/policy-engine/helpers/utils.ts +++ b/policy-service/src/policy-engine/helpers/utils.ts @@ -2000,4 +2000,36 @@ export class PolicyUtils { } } } + + public static deepAssign(target, ...sources) { + if (target == null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + const isObject = (obj) => + obj && typeof obj === 'object' && !Array.isArray(obj); + + for (const source of sources) { + if (!isObject(source) && !Array.isArray(source)) continue; + + for (const key of Object.keys(source)) { + const value = source[key]; + + if (Array.isArray(value)) { + target[key] = value.map((item) => + isObject(item) ? this.deepAssign({}, item) : item + ); + } else if (isObject(value)) { + if (!isObject(target[key])) { + target[key] = {}; + } + this.deepAssign(target[key], value); + } else { + target[key] = value; + } + } + } + + return target; + } } diff --git a/policy-service/src/policy-engine/policy-engine.interface.ts b/policy-service/src/policy-engine/policy-engine.interface.ts index 4dbac66ee1..342723282a 100644 --- a/policy-service/src/policy-engine/policy-engine.interface.ts +++ b/policy-service/src/policy-engine/policy-engine.interface.ts @@ -476,7 +476,7 @@ export interface IPolicyBlock { user?: PolicyUser | string ): Promise; - getOptions(user?: PolicyUser | null): any; + getOptions(user?: PolicyUser | null): Promise; } /** From 300c0f5bf9fa2f4f450389a11ee2dbd763c50c06 Mon Sep 17 00:00:00 2001 From: Borys Date: Fri, 27 Feb 2026 19:47:32 -0500 Subject: [PATCH 11/24] lint fixes Signed-off-by: Borys --- api-gateway/src/api/service/policy.ts | 2 +- guardian-service/src/app.ts | 1 - .../src/policy-engine/policy-engine.service.ts | 1 - interfaces/src/helpers/policy-editable-field.ts | 6 ------ policy-service/src/api/policy-process.ts | 2 +- .../src/policy-engine/blocks/aggregate-block.ts | 13 ++++++------- .../src/policy-engine/blocks/calculate-block.ts | 9 ++++----- .../blocks/calculate-math-variables.ts | 2 +- .../src/policy-engine/blocks/create-token-block.ts | 2 +- .../src/policy-engine/blocks/custom-logic-block.ts | 4 ++-- .../src/policy-engine/blocks/extract-data-block.ts | 2 +- .../src/policy-engine/blocks/http-request-block.ts | 2 +- .../blocks/integration-button-block.ts | 2 +- .../src/policy-engine/blocks/math-block.ts | 4 ++-- .../src/policy-engine/blocks/notification.block.ts | 4 ++-- .../src/policy-engine/blocks/retirement-block.ts | 2 +- .../policy-engine/helpers/decorators/basic-block.ts | 1 - policy-service/src/policy-engine/helpers/utils.ts | 10 ++++++---- 18 files changed, 30 insertions(+), 39 deletions(-) diff --git a/api-gateway/src/api/service/policy.ts b/api-gateway/src/api/service/policy.ts index 12e66b5eb6..84825a68f1 100644 --- a/api-gateway/src/api/service/policy.ts +++ b/api-gateway/src/api/service/policy.ts @@ -714,7 +714,7 @@ export class PolicyApi { model.categories = policy.categories; model.projectSchema = policy.projectSchema; model.editableParametersSettings = policy.editableParametersSettings; - + const invalidedCacheTags = [`${PREFIXES.POLICIES}${policyId}/navigation`, `${PREFIXES.POLICIES}${policyId}/groups`, `${PREFIXES.SCHEMES}schema-with-sub-schemas`]; await this.cacheService.invalidate(getCacheKey([req.url, ...invalidedCacheTags], user)); diff --git a/guardian-service/src/app.ts b/guardian-service/src/app.ts index ecf74ae451..45cf7b2e61 100644 --- a/guardian-service/src/app.ts +++ b/guardian-service/src/app.ts @@ -226,7 +226,6 @@ Promise.all([ console.warn(error); } } - if (process.env.OVERRIDE_HEDERA_MIRROR_NODES_BASE_API) { Environment.setMirrorNodesBaseApi(process.env.OVERRIDE_HEDERA_MIRROR_NODES_BASE_API); } diff --git a/guardian-service/src/policy-engine/policy-engine.service.ts b/guardian-service/src/policy-engine/policy-engine.service.ts index 5301ecaed7..27ec0f76fd 100644 --- a/guardian-service/src/policy-engine/policy-engine.service.ts +++ b/guardian-service/src/policy-engine/policy-engine.service.ts @@ -4575,7 +4575,6 @@ export class PolicyEngineService { async (msg: { owner: IOwner, userDID: string, policyId: string }) => { try { const { userDID, policyId } = msg; - let result; const parameters = await DatabaseServer.getPolicyParameters(userDID, policyId); if(parameters && parameters.config?.length) { diff --git a/interfaces/src/helpers/policy-editable-field.ts b/interfaces/src/helpers/policy-editable-field.ts index a624db5cc6..b5cdf2f7c5 100644 --- a/interfaces/src/helpers/policy-editable-field.ts +++ b/interfaces/src/helpers/policy-editable-field.ts @@ -1,7 +1,4 @@ export class PolicyEditableFieldDTO { - constructor() { - } - public blockType: string; public blockTag: string; public propertyPath: string; @@ -34,9 +31,6 @@ export class PolicyEditableField { public label: string = ''; public shortDescription: string = ''; - constructor() { - } - toDTO(): PolicyEditableFieldDTO { const dto = new PolicyEditableFieldDTO(); dto.blockType = this.blockType; diff --git a/policy-service/src/api/policy-process.ts b/policy-service/src/api/policy-process.ts index 3870f12229..411fe99a86 100644 --- a/policy-service/src/api/policy-process.ts +++ b/policy-service/src/api/policy-process.ts @@ -123,7 +123,7 @@ Promise.all([ console.warn(error); } } - + if (process.env.OVERRIDE_HEDERA_MIRROR_NODES_BASE_API) { Environment.setMirrorNodesBaseApi(process.env.OVERRIDE_HEDERA_MIRROR_NODES_BASE_API); } diff --git a/policy-service/src/policy-engine/blocks/aggregate-block.ts b/policy-service/src/policy-engine/blocks/aggregate-block.ts index 27f10730be..8d661287a8 100644 --- a/policy-service/src/policy-engine/blocks/aggregate-block.ts +++ b/policy-service/src/policy-engine/blocks/aggregate-block.ts @@ -10,7 +10,6 @@ import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-abo import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfaces/external-event.js'; import { LocationType } from '@guardian/interfaces'; import { RecordActionStep } from '../record-action-step.js'; -import { PolicyUser } from '../policy-user.js'; /** * Aggregate block @@ -255,8 +254,9 @@ export class AggregateBlock { @ActionCallback({ output: [PolicyOutputEventType.RunEvent, PolicyOutputEventType.RefreshEvent] }) - private async tickAggregate(ref: AnyBlockType, document: any, userId: string | null, actionStatus: RecordActionStep, user?: PolicyUser) { - let options = await ref.getOptions(user); + private async tickAggregate(ref: AnyBlockType, document: any, userId: string | null, actionStatus: RecordActionStep) { + const user = await PolicyUtils.getDocumentOwner(ref, document, userId); + const options = await ref.getOptions(user); const { expressions, condition, disableUserGrouping, groupByFields } = options; const groupByUser = !disableUserGrouping; @@ -292,7 +292,6 @@ export class AggregateBlock { } if (result === true) { - const user = await PolicyUtils.getDocumentOwner(ref, document, userId); rawEntities = await this.removeDocuments(ref, rawEntities); const state: IPolicyEventState = { data: rawEntities }; // actionStatus.saveResult(state); @@ -358,13 +357,13 @@ export class AggregateBlock { for (const doc of docs) { await this.saveDocuments(ref, doc); if (aggregateType === 'cumulative') { - await this.tickAggregate(ref, doc, event?.user?.userId, event.actionStatus, event.user); + await this.tickAggregate(ref, doc, event?.user?.userId, event.actionStatus); } } } else { await this.saveDocuments(ref, docs); if (aggregateType === 'cumulative') { - await this.tickAggregate(ref, docs, event?.user?.userId, event.actionStatus, event.user); + await this.tickAggregate(ref, docs, event?.user?.userId, event.actionStatus); } } @@ -374,4 +373,4 @@ export class AggregateBlock { return event.data; } -} +} \ No newline at end of file diff --git a/policy-service/src/policy-engine/blocks/calculate-block.ts b/policy-service/src/policy-engine/blocks/calculate-block.ts index f7118be5c0..c6278042c7 100644 --- a/policy-service/src/policy-engine/blocks/calculate-block.ts +++ b/policy-service/src/policy-engine/blocks/calculate-block.ts @@ -75,7 +75,7 @@ export class CalculateContainerBlock { userId: string | null, user?: PolicyUser ): Promise { - let options = await ref.getOptions(user); + const options = await ref.getOptions(user); const fields = options.inputFields; let scope = {}; @@ -132,7 +132,7 @@ export class CalculateContainerBlock { const context = await ref.debugContext({ documents }); const contextDocuments = context.documents as IPolicyDocument | IPolicyDocument[]; - let options = await ref.getOptions(user); + const options = await ref.getOptions(user); const isArray = Array.isArray(contextDocuments); if (!contextDocuments || (isArray && !contextDocuments.length)) { @@ -178,7 +178,6 @@ export class CalculateContainerBlock { const isArray = Array.isArray(documents); const firstDocument = isArray ? documents[0] : documents; const relationships = []; - let options = await ref.getOptions(user); let accounts: any = {}; let tokens: any = {}; @@ -249,7 +248,7 @@ export class CalculateContainerBlock { } = metadata; // <-- new vc const VCHelper = new VcHelper(); - let options = await ref.getOptions(user); + const options = await ref.getOptions(user); const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const vcSubject: any = { @@ -323,7 +322,7 @@ export class CalculateContainerBlock { @CatchErrors() public async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - let options = await ref.getOptions(event.user); + const options = await ref.getOptions(event.user); if (options.inputDocuments === 'separate') { if (Array.isArray(event.data.data)) { diff --git a/policy-service/src/policy-engine/blocks/calculate-math-variables.ts b/policy-service/src/policy-engine/blocks/calculate-math-variables.ts index a20dadbb9b..8e89dd000e 100644 --- a/policy-service/src/policy-engine/blocks/calculate-math-variables.ts +++ b/policy-service/src/policy-engine/blocks/calculate-math-variables.ts @@ -159,7 +159,7 @@ export class CalculateMathVariables { public async run(scope: any, user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); const options = await ref.getOptions(user); - + const filters: any = {}; if (options.onlyOwnDocuments) { filters.owner = user.did; diff --git a/policy-service/src/policy-engine/blocks/create-token-block.ts b/policy-service/src/policy-engine/blocks/create-token-block.ts index 4e4261bcfe..86bbf07857 100644 --- a/policy-service/src/policy-engine/blocks/create-token-block.ts +++ b/policy-service/src/policy-engine/blocks/create-token-block.ts @@ -328,7 +328,7 @@ export class CreateTokenBlock { const user = event.user; const eventData = event.data; - let options = await ref.getOptions(user); + const options = await ref.getOptions(user); if (!this.state.tokenNumber) { this.state.tokenNumber = 0; diff --git a/policy-service/src/policy-engine/blocks/custom-logic-block.ts b/policy-service/src/policy-engine/blocks/custom-logic-block.ts index 857ee7a8bc..4fe184a3e4 100644 --- a/policy-service/src/policy-engine/blocks/custom-logic-block.ts +++ b/policy-service/src/policy-engine/blocks/custom-logic-block.ts @@ -179,7 +179,7 @@ export class CustomLogicBlock { try { const ref = PolicyComponentsUtils.GetBlockRef(this); const options = await ref.getOptions(user); - + let documents: IPolicyDocument[]; if (Array.isArray(state.data)) { documents = state.data; @@ -450,7 +450,7 @@ export class CustomLogicBlock { // <-- new vc const VCHelper = new VcHelper(); - let options = await ref.getOptions(user); + const options = await ref.getOptions(user); const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); const vcSubject: any = { diff --git a/policy-service/src/policy-engine/blocks/extract-data-block.ts b/policy-service/src/policy-engine/blocks/extract-data-block.ts index d956d16877..f607a8adb2 100644 --- a/policy-service/src/policy-engine/blocks/extract-data-block.ts +++ b/policy-service/src/policy-engine/blocks/extract-data-block.ts @@ -256,7 +256,7 @@ export class ExtractDataBlock { @CatchErrors() async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - let options = await ref.getOptions(event.user); + const options = await ref.getOptions(event.user); if (options.action === 'set') { await this.setAction(ref, event); diff --git a/policy-service/src/policy-engine/blocks/http-request-block.ts b/policy-service/src/policy-engine/blocks/http-request-block.ts index 1807262fe8..481e81a4ab 100644 --- a/policy-service/src/policy-engine/blocks/http-request-block.ts +++ b/policy-service/src/policy-engine/blocks/http-request-block.ts @@ -144,7 +144,7 @@ export class HttpRequestBlock { const ref = PolicyComponentsUtils.GetBlockRef(this); event.data.data = event.data.data || {}; - let options = await ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const variablesObj: any = { did: event?.user?.did, diff --git a/policy-service/src/policy-engine/blocks/integration-button-block.ts b/policy-service/src/policy-engine/blocks/integration-button-block.ts index 53a3edd174..c83509ff37 100644 --- a/policy-service/src/policy-engine/blocks/integration-button-block.ts +++ b/policy-service/src/policy-engine/blocks/integration-button-block.ts @@ -27,7 +27,7 @@ export class IntegrationButtonBlock { async getData(user: PolicyUser): Promise { const ref = PolicyComponentsUtils.GetBlockRef(this); const options = await ref.getOptions(user); - + const data: IPolicyGetData = { id: ref.uuid, blockType: ref.blockType, diff --git a/policy-service/src/policy-engine/blocks/math-block.ts b/policy-service/src/policy-engine/blocks/math-block.ts index 3110d045b7..f1175b7f9f 100644 --- a/policy-service/src/policy-engine/blocks/math-block.ts +++ b/policy-service/src/policy-engine/blocks/math-block.ts @@ -165,7 +165,7 @@ export class MathBlock { throw new BlockActionError('Invalid VC', ref.blockType, ref.uuid); } - let options = await ref.getOptions(user); + const options = await ref.getOptions(user); const sources: IPolicyDocument[] = await PolicyUtils.findRelationships(ref, documents); @@ -272,7 +272,7 @@ export class MathBlock { // <-- new vc const VCHelper = new VcHelper(); - let options = await ref.getOptions(user); + const options = await ref.getOptions(user); const outputSchema = await PolicyUtils.loadSchemaByID(ref, options.outputSchema); diff --git a/policy-service/src/policy-engine/blocks/notification.block.ts b/policy-service/src/policy-engine/blocks/notification.block.ts index 9516366c22..63c92b97a8 100644 --- a/policy-service/src/policy-engine/blocks/notification.block.ts +++ b/policy-service/src/policy-engine/blocks/notification.block.ts @@ -167,7 +167,7 @@ export class NotificationBlock { ): Promise<(title: string, message: string, userId: string) => void> { let fn; const options = await ref.getOptions(user); - + switch (options.type) { case NotificationType.INFO: fn = NotificationHelper.info; @@ -211,7 +211,7 @@ export class NotificationBlock { PolicyComponentsUtils.GetBlockRef(this); const options = await ref.getOptions(event.user); - + const notify = await this.getNotificationFunction(ref, event.user); switch (options.user) { diff --git a/policy-service/src/policy-engine/blocks/retirement-block.ts b/policy-service/src/policy-engine/blocks/retirement-block.ts index f2b8909cad..f105bb9176 100644 --- a/policy-service/src/policy-engine/blocks/retirement-block.ts +++ b/policy-service/src/policy-engine/blocks/retirement-block.ts @@ -325,7 +325,7 @@ export class RetirementBlock { async runAction(event: IPolicyEvent) { const ref = PolicyComponentsUtils.GetBlockRef(this); - let options = await ref.getOptions(event.user); + const options = await ref.getOptions(event.user); const docs = PolicyUtils.getArray(event.data.data); if (!docs.length && docs[0]) { diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index 67fedc3352..89d07fe04d 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -932,7 +932,6 @@ export function BasicBlock(options: Partial) { ); } - setPropValue(properties:any, path:string, value:any) { const keys = path.split('.'); const last = keys.pop(); diff --git a/policy-service/src/policy-engine/helpers/utils.ts b/policy-service/src/policy-engine/helpers/utils.ts index e24c7f9938..856a75bdab 100644 --- a/policy-service/src/policy-engine/helpers/utils.ts +++ b/policy-service/src/policy-engine/helpers/utils.ts @@ -2002,7 +2002,7 @@ export class PolicyUtils { } public static deepAssign(target, ...sources) { - if (target == null) { + if (target === null) { throw new TypeError('Cannot convert undefined or null to object'); } @@ -2010,20 +2010,22 @@ export class PolicyUtils { obj && typeof obj === 'object' && !Array.isArray(obj); for (const source of sources) { - if (!isObject(source) && !Array.isArray(source)) continue; + if (!isObject(source) && !Array.isArray(source)) { + continue; + } for (const key of Object.keys(source)) { const value = source[key]; if (Array.isArray(value)) { target[key] = value.map((item) => - isObject(item) ? this.deepAssign({}, item) : item + isObject(item) ? PolicyUtils.deepAssign({}, item) : item ); } else if (isObject(value)) { if (!isObject(target[key])) { target[key] = {}; } - this.deepAssign(target[key], value); + PolicyUtils.deepAssign(target[key], value); } else { target[key] = value; } From 80c27f9d4862e83105da2e4fbe4cac05f2568c62 Mon Sep 17 00:00:00 2001 From: Borys Date: Fri, 27 Feb 2026 20:03:10 -0500 Subject: [PATCH 12/24] lint fix Signed-off-by: Borys --- guardian-service/src/policy-engine/policy-engine.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guardian-service/src/policy-engine/policy-engine.service.ts b/guardian-service/src/policy-engine/policy-engine.service.ts index 8464d0dad9..00d5bef69d 100644 --- a/guardian-service/src/policy-engine/policy-engine.service.ts +++ b/guardian-service/src/policy-engine/policy-engine.service.ts @@ -61,7 +61,7 @@ import { IgnoreRule, SchemaStatus, PolicyEditableFieldDTO, - MigrationConfig, + MigrationConfig, MigrationRunStatus } from '@guardian/interfaces'; import { AccountId, PrivateKey } from '@hiero-ledger/sdk'; From 7d0ac6679f80669c301a4e1611dff50887e4b500 Mon Sep 17 00:00:00 2001 From: Borys Date: Sat, 28 Feb 2026 12:33:08 -0500 Subject: [PATCH 13/24] styles for config dialog Signed-off-by: Borys --- ...cy-parameters-config-dialog.component.html | 97 +++++++++---------- ...cy-parameters-config-dialog.component.scss | 64 ++++++++++-- ...licy-parameters-config-dialog.component.ts | 3 - .../select-block/select-block.component.scss | 2 +- .../src/helpers/policy-editable-field.ts | 3 - 5 files changed, 106 insertions(+), 63 deletions(-) diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html index 31d2f721a3..133444de37 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html @@ -5,53 +5,54 @@
- + +
- + + +
- + + +
- + + +
- - + +
- - -
-
- - + +
-
+
; visible: FormControl; applyTo: FormControl; - defaultLabel: FormControl; required: FormControl; label: FormControl; shortDescription: FormControl; @@ -141,7 +140,6 @@ export class PolicyParametersConfigDialog implements OnInit { visible: this.fb.control(m?.visible ?? [], { nonNullable: true, validators: [Validators.required] }), applyTo: this.fb.control(m?.applyTo ?? [], { nonNullable: true, validators: [Validators.required] }), label: this.fb.control(m?.label ?? '', { nonNullable: true, validators: [Validators.required] }), - defaultLabel: this.fb.control(m?.defaultLabel ?? null), required: this.fb.control(m?.required ?? false, { nonNullable: true }), shortDescription: this.fb.control(m?.shortDescription ?? '', { nonNullable: true }), }); @@ -177,7 +175,6 @@ export class PolicyParametersConfigDialog implements OnInit { field.visible = val.visible; field.applyTo = val.applyTo; field.label = val.label; - field.defaultLabel = val.defaultLabel; field.required = val.required; field.shortDescription = val.shortDescription; return field; diff --git a/frontend/src/app/modules/policy-engine/helpers/select-block/select-block.component.scss b/frontend/src/app/modules/policy-engine/helpers/select-block/select-block.component.scss index 2842126ad4..28786fe0c3 100644 --- a/frontend/src/app/modules/policy-engine/helpers/select-block/select-block.component.scss +++ b/frontend/src/app/modules/policy-engine/helpers/select-block/select-block.component.scss @@ -64,7 +64,7 @@ } .guardian-dropdown::ng-deep .p-dropdown { - border-radius: 0px !important; + border-radius: 0px; } .guardian-multiselect::ng-deep .p-multiselect { diff --git a/interfaces/src/helpers/policy-editable-field.ts b/interfaces/src/helpers/policy-editable-field.ts index b5cdf2f7c5..67874a0191 100644 --- a/interfaces/src/helpers/policy-editable-field.ts +++ b/interfaces/src/helpers/policy-editable-field.ts @@ -5,7 +5,6 @@ export class PolicyEditableFieldDTO { public visible: string[]; public applyTo: string[]; public label: string; - public defaultLabel: any; public required: boolean; public shortDescription: string; @@ -22,7 +21,6 @@ export class PolicyEditableField { public propertyPath: string = ''; public visible: string[] = []; public applyTo: string[] = []; - public defaultLabel: any = null; public required: boolean = false; public blocks: any[] = []; public properties: any[] = []; @@ -39,7 +37,6 @@ export class PolicyEditableField { dto.visible = this.visible; dto.applyTo = this.applyTo; dto.label = this.label; - dto.defaultLabel = this.defaultLabel; dto.required = this.required; dto.shortDescription = this.shortDescription; From 4f4bc661e8e0d53a2c7d65ae414d65fb0b57e631 Mon Sep 17 00:00:00 2001 From: Borys Date: Mon, 2 Mar 2026 00:53:51 -0500 Subject: [PATCH 14/24] formControls usage approach Signed-off-by: Borys --- .../policy-parameter-property.component.html | 58 +++++------ .../policy-parameter-property.component.scss | 8 +- .../policy-parameter-property.component.ts | 64 ++++++++----- .../policy-parameters-dialog.component.html | 4 +- .../policy-parameters-dialog.component.ts | 95 ++++++++++++++++++- .../policy-viewer/policy-viewer.component.ts | 8 +- 6 files changed, 175 insertions(+), 62 deletions(-) diff --git a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html index d17bc5b10f..43e2d9a8a7 100644 --- a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html +++ b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html @@ -6,9 +6,9 @@
@@ -22,9 +22,9 @@
@@ -36,9 +36,9 @@ {{ config.shortDescription }} @@ -50,14 +50,12 @@ @@ -73,9 +71,7 @@ @@ -83,8 +79,7 @@ {{ config.shortDescription }}
- +
-
-
- +
+
+
diff --git a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.scss b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.scss index 373438030b..6828f49839 100644 --- a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.scss +++ b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.scss @@ -45,6 +45,12 @@ height: 28px; padding: 6px 16px; } + + .property-label { + display: flex; + flex-direction: column; + gap: 5px; + } } .element-array-group { @@ -66,7 +72,7 @@ .element-array-delete { position: relative; - top: 10px; + top: 22px; } .property-label { diff --git a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.ts b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.ts index 0c7791a25c..1b0f2701c2 100644 --- a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.ts +++ b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.ts @@ -1,4 +1,5 @@ import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges, ViewEncapsulation, } from '@angular/core'; +import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; import { PolicyEditableFieldDTO } from '@guardian/interfaces'; import { DialogService } from 'primeng/dynamicdialog'; import { CodeEditorDialogComponent } from 'src/app/modules/policy-engine/dialogs/code-editor-dialog/code-editor-dialog.component'; @@ -15,6 +16,7 @@ import { PolicyBlock } from 'src/app/modules/policy-engine/structures'; encapsulation: ViewEncapsulation.None, }) export class PolicyParameterPropertyComponent implements OnInit { + @Input() control!: AbstractControl; @Input('block') currentBlock?: PolicyBlock; @Input('property') property!: any; @Input('collapse') collapse!: any; @@ -26,22 +28,6 @@ export class PolicyParameterPropertyComponent implements OnInit { rootPath: string; pathValue: string; - - get value(): any { - if(this.isArrayElement) { - return (this.config as any)[this.property?.name]; - } else { - return this.config.value; - } - } - - set value(v: any) { - if(this.isArrayElement) { - (this.config as any)[this.property?.name] = v; - } else { - this.config.value = v; - } - } pathOptions = [ { label: 'Root', value: '', title: ' ' }, @@ -66,20 +52,49 @@ export class PolicyParameterPropertyComponent implements OnInit { ) { } + get isArray(): boolean { return this.control instanceof FormArray; } + get fc(): FormControl { return this.control as FormControl; } + + + get rows(): AbstractControl[] { + return (this.control as FormArray).controls; + } + + get group(): FormGroup { + return this.control as FormGroup; + } + + get pathCtrl(): FormControl { + return this.group.controls['path'] as FormControl; + } + + get valueCtrl(): FormControl { + return this.group.controls['value'] as FormControl; + } + addItems() { this.needUpdate = true; - const item: any = {}; - for (const p of this.property?.items?.properties) { - item[p.name] = ''; + const rows = this.control as FormArray; + const group: Record = {}; + for (const p of this.property?.items?.properties ?? []) { + group[p.name] = new FormControl('', []); } - this.value.push(item); + rows.push(new FormGroup(group)); this.update.emit(); } - removeItems(i: number) { + rowGroup(row: AbstractControl): FormGroup { + return row as FormGroup; + } + + removeItems(index: number) { + const rows = this.control as FormArray; + + if (!rows || index < 0 || index >= rows.length) return; + + rows.removeAt(index); this.needUpdate = true; - this.value.splice(i, 1); this.update.emit(); } @@ -94,7 +109,6 @@ export class PolicyParameterPropertyComponent implements OnInit { } onPathPropertyChanged() { - this.value = this.rootPath + this.pathValue; this.onSave(); } @@ -110,13 +124,13 @@ export class PolicyParameterPropertyComponent implements OnInit { styleClass: 'guardian-dialog', data: { test: false, - expression: this.value, + expression: this.fc.value, readonly: this.readonly } }) dialogRef.onClose.subscribe(result => { if (result) { - this.value = result.expression; + this.fc.setValue(result.expression); if (result.type === 'save') { this.needUpdate = true; this.update.emit(); diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html index 15dbcb6e22..dab2582bb2 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html @@ -15,13 +15,14 @@ These settings will be used during policy execution. Please fill in all required fields where applicable.
-
@@ -38,6 +39,7 @@
diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.ts b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.ts index 811c075a3a..1bfb67ac67 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.ts +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { UntypedFormControl } from '@angular/forms'; +import { AbstractControl, FormArray, FormControl, FormGroup, UntypedFormControl, Validators } from '@angular/forms'; import { PolicyEditableFieldDTO, UserPermissions } from '@guardian/interfaces'; import { DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog'; import { RegisteredService } from '../../services/registered.service'; @@ -35,6 +35,20 @@ export class PolicyParametersDialog { public items: PolicyParameterItem[] = []; + public form: FormGroup; + + public pathOptions = [ + { label: 'Root', value: '', title: ' ' }, + { label: 'Document', value: 'document.', title: 'document.' }, + { label: 'Credential Subjects', value: 'document.credentialSubject.', title: 'document.credentialSubject.' }, + { label: 'First Credential Subjects', value: 'document.credentialSubject.0.', title: 'document.credentialSubject.0.' }, + { label: 'Last Credential Subjects', value: 'document.credentialSubject.L.', title: 'document.credentialSubject.L.' }, + { label: 'Verifiable Credentials', value: 'document.verifiableCredential.', title: 'document.verifiableCredential.' }, + { label: 'First Verifiable Credential', value: 'document.verifiableCredential.0.', title: 'document.verifiableCredential.0.' }, + { label: 'Last Verifiable Credential', value: 'document.verifiableCredential.L.', title: 'document.verifiableCredential.L.' }, + { label: 'Attributes', value: 'option.', title: 'option.' } + ]; + constructor( public ref: DynamicDialogRef, public config: DynamicDialogConfig, @@ -42,6 +56,10 @@ export class PolicyParametersDialog { private policyEngineService: PolicyEngineService ) { this.policyId = this.config.data?.policyId; + + this.form = new FormGroup({ + items: new FormArray>([]) + }); } ngOnInit() { @@ -68,13 +86,72 @@ export class PolicyParametersDialog { const block = structuredClone(this.blockInfo[field.blockType]); const property = this.findByPath(block.properties, field.propertyPath); - + if (!property) { + continue; + } this.items.push({ block, property, config: field }); + if (property.type === 'Array') { + const values = Array.isArray(field.value) ? field.value : []; + + const arr = new FormArray( + values.map(v => { + const g: Record = {}; + for (const p of property.items.properties ?? []) { + g[p.name] = new FormControl( + v?.[p.name] ?? null, + p.required ? [Validators.required] : [] + ); + } + return new FormGroup(g); + }) + ); + + this.form.addControl(field.propertyPath, arr); + } else if (property.type === 'Path') { + const initial = (field.value ?? '') as string; + const options: string[] = this.pathOptions.map(o => String(o.value ?? '')); + + let prefix = ''; + for (const opt of options.sort((a, b) => b.length - a.length)) { + if (initial.startsWith(opt)) { + prefix = opt; + break; + } + } + + const suffix = initial.slice(prefix.length); + this.form.addControl( + property.name, + new FormGroup({ + path: new FormControl(prefix, []), + value: new FormControl( + suffix, + field.required ? [Validators.required] : [] + ), + }) + ); + } + else { + this.form.addControl( + field.propertyPath, + new FormControl( + field.value ?? null, + field.required ? [Validators.required] : [] + ) + ); + } } + + setTimeout(() => { + Object.values(this.form.controls).forEach(ctrl => { + ctrl.markAsDirty(); + ctrl.markAsTouched(); + }); + }) } findByPath(items: any[], path: string): any | undefined { @@ -93,6 +170,20 @@ export class PolicyParametersDialog { } async onSubmit() { + for(let i=0; i< this.editableParameters.length; i++) { + const field = this.editableParameters[i]; + const item = this.items.find(item => item.config.propertyPath === field.propertyPath); + let value = null; + if(item && item.property.type === 'Path') { + const group = this.form.get(field.propertyPath) as FormGroup; + const path = group.get('path')?.value ?? ''; + value = path + (group.get('value')?.value ?? ''); + } else { + value = this.form.get(field.propertyPath)?.value; + } + field.value = value; + } + this.policyEngineService.saveParameters( this.policyId, this.editableParameters diff --git a/frontend/src/app/modules/policy-engine/policy-viewer/policy-viewer/policy-viewer.component.ts b/frontend/src/app/modules/policy-engine/policy-viewer/policy-viewer/policy-viewer.component.ts index 3492188279..e65f69ca46 100644 --- a/frontend/src/app/modules/policy-engine/policy-viewer/policy-viewer/policy-viewer.component.ts +++ b/frontend/src/app/modules/policy-engine/policy-viewer/policy-viewer/policy-viewer.component.ts @@ -278,7 +278,8 @@ export class PolicyViewerComponent implements OnInit, OnDestroy { this.policyEngineService.policy(policyId), this.policyEngineService.policyBlock(policyId, null), this.policyEngineService.getGroups(policyId, this.savepointIds), - this.externalPoliciesService.getActionRequestsCount({ policyId }) + this.externalPoliciesService.getActionRequestsCount({ policyId }), + this.policyEngineService.getParametersConfig(policyId), ])) ).subscribe( (value) => { @@ -286,6 +287,7 @@ export class PolicyViewerComponent implements OnInit, OnDestroy { this.policy = value[1]; this.groups = value[2] || []; const count: any = value[3]?.body || {}; + const editableParameters = value[4]; this.virtualUsers = []; this.isMultipleGroups = !!(this.policyInfo?.policyGroups && this.groups?.length); @@ -324,6 +326,10 @@ export class PolicyViewerComponent implements OnInit, OnDestroy { this.newRequestsExist = count.requestsCount > 0; this.newActionsExist = count.actionsCount > 0 || count.delayCount > 0; + + if (editableParameters?.length && editableParameters.some((p: any) => p.required && !p.value)) { + this.openParametersSettings(); + } }, (e) => { this.loading = false; }); From 6eab03502b753abb72cc1f34966a990e18e10fbf Mon Sep 17 00:00:00 2001 From: Borys Date: Mon, 2 Mar 2026 10:27:02 -0500 Subject: [PATCH 15/24] fixes Signed-off-by: Borys --- ...cy-parameters-config-dialog.component.scss | 1 + ...licy-parameters-config-dialog.component.ts | 2 ++ .../policy-parameters-dialog.component.html | 24 ++++++++++--------- .../policy-parameters-dialog.component.ts | 8 ++++--- .../policy-viewer.component.html | 2 +- .../policy-viewer/policy-viewer.component.ts | 2 +- 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss index 33ca258a66..0de6fbaabb 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss @@ -131,6 +131,7 @@ form { .custom { position: inherit; line-height: 16px; + overflow: visible; } } diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts index fe365ee735..acb5b33f10 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts @@ -122,6 +122,8 @@ export class PolicyParametersConfigDialog implements OnInit { const fg = this.fields.at(index) as FormGroup; fg.controls.blockTag.setValue(selected?.tag ?? selected); + this.policyEditableFields[index].properties = []; + this.policyTemplate.allBlocks.forEach(block => { if (block.tag === selected) { const props = this.registeredService.getCustomProperties(block.blockType); diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html index dab2582bb2..4c7d864ad1 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-dialog/policy-parameters-dialog.component.html @@ -15,17 +15,19 @@ These settings will be used during policy execution. Please fill in all required fields where applicable.
-
-
+ +
+
+
diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss index 0de6fbaabb..8f5062e38d 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.scss @@ -151,4 +151,14 @@ form { color: #23252E; } +} + +input.ng-invalid.ng-touched, +::ng-deep .parameter-dropdown.ng-invalid.ng-touched .p-dropdown, +::ng-deep .parameter-dropdown.ng-invalid.ng-touched .p-multiselect { + border-color: #f44336; +} + +::ng-deep .is-invalid .guardian-dropdown .p-dropdown { + border-color: #f44336; } \ No newline at end of file diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts index acb5b33f10..9628a67412 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.ts @@ -28,6 +28,7 @@ type PolicyForm = { }) export class PolicyParametersConfigDialog implements OnInit { loading = true; + submitted = false; form: FormGroup; policyTemplate: PolicyTemplate; policyEditableFields: PolicyEditableField[] = []; @@ -122,6 +123,10 @@ export class PolicyParametersConfigDialog implements OnInit { const fg = this.fields.at(index) as FormGroup; fg.controls.blockTag.setValue(selected?.tag ?? selected); + fg.controls.blockTag.markAsDirty(); + fg.controls.blockTag.markAsTouched(); + fg.controls.blockTag.updateValueAndValidity({ emitEvent: true }); + this.policyEditableFields[index].properties = []; this.policyTemplate.allBlocks.forEach(block => { @@ -185,6 +190,8 @@ export class PolicyParametersConfigDialog implements OnInit { } async submit(): Promise { + this.submitted = true; + if (this.form.invalid) { this.form.markAllAsTouched(); return; From bcf0bb4b22669d4f5c93ca6612a8ac9375a64020 Mon Sep 17 00:00:00 2001 From: Borys Date: Mon, 2 Mar 2026 18:14:25 +0100 Subject: [PATCH 17/24] fix basic-block Signed-off-by: Borys --- .../helpers/decorators/basic-block.ts | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index 89d07fe04d..03c9b9c28f 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -933,18 +933,35 @@ export function BasicBlock(options: Partial) { } setPropValue(properties:any, path:string, value:any) { + if (!path) return; + const keys = path.split('.'); const last = keys.pop(); + if (!last) return; + + let current = properties; + for (const key of keys) { - if(!(properties[key] && typeof properties[key] === 'object')) { - properties[key] = {}; + if(!(current[key] && typeof current[key] === 'object')) { + current[key] = {}; } + + current = current[key]; } - properties[last] = value; + + current[last] = value; } public async getOptions(user?: any) { + console.log('this.tag', this.tag); + console.log('this.options', this.options); + + if(this.tag === 'revoke_pp_sr'){ + console.log('!!!!!!!!!!!!!!!1'); + } + if(!user) { + console.log('no user'); return this.options; } const row = await DatabaseServer.getPolicyParameters(user.did, this.policyId); @@ -984,6 +1001,8 @@ export function BasicBlock(options: Partial) { } else { properties = row.properties; } + console.log('properties', properties); + console.log('deep assign', PolicyUtils.deepAssign({}, this.options, properties[this.tag])); if(properties && properties[this.tag]) { return PolicyUtils.deepAssign({}, this.options, properties[this.tag]); From f12d18543a584102d76f503b50e66ea2080e16b8 Mon Sep 17 00:00:00 2001 From: Borys Date: Tue, 3 Mar 2026 16:19:31 +0100 Subject: [PATCH 18/24] performance improvements and validation updates in the config dialog Signed-off-by: Borys --- ...cy-parameters-config-dialog.component.html | 2 +- ...licy-parameters-config-dialog.component.ts | 66 +++++++++++++------ 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html index bf8d33f536..c95987d5b6 100644 --- a/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html +++ b/frontend/src/app/modules/policy-engine/dialogs/policy-parameters-config-dialog/policy-parameters-config-dialog.component.html @@ -8,7 +8,7 @@ ; policyTemplate: PolicyTemplate; - policyEditableFields: PolicyEditableField[] = []; + policyEditableFields: PolicyEditableField[] = []; + filteredBlocks: Map = new Map(); + currentBlocks: PolicyBlock[] = []; additionalOptionsApplyTo = [ { _name: 'All' }, { _name: 'Self' } @@ -64,10 +66,25 @@ export class PolicyParametersConfigDialog implements OnInit { .pipe(takeUntil(this._destroy$)) .subscribe(blockInfo => { this.registeredService.registerConfig(blockInfo); + this.filterBlocks(); this.loadData(); }); } - + + filterBlocks(): void { + this.currentBlocks = []; + this.policyTemplate.allBlocks.forEach(block => { + const props = this.registeredService.getCustomProperties(block.blockType); + if(props && props.length > 0) { + const propsWithPath = this.setPath(props.filter((prop: any) => prop.editable), []); + if(propsWithPath && propsWithPath.length > 0) { + this.filteredBlocks.set(block.tag, propsWithPath); + this.currentBlocks.push(block); + } + } + }); + } + loadData() { const fields = this.policyTemplate.editableParametersSettings; if(!fields?.length) { @@ -75,8 +92,7 @@ export class PolicyParametersConfigDialog implements OnInit { } fields.forEach((field: PolicyEditableFieldDTO) => { - const block = this.policyTemplate.allBlocks.find(b => b.tag === field.blockTag); - if(!block) { + if(!this.filteredBlocks.has(field.blockTag)) { return; } @@ -104,6 +120,24 @@ export class PolicyParametersConfigDialog implements OnInit { return this.policyEditableFields[index]?.properties ?? []; } + private propertyInCurrentBlock(): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (!control.parent) return null; + + const propertyValue = control.value; + if (!propertyValue) return null; + + const blockTag = control.parent.get('blockTag')?.value; + if (!blockTag) return null; + + const props = this.filteredBlocks.get(blockTag) ?? []; + + return props.some(p => p.path === propertyValue) + ? null + : { notInOptions: true }; + }; + } + private setPath(properties:any[], result:any[], parent?:string) { if(!properties) return; @@ -121,29 +155,19 @@ export class PolicyParametersConfigDialog implements OnInit { onBlockChange(selected: any, index: number): void { const fg = this.fields.at(index) as FormGroup; - fg.controls.blockTag.setValue(selected?.tag ?? selected); + fg.controls.blockTag.setValue(selected); + + this.policyEditableFields[index].properties = this.filteredBlocks.get(selected) ?? []; fg.controls.blockTag.markAsDirty(); fg.controls.blockTag.markAsTouched(); - fg.controls.blockTag.updateValueAndValidity({ emitEvent: true }); - - this.policyEditableFields[index].properties = []; - - this.policyTemplate.allBlocks.forEach(block => { - if (block.tag === selected) { - const props = this.registeredService.getCustomProperties(block.blockType); - const propsWithPath = this.setPath(props.filter((prop: any) => prop.editable), []); - if(propsWithPath && propsWithPath.length > 0) { - this.policyEditableFields[index].properties = propsWithPath; - } - } - }); + fg.controls.property.updateValueAndValidity({ emitEvent: false }); } createFieldGroup(m?: Partial): FormGroup { return this.fb.group({ blockTag: this.fb.control(m?.blockTag ?? '', { nonNullable: true, validators: [Validators.required] }), - property: this.fb.control(m?.propertyPath ?? '', { nonNullable: true, validators: [Validators.required] }), + property: this.fb.control(m?.propertyPath ?? '', { nonNullable: true, validators: [Validators.required, this.propertyInCurrentBlock()] }), visible: this.fb.control(m?.visible ?? [], { nonNullable: true, validators: [Validators.required] }), applyTo: this.fb.control(m?.applyTo ?? [], { nonNullable: true, validators: [Validators.required] }), label: this.fb.control(m?.label ?? '', { nonNullable: true, validators: [Validators.required] }), From fd03c85350af684c08e847f236d844042b130eec Mon Sep 17 00:00:00 2001 From: Borys Date: Mon, 9 Mar 2026 04:29:08 +0100 Subject: [PATCH 19/24] =?UTF-8?q?=D1=81hanged=20the=20structure=20of=20pro?= =?UTF-8?q?perties=20in=20blocks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Borys --- .../common-property.component.html | 1 + .../common-property.component.ts | 38 +++++- .../services/blocks-information.ts | 20 ++-- .../blocks/calculate-math-addon.ts | 28 ++++- .../policy-engine/blocks/container-block.ts | 28 ++++- .../blocks/data-transformation-addon.ts | 9 +- .../blocks/document-validator-block.ts | 93 ++++++++++++++- .../blocks/documents-source-addon.ts | 111 +++++++++++++++++- .../blocks/external-data-block.ts | 37 +++++- .../src/policy-engine/blocks/group-manager.ts | 30 ++++- .../blocks/http-request-block.ts | 64 +++++++++- .../policy-engine/blocks/information-block.ts | 35 +++++- .../policy-engine/blocks/reassigning.block.ts | 29 ++++- .../src/policy-engine/blocks/switch-block.ts | 67 ++++++++++- .../helpers/decorators/basic-block.ts | 10 -- .../policy-engine/interfaces/block-about.ts | 8 ++ 16 files changed, 565 insertions(+), 43 deletions(-) diff --git a/frontend/src/app/modules/policy-engine/policy-configuration/common-property/common-property.component.html b/frontend/src/app/modules/policy-engine/policy-configuration/common-property/common-property.component.html index 157cdfcaac..e74fcbe278 100644 --- a/frontend/src/app/modules/policy-engine/policy-configuration/common-property/common-property.component.html +++ b/frontend/src/app/modules/policy-engine/policy-configuration/common-property/common-property.component.html @@ -101,6 +101,7 @@ + {{ property.text }} diff --git a/frontend/src/app/modules/policy-engine/policy-configuration/common-property/common-property.component.ts b/frontend/src/app/modules/policy-engine/policy-configuration/common-property/common-property.component.ts index 4c0e7e7645..2c9e238ee3 100644 --- a/frontend/src/app/modules/policy-engine/policy-configuration/common-property/common-property.component.ts +++ b/frontend/src/app/modules/policy-engine/policy-configuration/common-property/common-property.component.ts @@ -3,6 +3,7 @@ import { RegisteredService } from '../../services/registered.service'; import { PolicyBlock, RoleVariables, SchemaVariables, } from '../../structures'; import { DialogService } from 'primeng/dynamicdialog'; import { CodeEditorDialogComponent } from '../../dialogs/code-editor-dialog/code-editor-dialog.component'; +import { CustomConfirmDialogComponent } from 'src/app/modules/common/custom-confirm-dialog/custom-confirm-dialog.component'; /** * common property @@ -47,6 +48,7 @@ export class CommonPropertyComponent implements OnInit { loaded: boolean = false; schemas!: SchemaVariables[]; roles!: RoleVariables[]; + lastValue: any; constructor( private registeredService: RegisteredService, @@ -121,15 +123,47 @@ export class CommonPropertyComponent implements OnInit { } } } + + this.lastValue = this.value; } customPropCollapse(property: any) { return this.collapse; } + openConfirmationDialog(config: any) { + const dialogRef = this.dialog.open(CustomConfirmDialogComponent, { + showHeader: false, + width: '640px', + styleClass: 'guardian-dialog', + data: { + header: config.title, + text: config.description, + buttons: [ + { name: 'No', class: 'secondary' }, + { name: 'Yes', class: 'primary' } + ] + } + }); + + dialogRef.onClose.subscribe(result => { + if (result !== 'Yes') { + this.value = this.lastValue; + } + this.lastValue = this.value; + this.needUpdate = true; + this.update.emit(); + }); + } + onSave() { - this.needUpdate = true; - this.update.emit(); + if (this.property.confirmation && this.property.confirmation.condition == this.value) { + this.openConfirmationDialog(this.property.confirmation); + } else { + this.lastValue = this.value; + this.needUpdate = true; + this.update.emit(); + } } editCode($event: MouseEvent) { diff --git a/frontend/src/app/modules/policy-engine/services/blocks-information.ts b/frontend/src/app/modules/policy-engine/services/blocks-information.ts index b4f70d2219..103ba2b992 100644 --- a/frontend/src/app/modules/policy-engine/services/blocks-information.ts +++ b/frontend/src/app/modules/policy-engine/services/blocks-information.ts @@ -67,7 +67,7 @@ const Container: IBlockSetting = { group: BlockGroup.Main, header: BlockHeaders.UIComponents, factory: ContainerBlockComponent, - property: ContainerConfigComponent, + property: null, code: null, allowedChildren: [ { type: BlockType.Information }, @@ -181,7 +181,7 @@ const GroupManagerBlock: IBlockSetting = { group: BlockGroup.Main, header: BlockHeaders.UIComponents, factory: GroupManagerBlockComponent, - property: GroupManagerConfigComponent, + property: null, code: null, } @@ -191,7 +191,7 @@ const container: IBlockSetting = { group: BlockGroup.Main, header: BlockHeaders.UIComponents, factory: InformationBlockComponent, - property: InformationConfigComponent, + property: null, code: null } @@ -313,7 +313,7 @@ const Switch: IBlockSetting = { group: BlockGroup.Main, header: BlockHeaders.ServerBlocks, factory: null, - property: SwitchConfigComponent, + property: null, code: null, about: { output: (value: any, block: PolicyBlock) => { @@ -456,7 +456,7 @@ const ExternalData: IBlockSetting = { group: BlockGroup.Documents, header: BlockHeaders.ServerBlocks, factory: null, - property: ExternalDataConfigComponent, + property: null, code: null, allowedChildren: [{ type: BlockType.DocumentValidatorBlock, @@ -544,7 +544,7 @@ const ReassigningBlock: IBlockSetting = { group: BlockGroup.Documents, header: BlockHeaders.ServerBlocks, factory: null, - property: ReassigningConfigComponent, + property: null, code: null, } @@ -612,7 +612,7 @@ const DocumentsSourceAddon: IBlockSetting = { group: BlockGroup.Documents, header: BlockHeaders.Addons, factory: null, - property: SourceAddonConfigComponent, + property: null, code: null, allowedChildren: [{ type: BlockType.FiltersAddon, @@ -639,7 +639,7 @@ const DataTransformationAddon: IBlockSetting = { group: BlockGroup.UnGrouped, header: BlockHeaders.Addons, factory: null, - property: DataTransformationConfigComponent, + property: null, code: null, } @@ -679,7 +679,7 @@ const DocumentValidatorBlock: IBlockSetting = { group: BlockGroup.Documents, header: BlockHeaders.Addons, factory: null, - property: DocumentValidatorConfigComponent, + property: null, code: null } @@ -800,7 +800,7 @@ const CalculateMathAddon: IBlockSetting = { group: BlockGroup.Calculate, header: BlockHeaders.Addons, factory: null, - property: CalculateMathConfigComponent, + property: null, code: null, } diff --git a/policy-service/src/policy-engine/blocks/calculate-math-addon.ts b/policy-service/src/policy-engine/blocks/calculate-math-addon.ts index b5eccdd541..0ed23ba538 100644 --- a/policy-service/src/policy-engine/blocks/calculate-math-addon.ts +++ b/policy-service/src/policy-engine/blocks/calculate-math-addon.ts @@ -1,7 +1,7 @@ import { CalculateAddon } from '../helpers/decorators/index.js'; import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { IPolicyCalculateAddon } from '../policy-engine.interface.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { PolicyUser } from '../policy-user.js'; import { ExternalEvent, ExternalEventType } from '../interfaces/external-event.js'; import { LocationType } from '@guardian/interfaces'; @@ -22,7 +22,31 @@ import { LocationType } from '@guardian/interfaces'; control: ControlType.Special, input: null, output: null, - defaultEvent: false + defaultEvent: false, + properties: [{ + name: 'equations', + label: 'Equations', + title: 'Equations', + type: PropertyType.Array, + editable: true, + items: { + label: 'Field', + value: '@variable = @formula', + properties: [{ + name: 'variable', + label: 'Variable', + title: 'Variable', + type: PropertyType.Input, + editable: true + }, { + name: 'formula', + label: 'Formula', + title: 'Formula', + type: PropertyType.Input, + editable: true + }] + } + }] }, variables: [] }) diff --git a/policy-service/src/policy-engine/blocks/container-block.ts b/policy-service/src/policy-engine/blocks/container-block.ts index 5c6f9775e9..df5eb4d2ac 100644 --- a/policy-service/src/policy-engine/blocks/container-block.ts +++ b/policy-service/src/policy-engine/blocks/container-block.ts @@ -1,6 +1,6 @@ import { ContainerBlock } from '../helpers/decorators/container-block.js'; import { PolicyInputEventType } from '../interfaces/index.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { PolicyUser } from '../policy-user.js'; import { LocationType } from '@guardian/interfaces'; @@ -25,7 +25,31 @@ import { IPolicyGetData } from '@policy-engine/policy-engine.interface.js'; PolicyInputEventType.RefreshEvent, ], output: null, - defaultEvent: false + defaultEvent: false, + properties: [{ + name: 'uiMetaData', + label: 'UI', + title: 'UI Properties', + type: PropertyType.Group, + editable: true, + properties: [{ + name: 'title', + label: 'Title', + title: 'Title', + type: PropertyType.Input, + editable: true + },{ + name: 'type', + label: 'Type', + title: 'Type', + type: PropertyType.Select, + items: [ + { label: 'BLANK', value: 'blank' }, + { label: 'TABS', value: 'tabs' }, + ], + editable: true, + }] + }] }, variables: [] }) diff --git a/policy-service/src/policy-engine/blocks/data-transformation-addon.ts b/policy-service/src/policy-engine/blocks/data-transformation-addon.ts index 7c1e300f2e..49b5691f38 100644 --- a/policy-service/src/policy-engine/blocks/data-transformation-addon.ts +++ b/policy-service/src/policy-engine/blocks/data-transformation-addon.ts @@ -1,6 +1,6 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { IPolicyAddonBlock, IPolicyCalculateBlock, IPolicyDocument, IPolicyEventState } from '../policy-engine.interface.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { PolicyUser } from '../policy-user.js'; import { fileURLToPath } from 'url'; import { Worker } from 'node:worker_threads'; @@ -29,6 +29,13 @@ const filename = fileURLToPath(import.meta.url); ], output: null, defaultEvent: false, + properties: [{ + name: 'expression', + label: 'Expression', + title: 'Expression', + type: PropertyType.Code, + editable: true, + }] }, variables: [] }) diff --git a/policy-service/src/policy-engine/blocks/document-validator-block.ts b/policy-service/src/policy-engine/blocks/document-validator-block.ts index fb0aeced20..32bf2ec5ab 100644 --- a/policy-service/src/policy-engine/blocks/document-validator-block.ts +++ b/policy-service/src/policy-engine/blocks/document-validator-block.ts @@ -2,7 +2,7 @@ import { BlockActionError } from '../errors/index.js'; import { ActionCallback, ValidatorBlock } from '../helpers/decorators/index.js'; import { CatchErrors } from '../helpers/decorators/catch-errors.js'; import { IPolicyEvent, PolicyInputEventType, PolicyOutputEventType } from '../interfaces/index.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { AnyBlockType, IPolicyDocument, IPolicyEventState, IPolicyValidatorBlock } from '../policy-engine.interface.js'; import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { PolicyUtils } from '../helpers/utils.js'; @@ -33,7 +33,96 @@ import { LocationType } from '@guardian/interfaces'; PolicyOutputEventType.RefreshEvent, PolicyOutputEventType.ErrorEvent ], - defaultEvent: true + defaultEvent: true, + properties: [{ + name: 'conditions', + label: 'Conditions', + title: 'Conditions', + type: PropertyType.Array, + editable: true, + items: { + label: 'Condition', + value: '', + properties: [ + { + name: 'type', + label: 'Type', + title: 'Type', + type: PropertyType.Select, + items: [ + { label: 'Equal', value: 'equal' }, + { label: 'Not Equal', value: 'not_equal' }, + { label: 'In', value: 'in' }, + { label: 'Not In', value: 'not_in' } + ], + editable: true + }, + { + name: 'field', + label: 'Field', + title: 'Field', + type: PropertyType.Input, + editable: true + }, + { + name: 'value', + label: 'Value', + title: 'Value', + type: PropertyType.Input, + editable: true + }, + ] + } + }, + { + name: 'documentType', + label: 'Document Type', + title: 'Document Type', + type: PropertyType.Select, + items: [ + { label: 'VC Document', value: 'vc-document'}, + { label: 'VP Document', value: 'vp-document'}, + { label: 'Related VC Document', value: 'related-vc-document'}, + { label: 'Related VP Document', value: 'related-vp-document'} + ], + editable: false + }, + { + name: 'schema', + label: 'Check Schema', + title: 'Check Schema', + type: PropertyType.Schemas, + editable: true + }, + { + name: 'checkOwnerDocument', + label: 'Check Owned by User', + title: 'Check Owned by User', + type: PropertyType.Checkbox, + editable: true + }, + { + name: 'checkOwnerByGroupDocument', + label: 'Check Owned by Group', + title: 'Check Owned by Group', + type: PropertyType.Checkbox, + editable: true + }, + { + name: 'checkAssignDocument', + label: 'Check Assigned to User', + title: 'Check Assigned to User', + type: PropertyType.Checkbox, + editable: true + }, + { + name: 'checkAssignByGroupDocument', + label: 'Check Assigned to Group', + title: 'Check Assigned to Group', + type: PropertyType.Checkbox, + editable: true + }, + ] }, variables: [ { path: 'options.schema', alias: 'schema', type: 'Schema' } diff --git a/policy-service/src/policy-engine/blocks/documents-source-addon.ts b/policy-service/src/policy-engine/blocks/documents-source-addon.ts index ab9d8ee8d5..487e1a9388 100644 --- a/policy-service/src/policy-engine/blocks/documents-source-addon.ts +++ b/policy-service/src/policy-engine/blocks/documents-source-addon.ts @@ -2,7 +2,7 @@ import { SourceAddon, StateField } from '../helpers/decorators/index.js'; import { BlockActionError } from '../errors/index.js'; import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { IPolicyAddonBlock, IPolicyDocument } from '../policy-engine.interface.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { PolicyUser } from '../policy-user.js'; import { PolicyUtils, QueryType } from '../helpers/utils.js'; import ObjGet from 'lodash.get'; @@ -24,7 +24,114 @@ import { LocationType } from '@guardian/interfaces'; control: ControlType.Special, input: null, output: null, - defaultEvent: false + defaultEvent: false, + properties: [{ + name: 'dataType', + label: 'Data Type', + title: 'Data Type', + type: PropertyType.Select, + items: [ + { label: 'Collection (VC)', value: 'vc-documents' }, + { label: 'Collection (DID)', value: 'did-documents' }, + { label: 'Collection (Approve)', value: 'approve' }, + { label: 'Collection (VP)', value: 'vp-documents' } + ], + editable: true + }, { + name: 'schema', + label: 'Schema', + title: 'Schema', + type: PropertyType.Schemas, + editable: true + }, { + name: 'onlyOwnDocuments', + label: 'Owned by User', + title: 'Owned by User', + type: PropertyType.Checkbox, + editable: true + }, { + name: 'onlyOwnByGroupDocuments', + label: 'Owned by Group', + title: 'Owned by Group', + type: PropertyType.Checkbox, + editable: true + }, { + name: 'onlyAssignDocuments', + label: 'Assigned to User', + title: 'Assigned to User', + type: PropertyType.Checkbox, + editable: true + }, { + name: 'onlyAssignByGroupDocuments', + label: 'Assigned to Group', + title: 'Assigned to Group', + type: PropertyType.Checkbox, + editable: true + }, { + name: 'hidePreviousVersions', + label: 'Hide Previous Versions', + title: 'Hide Previous Versions', + type: PropertyType.Checkbox, + editable: true + }, { + name: 'orderField', + label: 'Order Field', + title: 'Order Field', + type: PropertyType.Input, + editable: true + }, { + name: 'orderDirection', + label: 'Order Direction', + title: 'Order Direction', + type: PropertyType.Select, + items: [ + { label: 'None', value: '' }, + { label: 'ASC', value: 'ASC' }, + { label: 'DESC', value: 'DESC' } + ], + editable: true + }, { + name: 'filters', + label: 'Filters', + title: 'Filters', + type: PropertyType.Array, + editable: true, + items: { + label: 'Field', + value: '', + properties: [{ + name: 'type', + label: 'Type', + title: 'Type', + type: PropertyType.Select, + items: [ + { label: 'Equal', value: 'equal'}, + { label: 'Not Equal', value: 'not_equal'}, + { label: 'In', value: 'in'}, + { label: 'Not In', value: 'not_in'}, + { label: 'Greater Than', value: 'gt'}, + { label: 'Greater Than or Equal', value: 'gte'}, + { label: 'Less Than', value: 'lt'}, + { label: 'Less Than or Equal', value: 'lte'}, + { label: 'User Defined', value: 'user_defined'} + ], + editable: true + }, { + name: 'field', + label: 'Field', + title: 'Field', + type: PropertyType.Path, + editable: false + }, { + name: 'value', + label: 'Value', + title: 'Value', + type: PropertyType.Input, + editable: true + }] + } + } + ] }, variables: [ { path: 'options.schema', alias: 'schema', type: 'Schema' } diff --git a/policy-service/src/policy-engine/blocks/external-data-block.ts b/policy-service/src/policy-engine/blocks/external-data-block.ts index 325defb6ca..174e301991 100644 --- a/policy-service/src/policy-engine/blocks/external-data-block.ts +++ b/policy-service/src/policy-engine/blocks/external-data-block.ts @@ -3,7 +3,7 @@ import { DocumentSignature, LocationType, Schema } from '@guardian/interfaces'; import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { CatchErrors } from '../helpers/decorators/catch-errors.js'; import { PolicyOutputEventType } from '../interfaces/index.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { AnyBlockType, IPolicyDocument, IPolicyEventState, IPolicyValidatorBlock } from '../policy-engine.interface.js'; import { BlockActionError } from '../errors/index.js'; import { PolicyUser } from '../policy-user.js'; @@ -36,7 +36,40 @@ import { RecordActionStep } from '../record-action-step.js'; PolicyOutputEventType.RefreshEvent, PolicyOutputEventType.ErrorEvent ], - defaultEvent: true + defaultEvent: true, + properties: [{ + name: 'entityType', + label: 'Entity Type', + title: 'Entity Type', + type: PropertyType.Input, + editable: false + }, + { + name: 'schema', + label: 'Schema', + title: 'Schema', + type: PropertyType.Schemas, + editable: false + }, + { + name: 'relayerAccount', + label: 'Set Relayer Account', + title: 'Set Relayer Account', + type: PropertyType.Checkbox, + editable: false + }, + { + name: 'forceRelayerAccount', + label: 'Force User Account', + title: 'Force User Account', + type: PropertyType.Select, + items: [ + { label: '', value: '' }, + { label: 'Pre-set user account', value: 'preset' }, + { label: 'Current user account', value: 'current' }, + ], + editable: false + }] }, variables: [ { path: 'options.schema', alias: 'schema', type: 'Schema' } diff --git a/policy-service/src/policy-engine/blocks/group-manager.ts b/policy-service/src/policy-engine/blocks/group-manager.ts index e8d401d542..43b061426e 100644 --- a/policy-service/src/policy-engine/blocks/group-manager.ts +++ b/policy-service/src/policy-engine/blocks/group-manager.ts @@ -1,7 +1,7 @@ import { EventBlock } from '../helpers/decorators/index.js'; import { GroupAccessType, GroupRelationshipType, LocationType } from '@guardian/interfaces'; import { IPolicyGetData, IPolicyInterfaceBlock } from '../policy-engine.interface.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { PolicyInputEventType } from '../interfaces/index.js'; import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { PolicyUser } from '../policy-user.js'; @@ -30,7 +30,33 @@ import { RecordActionStep } from '../record-action-step.js'; PolicyInputEventType.RefreshEvent, ], output: null, - defaultEvent: false + defaultEvent: false, + properties: [ + { + name: 'canInvite', + label: 'Can Invite', + title: 'Can Invite', + type: PropertyType.Select, + default: 'owner', + items: [ + { label: 'Group Owner', value: 'owner'}, + { label: 'All', value: 'all'} + ], + editable: true + }, + { + name: 'canDelete', + label: 'Can Delete', + title: 'Can Delete', + type: PropertyType.Select, + default: 'owner', + items: [ + { label: 'Group Owner', value: 'owner'}, + { label: 'All', value: 'all'} + ], + editable: true + } + ] }, variables: [] }) diff --git a/policy-service/src/policy-engine/blocks/http-request-block.ts b/policy-service/src/policy-engine/blocks/http-request-block.ts index 481e81a4ab..aab8ac9cb6 100644 --- a/policy-service/src/policy-engine/blocks/http-request-block.ts +++ b/policy-service/src/policy-engine/blocks/http-request-block.ts @@ -1,5 +1,5 @@ import { BasicBlock } from '../helpers/decorators/basic-block.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { IPolicyEvent, PolicyInputEventType, PolicyOutputEventType } from '../interfaces/index.js'; import { ActionCallback } from '../helpers/decorators/index.js'; import { CatchErrors } from '../helpers/decorators/catch-errors.js'; @@ -32,7 +32,67 @@ import { LocationType, WorkerTaskType } from '@guardian/interfaces'; PolicyOutputEventType.RefreshEvent, PolicyOutputEventType.ErrorEvent ], - defaultEvent: true + defaultEvent: true, + properties: [{ + name: 'url', + label: 'URL', + title: 'URL', + type: PropertyType.Input, + editable: true + },{ + name: 'body', + label: 'Body', + title: 'Body', + type: PropertyType.Select, + items: [], + editable: true + },{ + name: 'body', + label: 'Body', + title: 'Body', + type: PropertyType.Code, + editable: true + }, + { + name: 'headers', + label: 'Headers', + title: 'Headers', + type: PropertyType.Array, + editable: true, + items: { + label: 'Header', + value: '', + properties: [ + { + name: 'name', + label: 'Header Name', + title: 'Header Name', + type: PropertyType.Input, + editable: true + }, + { + name: 'value', + label: 'Header Value', + title: 'Header Value', + type: PropertyType.Input, + editable: true + }, + { + name: 'included', + label: 'Included value', + title: 'Included value', + type: PropertyType.Checkbox, + text: 'Include value in exported policy', + confirmation: { + title: 'title', + description: 'description', + condition: true + }, + editable: true + }, + ] + } + }] }, variables: [] }) diff --git a/policy-service/src/policy-engine/blocks/information-block.ts b/policy-service/src/policy-engine/blocks/information-block.ts index 1391ae6058..55cb69b217 100644 --- a/policy-service/src/policy-engine/blocks/information-block.ts +++ b/policy-service/src/policy-engine/blocks/information-block.ts @@ -1,6 +1,6 @@ import { DataSourceBlock } from '../helpers/decorators/data-source-block.js'; import { PolicyInputEventType } from '../interfaces/index.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { PolicyUser } from '../policy-user.js'; import { LocationType } from '@guardian/interfaces'; @@ -25,7 +25,38 @@ import { IPolicyGetData } from '@policy-engine/policy-engine.interface.js'; PolicyInputEventType.RefreshEvent, ], output: null, - defaultEvent: false + defaultEvent: false, + properties: [{ + name: 'uiMetaData', + label: 'UI', + title: 'UI Properties', + type: PropertyType.Group, + editable: true, + properties: [{ + name: 'title', + label: 'Title', + title: 'Title', + type: PropertyType.Input, + editable: true + }, + { + name: 'description', + label: 'Description', + title: 'Description', + type: PropertyType.Input, + editable: true + },{ + name: 'type', + label: 'Type', + title: 'Type', + type: PropertyType.Select, + items: [ + { label: 'LOADER', value: 'loader'}, + { label: 'TEXT', value: 'text'} + ], + editable: true, + }] + }] }, variables: [] }) diff --git a/policy-service/src/policy-engine/blocks/reassigning.block.ts b/policy-service/src/policy-engine/blocks/reassigning.block.ts index 48f9cb67e9..96fd2a0c23 100644 --- a/policy-service/src/policy-engine/blocks/reassigning.block.ts +++ b/policy-service/src/policy-engine/blocks/reassigning.block.ts @@ -4,7 +4,7 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { AnyBlockType, IPolicyBlock, IPolicyDocument, IPolicyEventState } from '../policy-engine.interface.js'; import { CatchErrors } from '../helpers/decorators/catch-errors.js'; import { IPolicyEvent, PolicyInputEventType, PolicyOutputEventType } from '../interfaces/index.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { PolicyUser } from '../policy-user.js'; import { PolicyUtils } from '../helpers/utils.js'; import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfaces/external-event.js'; @@ -35,7 +35,32 @@ import { RecordActionStep } from '../record-action-step.js'; PolicyOutputEventType.RefreshEvent, PolicyOutputEventType.ErrorEvent ], - defaultEvent: true + defaultEvent: true, + properties: [ + { + name: 'issuer', + label: 'Issuer', + title: 'Issuer', + type: PropertyType.Select, + editable: true, + items: [ + { label: 'Current User', value: ''}, + { label: 'Document Owner', value: 'owner'}, + { label: 'Policy Owner', value: 'policyOwner'} + ] + }, + { + name: 'actor', + label: 'Actor', + title: 'Actor', + type: PropertyType.Select, + editable: true, + items: [ + { label: 'Current User', value: ''}, + { label: 'Document Owner', value: 'owner'}, + { label: 'Document Issuer', value: 'issuer'} + ] + }] }, variables: [] }) diff --git a/policy-service/src/policy-engine/blocks/switch-block.ts b/policy-service/src/policy-engine/blocks/switch-block.ts index 48dd004a07..2b148617a9 100644 --- a/policy-service/src/policy-engine/blocks/switch-block.ts +++ b/policy-service/src/policy-engine/blocks/switch-block.ts @@ -3,7 +3,7 @@ import { PolicyComponentsUtils } from '../policy-components-utils.js'; import { VcDocumentDefinition as VcDocument } from '@guardian/common'; import { PolicyUtils } from '../helpers/utils.js'; import { IPolicyEvent, PolicyInputEventType, PolicyOutputEventType } from '../interfaces/index.js'; -import { ChildrenType, ControlType } from '../interfaces/block-about.js'; +import { ChildrenType, ControlType, PropertyType } from '../interfaces/block-about.js'; import { PolicyUser } from '../policy-user.js'; import { IPolicyDocument, IPolicyEventState } from '../policy-engine.interface.js'; import { ExternalDocuments, ExternalEvent, ExternalEventType } from '../interfaces/external-event.js'; @@ -29,7 +29,70 @@ import { LocationType } from '@guardian/interfaces'; output: [ PolicyOutputEventType.RefreshEvent ], - defaultEvent: false + defaultEvent: false, + properties: [ + { + name: 'executionFlow', + label: 'Execution Flow', + title: 'Execution Flow', + type: PropertyType.Select, + editable: true, + items: [ + {label: 'First True', value: 'firstTrue'}, + {label: 'All True', value: 'allTrue'} + ] + }, { + name: 'conditions', + label: 'Conditions', + title: 'Conditions', + type: PropertyType.Array, + editable: true, + items: { + label: 'Condition Type', + value: '', + properties: [ + { + name: 'tag', + label: 'Condition tag', + title: 'Condition tag', + type: PropertyType.Input, + editable: true + }, + { + name: 'type', + label: 'Type', + title: 'Type', + type: PropertyType.Select, + items: [ + { label: 'Equal', value: 'equal'}, + { label: 'Not Equal', value: 'not_equal'}, + { label: 'Unconditional', value: 'unconditional'} + ], + editable: true + }, + { + name: 'condition', + label: 'Condition', + title: 'Condition', + type: PropertyType.Input, + editable: true + }, + { + name: 'actor', + label: 'Actor', + title: 'Actor', + type: PropertyType.Select, + editable: true, + items: [ + { label: 'Current User', value: ''}, + { label: 'Document Owner', value: 'owner'}, + { label: 'Document Issuer', value: 'issuer'} + ] + } + ] + } + }, + ] }, variables: [] }) diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index 03c9b9c28f..e7d7617295 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -953,15 +953,7 @@ export function BasicBlock(options: Partial) { } public async getOptions(user?: any) { - console.log('this.tag', this.tag); - console.log('this.options', this.options); - - if(this.tag === 'revoke_pp_sr'){ - console.log('!!!!!!!!!!!!!!!1'); - } - if(!user) { - console.log('no user'); return this.options; } const row = await DatabaseServer.getPolicyParameters(user.did, this.policyId); @@ -1001,8 +993,6 @@ export function BasicBlock(options: Partial) { } else { properties = row.properties; } - console.log('properties', properties); - console.log('deep assign', PolicyUtils.deepAssign({}, this.options, properties[this.tag])); if(properties && properties[this.tag]) { return PolicyUtils.deepAssign({}, this.options, properties[this.tag]); diff --git a/policy-service/src/policy-engine/interfaces/block-about.ts b/policy-service/src/policy-engine/interfaces/block-about.ts index 2893d135b3..805af8cb4a 100644 --- a/policy-service/src/policy-engine/interfaces/block-about.ts +++ b/policy-service/src/policy-engine/interfaces/block-about.ts @@ -79,6 +79,12 @@ export interface BlockProperties { visible?: string; editable?: boolean; + + confirmation?: { + title: string, + description: string, + condition: any + } } /** @@ -109,6 +115,8 @@ export interface CheckboxProperties extends BlockProperties { * Property type */ type: PropertyType.Checkbox; + + text?: string; } /** From 3984ec1a63a066b08bb23b663e16299769236cac Mon Sep 17 00:00:00 2001 From: Borys Date: Mon, 9 Mar 2026 04:33:31 +0100 Subject: [PATCH 20/24] lint fix Signed-off-by: Borys --- .../src/policy-engine/blocks/external-data-block.ts | 2 +- .../src/policy-engine/blocks/information-block.ts | 2 +- .../src/policy-engine/blocks/switch-block.ts | 2 +- .../policy-engine/helpers/decorators/basic-block.ts | 10 +++++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/policy-service/src/policy-engine/blocks/external-data-block.ts b/policy-service/src/policy-engine/blocks/external-data-block.ts index 174e301991..b20fb7e1ad 100644 --- a/policy-service/src/policy-engine/blocks/external-data-block.ts +++ b/policy-service/src/policy-engine/blocks/external-data-block.ts @@ -57,7 +57,7 @@ import { RecordActionStep } from '../record-action-step.js'; title: 'Set Relayer Account', type: PropertyType.Checkbox, editable: false - }, + }, { name: 'forceRelayerAccount', label: 'Force User Account', diff --git a/policy-service/src/policy-engine/blocks/information-block.ts b/policy-service/src/policy-engine/blocks/information-block.ts index 55cb69b217..d280aff8aa 100644 --- a/policy-service/src/policy-engine/blocks/information-block.ts +++ b/policy-service/src/policy-engine/blocks/information-block.ts @@ -39,7 +39,7 @@ import { IPolicyGetData } from '@policy-engine/policy-engine.interface.js'; type: PropertyType.Input, editable: true }, - { + { name: 'description', label: 'Description', title: 'Description', diff --git a/policy-service/src/policy-engine/blocks/switch-block.ts b/policy-service/src/policy-engine/blocks/switch-block.ts index 2b148617a9..dfbc7f750d 100644 --- a/policy-service/src/policy-engine/blocks/switch-block.ts +++ b/policy-service/src/policy-engine/blocks/switch-block.ts @@ -91,7 +91,7 @@ import { LocationType } from '@guardian/interfaces'; } ] } - }, + }, ] }, variables: [] diff --git a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts index e7d7617295..b3c4da1a04 100644 --- a/policy-service/src/policy-engine/helpers/decorators/basic-block.ts +++ b/policy-service/src/policy-engine/helpers/decorators/basic-block.ts @@ -933,12 +933,16 @@ export function BasicBlock(options: Partial) { } setPropValue(properties:any, path:string, value:any) { - if (!path) return; + if (!path) { + return; + } const keys = path.split('.'); const last = keys.pop(); - if (!last) return; - + if (!last) { + return; + } + let current = properties; for (const key of keys) { From fd32022dba587c51d01cf349d048aca2fdd9c776 Mon Sep 17 00:00:00 2001 From: Borys Date: Tue, 10 Mar 2026 16:33:27 +0100 Subject: [PATCH 21/24] fixed nested path field in array type Signed-off-by: Borys --- .../policy-parameter-property.component.html | 110 +++++++-------- .../policy-parameter-property.component.scss | 11 +- .../policy-parameter-property.component.ts | 24 +--- .../policy-parameters-dialog.component.ts | 52 +------- .../parameter-document-path.component.html | 22 +++ .../parameter-document-path.component.scss | 0 .../paramter-document-path.component.ts | 125 ++++++++++++++++++ .../policy-engine/policy-engine.module.ts | 2 + 8 files changed, 208 insertions(+), 138 deletions(-) create mode 100644 frontend/src/app/modules/policy-engine/helpers/parameter-document-path/parameter-document-path.component.html create mode 100644 frontend/src/app/modules/policy-engine/helpers/parameter-document-path/parameter-document-path.component.scss create mode 100644 frontend/src/app/modules/policy-engine/helpers/parameter-document-path/paramter-document-path.component.ts diff --git a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html index 43e2d9a8a7..7fdbd9dfed 100644 --- a/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html +++ b/frontend/src/app/components/policy-parameter-property/policy-parameter-property.component.html @@ -1,90 +1,72 @@
- + + {{ config.shortDescription }} + +
- +
- + + {{ config.shortDescription }} + +
- + + {{ config.shortDescription }} + +
- {{ config.shortDescription }} + {{ config.shortDescription }} -
- - - - -
+ +
@@ -103,7 +85,9 @@ [readonly]="readonly" [block]="currentBlock" (update)="onSave()" - [control]="rowGroup(rowCtrl).controls[p.name]"> + [control]="rowGroup(rowCtrl).controls[p.name]" + [isArrayElement]="true" + >