Added private permission and clean up codes, solved potential race condition in realtime.js

This commit is contained in:
Wu Cheng-Han 2016-01-17 09:51:27 -06:00
parent 473212676a
commit 49c7dded45
6 changed files with 297 additions and 199 deletions

View file

@ -90,46 +90,10 @@ var updater = setInterval(function () {
if (note.server.isDirty) {
if (config.debug)
logger.info("updater found dirty note: " + key);
Note.findNote(note.id, function (err, _note) {
if (err || !_note) return callback(err, null);
//mongo update
if (note.lastchangeuser && _note.lastchangeuser != note.lastchangeuser) {
var lastchangeuser = note.lastchangeuser;
var lastchangeuserprofile = null;
User.findUser(lastchangeuser, function (err, user) {
if (err) return callback(err, null);
if (user && user.profile) {
var profile = JSON.parse(user.profile);
if (profile) {
lastchangeuserprofile = {
name: profile.displayName || profile.username,
photo: User.parsePhotoByProfile(profile)
}
note.lastchangeuser = lastchangeuser;
note.lastchangeuserprofile = lastchangeuserprofile;
Note.updateLastChangeUser(_note, lastchangeuser, function (err, result) {
if (err) return callback(err, null);
});
}
}
});
} else {
note.lastchangeuser = null;
note.lastchangeuserprofile = null;
Note.updateLastChangeUser(_note, null, function (err, result) {
if (err) return callback(err, null);
});
}
//postgres update
var body = note.server.document;
var title = Note.getNoteTitle(body);
title = LZString.compressToBase64(title);
body = LZString.compressToBase64(body);
db.saveToDB(key, title, body, function (err, result) {
updaterUpdateMongo(note, function(err, result) {
if (err) return callback(err, null);
updaterUpdatePostgres(note, function(err, result) {
if (err) return callback(err, null);
note.server.isDirty = false;
note.updatetime = Date.now();
emitCheck(note);
callback(null, null);
});
});
@ -140,6 +104,56 @@ var updater = setInterval(function () {
if (err) return logger.error('updater error', err);
});
}, 1000);
function updaterUpdateMongo(note, callback) {
Note.findNote(note.id, function (err, _note) {
if (err || !_note) return callback(err, null);
if (note.lastchangeuser) {
if (_note.lastchangeuser != note.lastchangeuser) {
var lastchangeuser = note.lastchangeuser;
var lastchangeuserprofile = null;
User.findUser(lastchangeuser, function (err, user) {
if (err) return callback(err, null);
if (user && user.profile) {
var profile = JSON.parse(user.profile);
if (profile) {
lastchangeuserprofile = {
name: profile.displayName || profile.username,
photo: User.parsePhotoByProfile(profile)
}
_note.lastchangeuser = lastchangeuser;
note.lastchangeuserprofile = lastchangeuserprofile;
Note.updateLastChangeUser(_note, lastchangeuser, function (err, result) {
if (err) return callback(err, null);
callback(null, null);
});
}
}
});
}
} else {
_note.lastchangeuser = null;
note.lastchangeuserprofile = null;
Note.updateLastChangeUser(_note, null, function (err, result) {
if (err) return callback(err, null);
callback(null, null);
});
}
});
}
function updaterUpdatePostgres(note, callback) {
//postgres update
var body = note.server.document;
var title = Note.getNoteTitle(body);
title = LZString.compressToBase64(title);
body = LZString.compressToBase64(body);
db.saveToDB(note.id, title, body, function (err, result) {
if (err) return callback(err, null);
note.server.isDirty = false;
note.updatetime = Date.now();
emitCheck(note);
callback(null, null);
});
}
//clean when user not in any rooms or user not in connected list
var cleaner = setInterval(function () {
async.each(Object.keys(users), function (key, callback) {
@ -310,6 +324,19 @@ var disconnectSocketQueue = [];
function finishConnection(socket, note, user) {
if (!socket || !note || !user) return;
//check view permission
if (note.permission == 'private') {
if (socket.request.user && socket.request.user.logged_in && socket.request.user._id == note.owner) {
//na
} else {
socket.emit('info', {
code: 403
});
clearSocketQueue(connectionSocketQueue, socket);
isConnectionBusy = false;
return socket.disconnect(true);
}
}
note.users[socket.id] = user;
note.socks.push(socket);
note.server.addClient(socket);
@ -363,13 +390,9 @@ function startConnection(socket) {
var owner = data.rows[0].owner;
var ownerprofile = null;
var permission = "freely";
if (owner && owner != "null") {
permission = "editable";
}
//find or new note
Note.findOrNewNote(notename, permission, function (err, note) {
Note.findOrNewNote(notename, owner, function (err, note) {
if (err) {
responseError(res, "404", "Not Found", "oops.");
clearSocketQueue(connectionSocketQueue, socket);
@ -399,41 +422,52 @@ function startConnection(socket) {
updatetime: moment(updatetime).valueOf(),
server: server
};
if (lastchangeuser) {
//find last change user profile if lastchangeuser exists
User.findUser(lastchangeuser, function (err, user) {
if (!err && user && user.profile) {
var profile = JSON.parse(user.profile);
if (profile) {
lastchangeuserprofile = {
name: profile.displayName || profile.username,
photo: User.parsePhotoByProfile(profile)
async.parallel([
function getlastchangeuser(callback) {
if (lastchangeuser) {
//find last change user profile if lastchangeuser exists
User.findUser(lastchangeuser, function (err, user) {
if (!err && user && user.profile) {
var profile = JSON.parse(user.profile);
if (profile) {
lastchangeuserprofile = {
name: profile.displayName || profile.username,
photo: User.parsePhotoByProfile(profile)
}
notes[notename].lastchangeuserprofile = lastchangeuserprofile;
}
}
notes[notename].lastchangeuserprofile = lastchangeuserprofile;
}
callback(null, null);
});
} else {
callback(null, null);
}
});
}
if (owner && owner != "null") {
//find owner profile if owner exists
User.findUser(owner, function (err, user) {
if (!err && user && user.profile) {
var profile = JSON.parse(user.profile);
if (profile) {
ownerprofile = {
name: profile.displayName || profile.username,
photo: User.parsePhotoByProfile(profile)
},
function getowner(callback) {
if (owner && owner != "null") {
//find owner profile if owner exists
User.findUser(owner, function (err, user) {
if (!err && user && user.profile) {
var profile = JSON.parse(user.profile);
if (profile) {
ownerprofile = {
name: profile.displayName || profile.username,
photo: User.parsePhotoByProfile(profile)
}
notes[notename].ownerprofile = ownerprofile;
}
}
notes[notename].ownerprofile = ownerprofile;
}
callback(null, null);
});
} else {
callback(null, null);
}
finishConnection(socket, notes[notename], users[socket.id]);
});
} else {
}
], function(err, results){
if (err) return;
finishConnection(socket, notes[notename], users[socket.id]);
}
});
});
});
} else {
@ -545,14 +579,14 @@ function ifMayEdit(socket, callback) {
if (!socket.request.user || !socket.request.user.logged_in)
mayEdit = false;
break;
case "locked":
case "locked": case "private":
//only owner can change
if (note.owner != socket.request.user._id)
mayEdit = false;
break;
}
//if user may edit and this note have owner (not anonymous usage)
if (mayEdit && note.owner && note.owner != "null") {
if (socket.origin == 'operation' && mayEdit && note.owner && note.owner != "null") {
//save for the last change user id
if (socket.request.user && socket.request.user.logged_in) {
note.lastchangeuser = socket.request.user._id;
@ -652,12 +686,22 @@ function connection(socket) {
permission: permission
};
realtime.io.to(note.id).emit('permission', out);
/*
for (var i = 0, l = note.socks.length; i < l; i++) {
var sock = note.socks[i];
sock.emit('permission', out);
};
*/
if (typeof sock !== 'undefined' && sock) {
//check view permission
if (permission == 'private') {
if (sock.request.user && sock.request.user.logged_in && sock.request.user._id == note.owner) {
//na
} else {
sock.emit('info', {
code: 403
});
return sock.disconnect(true);
}
}
}
}
});
});
}