mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-21 07:56:16 -04:00
ReadOnly pad handling
This commit is contained in:
parent
ed7e254417
commit
480d0b8e25
2 changed files with 98 additions and 76 deletions
|
@ -72,3 +72,33 @@ exports.getPadId = function(readOnlyId, callback)
|
||||||
{
|
{
|
||||||
db.get("readonly2pad:" + 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
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -34,19 +34,18 @@ var log4js = require('log4js');
|
||||||
var messageLogger = log4js.getLogger("message");
|
var messageLogger = log4js.getLogger("message");
|
||||||
var _ = require('underscore');
|
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
|
* A associative array that saves which sessions belong to a pad
|
||||||
*/
|
*/
|
||||||
var pad2sessions = {};
|
var pad2sessions = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A associative array that saves some general informations about a session
|
* A associative array that saves informations about a session
|
||||||
* key = sessionId
|
* 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
|
* rev = That last revision that was send to this client
|
||||||
* author = the author name of this session
|
* author = the author name of this session
|
||||||
*/
|
*/
|
||||||
|
@ -72,8 +71,7 @@ exports.setSocketIO = function(socket_io)
|
||||||
*/
|
*/
|
||||||
exports.handleConnect = function(client)
|
exports.handleConnect = function(client)
|
||||||
{
|
{
|
||||||
//Initalize session2pad and sessioninfos for this new session
|
//Initalize sessioninfos for this new session
|
||||||
session2pad[client.id]=null;
|
|
||||||
sessioninfos[client.id]={};
|
sessioninfos[client.id]={};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +99,7 @@ exports.kickSessionsFromPad = function(padID)
|
||||||
exports.handleDisconnect = function(client)
|
exports.handleDisconnect = function(client)
|
||||||
{
|
{
|
||||||
//save the padname of this session
|
//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 this connection was already etablished with a handshake, send a disconnect message to the others
|
||||||
if(sessioninfos[client.id] && sessioninfos[client.id].author)
|
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 the sessioninfos entrys of this session
|
||||||
delete session2pad[client.id];
|
|
||||||
delete sessioninfos[client.id];
|
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
|
//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);
|
handleClientReady(client, message);
|
||||||
}
|
} else if(message.type == "CHANGESET_REQ") {
|
||||||
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")
|
|
||||||
{
|
|
||||||
handleChangesetRequest(client, message);
|
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);
|
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
|
* @param message the message from the client
|
||||||
*/
|
*/
|
||||||
function handleSaveRevisionMessage(client, message){
|
function handleSaveRevisionMessage(client, message){
|
||||||
var padId = session2pad[client.id];
|
var padId = sessioninfos[client.id].padId;
|
||||||
var userId = sessioninfos[client.id].author;
|
var userId = sessioninfos[client.id].author;
|
||||||
|
|
||||||
padManager.getPad(padId, function(err, pad)
|
padManager.getPad(padId, function(err, pad)
|
||||||
|
@ -242,7 +224,7 @@ function handleChatMessage(client, message)
|
||||||
var time = new Date().getTime();
|
var time = new Date().getTime();
|
||||||
var userId = sessioninfos[client.id].author;
|
var userId = sessioninfos[client.id].author;
|
||||||
var text = message.data.text;
|
var text = message.data.text;
|
||||||
var padId = session2pad[client.id];
|
var padId = sessioninfos[client.id].padId;
|
||||||
|
|
||||||
var pad;
|
var pad;
|
||||||
var userName;
|
var userName;
|
||||||
|
@ -318,7 +300,7 @@ function handleSuggestUserName(client, message)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var padId = session2pad[client.id];
|
var padId = sessioninfos[client.id].padId;
|
||||||
|
|
||||||
//search the author and send him this message
|
//search the author and send him this message
|
||||||
for(var i in pad2sessions[padId])
|
for(var i in pad2sessions[padId])
|
||||||
|
@ -352,7 +334,7 @@ function handleUserInfoUpdate(client, message)
|
||||||
authorManager.setAuthorColorId(author, message.data.userInfo.colorId);
|
authorManager.setAuthorColorId(author, message.data.userInfo.colorId);
|
||||||
authorManager.setAuthorName(author, message.data.userInfo.name);
|
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
|
//set a null name, when there is no name set. cause the client wants it null
|
||||||
if(message.data.userInfo.name == null)
|
if(message.data.userInfo.name == null)
|
||||||
|
@ -410,7 +392,7 @@ function handleUserChanges(client, message)
|
||||||
//get the pad
|
//get the pad
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
padManager.getPad(session2pad[client.id], function(err, value)
|
padManager.getPad(sessioninfos[client.id].padId, function(err, value)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
pad = value;
|
pad = value;
|
||||||
|
@ -680,14 +662,28 @@ function handleClientReady(client, message)
|
||||||
var pad;
|
var pad;
|
||||||
var historicalAuthorData = {};
|
var historicalAuthorData = {};
|
||||||
var currentTime;
|
var currentTime;
|
||||||
var readOnlyId;
|
|
||||||
var chatMessages;
|
var chatMessages;
|
||||||
|
var padIds;
|
||||||
|
|
||||||
async.series([
|
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
|
//check permissions
|
||||||
function(callback)
|
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;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
|
@ -730,21 +726,12 @@ function handleClientReady(client, message)
|
||||||
},
|
},
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
padManager.getPad(message.padId, function(err, value)
|
padManager.getPad(padIds.padId, function(err, value)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
pad = value;
|
pad = value;
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
|
||||||
function(callback)
|
|
||||||
{
|
|
||||||
readOnlyManager.getReadOnlyId(message.padId, function(err, value)
|
|
||||||
{
|
|
||||||
if(ERR(err, callback)) return;
|
|
||||||
readOnlyId = value;
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
], callback);
|
], callback);
|
||||||
},
|
},
|
||||||
|
@ -794,30 +781,32 @@ function handleClientReady(client, message)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
//Check if this author is already on the pad, if yes, kick the other sessions!
|
//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"});
|
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);
|
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
|
//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
|
//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
|
//prepare all values for the wire
|
||||||
var atext = Changeset.cloneAText(pad.atext);
|
var atext = Changeset.cloneAText(pad.atext);
|
||||||
|
@ -825,6 +814,9 @@ function handleClientReady(client, message)
|
||||||
var apool = attribsForWire.pool.toJsonable();
|
var apool = attribsForWire.pool.toJsonable();
|
||||||
atext.attribs = attribsForWire.translated;
|
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 = {
|
var clientVars = {
|
||||||
"accountPrivs": {
|
"accountPrivs": {
|
||||||
"maxRevisions": 100
|
"maxRevisions": 100
|
||||||
|
@ -853,9 +845,9 @@ function handleClientReady(client, message)
|
||||||
"initialTitle": "Pad: " + message.padId,
|
"initialTitle": "Pad: " + message.padId,
|
||||||
"opts": {},
|
"opts": {},
|
||||||
"chatHistory": chatMessages,
|
"chatHistory": chatMessages,
|
||||||
"numConnectedUsers": pad2sessions[message.padId].length,
|
"numConnectedUsers": pad2sessions[padIds.padId].length,
|
||||||
"isProPad": false,
|
"isProPad": false,
|
||||||
"readOnlyId": readOnlyId,
|
"readOnlyId": padIds.readOnlyPadId,
|
||||||
"serverTimestamp": new Date().getTime(),
|
"serverTimestamp": new Date().getTime(),
|
||||||
"globalPadId": message.padId,
|
"globalPadId": message.padId,
|
||||||
"userId": author,
|
"userId": author,
|
||||||
|
@ -920,7 +912,7 @@ function handleClientReady(client, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Run trough all sessions of this pad
|
//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;
|
var author, socket, sessionAuthorName, sessionAuthorColorId;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue