diff --git a/common/flow.d.ts b/common/flow.d.ts index 6cdb1ff..b2a4c31 100644 --- a/common/flow.d.ts +++ b/common/flow.d.ts @@ -112,11 +112,16 @@ interface ImportState { classes: string[] } +type PropertyValue = { + value: string|null, + type: "default"|"custom" +} + interface Component extends Positionable { id: Uuid, type: string, name: string, - properties: {[name: string]: string|null} + properties: {[name: string]: PropertyValue} visibleProperties?: string[] running?: ComponentState parentGroup?: Uuid|null @@ -194,10 +199,9 @@ interface ConnectionSize { interface Connection { id: Uuid, name: string|null, - errors: string[], attributes: string[], source: {id: Uuid, port: string|null}, - sourceRelationships: {[name: string]: boolean}, + sourceRelationships: string[], destination: {id: Uuid, port: string|null}, flowFileExpiration: string, swapThreshold: string|null, diff --git a/examples/minifi/agent-cpp.dockerfile b/examples/minifi/agent-cpp.dockerfile index 99e0a33..3d2d013 100644 --- a/examples/minifi/agent-cpp.dockerfile +++ b/examples/minifi/agent-cpp.dockerfile @@ -1,6 +1,7 @@ FROM apache/nifi-minifi-cpp:latest RUN echo "nifi.c2.enable=true" >> /opt/minifi/minifi-current/conf/minifi.properties && \ + echo "nifi.c2.rest.path.base=http://c2:13405/api" >> /opt/minifi/minifi-current/conf/minifi.properties && \ echo "nifi.c2.flow.base.url=http://c2:13405/api/flows" >> /opt/minifi/minifi-current/conf/minifi.properties && \ echo "nifi.c2.rest.url=http://c2:13405/api/heartbeat" >> /opt/minifi/minifi-current/conf/minifi.properties && \ echo "nifi.c2.rest.url.ack=http://c2:13405/api/acknowledge" >> /opt/minifi/minifi-current/conf/minifi.properties && \ diff --git a/server/src/utils/flow-serializer.ts b/server/src/utils/flow-serializer.ts index 5586a06..c3f9b9e 100644 --- a/server/src/utils/flow-serializer.ts +++ b/server/src/utils/flow-serializer.ts @@ -37,7 +37,7 @@ export function SerializeFlow(id: string, flow: FlowObject): string { for (const conn of flow.connections) { const src = flow.processors.find(proc => conn.source.id === proc.id)!; const dst = flow.processors.find(proc => conn.destination.id === proc.id)!; - const rels = Object.keys(conn.sourceRelationships).filter(rel => conn.sourceRelationships[rel]); + const rels = conn.sourceRelationships; result += " - name: " + (conn.name ?? `${src.name}/${rels.join(",")}/${dst.name}`) + "\n"; result += " id: " + conn.id + "\n"; result += " source name: " + src.name + "\n"; diff --git a/server/src/utils/json-flow-serializer.ts b/server/src/utils/json-flow-serializer.ts index 5fe21be..cd0ef93 100644 --- a/server/src/utils/json-flow-serializer.ts +++ b/server/src/utils/json-flow-serializer.ts @@ -108,7 +108,7 @@ function serializeProcessGroup(id: Uuid | null, flow: FlowObject): object { }).map(conn => { const src = findComponent(flow, conn.source.id)!; const dst = findComponent(flow, conn.destination.id)!; - const rels = Object.keys(conn.sourceRelationships).filter(rel => conn.sourceRelationships[rel]); + const rels = conn.sourceRelationships; return { "position": { "x": typeof conn.midPoint === "number" ? conn.midPoint : (conn.midPoint?.x ?? 0.0), @@ -159,11 +159,11 @@ function findComponent(flow: FlowObject, id: Uuid): Component | undefined | null flow.funnels.find(val => val.id === id); } -function filterNullish(obj: { [key: string]: string | null }): { [key: string]: string } { +function filterNullish(obj: { [key: string]: PropertyValue }): { [key: string]: string } { let result: { [key: string]: string } = {}; for (let key in obj) { - if (isNullish(obj[key])) continue; - result[key] = obj[key]!; + if (isNullish(obj[key].value)) continue; + result[key] = obj[key].value; } return result; } @@ -268,7 +268,6 @@ function deserializeProcessGroup(flow_object: FlowObject, group_id: Uuid | null, flow_object.connections = flow_object.connections.concat(process_group_json.connections.map((conn: any) => ({ id: conn.identifier, name: conn.name, - errors: [], attributes: [], source: { id: conn.source.id, @@ -362,7 +361,7 @@ function fixFlowObject(flow_object: FlowObject) { if (processor_manifest && processor_manifest.propertyDescriptors) { for (let property_name in processor_manifest.propertyDescriptors) { if (!(property_name in processor.properties)) { - processor.properties[property_name] = null; + processor.properties[property_name].value = null; } } } @@ -379,22 +378,12 @@ function fixFlowObject(flow_object: FlowObject) { if (service_manifest && service_manifest.propertyDescriptors) { for (let property_name in service_manifest.propertyDescriptors) { if (!(property_name in service.properties)) { - service.properties[property_name] = null; + service.properties[property_name].value = null; } } } } for (let connection of flow_object.connections) { - const source_processor = flow_object.processors.find(processor => processor.id === connection.source.id); - if (source_processor) { - const source_manifest = flow_object.manifest.processors.find(processor_manifest => processor_manifest.type === source_processor.type); - if (source_manifest) { - for (let relationship of source_manifest.supportedRelationships) { - if (!(relationship.name in connection.sourceRelationships)) { - connection.sourceRelationships[relationship.name] = false; - } - } - } - } + connection.sourceRelationships = [] } } diff --git a/website/src/components/connection-editor/index.tsx b/website/src/components/connection-editor/index.tsx index 9d70830..63d9e2e 100644 --- a/website/src/components/connection-editor/index.tsx +++ b/website/src/components/connection-editor/index.tsx @@ -5,7 +5,7 @@ import { InputField } from "../component-editor-input"; import { Toggle } from "../component-editor-toggle"; import "./index.scss" -export function ConnectionEditor(props: {model: Connection, readonly?: boolean}) { +export function ConnectionEditor(props: {model: Connection, supportedRels: string[], readonly?: boolean, errors: ErrorObject[]}) { const flow_context = useContext(FlowContext); const setModel = React.useMemo(()=>{ return (fn: (curr: Connection)=>Connection) => flow_context!.updateConnection(props.model.id, fn); @@ -24,7 +24,7 @@ export function ConnectionEditor(props: {model: Connection, readonly?: boolean})