ReadOnly pad handling

This commit is contained in:
Egil Moeller 2012-04-23 16:18:14 +02:00
parent ed7e254417
commit 480d0b8e25
2 changed files with 98 additions and 76 deletions

View file

@ -72,3 +72,33 @@ exports.getPadId = function(readOnlyId, callback)
{
db.get("readonly2pad:" + readOnlyId, callback);
}
/**
* returns a the padId and readonlyPadId in an object for any id
* @param {String} padIdOrReadonlyPadId read only id or real pad id
*/
exports.getIds = function(padIdOrReadonlyPadId, callback) {
var handleRealPadId = function () {
exports.getReadOnlyId(padIdOrReadonlyPadId, function (err, value) {
callback(null, {
readOnlyPadId: value,
padId: padIdOrReadonlyPadId,
readonly: false
});
});
}
if (padIdOrReadonlyPadId.indexOf("r.") != 0)
return handleRealPadId();
exports.getPadId(padIdOrReadonlyPadId, function (err, value) {
if(ERR(err, callback)) return;
if (value == null)
return handleRealPadId();
callback(null, {
readOnlyPadId: padIdOrReadonlyPadId,
padId: value,
readonly: true
});
});
}

View file

@ -34,19 +34,18 @@ var log4js = require('log4js');
var messageLogger = log4js.getLogger("message");
var _ = require('underscore');
/**
* A associative array that translates a session to a pad
*/
var session2pad = {};
/**
* A associative array that saves which sessions belong to a pad
*/
var pad2sessions = {};
/**
* A associative array that saves some general informations about a session
* A associative array that saves informations about a session
* key = sessionId
* values = author, rev
* values = padId, readonlyPadId, readonly, author, rev
* padId = the real padId of the pad
* readonlyPadId = The readonly pad id of the pad
* readonly = Wether the client has only read access (true) or read/write access (false)
* rev = That last revision that was send to this client
* author = the author name of this session
*/
@ -72,8 +71,7 @@ exports.setSocketIO = function(socket_io)
*/
exports.handleConnect = function(client)
{
//Initalize session2pad and sessioninfos for this new session
session2pad[client.id]=null;
//Initalize sessioninfos for this new session
sessioninfos[client.id]={};
}
@ -101,7 +99,7 @@ exports.kickSessionsFromPad = function(padID)
exports.handleDisconnect = function(client)
{
//save the padname of this session
var sessionPad=session2pad[client.id];
var sessionPad=sessioninfos[client.id].padId;
//if this connection was already etablished with a handshake, send a disconnect message to the others
if(sessioninfos[client.id] && sessioninfos[client.id].author)
@ -149,8 +147,7 @@ exports.handleDisconnect = function(client)
}
}
//Delete the session2pad and sessioninfos entrys of this session
delete session2pad[client.id];
//Delete the sessioninfos entrys of this session
delete sessioninfos[client.id];
}
@ -173,43 +170,28 @@ exports.handleMessage = function(client, message)
}
//Check what type of message we get and delegate to the other methodes
if(message.type == "CLIENT_READY")
{
if(message.type == "CLIENT_READY") {
handleClientReady(client, message);
}
else if(message.type == "COLLABROOM" &&
message.data.type == "USER_CHANGES")
{
handleUserChanges(client, message);
}
else if(message.type == "COLLABROOM" &&
message.data.type == "USERINFO_UPDATE")
{
handleUserInfoUpdate(client, message);
}
else if(message.type == "COLLABROOM" &&
message.data.type == "CHAT_MESSAGE")
{
handleChatMessage(client, message);
}
else if(message.type == "COLLABROOM" &&
message.data.type == "SAVE_REVISION")
{
handleSaveRevisionMessage(client, message);
}
else if(message.type == "COLLABROOM" &&
message.data.type == "CLIENT_MESSAGE" &&
message.data.payload.type == "suggestUserName")
{
handleSuggestUserName(client, message);
}
else if(message.type == "CHANGESET_REQ")
{
} else if(message.type == "CHANGESET_REQ") {
handleChangesetRequest(client, message);
} else if(message.type == "COLLABROOM") {
if (sessioninfos[client.id].readonly) {
messageLogger.warn("Dropped message, COLLABROOM for readonly pad");
} else if (message.data.type == "USER_CHANGES") {
handleUserChanges(client, message);
} else if (message.data.type == "USERINFO_UPDATE") {
handleUserInfoUpdate(client, message);
} else if (message.data.type == "CHAT_MESSAGE") {
handleChatMessage(client, message);
} else if (message.data.type == "SAVE_REVISION") {
handleSaveRevisionMessage(client, message);
} else if (message.data.type == "CLIENT_MESSAGE" &&
message.data.payload.type == "suggestUserName") {
handleSuggestUserName(client, message);
} else {
messageLogger.warn("Dropped message, unknown COLLABROOM Data Type " + message.data.type);
}
//if the message type is unknown, throw an exception
else
{
} else {
messageLogger.warn("Dropped message, unknown Message Type " + message.type);
}
}
@ -221,7 +203,7 @@ exports.handleMessage = function(client, message)
* @param message the message from the client
*/
function handleSaveRevisionMessage(client, message){
var padId = session2pad[client.id];
var padId = sessioninfos[client.id].padId;
var userId = sessioninfos[client.id].author;
padManager.getPad(padId, function(err, pad)
@ -242,7 +224,7 @@ function handleChatMessage(client, message)
var time = new Date().getTime();
var userId = sessioninfos[client.id].author;
var text = message.data.text;
var padId = session2pad[client.id];
var padId = sessioninfos[client.id].padId;
var pad;
var userName;
@ -318,7 +300,7 @@ function handleSuggestUserName(client, message)
return;
}
var padId = session2pad[client.id];
var padId = sessioninfos[client.id].padId;
//search the author and send him this message
for(var i in pad2sessions[padId])
@ -352,7 +334,7 @@ function handleUserInfoUpdate(client, message)
authorManager.setAuthorColorId(author, message.data.userInfo.colorId);
authorManager.setAuthorName(author, message.data.userInfo.name);
var padId = session2pad[client.id];
var padId = sessioninfos[client.id].padId;
//set a null name, when there is no name set. cause the client wants it null
if(message.data.userInfo.name == null)
@ -410,7 +392,7 @@ function handleUserChanges(client, message)
//get the pad
function(callback)
{
padManager.getPad(session2pad[client.id], function(err, value)
padManager.getPad(sessioninfos[client.id].padId, function(err, value)
{
if(ERR(err, callback)) return;
pad = value;
@ -680,14 +662,28 @@ function handleClientReady(client, message)
var pad;
var historicalAuthorData = {};
var currentTime;
var readOnlyId;
var chatMessages;
var padIds;
async.series([
// Get ro/rw id:s
function (callback) {
readOnlyManager.getIds(message.padId, function(err, value) {
if(ERR(err, callback)) return;
padIds = value;
callback();
});
},
//check permissions
function(callback)
{
securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject)
// Note: message.sessionID is an entierly different kind of
// session from the sessions we use here! Beware! FIXME: Call
// our "sessions" "connections".
// FIXME: Use a hook instead
// FIXME: Allow to override readwrite access with readonly
securityManager.checkAccess (padIds.padId, message.sessionID, message.token, message.password, function(err, statusObject)
{
if(ERR(err, callback)) return;
@ -730,21 +726,12 @@ function handleClientReady(client, message)
},
function(callback)
{
padManager.getPad(message.padId, function(err, value)
padManager.getPad(padIds.padId, function(err, value)
{
if(ERR(err, callback)) return;
pad = value;
callback();
});
},
function(callback)
{
readOnlyManager.getReadOnlyId(message.padId, function(err, value)
{
if(ERR(err, callback)) return;
readOnlyId = value;
callback();
});
}
], callback);
},
@ -794,30 +781,32 @@ function handleClientReady(client, message)
function(callback)
{
//Check if this author is already on the pad, if yes, kick the other sessions!
if(pad2sessions[message.padId])
if(pad2sessions[padIds.padId])
{
for(var i in pad2sessions[message.padId])
for(var i in pad2sessions[padIds.padId])
{
if(sessioninfos[pad2sessions[message.padId][i]] && sessioninfos[pad2sessions[message.padId][i]].author == author)
if(sessioninfos[pad2sessions[padIds.padId][i]] && sessioninfos[pad2sessions[padIds.padId][i]].author == author)
{
var socket = socketio.sockets.sockets[pad2sessions[message.padId][i]];
var socket = socketio.sockets.sockets[pad2sessions[padIds.padId][i]];
if(socket) socket.json.send({disconnect:"userdup"});
}
}
}
//Save in session2pad that this session belonges to this pad
//Save in sessioninfos that this session belonges to this pad
var sessionId=String(client.id);
session2pad[sessionId] = message.padId;
sessioninfos[sessionId].padId = padIds.padId;
sessioninfos[sessionId].readOnlyPadId = padIds.readOnlyPadId;
sessioninfos[sessionId].readonly = padIds.readonly;
//check if there is already a pad2sessions entry, if not, create one
if(!pad2sessions[message.padId])
if(!pad2sessions[padIds.padId])
{
pad2sessions[message.padId] = [];
pad2sessions[padIds.padId] = [];
}
//Saves in pad2sessions that this session belongs to this pad
pad2sessions[message.padId].push(sessionId);
pad2sessions[padIds.padId].push(sessionId);
//prepare all values for the wire
var atext = Changeset.cloneAText(pad.atext);
@ -825,6 +814,9 @@ function handleClientReady(client, message)
var apool = attribsForWire.pool.toJsonable();
atext.attribs = attribsForWire.translated;
// Warning: never ever send padIds.padId to the client. If the
// client is read only you would open a security hole 1 swedish
// mile wide...
var clientVars = {
"accountPrivs": {
"maxRevisions": 100
@ -853,9 +845,9 @@ function handleClientReady(client, message)
"initialTitle": "Pad: " + message.padId,
"opts": {},
"chatHistory": chatMessages,
"numConnectedUsers": pad2sessions[message.padId].length,
"numConnectedUsers": pad2sessions[padIds.padId].length,
"isProPad": false,
"readOnlyId": readOnlyId,
"readOnlyId": padIds.readOnlyPadId,
"serverTimestamp": new Date().getTime(),
"globalPadId": message.padId,
"userId": author,
@ -920,7 +912,7 @@ function handleClientReady(client, message)
}
//Run trough all sessions of this pad
async.forEach(pad2sessions[message.padId], function(sessionID, callback)
async.forEach(pad2sessions[padIds.padId], function(sessionID, callback)
{
var author, socket, sessionAuthorName, sessionAuthorColorId;