Skip to content

Commit

Permalink
feat: sync flows over websocket
Browse files Browse the repository at this point in the history
  • Loading branch information
Tethik committed Aug 13, 2024
1 parent 0757ba0 commit 15b6cb2
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 66 deletions.
7 changes: 7 additions & 0 deletions api/src/ws/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ export function attachWebsocketServer(server: Server, dal: DataAccessLayer) {
server.tellClientsToRefetch("links", { objectType, objectId });
});

dal.flowService.on("updated-for", ({ modelId, dataFlowId }) => {
const server = wssRegistry.get(modelId);
log.debug(`flows was updated for ${modelId} ${dataFlowId}`);
if (!server) return;
server.tellClientsToRefetch("flows", { modelId, dataFlowId });
});

// Clean up leftover websocket servers
const cleanupInterval = setInterval(() => {
log.debug(`Number active channels: ${wssRegistry.size}`);
Expand Down
3 changes: 1 addition & 2 deletions app/src/api/gram/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ export const BASE_URL = `${window.location.origin}`;
export const api = createApi({
tagTypes: [
"ActionItems",
"Controls",
"Flow",
"Controls",
"Flows",
"Mitigations",
"Model",
Expand Down
6 changes: 2 additions & 4 deletions app/src/api/gram/flows.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ const flowsApi = api.injectEndpoints({
return response.flows;
},
providesTags: (result, error, arg) => [
{ type: "Flows", id: `${arg.modelId}-${arg.dataFlowId}` },
...result.map((flow) => ({ type: "Flow", id: flow.id })),
{ type: "Flows", id: `${arg.modelId}-${arg.dataFlowId}` },
],
}),
createFlow: build.mutation({
Expand Down Expand Up @@ -39,8 +38,7 @@ const flowsApi = api.injectEndpoints({
}),
transformResponse: (response, meta, arg) => response,
// providesTags: (result, error, arg) => [{ type: "Flow", id: arg.flowId }],
invalidatesTags: (result, error, arg) => [
{ type: "Flow", id: arg.flowId },
invalidatesTags: (result, error, arg) => [
{ type: "Flows" },
],
}),
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/model/board/Board.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export default function Board() {
useEffect(() => {
setStage((prevStage) => ({
...prevStage,
panning: cursorType === CURSOR_PAN ? true : false,
panning: cursorType === CURSOR_PAN,
}));
}, [cursorType]);

Expand Down
32 changes: 12 additions & 20 deletions app/src/components/model/panels/left/Flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,15 @@ import {
Box,
Divider,
FormControl,
FormControlLabel,
IconButton,
InputLabel,
MenuItem,
Paper,
Select,
Switch,
TextField,
Tooltip,
Tooltip
} from "@mui/material";
import { useState } from "react";
import { useEffect, useState } from "react";
import { useGetFlowAttributesQuery } from "../../../../api/gram/attributes";
import {
useDeleteFlowMutation,
Expand All @@ -27,25 +25,14 @@ import {
import { useReadOnly } from "../../../../hooks/useReadOnly";
import { EditableTypography } from "../../../elements/EditableTypography";

function DynamicSwitch({ value, onChange, label, ...props }) {
return (
<FormControlLabel
labelPlacement="start"
control={
<Switch
checked={value}
onChange={(e) => onChange({ target: { value: e.target.checked } })}
{...props}
/>
}
label={label}
/>
);
}

function DynamicDropdown({ value, onChange, label, attribute, ...props }) {
const { options, allowMultiple, allowCustomValue } = attribute;
const [val, setVal] = useState(value);

useEffect(() => {
setVal(value)
}, [value]);

return (
<FormControl fullWidth>
<Autocomplete
Expand Down Expand Up @@ -77,6 +64,11 @@ function DynamicDropdown({ value, onChange, label, attribute, ...props }) {

function DynamicTextField({ value, onChange, label, attribute, ...props }) {
const [val, setVal] = useState(value);

useEffect(() => {
setVal(value)
}, [value]);

return (
<TextField
{...props}
Expand Down
16 changes: 12 additions & 4 deletions app/src/redux/middleware/webSocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ function bind(dispatch, modelId) {
"Mitigations",
"Suggestions",
"ActionItems",
"Flows"
])
);
};
Expand Down Expand Up @@ -158,10 +159,6 @@ function refetch(dispatch, event, modelId) {
break;

case "links":
// dispatch(api.util.invalidateTags(["Links"]));
// For some reason the below didn't work.
// console.log(event);

dispatch(
api.util.invalidateTags([
{
Expand All @@ -171,6 +168,17 @@ function refetch(dispatch, event, modelId) {
])
);
break;

case "flows":
dispatch(
api.util.invalidateTags([
{
type: "Flows",
id: `${event.args.modelId}-${event.args.dataFlowId}`,
},
])
);
break;

// case "model":
// dispatch(api.util.invalidateTags(["Model"]));
Expand Down
42 changes: 7 additions & 35 deletions core/src/data/flow/FlowDataService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ export class FlowDataService extends EventEmitter {
createdBy,
]);

// this.notifyUpdatedFor(objectType, objectId);

const flow = new Flow(
res.rows[0].id,
res.rows[0].model_id,
Expand All @@ -94,6 +92,8 @@ export class FlowDataService extends EventEmitter {
res.rows[0].updated_at
);

this.emit("updated-for", { modelId, dataFlowId });

return flow;
}

Expand All @@ -104,48 +104,20 @@ export class FlowDataService extends EventEmitter {
attributes: FlowAttributes
): Promise<void> {
const query = `
UPDATE flows SET summary = $1, origin_component_id = $2, attributes = $3 WHERE id = $4
UPDATE flows SET summary = $1, origin_component_id = $2, attributes = $3 WHERE id = $4 RETURNING *
`;

await this.pool.query(query, [summary, originComponentId, attributes, id]);
const res = await this.pool.query(query, [summary, originComponentId, attributes, id]);
this.emit("updated-for", { modelId: res.rows[0].model_id, dataFlowId: res.rows[0].data_flow_id });
}

async deleteFlow(id: number): Promise<void> {
const query = `
DELETE FROM flows WHERE id = $1 RETURNING *
`;

await this.pool.query(query, [id]);
// const res = await this.pool.query(query, [id]);
// if (res.rows.length > 0) {
// const objectType = res.rows[0].object_type;
// const objectId = res.rows[0].object_id;

// // this.notifyUpdatedFor(objectType, objectId);
// }
const res = await this.pool.query(query, [id]);
this.emit("updated-for", { modelId: res.rows[0].model_id, dataFlowId: res.rows[0].data_flow_id });
}

// async notifyUpdatedFor(objectType: LinkObjectType, objectId: LinkObjectId) {
// let modelId: string | undefined;
// if (objectType === LinkObjectType.Threat) {
// const threat = await this.dal.threatService.getById(objectId);
// if (threat) {
// modelId = threat.modelId;
// }
// } else if (objectType === LinkObjectType.Control) {
// const control = await this.dal.controlService.getById(objectId);
// if (control) {
// modelId = control.modelId;
// }
// } else if (objectType === LinkObjectType.Model) {
// modelId = objectId;
// }

// if (modelId) {
// this.emit("updated-for", { modelId, objectType, objectId });
// }
// }

async copyFlowsBetweenModels(
srcModelId: string,
targetModelId: string,
Expand Down

0 comments on commit 15b6cb2

Please sign in to comment.