diff --git a/bin/createUserSession.js b/bin/createUserSession.js new file mode 100644 index 00000000..5a9fb5cc --- /dev/null +++ b/bin/createUserSession.js @@ -0,0 +1,78 @@ +/* + * A tool for generating a test user session which can be used for debugging configs + * that require sessions. + */ + +const request = require('../src/node_modules/request'); +const settings = require(__dirname+'/../tests/container/loadSettings').loadSettings(); +const supertest = require(__dirname+'/../src/node_modules/supertest'); +const api = supertest('http://'+settings.ip+":"+settings.port); +const path = require('path'); +const fs = require('fs'); + +// get the API Key +var filePath = path.join(__dirname, '../APIKEY.txt'); +var apikey = fs.readFileSync(filePath, {encoding: 'utf-8'}); + +// Set apiVersion to base value, we change this later. +var apiVersion = 1; + +// Update the apiVersion +api.get('/api/') + .expect(function(res){ + apiVersion = res.body.currentVersion; + if (!res.body.currentVersion) throw new Error("No version set in API"); + return; + }) + .end(function(err, res){ + // Now we know the latest API version, let's create a group + var uri = '/api/'+apiVersion+'/createGroup?apikey='+apikey; + api.post(uri) + .expect(function(res){ + if (res.body.code === 1){ + console.error("Error creating group", res.body); + }else{ + var groupID = res.body.data.groupID; + console.log("groupID", groupID); + + // creating a group pad + api.post('/api/'+apiVersion+'/createGroupPad?apikey='+apikey+'&groupID='+groupID) + .expect(function(res){ + if (res.body.code === 1){ + console.error("Error creating author", res.body); + }else{ + console.log("Test Pad ID ====> ", res.body.data.padID) + } + }).end(function(){}) + + // create an author + api.post('/api/'+apiVersion+'/createAuthor?apikey='+apikey) + .expect(function(res){ + if (res.body.code === 1){ + console.error("Error creating author", res.body); + }else{ + console.log("authorID", res.body.data.authorID) + var authorID = res.body.data.authorID; + // create a session for this authorID + var validUntil = Math.floor(new Date() / 1000) + 60000; + console.log("validUntil", validUntil) + api.post('/api/'+apiVersion+'/createSession?apikey='+apikey + '&groupID='+groupID+'&authorID='+authorID+'&validUntil='+validUntil) + .expect(function(res){ + if (res.body.code === 1){ + console.error("Error creating author", res.body); + }else{ + console.log("Session made: ====> create a cookie named sessionID and set it's value to ", res.body.data.sessionID); + } + }) + .end(function(){}) // I shouldn't have nested but here we are.. it's not too ugly :P + + } + }) + .end(function(){}) + + } + return; + }) + .end(function(){}) + }); +// end diff --git a/src/node/db/AuthorManager.js b/src/node/db/AuthorManager.js index a1795224..af867ec0 100644 --- a/src/node/db/AuthorManager.js +++ b/src/node/db/AuthorManager.js @@ -77,6 +77,17 @@ exports.createAuthorIfNotExistsFor = async function(authorMapper, name) return author; }; +/** + * Sets the token <> AuthorID relationship. + * Discussion at https://github.com/ether/etherpad-lite/issues/4006 + * @param {String} token The token (generated by a client) + * @param {String} authorID The authorID (returned by the Security Manager) + */ +exports.setToken2Author = async function(token, authorID) +{ + await db.set("token2author:"+token, authorID); +} + /** * Returns the AuthorID for a mapper. We can map using a mapperkey, * so far this is token2author and mapper2author diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index 8621a750..2d2b8c06 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -918,6 +918,15 @@ async function handleClientReady(client, message) let authorColorId = value.colorId; let authorName = value.name; + /* + * Here we know authorID, token and session. We should ?always? store it.. + * TODO: I fear that this might allow a user to pass a token for an authorID + * meaning that they could in theory "imitate" another author? + * Perhaps the fix to this is check to see if it exists first and if it + * does then abort.. Details: https://github.com/ether/etherpad-lite/issues/4006 + */ + await authorManager.setToken2Author(message.token, statusObject.authorID) + // load the pad-object from the database let pad = await padManager.getPad(padIds.padId);