pad.libre-service.eu-etherpad/src/node/handler/APIHandler.js

189 lines
5.7 KiB
JavaScript
Raw Normal View History

2021-01-21 22:06:52 +01:00
'use strict';
/**
* The API Handler handles all API http requests
*/
/*
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
2020-11-23 19:24:19 +01:00
const absolutePaths = require('../utils/AbsolutePaths');
const fs = require('fs');
const api = require('../db/API');
const log4js = require('log4js');
const padManager = require('../db/PadManager');
const randomString = require('../utils/randomstring');
const argv = require('../utils/Cli').argv;
const createHTTPError = require('http-errors');
2020-11-23 19:24:19 +01:00
const apiHandlerLogger = log4js.getLogger('APIHandler');
2020-11-23 19:24:19 +01:00
// ensure we have an apikey
let apikey = null;
const apikeyFilename = absolutePaths.makeAbsolute(argv.apikey || './APIKEY.txt');
try {
2020-11-23 19:24:19 +01:00
apikey = fs.readFileSync(apikeyFilename, 'utf8');
apiHandlerLogger.info(`Api key file read from: "${apikeyFilename}"`);
2020-11-23 19:24:19 +01:00
} catch (e) {
2021-01-21 22:06:52 +01:00
apiHandlerLogger.info(
`Api key file "${apikeyFilename}" not found. Creating with random contents.`);
apikey = randomString(32);
2020-11-23 19:24:19 +01:00
fs.writeFileSync(apikeyFilename, apikey, 'utf8');
}
// a list of all functions
2020-11-23 19:24:19 +01:00
const version = {};
version['1'] = Object.assign({},
{createGroup: [],
createGroupIfNotExistsFor: ['groupMapper'],
deleteGroup: ['groupID'],
listPads: ['groupID'],
createPad: ['padID', 'text'],
createGroupPad: ['groupID', 'padName', 'text'],
createAuthor: ['name'],
createAuthorIfNotExistsFor: ['authorMapper', 'name'],
listPadsOfAuthor: ['authorID'],
createSession: ['groupID', 'authorID', 'validUntil'],
deleteSession: ['sessionID'],
getSessionInfo: ['sessionID'],
listSessionsOfGroup: ['groupID'],
listSessionsOfAuthor: ['authorID'],
getText: ['padID', 'rev'],
setText: ['padID', 'text'],
getHTML: ['padID', 'rev'],
setHTML: ['padID', 'html'],
getRevisionsCount: ['padID'],
getLastEdited: ['padID'],
deletePad: ['padID'],
getReadOnlyID: ['padID'],
setPublicStatus: ['padID', 'publicStatus'],
getPublicStatus: ['padID'],
listAuthorsOfPad: ['padID'],
2020-12-16 22:51:43 +01:00
padUsersCount: ['padID']}
);
2020-11-23 19:24:19 +01:00
version['1.1'] = Object.assign({}, version['1'],
{getAuthorName: ['authorID'],
padUsers: ['padID'],
sendClientsMessage: ['padID', 'msg'],
2020-12-16 22:51:43 +01:00
listAllGroups: []}
);
2020-11-23 19:24:19 +01:00
version['1.2'] = Object.assign({}, version['1.1'],
2020-12-16 22:51:43 +01:00
{checkToken: []}
);
2020-11-23 19:24:19 +01:00
version['1.2.1'] = Object.assign({}, version['1.2'],
2020-12-16 22:51:43 +01:00
{listAllPads: []}
);
2020-11-23 19:24:19 +01:00
version['1.2.7'] = Object.assign({}, version['1.2.1'],
{createDiffHTML: ['padID', 'startRev', 'endRev'],
getChatHistory: ['padID', 'start', 'end'],
2020-12-16 22:51:43 +01:00
getChatHead: ['padID']}
);
2020-11-23 19:24:19 +01:00
version['1.2.8'] = Object.assign({}, version['1.2.7'],
{getAttributePool: ['padID'],
2020-12-16 22:51:43 +01:00
getRevisionChangeset: ['padID', 'rev']}
);
2020-11-23 19:24:19 +01:00
version['1.2.9'] = Object.assign({}, version['1.2.8'],
{copyPad: ['sourceID', 'destinationID', 'force'],
2020-12-16 22:51:43 +01:00
movePad: ['sourceID', 'destinationID', 'force']}
);
2020-11-23 19:24:19 +01:00
version['1.2.10'] = Object.assign({}, version['1.2.9'],
2020-12-16 22:51:43 +01:00
{getPadID: ['roID']}
);
2020-11-23 19:24:19 +01:00
version['1.2.11'] = Object.assign({}, version['1.2.10'],
{getSavedRevisionsCount: ['padID'],
listSavedRevisions: ['padID'],
saveRevision: ['padID', 'rev'],
2020-12-16 22:51:43 +01:00
restoreRevision: ['padID', 'rev']}
);
2020-11-23 19:24:19 +01:00
version['1.2.12'] = Object.assign({}, version['1.2.11'],
2020-12-16 22:51:43 +01:00
{appendChatMessage: ['padID', 'text', 'authorID', 'time']}
);
2020-11-23 19:24:19 +01:00
version['1.2.13'] = Object.assign({}, version['1.2.12'],
2020-12-16 22:51:43 +01:00
{appendText: ['padID', 'text']}
);
2020-11-23 19:24:19 +01:00
version['1.2.14'] = Object.assign({}, version['1.2.13'],
2020-12-16 22:51:43 +01:00
{getStats: []}
2020-04-01 10:57:43 +02:00
);
2020-11-23 19:24:19 +01:00
version['1.2.15'] = Object.assign({}, version['1.2.14'],
2020-12-16 22:51:43 +01:00
{copyPadWithoutHistory: ['sourceID', 'destinationID', 'force']}
);
2013-02-12 21:50:14 +01:00
// set the latest available API version here
exports.latestApiVersion = '1.2.15';
2013-02-12 21:50:14 +01:00
2013-02-13 17:29:01 +01:00
// exports the versions so it can be used by the new Swagger endpoint
exports.version = version;
/**
* Handles a HTTP API call
* @param functionName the name of the called function
* @param fields the params of the called function
* @req express request object
* @res express response object
*/
2020-11-23 19:24:19 +01:00
exports.handle = async function (apiVersion, functionName, fields, req, res) {
// say goodbye if this is an unknown API version
if (!(apiVersion in version)) {
throw new createHTTPError.NotFound('no such api version');
}
// say goodbye if this is an unknown function
if (!(functionName in version[apiVersion])) {
throw new createHTTPError.NotFound('no such function');
}
// check the api key!
2020-11-23 19:24:19 +01:00
fields.apikey = fields.apikey || fields.api_key;
2020-11-23 19:24:19 +01:00
if (fields.apikey !== apikey.trim()) {
throw new createHTTPError.Unauthorized('no or wrong API Key');
2012-09-09 18:20:16 +02:00
}
2011-12-16 21:41:11 +01:00
// sanitize any padIDs before continuing
2020-11-23 19:24:19 +01:00
if (fields.padID) {
fields.padID = await padManager.sanitizePadId(fields.padID);
}
// there was an 'else' here before - removed it to ensure
// that this sanitize step can't be circumvented by forcing
// the first branch to be taken
2020-11-23 19:24:19 +01:00
if (fields.padName) {
fields.padName = await padManager.sanitizePadId(fields.padName);
2011-12-16 21:41:11 +01:00
}
// put the function parameters in an array
2020-11-23 19:24:19 +01:00
const functionParams = version[apiVersion][functionName].map((field) => fields[field]);
2020-03-29 19:35:25 +02:00
// call the api function
return api[functionName].apply(this, functionParams);
2020-11-23 19:24:19 +01:00
};
exports.exportedForTestingOnly = {
apiKey: apikey,
};