diff --git a/src/node/db/API.js b/src/node/db/API.js index 3f92c47dd..b9efb5411 100644 --- a/src/node/db/API.js +++ b/src/node/db/API.js @@ -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} + */ 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 Text"}} {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; diff --git a/src/node/db/AuthorManager.js b/src/node/db/AuthorManager.js index 7049be5db..7413b5806 100644 --- a/src/node/db/AuthorManager.js +++ b/src/node/db/AuthorManager.js @@ -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} + */ +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) => { diff --git a/src/node/db/GroupManager.js b/src/node/db/GroupManager.js index 4302048c4..2ab20ac16 100644 --- a/src/node/db/GroupManager.js +++ b/src/node/db/GroupManager.js @@ -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} 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} 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); diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index 751da1ae5..884b420f0 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -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} + */ 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( diff --git a/src/node/db/PadManager.js b/src/node/db/PadManager.js index cdcb58176..7c4021541 100644 --- a/src/node/db/PadManager.js +++ b/src/node/db/PadManager.js @@ -59,6 +59,7 @@ const padList = new class { /** * Returns all pads in alphabetical order as array. + * @returns {Promise} A promise that resolves to an array of pad IDs. */ async getPads() { if (!this._loaded) { diff --git a/src/node/db/ReadOnlyManager.js b/src/node/db/ReadOnlyManager.js index 33ce2930a..b96dd3413 100644 --- a/src/node/db/ReadOnlyManager.js +++ b/src/node/db/ReadOnlyManager.js @@ -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); diff --git a/src/node/db/SecurityManager.js b/src/node/db/SecurityManager.js index 280c753bb..0e5b2c77c 100644 --- a/src/node/db/SecurityManager.js +++ b/src/node/db/SecurityManager.js @@ -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) { diff --git a/src/node/db/SessionManager.js b/src/node/db/SessionManager.js index 5ef75acfa..3d39ed747 100644 --- a/src/node/db/SessionManager.js +++ b/src/node/db/SessionManager.js @@ -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} 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} 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} 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} 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} 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); diff --git a/src/node/handler/APIHandler.js b/src/node/handler/APIHandler.js index 2c060c239..3b5a3fb63 100644 --- a/src/node/handler/APIHandler.js +++ b/src/node/handler/APIHandler.js @@ -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'); diff --git a/src/node/handler/ExportHandler.js b/src/node/handler/ExportHandler.js index 417380866..e0a89e6d0 100644 --- a/src/node/handler/ExportHandler.js +++ b/src/node/handler/ExportHandler.js @@ -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 diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index 5dfc152c5..6caf7ba93 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -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} a promise + */ exports.doImport = async (req, res, padId, authorId = '') => { let httpStatus = 200; let code = 0; diff --git a/src/node/handler/SocketIORouter.js b/src/node/handler/SocketIORouter.js index 863401ace..d9e76158d 100644 --- a/src/node/handler/SocketIORouter.js +++ b/src/node/handler/SocketIORouter.js @@ -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; diff --git a/src/node/hooks/express/admin.js b/src/node/hooks/express/admin.js index 763698332..ed272efd8 100644 --- a/src/node/hooks/express/admin.js +++ b/src/node/hooks/express/admin.js @@ -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/'); diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js index 543f04c0f..19908cf59 100644 --- a/src/node/hooks/express/adminplugins.js +++ b/src/node/hooks/express/adminplugins.js @@ -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; diff --git a/src/node/hooks/express/openapi.js b/src/node/hooks/express/openapi.js index 240b6fcf5..69f268256 100644 --- a/src/node/hooks/express/openapi.js +++ b/src/node/hooks/express/openapi.js @@ -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}`, }); diff --git a/src/node/security/crypto.js b/src/node/security/crypto.js index ebe918509..9cf0a95a0 100644 --- a/src/node/security/crypto.js +++ b/src/node/security/crypto.js @@ -12,4 +12,4 @@ exports.hkdf = util.promisify(crypto.hkdf); /** * Promisified version of Node.js's crypto.randomBytes */ -exports.randomBytes = util.promisify(crypto.randomBytes); \ No newline at end of file +exports.randomBytes = util.promisify(crypto.randomBytes);