mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
Added jsdoc for the node part of etherpad. (#5983)
This commit is contained in:
parent
53d1e8a160
commit
ff1b929eb2
16 changed files with 284 additions and 71 deletions
|
@ -33,7 +33,7 @@ const exportTxt = require('../utils/ExportTxt');
|
|||
const importHtml = require('../utils/ImportHtml');
|
||||
const cleanText = require('./Pad').cleanText;
|
||||
const PadDiff = require('../utils/padDiff');
|
||||
const { checkValidRev, isInt } = require('../utils/checkValidRev');
|
||||
const {checkValidRev, isInt} = require('../utils/checkValidRev');
|
||||
|
||||
/* ********************
|
||||
* GROUP FUNCTIONS ****
|
||||
|
@ -193,6 +193,13 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
{code: 1, message:"text too long", data: null}
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @param {String} padID the id of the pad
|
||||
* @param {String} text the text of the pad
|
||||
* @param {String} authorId the id of the author, defaulting to empty string
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
exports.setText = async (padID, text, authorId = '') => {
|
||||
// text is required
|
||||
if (typeof text !== 'string') {
|
||||
|
@ -214,7 +221,10 @@ Example returns:
|
|||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
{code: 1, message:"text too long", data: null}
|
||||
*/
|
||||
@param {String} padID the id of the pad
|
||||
@param {String} text the text of the pad
|
||||
@param {String} authorId the id of the author, defaulting to empty string
|
||||
*/
|
||||
exports.appendText = async (padID, text, authorId = '') => {
|
||||
// text is required
|
||||
if (typeof text !== 'string') {
|
||||
|
@ -233,6 +243,9 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {text:"Welcome <strong>Text</strong>"}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
@param {String} rev the revision number, defaulting to the latest revision
|
||||
@return {Promise<{html: string}>} the html of the pad
|
||||
*/
|
||||
exports.getHTML = async (padID, rev) => {
|
||||
if (rev !== undefined) {
|
||||
|
@ -265,6 +278,10 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
|
||||
@param {String} padID the id of the pad
|
||||
@param {String} html the html of the pad
|
||||
@param {String} authorId the id of the author, defaulting to empty string
|
||||
*/
|
||||
exports.setHTML = async (padID, html, authorId = '') => {
|
||||
// html string is required
|
||||
|
@ -303,6 +320,9 @@ Example returns:
|
|||
{code: 1, message:"start is higher or equal to the current chatHead", data: null}
|
||||
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
@param {Number} start the start point of the chat-history
|
||||
@param {Number} end the end point of the chat-history
|
||||
*/
|
||||
exports.getChatHistory = async (padID, start, end) => {
|
||||
if (start && end) {
|
||||
|
@ -349,6 +369,10 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
@param {String} text the text of the chat-message
|
||||
@param {String} authorID the id of the author
|
||||
@param {Number} time the timestamp of the chat-message
|
||||
*/
|
||||
exports.appendChatMessage = async (padID, text, authorID, time) => {
|
||||
// text is required
|
||||
|
@ -378,6 +402,7 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {revisions: 56}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.getRevisionsCount = async (padID) => {
|
||||
// get the pad
|
||||
|
@ -392,6 +417,7 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {savedRevisions: 42}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.getSavedRevisionsCount = async (padID) => {
|
||||
// get the pad
|
||||
|
@ -406,6 +432,7 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {savedRevisions: [2, 42, 1337]}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.listSavedRevisions = async (padID) => {
|
||||
// get the pad
|
||||
|
@ -420,6 +447,8 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
@param {Number} rev the revision number, defaulting to the latest revision
|
||||
*/
|
||||
exports.saveRevision = async (padID, rev) => {
|
||||
// check if rev is a number
|
||||
|
@ -451,6 +480,8 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {lastEdited: 1340815946602}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
@return {Promise<{lastEdited: number}>} the timestamp of the last revision of the pad
|
||||
*/
|
||||
exports.getLastEdited = async (padID) => {
|
||||
// get the pad
|
||||
|
@ -466,6 +497,9 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"pad does already exist", data: null}
|
||||
@param {String} padName the name of the new pad
|
||||
@param {String} text the initial text of the pad
|
||||
@param {String} authorId the id of the author, defaulting to empty string
|
||||
*/
|
||||
exports.createPad = async (padID, text, authorId = '') => {
|
||||
if (padID) {
|
||||
|
@ -491,6 +525,7 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.deletePad = async (padID) => {
|
||||
const pad = await getPadSafe(padID, true);
|
||||
|
@ -504,6 +539,9 @@ exports.deletePad = async (padID) => {
|
|||
|
||||
{code:0, message:"ok", data:null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
@param {Number} rev the revision number, defaulting to the latest revision
|
||||
@param {String} authorId the id of the author, defaulting to empty string
|
||||
*/
|
||||
exports.restoreRevision = async (padID, rev, authorId = '') => {
|
||||
// check if rev is a number
|
||||
|
@ -568,6 +606,9 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {padID: destinationID}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} sourceID the id of the source pad
|
||||
@param {String} destinationID the id of the destination pad
|
||||
@param {Boolean} force whether to overwrite the destination pad if it exists
|
||||
*/
|
||||
exports.copyPad = async (sourceID, destinationID, force) => {
|
||||
const pad = await getPadSafe(sourceID, true);
|
||||
|
@ -582,6 +623,10 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {padID: destinationID}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} sourceID the id of the source pad
|
||||
@param {String} destinationID the id of the destination pad
|
||||
@param {Boolean} force whether to overwrite the destination pad if it exists
|
||||
@param {String} authorId the id of the author, defaulting to empty string
|
||||
*/
|
||||
exports.copyPadWithoutHistory = async (sourceID, destinationID, force, authorId = '') => {
|
||||
const pad = await getPadSafe(sourceID, true);
|
||||
|
@ -596,6 +641,9 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {padID: destinationID}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} sourceID the id of the source pad
|
||||
@param {String} destinationID the id of the destination pad
|
||||
@param {Boolean} force whether to overwrite the destination pad if it exists
|
||||
*/
|
||||
exports.movePad = async (sourceID, destinationID, force) => {
|
||||
const pad = await getPadSafe(sourceID, true);
|
||||
|
@ -610,6 +658,7 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.getReadOnlyID = async (padID) => {
|
||||
// we don't need the pad object, but this function does all the security stuff for us
|
||||
|
@ -628,6 +677,7 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {padID: padID}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} roID the readonly id of the pad
|
||||
*/
|
||||
exports.getPadID = async (roID) => {
|
||||
// get the PadId
|
||||
|
@ -646,6 +696,8 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: null}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
@param {Boolean} publicStatus the public status of the pad
|
||||
*/
|
||||
exports.setPublicStatus = async (padID, publicStatus) => {
|
||||
// ensure this is a group pad
|
||||
|
@ -669,6 +721,7 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {publicStatus: true}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.getPublicStatus = async (padID) => {
|
||||
// ensure this is a group pad
|
||||
|
@ -686,6 +739,7 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {authorIDs : ["a.s8oes9dhwrvt0zif", "a.akf8finncvomlqva"]}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.listAuthorsOfPad = async (padID) => {
|
||||
// get the pad
|
||||
|
@ -715,6 +769,8 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok"}
|
||||
{code: 1, message:"padID does not exist"}
|
||||
@param {String} padID the id of the pad
|
||||
@param {String} msg the message to send
|
||||
*/
|
||||
|
||||
exports.sendClientsMessage = async (padID, msg) => {
|
||||
|
@ -740,6 +796,8 @@ Example returns:
|
|||
|
||||
{code: 0, message:"ok", data: {chatHead: 42}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
@return {Promise<{chatHead: number}>} the chatHead of the pad
|
||||
*/
|
||||
exports.getChatHead = async (padID) => {
|
||||
// get the pad
|
||||
|
@ -763,7 +821,9 @@ Example returns:
|
|||
}
|
||||
}
|
||||
{"code":4,"message":"no or wrong API Key","data":null}
|
||||
|
||||
@param {String} padID the id of the pad
|
||||
@param {Number} startRev the start revision number
|
||||
@param {Number} endRev the end revision number
|
||||
*/
|
||||
exports.createDiffHTML = async (padID, startRev, endRev) => {
|
||||
// check if startRev is a number
|
||||
|
@ -779,11 +839,9 @@ exports.createDiffHTML = async (padID, startRev, endRev) => {
|
|||
// get the pad
|
||||
const pad = await getPadSafe(padID, true);
|
||||
const headRev = pad.getHeadRevisionNumber();
|
||||
if (startRev > headRev)
|
||||
startRev = headRev;
|
||||
if (startRev > headRev) startRev = headRev;
|
||||
|
||||
if (endRev > headRev)
|
||||
endRev = headRev;
|
||||
if (endRev > headRev) endRev = headRev;
|
||||
|
||||
let padDiff;
|
||||
try {
|
||||
|
@ -810,7 +868,6 @@ exports.createDiffHTML = async (padID, startRev, endRev) => {
|
|||
{"code":0,"message":"ok","data":{"totalPads":3,"totalSessions": 2,"totalActivePads": 1}}
|
||||
{"code":4,"message":"no or wrong API Key","data":null}
|
||||
*/
|
||||
|
||||
exports.getStats = async () => {
|
||||
const sessionInfos = padMessageHandler.sessioninfos;
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@ exports.getColorPalette = () => [
|
|||
|
||||
/**
|
||||
* Checks if the author exists
|
||||
* @param {String} authorID The id of the author
|
||||
*/
|
||||
exports.doesAuthorExist = async (authorID) => {
|
||||
const author = await db.get(`globalAuthor:${authorID}`);
|
||||
|
@ -100,50 +101,12 @@ exports.doesAuthorExist = async (authorID) => {
|
|||
return author != null;
|
||||
};
|
||||
|
||||
/* exported for backwards compatibility */
|
||||
/**
|
||||
exported for backwards compatibility
|
||||
@param {String} authorID The id of the author
|
||||
*/
|
||||
exports.doesAuthorExists = exports.doesAuthorExist;
|
||||
|
||||
const getAuthor4Token = async (token) => {
|
||||
const author = await mapAuthorWithDBKey('token2author', token);
|
||||
|
||||
// return only the sub value authorID
|
||||
return author ? author.authorID : author;
|
||||
};
|
||||
|
||||
exports.getAuthorId = async (token, user) => {
|
||||
const context = {dbKey: token, token, user};
|
||||
let [authorId] = await hooks.aCallFirst('getAuthorId', context);
|
||||
if (!authorId) authorId = await getAuthor4Token(context.dbKey);
|
||||
return authorId;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the AuthorID for a token.
|
||||
*
|
||||
* @deprecated Use `getAuthorId` instead.
|
||||
* @param {String} token The token
|
||||
*/
|
||||
exports.getAuthor4Token = async (token) => {
|
||||
warnDeprecated(
|
||||
'AuthorManager.getAuthor4Token() is deprecated; use AuthorManager.getAuthorId() instead');
|
||||
return await getAuthor4Token(token);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the AuthorID for a mapper.
|
||||
* @param {String} token The mapper
|
||||
* @param {String} name The name of the author (optional)
|
||||
*/
|
||||
exports.createAuthorIfNotExistsFor = async (authorMapper, name) => {
|
||||
const author = await mapAuthorWithDBKey('mapper2author', authorMapper);
|
||||
|
||||
if (name) {
|
||||
// set the name of this author
|
||||
await exports.setAuthorName(author.authorID, name);
|
||||
}
|
||||
|
||||
return author;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the AuthorID for a mapper. We can map using a mapperkey,
|
||||
|
@ -174,6 +137,60 @@ const mapAuthorWithDBKey = async (mapperkey, mapper) => {
|
|||
return {authorID: author};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the AuthorID for a token.
|
||||
* @param {String} token The token of the author
|
||||
* @return {Promise<string|*|{authorID: string}|{authorID: *}>}
|
||||
*/
|
||||
const getAuthor4Token = async (token) => {
|
||||
const author = await mapAuthorWithDBKey('token2author', token);
|
||||
|
||||
// return only the sub value authorID
|
||||
return author ? author.authorID : author;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the AuthorID for a token.
|
||||
* @param {String} token
|
||||
* @param {Object} user
|
||||
* @return {Promise<*>}
|
||||
*/
|
||||
exports.getAuthorId = async (token, user) => {
|
||||
const context = {dbKey: token, token, user};
|
||||
let [authorId] = await hooks.aCallFirst('getAuthorId', context);
|
||||
if (!authorId) authorId = await getAuthor4Token(context.dbKey);
|
||||
return authorId;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the AuthorID for a token.
|
||||
*
|
||||
* @deprecated Use `getAuthorId` instead.
|
||||
* @param {String} token The token
|
||||
*/
|
||||
exports.getAuthor4Token = async (token) => {
|
||||
warnDeprecated(
|
||||
'AuthorManager.getAuthor4Token() is deprecated; use AuthorManager.getAuthorId() instead');
|
||||
return await getAuthor4Token(token);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the AuthorID for a mapper.
|
||||
* @param {String} authorMapper The mapper
|
||||
* @param {String} name The name of the author (optional)
|
||||
*/
|
||||
exports.createAuthorIfNotExistsFor = async (authorMapper, name) => {
|
||||
const author = await mapAuthorWithDBKey('mapper2author', authorMapper);
|
||||
|
||||
if (name) {
|
||||
// set the name of this author
|
||||
await exports.setAuthorName(author.authorID, name);
|
||||
}
|
||||
|
||||
return author;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Internal function that creates the database entry for an author
|
||||
* @param {String} name The name of the author
|
||||
|
@ -231,7 +248,7 @@ exports.setAuthorName = async (author, name) => await db.setSub(
|
|||
|
||||
/**
|
||||
* Returns an array of all pads this author contributed to
|
||||
* @param {String} author The id of the author
|
||||
* @param {String} authorID The id of the author
|
||||
*/
|
||||
exports.listPadsOfAuthor = async (authorID) => {
|
||||
/* There are two other places where this array is manipulated:
|
||||
|
@ -255,7 +272,7 @@ exports.listPadsOfAuthor = async (authorID) => {
|
|||
|
||||
/**
|
||||
* Adds a new pad to the list of contributions
|
||||
* @param {String} author The id of the author
|
||||
* @param {String} authorID The id of the author
|
||||
* @param {String} padID The id of the pad the author contributes to
|
||||
*/
|
||||
exports.addPad = async (authorID, padID) => {
|
||||
|
@ -282,7 +299,7 @@ exports.addPad = async (authorID, padID) => {
|
|||
|
||||
/**
|
||||
* Removes a pad from the list of contributions
|
||||
* @param {String} author The id of the author
|
||||
* @param {String} authorID The id of the author
|
||||
* @param {String} padID The id of the pad the author contributes to
|
||||
*/
|
||||
exports.removePad = async (authorID, padID) => {
|
||||
|
|
|
@ -25,6 +25,10 @@ const db = require('./DB');
|
|||
const padManager = require('./PadManager');
|
||||
const sessionManager = require('./SessionManager');
|
||||
|
||||
/**
|
||||
* Lists all groups
|
||||
* @return {Promise<{groupIDs: string[]}>} The ids of all groups
|
||||
*/
|
||||
exports.listAllGroups = async () => {
|
||||
let groups = await db.get('groups');
|
||||
groups = groups || {};
|
||||
|
@ -33,6 +37,11 @@ exports.listAllGroups = async () => {
|
|||
return {groupIDs};
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a group and all associated pads
|
||||
* @param {String} groupID The id of the group
|
||||
* @return {Promise<void>} Resolves when the group is deleted
|
||||
*/
|
||||
exports.deleteGroup = async (groupID) => {
|
||||
const group = await db.get(`group:${groupID}`);
|
||||
|
||||
|
@ -68,6 +77,11 @@ exports.deleteGroup = async (groupID) => {
|
|||
await db.remove(`group:${groupID}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a group exists
|
||||
* @param {String} groupID the id of the group to delete
|
||||
* @return {Promise<boolean>} Resolves to true if the group exists
|
||||
*/
|
||||
exports.doesGroupExist = async (groupID) => {
|
||||
// try to get the group entry
|
||||
const group = await db.get(`group:${groupID}`);
|
||||
|
@ -75,6 +89,10 @@ exports.doesGroupExist = async (groupID) => {
|
|||
return (group != null);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new group
|
||||
* @return {Promise<{groupID: string}>} the id of the new group
|
||||
*/
|
||||
exports.createGroup = async () => {
|
||||
const groupID = `g.${randomString(16)}`;
|
||||
await db.set(`group:${groupID}`, {pads: {}, mappings: {}});
|
||||
|
@ -85,6 +103,11 @@ exports.createGroup = async () => {
|
|||
return {groupID};
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new group if it does not exist already and returns the group ID
|
||||
* @param groupMapper the mapper of the group
|
||||
* @return {Promise<{groupID: string}|{groupID: *}>} a promise that resolves to the group ID
|
||||
*/
|
||||
exports.createGroupIfNotExistsFor = async (groupMapper) => {
|
||||
if (typeof groupMapper !== 'string') {
|
||||
throw new CustomError('groupMapper is not a string', 'apierror');
|
||||
|
@ -103,6 +126,14 @@ exports.createGroupIfNotExistsFor = async (groupMapper) => {
|
|||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a group pad
|
||||
* @param {String} groupID The id of the group
|
||||
* @param {String} padName The name of the pad
|
||||
* @param {String} text The text of the pad
|
||||
* @param {String} authorId The id of the author
|
||||
* @return {Promise<{padID: string}>} a promise that resolves to the id of the new pad
|
||||
*/
|
||||
exports.createGroupPad = async (groupID, padName, text, authorId = '') => {
|
||||
// create the padID
|
||||
const padID = `${groupID}$${padName}`;
|
||||
|
@ -131,6 +162,11 @@ exports.createGroupPad = async (groupID, padName, text, authorId = '') => {
|
|||
return {padID};
|
||||
};
|
||||
|
||||
/**
|
||||
* Lists all pads of a group
|
||||
* @param {String} groupID The id of the group
|
||||
* @return {Promise<{padIDs: string[]}>} a promise that resolves to the ids of all pads of the group
|
||||
*/
|
||||
exports.listPads = async (groupID) => {
|
||||
const exists = await exports.doesGroupExist(groupID);
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@ const promises = require('../utils/promises');
|
|||
/**
|
||||
* Copied from the Etherpad source code. It converts Windows line breaks to Unix
|
||||
* line breaks and convert Tabs to spaces
|
||||
* @param txt
|
||||
* @param {String} txt The text to clean
|
||||
* @returns {String} The cleaned text
|
||||
*/
|
||||
exports.cleanText = (txt) => txt.replace(/\r\n/g, '\n')
|
||||
.replace(/\r/g, '\n')
|
||||
|
@ -73,9 +74,16 @@ class Pad {
|
|||
return this.publicStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a new revision
|
||||
* @param {Object} aChangeset The changeset to append to the pad
|
||||
* @param {String} authorId The id of the author
|
||||
* @return {Promise<number|string>}
|
||||
*/
|
||||
async appendRevision(aChangeset, authorId = '') {
|
||||
const newAText = Changeset.applyToAText(aChangeset, this.atext, this.pool);
|
||||
if (newAText.text === this.atext.text && newAText.attribs === this.atext.attribs && this.head !== -1) {
|
||||
if (newAText.text === this.atext.text && newAText.attribs === this.atext.attribs &&
|
||||
this.head !== -1) {
|
||||
return this.head;
|
||||
}
|
||||
Changeset.copyAText(newAText, this.atext);
|
||||
|
@ -158,6 +166,10 @@ class Pad {
|
|||
return await this.db.getSub(`pad:${this.id}:revs:${revNum}`, ['meta', 'atext']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all authors that worked on this pad
|
||||
* @return {[String]} The id of authors who contributed to this pad
|
||||
*/
|
||||
getAllAuthors() {
|
||||
const authorIds = [];
|
||||
|
||||
|
@ -173,8 +185,7 @@ class Pad {
|
|||
async getInternalRevisionAText(targetRev) {
|
||||
const keyRev = this.getKeyRevisionNumber(targetRev);
|
||||
const headRev = this.getHeadRevisionNumber();
|
||||
if (targetRev > headRev)
|
||||
targetRev = headRev;
|
||||
if (targetRev > headRev) targetRev = headRev;
|
||||
const [keyAText, changesets] = await Promise.all([
|
||||
this._getKeyRevisionAText(keyRev),
|
||||
Promise.all(
|
||||
|
|
|
@ -59,6 +59,7 @@ const padList = new class {
|
|||
|
||||
/**
|
||||
* Returns all pads in alphabetical order as array.
|
||||
* @returns {Promise<string[]>} A promise that resolves to an array of pad IDs.
|
||||
*/
|
||||
async getPads() {
|
||||
if (!this._loaded) {
|
||||
|
|
|
@ -26,13 +26,15 @@ const randomString = require('../utils/randomstring');
|
|||
|
||||
/**
|
||||
* checks if the id pattern matches a read-only pad id
|
||||
* @param {String} the pad's id
|
||||
* @param {String} id the pad's id
|
||||
* @return {Boolean} true if the id is readonly
|
||||
*/
|
||||
exports.isReadOnlyId = (id) => id.startsWith('r.');
|
||||
|
||||
/**
|
||||
* returns a read only id for a pad
|
||||
* @param {String} padId the id of the pad
|
||||
* @return {String} the read only id
|
||||
*/
|
||||
exports.getReadOnlyId = async (padId) => {
|
||||
// check if there is a pad2readonly entry
|
||||
|
@ -53,12 +55,14 @@ exports.getReadOnlyId = async (padId) => {
|
|||
/**
|
||||
* returns the padId for a read only id
|
||||
* @param {String} readOnlyId read only id
|
||||
* @return {String} the padId
|
||||
*/
|
||||
exports.getPadId = async (readOnlyId) => await db.get(`readonly2pad:${readOnlyId}`);
|
||||
|
||||
/**
|
||||
* returns the padId and readonlyPadId in an object for any id
|
||||
* @param {String} padIdOrReadonlyPadId read only id or real pad id
|
||||
* @param {String} id read only id or real pad id
|
||||
* @return {Object} an object with the padId and readonlyPadId
|
||||
*/
|
||||
exports.getIds = async (id) => {
|
||||
const readonly = exports.isReadOnlyId(id);
|
||||
|
|
|
@ -49,6 +49,11 @@ const DENY = Object.freeze({accessStatus: 'deny'});
|
|||
*
|
||||
* WARNING: Tokens and session IDs MUST be kept secret, otherwise users will be able to impersonate
|
||||
* each other (which might allow them to gain privileges).
|
||||
* @param {String} padID
|
||||
* @param {String} sessionCookie
|
||||
* @param {String} token
|
||||
* @param {Object} userSettings
|
||||
* @return {DENY|{accessStatus: String, authorID: String}}
|
||||
*/
|
||||
exports.checkAccess = async (padID, sessionCookie, token, userSettings) => {
|
||||
if (!padID) {
|
||||
|
|
|
@ -81,6 +81,11 @@ exports.findAuthorID = async (groupID, sessionCookie) => {
|
|||
return sessionInfo.authorID;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a session exists
|
||||
* @param {String} sessionID The id of the session
|
||||
* @return {Promise<boolean>} Resolves to true if the session exists
|
||||
*/
|
||||
exports.doesSessionExist = async (sessionID) => {
|
||||
// check if the database entry of this session exists
|
||||
const session = await db.get(`session:${sessionID}`);
|
||||
|
@ -89,6 +94,10 @@ exports.doesSessionExist = async (sessionID) => {
|
|||
|
||||
/**
|
||||
* Creates a new session between an author and a group
|
||||
* @param {String} groupID The id of the group
|
||||
* @param {String} authorID The id of the author
|
||||
* @param {Number} validUntil The unix timestamp when the session should expire
|
||||
* @return {Promise<{sessionID: string}>} the id of the new session
|
||||
*/
|
||||
exports.createSession = async (groupID, authorID, validUntil) => {
|
||||
// check if the group exists
|
||||
|
@ -146,6 +155,11 @@ exports.createSession = async (groupID, authorID, validUntil) => {
|
|||
return {sessionID};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the sessioninfos for a session
|
||||
* @param {String} sessionID The id of the session
|
||||
* @return {Promise<Object>} the sessioninfos
|
||||
*/
|
||||
exports.getSessionInfo = async (sessionID) => {
|
||||
// check if the database entry of this session exists
|
||||
const session = await db.get(`session:${sessionID}`);
|
||||
|
@ -161,6 +175,8 @@ exports.getSessionInfo = async (sessionID) => {
|
|||
|
||||
/**
|
||||
* Deletes a session
|
||||
* @param {String} sessionID The id of the session
|
||||
* @return {Promise<void>} Resolves when the session is deleted
|
||||
*/
|
||||
exports.deleteSession = async (sessionID) => {
|
||||
// ensure that the session exists
|
||||
|
@ -186,6 +202,11 @@ exports.deleteSession = async (sessionID) => {
|
|||
await db.remove(`session:${sessionID}`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an array of all sessions of a group
|
||||
* @param {String} groupID The id of the group
|
||||
* @return {Promise<Object>} The sessioninfos of all sessions of this group
|
||||
*/
|
||||
exports.listSessionsOfGroup = async (groupID) => {
|
||||
// check that the group exists
|
||||
const exists = await groupManager.doesGroupExist(groupID);
|
||||
|
@ -197,6 +218,11 @@ exports.listSessionsOfGroup = async (groupID) => {
|
|||
return sessions;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an array of all sessions of an author
|
||||
* @param {String} authorID The id of the author
|
||||
* @return {Promise<Object>} The sessioninfos of all sessions of this author
|
||||
*/
|
||||
exports.listSessionsOfAuthor = async (authorID) => {
|
||||
// check that the author exists
|
||||
const exists = await authorManager.doesAuthorExist(authorID);
|
||||
|
@ -204,12 +230,16 @@ exports.listSessionsOfAuthor = async (authorID) => {
|
|||
throw new CustomError('authorID does not exist', 'apierror');
|
||||
}
|
||||
|
||||
const sessions = await listSessionsWithDBKey(`author2sessions:${authorID}`);
|
||||
return sessions;
|
||||
return await listSessionsWithDBKey(`author2sessions:${authorID}`);
|
||||
};
|
||||
|
||||
// this function is basically the code listSessionsOfAuthor and listSessionsOfGroup has in common
|
||||
// required to return null rather than an empty object if there are none
|
||||
/**
|
||||
* Returns an array of all sessions of a group
|
||||
* @param {String} dbkey The db key to use to get the sessions
|
||||
* @return {Promise<*>}
|
||||
*/
|
||||
const listSessionsWithDBKey = async (dbkey) => {
|
||||
// get the group2sessions entry
|
||||
const sessionObject = await db.get(dbkey);
|
||||
|
@ -218,8 +248,7 @@ const listSessionsWithDBKey = async (dbkey) => {
|
|||
// iterate through the sessions and get the sessioninfos
|
||||
for (const sessionID of Object.keys(sessions || {})) {
|
||||
try {
|
||||
const sessionInfo = await exports.getSessionInfo(sessionID);
|
||||
sessions[sessionID] = sessionInfo;
|
||||
sessions[sessionID] = await exports.getSessionInfo(sessionID);
|
||||
} catch (err) {
|
||||
if (err.name === 'apierror') {
|
||||
console.warn(`Found bad session ${sessionID} in ${dbkey}`);
|
||||
|
@ -233,5 +262,9 @@ const listSessionsWithDBKey = async (dbkey) => {
|
|||
return sessions;
|
||||
};
|
||||
|
||||
// checks if a number is an int
|
||||
/**
|
||||
* checks if a number is an int
|
||||
* @param {number|string} value
|
||||
* @return {boolean} If the value is an integer
|
||||
*/
|
||||
const isInt = (value) => (parseFloat(value) === parseInt(value)) && !isNaN(value);
|
||||
|
|
|
@ -165,12 +165,13 @@ exports.version = version;
|
|||
|
||||
/**
|
||||
* Handles a HTTP API call
|
||||
* @param functionName the name of the called function
|
||||
* @param {String} apiVersion the version of the api
|
||||
* @param {String} functionName the name of the called function
|
||||
* @param fields the params of the called function
|
||||
* @req express request object
|
||||
* @res express response object
|
||||
*/
|
||||
exports.handle = async function (apiVersion, functionName, fields, req, res) {
|
||||
exports.handle = async function (apiVersion, functionName, fields) {
|
||||
// say goodbye if this is an unknown API version
|
||||
if (!(apiVersion in version)) {
|
||||
throw new createHTTPError.NotFound('no such api version');
|
||||
|
|
|
@ -38,6 +38,11 @@ const tempDirectory = os.tmpdir();
|
|||
|
||||
/**
|
||||
* do a requested export
|
||||
* @param {Object} req the request object
|
||||
* @param {Object} res the response object
|
||||
* @param {String} padId the pad id to export
|
||||
* @param {String} readOnlyId the read only id of the pad to export
|
||||
* @param {String} type the type to export
|
||||
*/
|
||||
exports.doExport = async (req, res, padId, readOnlyId, type) => {
|
||||
// avoid naming the read-only file as the original pad's id
|
||||
|
|
|
@ -73,6 +73,10 @@ const tmpDirectory = os.tmpdir();
|
|||
|
||||
/**
|
||||
* do a requested import
|
||||
* @param {Object} req the request object
|
||||
* @param {Object} res the response object
|
||||
* @param {String} padId the pad id to export
|
||||
* @param {String} authorId the author id to use for the import
|
||||
*/
|
||||
const doImport = async (req, res, padId, authorId) => {
|
||||
// pipe to a file
|
||||
|
@ -233,6 +237,14 @@ const doImport = async (req, res, padId, authorId) => {
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the request to import a file
|
||||
* @param {Request} req the request object
|
||||
* @param {Response} res the response object
|
||||
* @param {String} padId the pad id to export
|
||||
* @param {String} authorId the author id to use for the import
|
||||
* @return {Promise<void>} a promise
|
||||
*/
|
||||
exports.doImport = async (req, res, padId, authorId = '') => {
|
||||
let httpStatus = 200;
|
||||
let code = 0;
|
||||
|
|
|
@ -35,8 +35,9 @@ const components = {};
|
|||
|
||||
let io;
|
||||
|
||||
/**
|
||||
* adds a component
|
||||
/** adds a component
|
||||
* @param {string} moduleName
|
||||
* @param {Module} module
|
||||
*/
|
||||
exports.addComponent = (moduleName, module) => {
|
||||
if (module == null) return exports.deleteComponent(moduleName);
|
||||
|
@ -44,10 +45,15 @@ exports.addComponent = (moduleName, module) => {
|
|||
module.setSocketIO(io);
|
||||
};
|
||||
|
||||
/**
|
||||
* removes a component
|
||||
* @param {Module} moduleName
|
||||
*/
|
||||
exports.deleteComponent = (moduleName) => { delete components[moduleName]; };
|
||||
|
||||
/**
|
||||
* sets the socket.io and adds event functions for routing
|
||||
* @param {Object} _io the socket.io instance
|
||||
*/
|
||||
exports.setSocketIO = (_io) => {
|
||||
io = _io;
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
'use strict';
|
||||
const eejs = require('../../eejs');
|
||||
|
||||
|
||||
/**
|
||||
* Add the admin navigation link
|
||||
* @param hookName {String} the name of the hook
|
||||
* @param args {Object} the object containing the arguments
|
||||
* @param {Function} cb the callback function
|
||||
* @return {*}
|
||||
*/
|
||||
exports.expressCreateServer = (hookName, args, cb) => {
|
||||
args.app.get('/admin', (req, res) => {
|
||||
if ('/' !== req.path[req.path.length - 1]) return res.redirect('./admin/');
|
||||
|
|
|
@ -121,6 +121,13 @@ exports.socketio = (hookName, args, cb) => {
|
|||
return cb();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sorts a list of plugins by a property
|
||||
* @param {Object} plugins The plugins to sort
|
||||
* @param {Object} property The property to sort by
|
||||
* @param {String} dir The directory of the plugin
|
||||
* @return {Object[]}
|
||||
*/
|
||||
const sortPluginList = (plugins, property, /* ASC?*/dir) => plugins.sort((a, b) => {
|
||||
if (a[property] < b[property]) {
|
||||
return dir ? -1 : 1;
|
||||
|
|
|
@ -696,10 +696,20 @@ exports.expressPreSession = async (hookName, {app}) => {
|
|||
}
|
||||
};
|
||||
|
||||
// helper to get api root
|
||||
/**
|
||||
* Helper to get the current root path for an API version
|
||||
* @param {String} version The API version
|
||||
* @param {APIPathStyle} style The style of the API path
|
||||
* @return {String} The root path for the API version
|
||||
*/
|
||||
const getApiRootForVersion = (version, style = APIPathStyle.FLAT) => `/${style}/${version}`;
|
||||
|
||||
// helper to generate an OpenAPI server object when serving definitions
|
||||
/**
|
||||
* Helper to generate an OpenAPI server object when serving definitions
|
||||
* @param {String} apiRoot The root path for the API version
|
||||
* @param {Request} req The express request object
|
||||
* @return {url: String} The server object for the OpenAPI definition location
|
||||
*/
|
||||
const generateServerForApiVersion = (apiRoot, req) => ({
|
||||
url: `${settings.ssl ? 'https' : 'http'}://${req.headers.host}${apiRoot}`,
|
||||
});
|
||||
|
|
|
@ -12,4 +12,4 @@ exports.hkdf = util.promisify(crypto.hkdf);
|
|||
/**
|
||||
* Promisified version of Node.js's crypto.randomBytes
|
||||
*/
|
||||
exports.randomBytes = util.promisify(crypto.randomBytes);
|
||||
exports.randomBytes = util.promisify(crypto.randomBytes);
|
||||
|
|
Loading…
Reference in a new issue