Skip to content

Commit

Permalink
[MRG] Merge pull request #385 from dfir-iris/develop
Browse files Browse the repository at this point in the history
Fix major collaboration issue in notes
  • Loading branch information
whikernel authored Jan 18, 2024
2 parents 2fca5a8 + a78f632 commit 53879ee
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 2.4.3
current_version = 2.4.4
commit = True
tag = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(-(?P<release>.*)-(?P<build>\d+))?
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<p align="center">
Incident Response Investigation System
<br>
<i>Current Version v2.4.3</i>
<i>Current Version v2.4.4</i>
<br>
<a href="https://v200.beta.dfir-iris.org">Online Demonstration</a>
</p>
Expand Down Expand Up @@ -52,7 +52,7 @@ git clone https://github.com/dfir-iris/iris-web.git
cd iris-web

# Checkout to the last tagged version
git checkout v2.4.3
git checkout v2.4.4

# Copy the environment file
cp .env.model .env
Expand Down
8 changes: 4 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ services:
build:
context: docker/db
container_name: iriswebapp_db
image: iriswebapp_db:v2.4.3
image: iriswebapp_db:v2.4.4
restart: always
# Used for debugging purposes, should be deleted for production
ports:
Expand All @@ -47,7 +47,7 @@ services:
build:
context: .
dockerfile: docker/webApp/Dockerfile
image: iriswebapp_app:v2.4.3
image: iriswebapp_app:v2.4.4
container_name: iriswebapp_app
command: ['nohup', './iris-entrypoint.sh', 'iriswebapp']
volumes:
Expand Down Expand Up @@ -85,7 +85,7 @@ services:
build:
context: .
dockerfile: docker/webApp/Dockerfile
image: iriswebapp_app:v2.4.3
image: iriswebapp_app:v2.4.4
container_name: iriswebapp_worker
command: ['./wait-for-iriswebapp.sh', 'app:8000', './iris-entrypoint.sh', 'iris-worker']
volumes:
Expand Down Expand Up @@ -121,7 +121,7 @@ services:
args:
NGINX_CONF_GID: 1234
NGINX_CONF_FILE: nginx.conf
image: iriswebapp_nginx:v2.4.3
image: iriswebapp_nginx:v2.4.4
container_name: iriswebapp_nginx
environment:
- IRIS_UPSTREAM_SERVER
Expand Down
2 changes: 1 addition & 1 deletion source/app/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ class CeleryConfig:
# --------- APP ---------
class Config:
# Handled by bumpversion
IRIS_VERSION = "v2.4.3" # DO NOT EDIT THIS LINE MANUALLY
IRIS_VERSION = "v2.4.4" # DO NOT EDIT THIS LINE MANUALLY

if os.environ.get('IRIS_DEMO_VERSION') is not None and os.environ.get('IRIS_DEMO_VERSION') != 'None':
IRIS_VERSION = os.environ.get('IRIS_DEMO_VERSION')
Expand Down
93 changes: 80 additions & 13 deletions source/app/static/assets/js/iris/case.notes.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,24 @@ const preventFormDefaultBehaviourOnSubmit = (event) => {
};


function Collaborator( session_id, note_id ) {
function Collaborator( session_id, n_id ) {
this.collaboration_socket = collaborator_socket;

this.channel = "case-" + session_id + "-notes";

this.collaboration_socket.off("change-note");
this.collaboration_socket.off("clear_buffer-note");
this.collaboration_socket.off("save-note");
this.collaboration_socket.off("leave-note");
this.collaboration_socket.off("join-note");
this.collaboration_socket.off("pong-note");
this.collaboration_socket.off("disconnect");


this.collaboration_socket.on("change-note", function (data) {
if (data.note_id !== note_id) return;
// Set as int to avoid type mismatch
if (parseInt(data.note_id) !== parseInt(note_id)) return;

let delta = JSON.parse(data.delta);
last_applied_change = delta;
$("#content_typing").text(data.last_change + " is typing..");
Expand All @@ -35,13 +46,13 @@ function Collaborator( session_id, note_id ) {
}.bind());

this.collaboration_socket.on("clear_buffer-note", function () {
if (data.note_id !== note_id) return;
if (parseInt(data.note_id) !== parseInt(note_id)) return;
just_cleared_buffer = true;
note_editor.setValue("");
}.bind());

this.collaboration_socket.on("save-note", function (data) {
if (data.note_id !== note_id) return;
if (parseInt(data.note_id) !== parseInt(note_id)) return;
sync_note(note_id)
.then(function () {
$("#content_last_saved_by").text("Last saved by " + data.last_saved);
Expand All @@ -58,7 +69,7 @@ function Collaborator( session_id, note_id ) {
});

this.collaboration_socket.on('join-note', function (data) {
if (data.note_id !== note_id) return;
if (parseInt(data.note_id) !== parseInt(note_id)) return;
if ((data.user in ppl_viewing)) return;
ppl_viewing.set(filterXSS(data.user), 1);
refresh_ppl_list(session_id, note_id);
Expand Down Expand Up @@ -112,6 +123,50 @@ async function get_remote_note(note_id) {
}

async function sync_note(node_id) {
// Get the remote note
let remote_note = await get_remote_note(node_id);
if (remote_note.status !== 'success') {
return;
}

// Get the local note
let local_note = note_editor.getValue();

// If the local note is empty, set it to the remote note
if (local_note === '') {
note_editor.setValue(remote_note.data.note_content, -1);
return;
}

// If the local note is not empty, check if it is different from the remote note
if (local_note !== remote_note.data.note_content) {
swal({
title: 'Note conflict',
text: 'The note has been saved by someone else. Do you want to overwrite your changes?',
icon: 'warning',
buttons: {
cancel: {
text: 'Cancel',
value: null,
visible: true,
},
confirm: {
text: 'Overwrite',
value: true,
}
},
dangerMode: true,
closeOnEsc: false,
allowOutsideClick: false,
allowEnterKey: false
})
.then((overwrite) => {
if (overwrite) {
// Overwrite the local note with the remote note
note_editor.setValue(remote_note.data.note_content, -1);
}
});
}

return;
}
Expand Down Expand Up @@ -216,16 +271,24 @@ async function note_detail(id) {

note_id = id;

collaborator = new Collaborator( get_caseid(), id );
if (collaborator !== null) {
collaborator.close(note_id);
}

collaborator = new Collaborator( get_caseid() );

if (note_editor !== undefined || note_editor !== null) {
note_editor = get_new_ace_editor('editor_detail', 'note_content', 'targetDiv', function () {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
$('#btn_save_note').text("Save").removeClass('btn-success').addClass('btn-warning').removeClass('btn-danger');
}, save_note);
// Destroy the note editor if it exists
if (note_editor !== undefined && note_editor !== null) {
note_editor.destroy();
note_editor = null;
}

note_editor = get_new_ace_editor('editor_detail', 'note_content', 'targetDiv', function () {
$('#last_saved').addClass('btn-danger').removeClass('btn-success');
$('#last_saved > i').attr('class', "fa-solid fa-file-circle-exclamation");
$('#btn_save_note').text("Save").removeClass('btn-success').addClass('btn-warning').removeClass('btn-danger');
}, save_note);

note_editor.focus();

note_editor.setValue(data.data.note_content, -1);
Expand All @@ -236,7 +299,8 @@ async function note_detail(id) {

note_editor.on( "change", function( e ) {
if( last_applied_change != e && note_editor.curOp && note_editor.curOp.command.name) {
collaborator.change( JSON.stringify(e), id ) ;
console.log('Change detected - signaling teammates');
collaborator.change( JSON.stringify(e), note_id ) ;
}
}, false
);
Expand Down Expand Up @@ -875,6 +939,9 @@ $(document).ready(function(){
collaborator_socket.on('ping-note', function(data) {
last_ping = new Date();

// Set as int to avoid type mismatch
if (parseInt(data.note_id) !== parseInt(note_id)) return;

ppl_viewing.set(data.user, 1);
for (let [key, value] of ppl_viewing) {
if (key !== data.user) {
Expand Down
3 changes: 3 additions & 0 deletions source/app/static/assets/js/iris/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,9 @@ function get_new_ace_editor(anchor_id, content_anchor, target_anchor, onchange_c

if (live_preview === undefined || live_preview === true) {
let textarea = $('#'+content_anchor);
// Remove any previous event handler
editor.getSession().off("change");

editor.getSession().on("change", function () {
if (onchange_callback !== undefined && onchange_callback !== null) {
onchange_callback();
Expand Down

0 comments on commit 53879ee

Please # to comment.