Skip to content

Commit

Permalink
Merge branch 'collab-findings-bugfixes-2' into 'main'
Browse files Browse the repository at this point in the history
Collab findings bugfixes 2

See merge request reportcreator/reportcreator!521
  • Loading branch information
MWedl committed Apr 17, 2024
2 parents 31f4552 + e4348f2 commit 7202fac
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 22 deletions.
16 changes: 9 additions & 7 deletions frontend/src/stores/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ export const useProjectStore = defineStore('project', {
// notes: ProjectNote[],
getByIdSync: Promise<PentestProject> | null,
notesCollabState: CollabStoreState<{ notes: {[key: string]: ProjectNote}}>,
reportingCollabState: CollabStoreState<{ findings: {[key: string]: PentestFinding }, sections: {[key: string]: ReportSection } }>,
reportingCollabState: CollabStoreState<{
project: {id: string, project_type: string, override_finding_order: boolean},
findings: {[key: string]: PentestFinding },
sections: {[key: string]: ReportSection }
}>,
}
},
}),
Expand Down Expand Up @@ -102,9 +106,8 @@ export const useProjectStore = defineStore('project', {
getByIdSync: null,
notesCollabState: makeCollabStoreState({
websocketPath: `/ws/pentestprojects/${projectId}/notes/`,
initialData: { notes: {} },
handleAdditionalWebSocketMessages: (msgData: any) => {
const collabState = this.data[projectId].notesCollabState;
initialData: { notes: {} as {[key: string]: ProjectNote} },
handleAdditionalWebSocketMessages: (msgData: any, collabState) => {
if (msgData.type === CollabEventType.SORT && msgData.path === 'notes') {
for (const note of Object.values(collabState.data.notes)) {
const no = msgData.sort.find((n: ProjectNote) => n.id === note.id);
Expand All @@ -119,9 +122,8 @@ export const useProjectStore = defineStore('project', {
}),
reportingCollabState: makeCollabStoreState({
websocketPath: `/ws/pentestprojects/${projectId}/reporting/`,
initialData: { project: {}, findings: {}, sections: {} },
handleAdditionalWebSocketMessages: (msgData: any) => {
const collabState = this.data[projectId].reportingCollabState;
initialData: { project: {} as any, findings: {} as {[key: string]: PentestFinding}, sections: {} as {[key: string]: ReportSection} },
handleAdditionalWebSocketMessages: (msgData: any, collabState) => {
if (msgData.type === CollabEventType.SORT && msgData.path === 'findings') {
for (const finding of Object.values(collabState.data.findings)) {
const fo = msgData.sort.find((n: PentestFinding) => n.id === finding.id);
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/stores/usernotes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ export const useUserNotesStore = defineStore('usernotes', {
notesCollabState: makeCollabStoreState({
websocketPath: '/ws/pentestusers/self/notes/',
initialData: { notes: {} as {[key: string]: UserNote} },
handleAdditionalWebSocketMessages: (msgData: any) => {
const collabState = (this as any).notesCollabState;
handleAdditionalWebSocketMessages: (msgData: any, collabState) => {
if (msgData.type === CollabEventType.SORT && msgData.path === 'notes') {
for (const note of Object.values(collabState.data.notes) as UserNote[]) {
const no = msgData.sort.find((n: UserNote) => n.id === note.id);
Expand Down
33 changes: 20 additions & 13 deletions frontend/src/utils/collab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export type CollabStoreState<T> = {
websocketPath: string;
connectionError?: { error: any, message?: string };
websocketConnectionLostTimeout?: ReturnType<typeof throttle>;
handleAdditionalWebSocketMessages?: (event: any) => boolean;
handleAdditionalWebSocketMessages?: (event: any, collabState: CollabStoreState<T>) => boolean;
perPathState: Map<string, {
sendUpdateTextThrottled: ReturnType<typeof throttle>;
unconfirmedTextUpdates: TextUpdate[];
Expand Down Expand Up @@ -74,7 +74,7 @@ export type CollabStoreState<T> = {
export function makeCollabStoreState<T>(options: {
websocketPath: string,
initialData: T,
handleAdditionalWebSocketMessages?: (event: any) => boolean
handleAdditionalWebSocketMessages?: (event: any, storeState: CollabStoreState<T>) => boolean
}): CollabStoreState<T> {
return {
data: options.initialData,
Expand Down Expand Up @@ -166,7 +166,7 @@ export function useCollab<T = any>(storeState: CollabStoreState<T>) {
storeState.version = msgData.version;
}

if (storeState.handleAdditionalWebSocketMessages?.(msgData)) {
if (storeState.handleAdditionalWebSocketMessages?.(msgData, storeState)) {
// Already handled
} else if (msgData.type === CollabEventType.INIT) {
storeState.connectionState = CollabConnectionState.OPEN;
Expand All @@ -187,32 +187,27 @@ export function useCollab<T = any>(storeState: CollabStoreState<T>) {
v.sendUpdateTextThrottled.cancel();
}
}
// Filter out invalid selections
for (const a of [storeState.awareness.self].concat(Object.values(storeState.awareness.other))) {
if (a.path && (msgData.path === a.path || msgData.path.startsWith(a.path + '.')) && a.selection) {
const text = get(storeState.data as Object, a.path);
if (typeof text !== 'string' || !a.selection.ranges.every(r => r.from >= 0 && r.to <= (text || '').length)) {
a.selection = undefined;
}
}
}

// Update local state
set(storeState.data as Object, msgData.path, msgData.value);

removeInvalidSelections(msgData.path);
} else if (msgData.type === CollabEventType.UPDATE_TEXT) {
receiveUpdateText(msgData);
} else if (msgData.type === CollabEventType.CREATE) {
set(storeState.data as Object, msgData.path, msgData.value);
} else if (msgData.type === CollabEventType.DELETE) {
const pathParts = msgData.path.split('.');
const parentList = get(storeState.data as Object, pathParts.slice(0, -1).join('.'));
const parentPath = pathParts.slice(0, -1).join('.');
const parentList = get(storeState.data as Object, parentPath);
const parentListIndex = Number.parseInt(pathParts.slice(-1)?.[0].startsWith('[') ? pathParts.slice(-1)[0].slice(1, -1) : undefined);

if (Array.isArray(parentList) && !Number.isNaN(parentListIndex)) {
parentList!.splice(parentListIndex, 1);
} else {
unset(storeState.data as Object, msgData.path);
}
removeInvalidSelections(parentPath);
} else if (msgData.type === CollabEventType.CONNECT) {
if (msgData.client_id !== storeState.clientID) {
// Add new client
Expand Down Expand Up @@ -541,6 +536,18 @@ export function useCollab<T = any>(storeState: CollabStoreState<T>) {
}
}

function removeInvalidSelections(path?: string) {
// Filter out invalid selections
for (const a of [storeState.awareness.self].concat(Object.values(storeState.awareness.other))) {
if (a.path && (!path || path === a.path || path.startsWith(a.path + '.')) && a.selection) {
const text = get(storeState.data as Object, a.path);
if (typeof text !== 'string' || !a.selection.ranges.every(r => r.from >= 0 && r.to <= (text || '').length)) {
a.selection = undefined;
}
}
}
}

function onCollabEvent(event: any) {
if (event.type === CollabEventType.UPDATE_KEY) {
updateKey(event);
Expand Down

0 comments on commit 7202fac

Please sign in to comment.