mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-24 01:16:15 -04:00
Moved more classes to ts. (#6179)
This commit is contained in:
parent
3ea6f1072d
commit
4bd27a1c79
22 changed files with 790 additions and 653 deletions
|
@ -104,7 +104,7 @@ Example returns:
|
|||
}
|
||||
|
||||
*/
|
||||
exports.getAttributePool = async (padID) => {
|
||||
exports.getAttributePool = async (padID: string) => {
|
||||
const pad = await getPadSafe(padID, true);
|
||||
return {pool: pad.pool};
|
||||
};
|
||||
|
@ -122,7 +122,7 @@ Example returns:
|
|||
}
|
||||
|
||||
*/
|
||||
exports.getRevisionChangeset = async (padID, rev) => {
|
||||
exports.getRevisionChangeset = async (padID: string, rev: string) => {
|
||||
// try to parse the revision number
|
||||
if (rev !== undefined) {
|
||||
rev = checkValidRev(rev);
|
||||
|
@ -155,7 +155,7 @@ Example returns:
|
|||
{code: 0, message:"ok", data: {text:"Welcome Text"}}
|
||||
{code: 1, message:"padID does not exist", data: null}
|
||||
*/
|
||||
exports.getText = async (padID, rev) => {
|
||||
exports.getText = async (padID: string, rev: string) => {
|
||||
// try to parse the revision number
|
||||
if (rev !== undefined) {
|
||||
rev = checkValidRev(rev);
|
||||
|
@ -173,7 +173,7 @@ exports.getText = async (padID, rev) => {
|
|||
}
|
||||
|
||||
// get the text of this revision
|
||||
// getInternalRevisionAText() returns an atext object but we only want the .text inside it.
|
||||
// getInternalRevisionAText() returns an atext object, but we only want the .text inside it.
|
||||
// Details at https://github.com/ether/etherpad-lite/issues/5073
|
||||
const {text} = await pad.getInternalRevisionAText(rev);
|
||||
return {text};
|
||||
|
@ -200,7 +200,7 @@ Example returns:
|
|||
* @param {String} authorId the id of the author, defaulting to empty string
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
exports.setText = async (padID, text, authorId = '') => {
|
||||
exports.setText = async (padID: string, text?: string, authorId: string = ''): Promise<void> => {
|
||||
// text is required
|
||||
if (typeof text !== 'string') {
|
||||
throw new CustomError('text is not a string', 'apierror');
|
||||
|
@ -225,7 +225,7 @@ Example returns:
|
|||
@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 = '') => {
|
||||
exports.appendText = async (padID:string, text?: string, authorId:string = '') => {
|
||||
// text is required
|
||||
if (typeof text !== 'string') {
|
||||
throw new CustomError('text is not a string', 'apierror');
|
||||
|
@ -247,7 +247,7 @@ Example returns:
|
|||
@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) => {
|
||||
exports.getHTML = async (padID: string, rev: string): Promise<{ html: string; }> => {
|
||||
if (rev !== undefined) {
|
||||
rev = checkValidRev(rev);
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ Example returns:
|
|||
@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 = '') => {
|
||||
exports.setHTML = async (padID: string, html:string|object, authorId = '') => {
|
||||
// html string is required
|
||||
if (typeof html !== 'string') {
|
||||
throw new CustomError('html is not a string', 'apierror');
|
||||
|
@ -324,7 +324,7 @@ Example returns:
|
|||
@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) => {
|
||||
exports.getChatHistory = async (padID: string, start:number, end:number) => {
|
||||
if (start && end) {
|
||||
if (start < 0) {
|
||||
throw new CustomError('start is below zero', 'apierror');
|
||||
|
@ -374,7 +374,7 @@ Example returns:
|
|||
@param {String} authorID the id of the author
|
||||
@param {Number} time the timestamp of the chat-message
|
||||
*/
|
||||
exports.appendChatMessage = async (padID, text, authorID, time) => {
|
||||
exports.appendChatMessage = async (padID: string, text: string|object, authorID: string, time: number) => {
|
||||
// text is required
|
||||
if (typeof text !== 'string') {
|
||||
throw new CustomError('text is not a string', 'apierror');
|
||||
|
@ -404,7 +404,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.getRevisionsCount = async (padID) => {
|
||||
exports.getRevisionsCount = async (padID: string) => {
|
||||
// get the pad
|
||||
const pad = await getPadSafe(padID, true);
|
||||
return {revisions: pad.getHeadRevisionNumber()};
|
||||
|
@ -419,7 +419,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.getSavedRevisionsCount = async (padID) => {
|
||||
exports.getSavedRevisionsCount = async (padID: string) => {
|
||||
// get the pad
|
||||
const pad = await getPadSafe(padID, true);
|
||||
return {savedRevisions: pad.getSavedRevisionsNumber()};
|
||||
|
@ -434,7 +434,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.listSavedRevisions = async (padID) => {
|
||||
exports.listSavedRevisions = async (padID: string) => {
|
||||
// get the pad
|
||||
const pad = await getPadSafe(padID, true);
|
||||
return {savedRevisions: pad.getSavedRevisionsList()};
|
||||
|
@ -450,7 +450,7 @@ Example returns:
|
|||
@param {String} padID the id of the pad
|
||||
@param {Number} rev the revision number, defaulting to the latest revision
|
||||
*/
|
||||
exports.saveRevision = async (padID, rev) => {
|
||||
exports.saveRevision = async (padID: string, rev: number) => {
|
||||
// check if rev is a number
|
||||
if (rev !== undefined) {
|
||||
rev = checkValidRev(rev);
|
||||
|
@ -483,7 +483,7 @@ Example returns:
|
|||
@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) => {
|
||||
exports.getLastEdited = async (padID: string): Promise<{ lastEdited: number; }> => {
|
||||
// get the pad
|
||||
const pad = await getPadSafe(padID, true);
|
||||
const lastEdited = await pad.getLastEdit();
|
||||
|
@ -497,11 +497,11 @@ 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} padID 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 = '') => {
|
||||
exports.createPad = async (padID: string, text: string, authorId = '') => {
|
||||
if (padID) {
|
||||
// ensure there is no $ in the padID
|
||||
if (padID.indexOf('$') !== -1) {
|
||||
|
@ -527,7 +527,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.deletePad = async (padID) => {
|
||||
exports.deletePad = async (padID: string) => {
|
||||
const pad = await getPadSafe(padID, true);
|
||||
await pad.remove();
|
||||
};
|
||||
|
@ -543,7 +543,7 @@ exports.deletePad = async (padID) => {
|
|||
@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 = '') => {
|
||||
exports.restoreRevision = async (padID: string, rev: number, authorId = '') => {
|
||||
// check if rev is a number
|
||||
if (rev === undefined) {
|
||||
throw new CustomError('rev is not defined', 'apierror');
|
||||
|
@ -563,7 +563,7 @@ exports.restoreRevision = async (padID, rev, authorId = '') => {
|
|||
const oldText = pad.text();
|
||||
atext.text += '\n';
|
||||
|
||||
const eachAttribRun = (attribs, func) => {
|
||||
const eachAttribRun = (attribs: string[], func:Function) => {
|
||||
let textIndex = 0;
|
||||
const newTextStart = 0;
|
||||
const newTextEnd = atext.text.length;
|
||||
|
@ -580,7 +580,7 @@ exports.restoreRevision = async (padID, rev, authorId = '') => {
|
|||
const builder = Changeset.builder(oldText.length);
|
||||
|
||||
// assemble each line into the builder
|
||||
eachAttribRun(atext.attribs, (start, end, attribs) => {
|
||||
eachAttribRun(atext.attribs, (start: number, end: number, attribs:string[]) => {
|
||||
builder.insert(atext.text.substring(start, end), attribs);
|
||||
});
|
||||
|
||||
|
@ -610,7 +610,7 @@ Example returns:
|
|||
@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) => {
|
||||
exports.copyPad = async (sourceID: string, destinationID: string, force: boolean) => {
|
||||
const pad = await getPadSafe(sourceID, true);
|
||||
await pad.copy(destinationID, force);
|
||||
};
|
||||
|
@ -628,7 +628,7 @@ Example returns:
|
|||
@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 = '') => {
|
||||
exports.copyPadWithoutHistory = async (sourceID: string, destinationID: string, force:boolean, authorId = '') => {
|
||||
const pad = await getPadSafe(sourceID, true);
|
||||
await pad.copyPadWithoutHistory(destinationID, force, authorId);
|
||||
};
|
||||
|
@ -645,7 +645,7 @@ Example returns:
|
|||
@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) => {
|
||||
exports.movePad = async (sourceID: string, destinationID: string, force:boolean) => {
|
||||
const pad = await getPadSafe(sourceID, true);
|
||||
await pad.copy(destinationID, force);
|
||||
await pad.remove();
|
||||
|
@ -660,7 +660,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.getReadOnlyID = async (padID) => {
|
||||
exports.getReadOnlyID = async (padID: string) => {
|
||||
// we don't need the pad object, but this function does all the security stuff for us
|
||||
await getPadSafe(padID, true);
|
||||
|
||||
|
@ -679,7 +679,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} roID the readonly id of the pad
|
||||
*/
|
||||
exports.getPadID = async (roID) => {
|
||||
exports.getPadID = async (roID: string) => {
|
||||
// get the PadId
|
||||
const padID = await readOnlyManager.getPadId(roID);
|
||||
if (padID == null) {
|
||||
|
@ -699,7 +699,7 @@ Example returns:
|
|||
@param {String} padID the id of the pad
|
||||
@param {Boolean} publicStatus the public status of the pad
|
||||
*/
|
||||
exports.setPublicStatus = async (padID, publicStatus) => {
|
||||
exports.setPublicStatus = async (padID: string, publicStatus: boolean|string) => {
|
||||
// ensure this is a group pad
|
||||
checkGroupPad(padID, 'publicStatus');
|
||||
|
||||
|
@ -723,7 +723,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.getPublicStatus = async (padID) => {
|
||||
exports.getPublicStatus = async (padID: string) => {
|
||||
// ensure this is a group pad
|
||||
checkGroupPad(padID, 'publicStatus');
|
||||
|
||||
|
@ -741,7 +741,7 @@ Example returns:
|
|||
{code: 1, message:"padID does not exist", data: null}
|
||||
@param {String} padID the id of the pad
|
||||
*/
|
||||
exports.listAuthorsOfPad = async (padID) => {
|
||||
exports.listAuthorsOfPad = async (padID: string) => {
|
||||
// get the pad
|
||||
const pad = await getPadSafe(padID, true);
|
||||
const authorIDs = pad.getAllAuthors();
|
||||
|
@ -773,7 +773,7 @@ Example returns:
|
|||
@param {String} msg the message to send
|
||||
*/
|
||||
|
||||
exports.sendClientsMessage = async (padID, msg) => {
|
||||
exports.sendClientsMessage = async (padID: string, msg: string) => {
|
||||
await getPadSafe(padID, true); // Throw if the padID is invalid or if the pad does not exist.
|
||||
padMessageHandler.handleCustomMessage(padID, msg);
|
||||
};
|
||||
|
@ -799,7 +799,7 @@ Example returns:
|
|||
@param {String} padID the id of the pad
|
||||
@return {Promise<{chatHead: number}>} the chatHead of the pad
|
||||
*/
|
||||
exports.getChatHead = async (padID) => {
|
||||
exports.getChatHead = async (padID:string): Promise<{ chatHead: number; }> => {
|
||||
// get the pad
|
||||
const pad = await getPadSafe(padID, true);
|
||||
return {chatHead: pad.chatHead};
|
||||
|
@ -825,7 +825,7 @@ Example returns:
|
|||
@param {Number} startRev the start revision number
|
||||
@param {Number} endRev the end revision number
|
||||
*/
|
||||
exports.createDiffHTML = async (padID, startRev, endRev) => {
|
||||
exports.createDiffHTML = async (padID: string, startRev: number, endRev: number) => {
|
||||
// check if startRev is a number
|
||||
if (startRev !== undefined) {
|
||||
startRev = checkValidRev(startRev);
|
||||
|
@ -846,7 +846,7 @@ exports.createDiffHTML = async (padID, startRev, endRev) => {
|
|||
let padDiff;
|
||||
try {
|
||||
padDiff = new PadDiff(pad, startRev, endRev);
|
||||
} catch (e) {
|
||||
} catch (e:any) {
|
||||
throw {stop: e.message};
|
||||
}
|
||||
|
||||
|
@ -872,6 +872,7 @@ exports.getStats = async () => {
|
|||
const sessionInfos = padMessageHandler.sessioninfos;
|
||||
|
||||
const sessionKeys = Object.keys(sessionInfos);
|
||||
// @ts-ignore
|
||||
const activePads = new Set(Object.entries(sessionInfos).map((k) => k[1].padId));
|
||||
|
||||
const {padIDs} = await padManager.listAllPads();
|
||||
|
@ -888,7 +889,7 @@ exports.getStats = async () => {
|
|||
**************************** */
|
||||
|
||||
// gets a pad safe
|
||||
const getPadSafe = async (padID, shouldExist, text, authorId = '') => {
|
||||
const getPadSafe = async (padID: string|object, shouldExist: boolean, text?:string, authorId:string = '') => {
|
||||
// check if padID is a string
|
||||
if (typeof padID !== 'string') {
|
||||
throw new CustomError('padID is not a string', 'apierror');
|
||||
|
@ -917,7 +918,7 @@ const getPadSafe = async (padID, shouldExist, text, authorId = '') => {
|
|||
};
|
||||
|
||||
// checks if a padID is part of a group
|
||||
const checkGroupPad = (padID, field) => {
|
||||
const checkGroupPad = (padID: string, field: string) => {
|
||||
// ensure this is a group pad
|
||||
if (padID && padID.indexOf('$') === -1) {
|
||||
throw new CustomError(
|
|
@ -95,7 +95,7 @@ exports.getColorPalette = () => [
|
|||
* Checks if the author exists
|
||||
* @param {String} authorID The id of the author
|
||||
*/
|
||||
exports.doesAuthorExist = async (authorID) => {
|
||||
exports.doesAuthorExist = async (authorID: string) => {
|
||||
const author = await db.get(`globalAuthor:${authorID}`);
|
||||
|
||||
return author != null;
|
||||
|
@ -114,7 +114,7 @@ exports.doesAuthorExists = exports.doesAuthorExist;
|
|||
* @param {String} mapperkey The database key name for this mapper
|
||||
* @param {String} mapper The mapper
|
||||
*/
|
||||
const mapAuthorWithDBKey = async (mapperkey, mapper) => {
|
||||
const mapAuthorWithDBKey = async (mapperkey: string, mapper:string) => {
|
||||
// try to map to an author
|
||||
const author = await db.get(`${mapperkey}:${mapper}`);
|
||||
|
||||
|
@ -142,7 +142,7 @@ const mapAuthorWithDBKey = async (mapperkey, mapper) => {
|
|||
* @param {String} token The token of the author
|
||||
* @return {Promise<string|*|{authorID: string}|{authorID: *}>}
|
||||
*/
|
||||
const getAuthor4Token = async (token) => {
|
||||
const getAuthor4Token = async (token: string) => {
|
||||
const author = await mapAuthorWithDBKey('token2author', token);
|
||||
|
||||
// return only the sub value authorID
|
||||
|
@ -155,7 +155,7 @@ const getAuthor4Token = async (token) => {
|
|||
* @param {Object} user
|
||||
* @return {Promise<*>}
|
||||
*/
|
||||
exports.getAuthorId = async (token, user) => {
|
||||
exports.getAuthorId = async (token: string, user: object) => {
|
||||
const context = {dbKey: token, token, user};
|
||||
let [authorId] = await hooks.aCallFirst('getAuthorId', context);
|
||||
if (!authorId) authorId = await getAuthor4Token(context.dbKey);
|
||||
|
@ -168,7 +168,7 @@ exports.getAuthorId = async (token, user) => {
|
|||
* @deprecated Use `getAuthorId` instead.
|
||||
* @param {String} token The token
|
||||
*/
|
||||
exports.getAuthor4Token = async (token) => {
|
||||
exports.getAuthor4Token = async (token: string) => {
|
||||
warnDeprecated(
|
||||
'AuthorManager.getAuthor4Token() is deprecated; use AuthorManager.getAuthorId() instead');
|
||||
return await getAuthor4Token(token);
|
||||
|
@ -179,7 +179,7 @@ exports.getAuthor4Token = async (token) => {
|
|||
* @param {String} authorMapper The mapper
|
||||
* @param {String} name The name of the author (optional)
|
||||
*/
|
||||
exports.createAuthorIfNotExistsFor = async (authorMapper, name) => {
|
||||
exports.createAuthorIfNotExistsFor = async (authorMapper: string, name: string) => {
|
||||
const author = await mapAuthorWithDBKey('mapper2author', authorMapper);
|
||||
|
||||
if (name) {
|
||||
|
@ -195,7 +195,7 @@ exports.createAuthorIfNotExistsFor = async (authorMapper, name) => {
|
|||
* Internal function that creates the database entry for an author
|
||||
* @param {String} name The name of the author
|
||||
*/
|
||||
exports.createAuthor = async (name) => {
|
||||
exports.createAuthor = async (name: string) => {
|
||||
// create the new author name
|
||||
const author = `a.${randomString(16)}`;
|
||||
|
||||
|
@ -216,41 +216,41 @@ exports.createAuthor = async (name) => {
|
|||
* Returns the Author Obj of the author
|
||||
* @param {String} author The id of the author
|
||||
*/
|
||||
exports.getAuthor = async (author) => await db.get(`globalAuthor:${author}`);
|
||||
exports.getAuthor = async (author: string) => await db.get(`globalAuthor:${author}`);
|
||||
|
||||
/**
|
||||
* Returns the color Id of the author
|
||||
* @param {String} author The id of the author
|
||||
*/
|
||||
exports.getAuthorColorId = async (author) => await db.getSub(`globalAuthor:${author}`, ['colorId']);
|
||||
exports.getAuthorColorId = async (author: string) => await db.getSub(`globalAuthor:${author}`, ['colorId']);
|
||||
|
||||
/**
|
||||
* Sets the color Id of the author
|
||||
* @param {String} author The id of the author
|
||||
* @param {String} colorId The color id of the author
|
||||
*/
|
||||
exports.setAuthorColorId = async (author, colorId) => await db.setSub(
|
||||
exports.setAuthorColorId = async (author: string, colorId: string) => await db.setSub(
|
||||
`globalAuthor:${author}`, ['colorId'], colorId);
|
||||
|
||||
/**
|
||||
* Returns the name of the author
|
||||
* @param {String} author The id of the author
|
||||
*/
|
||||
exports.getAuthorName = async (author) => await db.getSub(`globalAuthor:${author}`, ['name']);
|
||||
exports.getAuthorName = async (author: string) => await db.getSub(`globalAuthor:${author}`, ['name']);
|
||||
|
||||
/**
|
||||
* Sets the name of the author
|
||||
* @param {String} author The id of the author
|
||||
* @param {String} name The name of the author
|
||||
*/
|
||||
exports.setAuthorName = async (author, name) => await db.setSub(
|
||||
exports.setAuthorName = async (author: string, name: string) => await db.setSub(
|
||||
`globalAuthor:${author}`, ['name'], name);
|
||||
|
||||
/**
|
||||
* Returns an array of all pads this author contributed to
|
||||
* @param {String} authorID The id of the author
|
||||
*/
|
||||
exports.listPadsOfAuthor = async (authorID) => {
|
||||
exports.listPadsOfAuthor = async (authorID: string) => {
|
||||
/* There are two other places where this array is manipulated:
|
||||
* (1) When the author is added to a pad, the author object is also updated
|
||||
* (2) When a pad is deleted, each author of that pad is also updated
|
||||
|
@ -275,7 +275,7 @@ exports.listPadsOfAuthor = async (authorID) => {
|
|||
* @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) => {
|
||||
exports.addPad = async (authorID: string, padID: string) => {
|
||||
// get the entry
|
||||
const author = await db.get(`globalAuthor:${authorID}`);
|
||||
|
||||
|
@ -302,7 +302,7 @@ exports.addPad = async (authorID, padID) => {
|
|||
* @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) => {
|
||||
exports.removePad = async (authorID: string, padID: string) => {
|
||||
const author = await db.get(`globalAuthor:${authorID}`);
|
||||
|
||||
if (author == null) return;
|
|
@ -42,7 +42,7 @@ exports.listAllGroups = async () => {
|
|||
* @param {String} groupID The id of the group
|
||||
* @return {Promise<void>} Resolves when the group is deleted
|
||||
*/
|
||||
exports.deleteGroup = async (groupID) => {
|
||||
exports.deleteGroup = async (groupID: string): Promise<void> => {
|
||||
const group = await db.get(`group:${groupID}`);
|
||||
|
||||
// ensure group exists
|
||||
|
@ -82,7 +82,7 @@ exports.deleteGroup = async (groupID) => {
|
|||
* @param {String} groupID the id of the group to delete
|
||||
* @return {Promise<boolean>} Resolves to true if the group exists
|
||||
*/
|
||||
exports.doesGroupExist = async (groupID) => {
|
||||
exports.doesGroupExist = async (groupID: string) => {
|
||||
// try to get the group entry
|
||||
const group = await db.get(`group:${groupID}`);
|
||||
|
||||
|
@ -108,7 +108,7 @@ exports.createGroup = async () => {
|
|||
* @param groupMapper the mapper of the group
|
||||
* @return {Promise<{groupID: string}|{groupID: *}>} a promise that resolves to the group ID
|
||||
*/
|
||||
exports.createGroupIfNotExistsFor = async (groupMapper) => {
|
||||
exports.createGroupIfNotExistsFor = async (groupMapper: string|object) => {
|
||||
if (typeof groupMapper !== 'string') {
|
||||
throw new CustomError('groupMapper is not a string', 'apierror');
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ exports.createGroupIfNotExistsFor = async (groupMapper) => {
|
|||
* @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 = '') => {
|
||||
exports.createGroupPad = async (groupID: string, padName: string, text: string, authorId: string = ''): Promise<{ padID: string; }> => {
|
||||
// create the padID
|
||||
const padID = `${groupID}$${padName}`;
|
||||
|
||||
|
@ -167,7 +167,7 @@ exports.createGroupPad = async (groupID, padName, text, authorId = '') => {
|
|||
* @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) => {
|
||||
exports.listPads = async (groupID: string): Promise<{ padIDs: string[]; }> => {
|
||||
const exists = await exports.doesGroupExist(groupID);
|
||||
|
||||
// ensure the group exists
|
|
@ -1,4 +1,8 @@
|
|||
'use strict';
|
||||
import {Database} from "ueberdb2";
|
||||
import {AChangeSet, APool, AText} from "../types/PadType";
|
||||
import {MapArrayType} from "../types/MapType";
|
||||
|
||||
/**
|
||||
* The pad object, defined with joose
|
||||
*/
|
||||
|
@ -28,20 +32,29 @@ const promises = require('../utils/promises');
|
|||
* @param {String} txt The text to clean
|
||||
* @returns {String} The cleaned text
|
||||
*/
|
||||
exports.cleanText = (txt) => txt.replace(/\r\n/g, '\n')
|
||||
exports.cleanText = (txt:string): string => txt.replace(/\r\n/g, '\n')
|
||||
.replace(/\r/g, '\n')
|
||||
.replace(/\t/g, ' ')
|
||||
.replace(/\xa0/g, ' ');
|
||||
|
||||
class Pad {
|
||||
private db: Database;
|
||||
private atext: AText;
|
||||
private pool: APool;
|
||||
private head: number;
|
||||
private chatHead: number;
|
||||
private publicStatus: boolean;
|
||||
private id: string;
|
||||
private savedRevisions: any[];
|
||||
/**
|
||||
* @param id
|
||||
* @param [database] - Database object to access this pad's records (and only this pad's records;
|
||||
* the shared global Etherpad database object is still used for all other pad accesses, such
|
||||
* as copying the pad). Defaults to the shared global Etherpad database object. This parameter
|
||||
* can be used to shard pad storage across multiple database backends, to put each pad in its
|
||||
* own database table, or to validate imported pad data before it is written to the database.
|
||||
*/
|
||||
constructor(id, database = db) {
|
||||
constructor(id:string, database = db) {
|
||||
this.db = database;
|
||||
this.atext = Changeset.makeAText('\n');
|
||||
this.pool = new AttributePool();
|
||||
|
@ -80,7 +93,7 @@ class Pad {
|
|||
* @param {String} authorId The id of the author
|
||||
* @return {Promise<number|string>}
|
||||
*/
|
||||
async appendRevision(aChangeset, authorId = '') {
|
||||
async appendRevision(aChangeset: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) {
|
||||
|
@ -95,6 +108,7 @@ class Pad {
|
|||
|
||||
const hook = this.head === 0 ? 'padCreate' : 'padUpdate';
|
||||
await Promise.all([
|
||||
// @ts-ignore
|
||||
this.db.set(`pad:${this.id}:revs:${newRev}`, {
|
||||
changeset: aChangeset,
|
||||
meta: {
|
||||
|
@ -129,32 +143,39 @@ class Pad {
|
|||
}
|
||||
|
||||
toJSON() {
|
||||
const o = {...this, pool: this.pool.toJsonable()};
|
||||
const o:Pad = {...this, pool: this.pool.toJsonable()};
|
||||
// @ts-ignore
|
||||
delete o.db;
|
||||
// @ts-ignore
|
||||
delete o.id;
|
||||
return o;
|
||||
}
|
||||
|
||||
// save all attributes to the database
|
||||
async saveToDatabase() {
|
||||
// @ts-ignore
|
||||
await this.db.set(`pad:${this.id}`, this);
|
||||
}
|
||||
|
||||
// get time of last edit (changeset application)
|
||||
async getLastEdit() {
|
||||
const revNum = this.getHeadRevisionNumber();
|
||||
// @ts-ignore
|
||||
return await this.db.getSub(`pad:${this.id}:revs:${revNum}`, ['meta', 'timestamp']);
|
||||
}
|
||||
|
||||
async getRevisionChangeset(revNum) {
|
||||
async getRevisionChangeset(revNum: number) {
|
||||
// @ts-ignore
|
||||
return await this.db.getSub(`pad:${this.id}:revs:${revNum}`, ['changeset']);
|
||||
}
|
||||
|
||||
async getRevisionAuthor(revNum) {
|
||||
async getRevisionAuthor(revNum: number) {
|
||||
// @ts-ignore
|
||||
return await this.db.getSub(`pad:${this.id}:revs:${revNum}`, ['meta', 'author']);
|
||||
}
|
||||
|
||||
async getRevisionDate(revNum) {
|
||||
async getRevisionDate(revNum: number) {
|
||||
// @ts-ignore
|
||||
return await this.db.getSub(`pad:${this.id}:revs:${revNum}`, ['meta', 'timestamp']);
|
||||
}
|
||||
|
||||
|
@ -162,7 +183,8 @@ class Pad {
|
|||
* @param {number} revNum - Must be a key revision number (see `getKeyRevisionNumber`).
|
||||
* @returns The attribute text stored at `revNum`.
|
||||
*/
|
||||
async _getKeyRevisionAText(revNum) {
|
||||
async _getKeyRevisionAText(revNum: number) {
|
||||
// @ts-ignore
|
||||
return await this.db.getSub(`pad:${this.id}:revs:${revNum}`, ['meta', 'atext']);
|
||||
}
|
||||
|
||||
|
@ -182,7 +204,7 @@ class Pad {
|
|||
return authorIds;
|
||||
}
|
||||
|
||||
async getInternalRevisionAText(targetRev) {
|
||||
async getInternalRevisionAText(targetRev: number) {
|
||||
const keyRev = this.getKeyRevisionNumber(targetRev);
|
||||
const headRev = this.getHeadRevisionNumber();
|
||||
if (targetRev > headRev) targetRev = headRev;
|
||||
|
@ -197,17 +219,17 @@ class Pad {
|
|||
return atext;
|
||||
}
|
||||
|
||||
async getRevision(revNum) {
|
||||
async getRevision(revNum: number) {
|
||||
return await this.db.get(`pad:${this.id}:revs:${revNum}`);
|
||||
}
|
||||
|
||||
async getAllAuthorColors() {
|
||||
const authorIds = this.getAllAuthors();
|
||||
const returnTable = {};
|
||||
const returnTable:MapArrayType<string> = {};
|
||||
const colorPalette = authorManager.getColorPalette();
|
||||
|
||||
await Promise.all(
|
||||
authorIds.map((authorId) => authorManager.getAuthorColorId(authorId).then((colorId) => {
|
||||
authorIds.map((authorId) => authorManager.getAuthorColorId(authorId).then((colorId:string) => {
|
||||
// colorId might be a hex color or an number out of the palette
|
||||
returnTable[authorId] = colorPalette[colorId] || colorId;
|
||||
})));
|
||||
|
@ -215,7 +237,7 @@ class Pad {
|
|||
return returnTable;
|
||||
}
|
||||
|
||||
getValidRevisionRange(startRev, endRev) {
|
||||
getValidRevisionRange(startRev: any, endRev:any) {
|
||||
startRev = parseInt(startRev, 10);
|
||||
const head = this.getHeadRevisionNumber();
|
||||
endRev = endRev ? parseInt(endRev, 10) : head;
|
||||
|
@ -236,14 +258,14 @@ class Pad {
|
|||
return null;
|
||||
}
|
||||
|
||||
getKeyRevisionNumber(revNum) {
|
||||
getKeyRevisionNumber(revNum: number) {
|
||||
return Math.floor(revNum / 100) * 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} The pad's text.
|
||||
*/
|
||||
text() {
|
||||
text(): string {
|
||||
return this.atext.text;
|
||||
}
|
||||
|
||||
|
@ -258,7 +280,7 @@ class Pad {
|
|||
* @param {string} ins - New text to insert at `start` (after the `ndel` characters are deleted).
|
||||
* @param {string} [authorId] - Author ID of the user making the change (if applicable).
|
||||
*/
|
||||
async spliceText(start, ndel, ins, authorId = '') {
|
||||
async spliceText(start:number, ndel:number, ins: string, authorId: string = '') {
|
||||
if (start < 0) throw new RangeError(`start index must be non-negative (is ${start})`);
|
||||
if (ndel < 0) throw new RangeError(`characters to delete must be non-negative (is ${ndel})`);
|
||||
const orig = this.text();
|
||||
|
@ -283,7 +305,7 @@ class Pad {
|
|||
* @param {string} [authorId] - The author ID of the user that initiated the change, if
|
||||
* applicable.
|
||||
*/
|
||||
async setText(newText, authorId = '') {
|
||||
async setText(newText: string, authorId = '') {
|
||||
await this.spliceText(0, this.text().length, newText, authorId);
|
||||
}
|
||||
|
||||
|
@ -294,7 +316,7 @@ class Pad {
|
|||
* @param {string} [authorId] - The author ID of the user that initiated the change, if
|
||||
* applicable.
|
||||
*/
|
||||
async appendText(newText, authorId = '') {
|
||||
async appendText(newText:string, authorId = '') {
|
||||
await this.spliceText(this.text().length - 1, 0, newText, authorId);
|
||||
}
|
||||
|
||||
|
@ -308,7 +330,7 @@ class Pad {
|
|||
* @param {?number} [time] - Message timestamp (milliseconds since epoch). Deprecated; use
|
||||
* `msgOrText.time` instead.
|
||||
*/
|
||||
async appendChatMessage(msgOrText, authorId = null, time = null) {
|
||||
async appendChatMessage(msgOrText: string|typeof ChatMessage, authorId = null, time = null) {
|
||||
const msg =
|
||||
msgOrText instanceof ChatMessage ? msgOrText : new ChatMessage(msgOrText, authorId, time);
|
||||
this.chatHead++;
|
||||
|
@ -325,7 +347,7 @@ class Pad {
|
|||
* @param {number} entryNum - ID of the desired chat message.
|
||||
* @returns {?ChatMessage}
|
||||
*/
|
||||
async getChatMessage(entryNum) {
|
||||
async getChatMessage(entryNum: number) {
|
||||
const entry = await this.db.get(`pad:${this.id}:chat:${entryNum}`);
|
||||
if (entry == null) return null;
|
||||
const message = ChatMessage.fromObject(entry);
|
||||
|
@ -340,7 +362,7 @@ class Pad {
|
|||
* (inclusive), in order. Note: `start` and `end` form a closed interval, not a half-open
|
||||
* interval as is typical in code.
|
||||
*/
|
||||
async getChatMessages(start, end) {
|
||||
async getChatMessages(start: string, end: number) {
|
||||
const entries =
|
||||
await Promise.all(Stream.range(start, end + 1).map(this.getChatMessage.bind(this)));
|
||||
|
||||
|
@ -356,7 +378,7 @@ class Pad {
|
|||
});
|
||||
}
|
||||
|
||||
async init(text, authorId = '') {
|
||||
async init(text:string, authorId = '') {
|
||||
// try to load the pad
|
||||
const value = await this.db.get(`pad:${this.id}`);
|
||||
|
||||
|
@ -377,7 +399,7 @@ class Pad {
|
|||
await hooks.aCallAll('padLoad', {pad: this});
|
||||
}
|
||||
|
||||
async copy(destinationID, force) {
|
||||
async copy(destinationID: string, force: boolean) {
|
||||
// Kick everyone from this pad.
|
||||
// This was commented due to https://github.com/ether/etherpad-lite/issues/3183.
|
||||
// Do we really need to kick everyone out?
|
||||
|
@ -392,15 +414,18 @@ class Pad {
|
|||
// if force is true and already exists a Pad with the same id, remove that Pad
|
||||
await this.removePadIfForceIsTrueAndAlreadyExist(destinationID, force);
|
||||
|
||||
const copyRecord = async (keySuffix) => {
|
||||
const copyRecord = async (keySuffix: string) => {
|
||||
const val = await this.db.get(`pad:${this.id}${keySuffix}`);
|
||||
await db.set(`pad:${destinationID}${keySuffix}`, val);
|
||||
};
|
||||
|
||||
const promises = (function* () {
|
||||
yield copyRecord('');
|
||||
// @ts-ignore
|
||||
yield* Stream.range(0, this.head + 1).map((i) => copyRecord(`:revs:${i}`));
|
||||
// @ts-ignore
|
||||
yield* Stream.range(0, this.chatHead + 1).map((i) => copyRecord(`:chat:${i}`));
|
||||
// @ts-ignore
|
||||
yield this.copyAuthorInfoToDestinationPad(destinationID);
|
||||
if (destGroupID) yield db.setSub(`group:${destGroupID}`, ['pads', destinationID], 1);
|
||||
}).call(this);
|
||||
|
@ -427,8 +452,8 @@ class Pad {
|
|||
return {padID: destinationID};
|
||||
}
|
||||
|
||||
async checkIfGroupExistAndReturnIt(destinationID) {
|
||||
let destGroupID = false;
|
||||
async checkIfGroupExistAndReturnIt(destinationID: string) {
|
||||
let destGroupID:false|string = false;
|
||||
|
||||
if (destinationID.indexOf('$') >= 0) {
|
||||
destGroupID = destinationID.split('$')[0];
|
||||
|
@ -442,7 +467,7 @@ class Pad {
|
|||
return destGroupID;
|
||||
}
|
||||
|
||||
async removePadIfForceIsTrueAndAlreadyExist(destinationID, force) {
|
||||
async removePadIfForceIsTrueAndAlreadyExist(destinationID: string, force: boolean|string) {
|
||||
// if the pad exists, we should abort, unless forced.
|
||||
const exists = await padManager.doesPadExist(destinationID);
|
||||
|
||||
|
@ -465,13 +490,13 @@ class Pad {
|
|||
}
|
||||
}
|
||||
|
||||
async copyAuthorInfoToDestinationPad(destinationID) {
|
||||
async copyAuthorInfoToDestinationPad(destinationID: string) {
|
||||
// add the new sourcePad to all authors who contributed to the old one
|
||||
await Promise.all(this.getAllAuthors().map(
|
||||
(authorID) => authorManager.addPad(authorID, destinationID)));
|
||||
}
|
||||
|
||||
async copyPadWithoutHistory(destinationID, force, authorId = '') {
|
||||
async copyPadWithoutHistory(destinationID: string, force: string|boolean, authorId = '') {
|
||||
// flush the source pad
|
||||
this.saveToDatabase();
|
||||
|
||||
|
@ -554,18 +579,18 @@ class Pad {
|
|||
}
|
||||
|
||||
// remove the readonly entries
|
||||
p.push(readOnlyManager.getReadOnlyId(padID).then(async (readonlyID) => {
|
||||
p.push(readOnlyManager.getReadOnlyId(padID).then(async (readonlyID: string) => {
|
||||
await db.remove(`readonly2pad:${readonlyID}`);
|
||||
}));
|
||||
p.push(db.remove(`pad2readonly:${padID}`));
|
||||
|
||||
// delete all chat messages
|
||||
p.push(promises.timesLimit(this.chatHead + 1, 500, async (i) => {
|
||||
p.push(promises.timesLimit(this.chatHead + 1, 500, async (i: string) => {
|
||||
await this.db.remove(`pad:${this.id}:chat:${i}`, null);
|
||||
}));
|
||||
|
||||
// delete all revisions
|
||||
p.push(promises.timesLimit(this.head + 1, 500, async (i) => {
|
||||
p.push(promises.timesLimit(this.head + 1, 500, async (i: string) => {
|
||||
await this.db.remove(`pad:${this.id}:revs:${i}`, null);
|
||||
}));
|
||||
|
||||
|
@ -587,12 +612,12 @@ class Pad {
|
|||
}
|
||||
|
||||
// set in db
|
||||
async setPublicStatus(publicStatus) {
|
||||
async setPublicStatus(publicStatus: boolean) {
|
||||
this.publicStatus = publicStatus;
|
||||
await this.saveToDatabase();
|
||||
}
|
||||
|
||||
async addSavedRevision(revNum, savedById, label) {
|
||||
async addSavedRevision(revNum: string, savedById: string, label: string) {
|
||||
// if this revision is already saved, return silently
|
||||
for (const i in this.savedRevisions) {
|
||||
if (this.savedRevisions[i] && this.savedRevisions[i].revNum === revNum) {
|
||||
|
@ -601,7 +626,7 @@ class Pad {
|
|||
}
|
||||
|
||||
// build the saved revision object
|
||||
const savedRevision = {};
|
||||
const savedRevision:MapArrayType<any> = {};
|
||||
savedRevision.revNum = revNum;
|
||||
savedRevision.savedById = savedById;
|
||||
savedRevision.label = label || `Revision ${revNum}`;
|
||||
|
@ -664,7 +689,7 @@ class Pad {
|
|||
if (k === 'author' && v) authorIds.add(v);
|
||||
});
|
||||
const revs = Stream.range(0, head + 1)
|
||||
.map(async (r) => {
|
||||
.map(async (r: number) => {
|
||||
const isKeyRev = r === this.getKeyRevisionNumber(r);
|
||||
try {
|
||||
return await Promise.all([
|
||||
|
@ -675,7 +700,7 @@ class Pad {
|
|||
isKeyRev,
|
||||
isKeyRev ? this._getKeyRevisionAText(r) : null,
|
||||
]);
|
||||
} catch (err) {
|
||||
} catch (err:any) {
|
||||
err.message = `(pad ${this.id} revision ${r}) ${err.message}`;
|
||||
throw err;
|
||||
}
|
||||
|
@ -708,7 +733,7 @@ class Pad {
|
|||
}
|
||||
atext = Changeset.applyToAText(changeset, atext, pool);
|
||||
if (isKeyRev) assert.deepEqual(keyAText, atext);
|
||||
} catch (err) {
|
||||
} catch (err:any) {
|
||||
err.message = `(pad ${this.id} revision ${r}) ${err.message}`;
|
||||
throw err;
|
||||
}
|
||||
|
@ -721,12 +746,12 @@ class Pad {
|
|||
assert(Number.isInteger(this.chatHead));
|
||||
assert(this.chatHead >= -1);
|
||||
const chats = Stream.range(0, this.chatHead + 1)
|
||||
.map(async (c) => {
|
||||
.map(async (c: number) => {
|
||||
try {
|
||||
const msg = await this.getChatMessage(c);
|
||||
assert(msg != null);
|
||||
assert(msg instanceof ChatMessage);
|
||||
} catch (err) {
|
||||
} catch (err:any) {
|
||||
err.message = `(pad ${this.id} chat message ${c}) ${err.message}`;
|
||||
throw err;
|
||||
}
|
|
@ -19,6 +19,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {MapArrayType} from "../types/MapType";
|
||||
|
||||
const CustomError = require('../utils/customError');
|
||||
const Pad = require('../db/Pad');
|
||||
const db = require('./DB');
|
||||
|
@ -35,12 +37,16 @@ const settings = require('../utils/Settings');
|
|||
* If this is needed in other places, it would be wise to make this a prototype
|
||||
* that's defined somewhere more sensible.
|
||||
*/
|
||||
const globalPads = {
|
||||
get(name) { return this[`:${name}`]; },
|
||||
set(name, value) {
|
||||
const globalPads:MapArrayType<any> = {
|
||||
get(name: string)
|
||||
{
|
||||
return this[`:${name}`];
|
||||
},
|
||||
set(name: string, value: any)
|
||||
{
|
||||
this[`:${name}`] = value;
|
||||
},
|
||||
remove(name) {
|
||||
remove(name: string) {
|
||||
delete this[`:${name}`];
|
||||
},
|
||||
};
|
||||
|
@ -51,6 +57,9 @@ const globalPads = {
|
|||
* Updated without db access as new pads are created/old ones removed.
|
||||
*/
|
||||
const padList = new class {
|
||||
private _cachedList: string[] | null;
|
||||
private _list: Set<string>;
|
||||
private _loaded: Promise<void> | null;
|
||||
constructor() {
|
||||
this._cachedList = null;
|
||||
this._list = new Set();
|
||||
|
@ -74,13 +83,13 @@ const padList = new class {
|
|||
return this._cachedList;
|
||||
}
|
||||
|
||||
addPad(name) {
|
||||
addPad(name: string) {
|
||||
if (this._list.has(name)) return;
|
||||
this._list.add(name);
|
||||
this._cachedList = null;
|
||||
}
|
||||
|
||||
removePad(name) {
|
||||
removePad(name: string) {
|
||||
if (!this._list.has(name)) return;
|
||||
this._list.delete(name);
|
||||
this._cachedList = null;
|
||||
|
@ -96,7 +105,7 @@ const padList = new class {
|
|||
* @param {string} [authorId] - Optional author ID of the user that initiated the pad creation (if
|
||||
* applicable).
|
||||
*/
|
||||
exports.getPad = async (id, text, authorId = '') => {
|
||||
exports.getPad = async (id: string, text: string, authorId:string = '') => {
|
||||
// check if this is a valid padId
|
||||
if (!exports.isValidPadId(id)) {
|
||||
throw new CustomError(`${id} is not a valid padId`, 'apierror');
|
||||
|
@ -140,7 +149,7 @@ exports.listAllPads = async () => {
|
|||
};
|
||||
|
||||
// checks if a pad exists
|
||||
exports.doesPadExist = async (padId) => {
|
||||
exports.doesPadExist = async (padId: string) => {
|
||||
const value = await db.get(`pad:${padId}`);
|
||||
|
||||
return (value != null && value.atext);
|
||||
|
@ -159,7 +168,7 @@ const padIdTransforms = [
|
|||
];
|
||||
|
||||
// returns a sanitized padId, respecting legacy pad id formats
|
||||
exports.sanitizePadId = async (padId) => {
|
||||
exports.sanitizePadId = async (padId: string) => {
|
||||
for (let i = 0, n = padIdTransforms.length; i < n; ++i) {
|
||||
const exists = await exports.doesPadExist(padId);
|
||||
|
||||
|
@ -169,6 +178,7 @@ exports.sanitizePadId = async (padId) => {
|
|||
|
||||
const [from, to] = padIdTransforms[i];
|
||||
|
||||
// @ts-ignore
|
||||
padId = padId.replace(from, to);
|
||||
}
|
||||
|
||||
|
@ -178,12 +188,12 @@ exports.sanitizePadId = async (padId) => {
|
|||
return padId;
|
||||
};
|
||||
|
||||
exports.isValidPadId = (padId) => /^(g.[a-zA-Z0-9]{16}\$)?[^$]{1,50}$/.test(padId);
|
||||
exports.isValidPadId = (padId: string) => /^(g.[a-zA-Z0-9]{16}\$)?[^$]{1,50}$/.test(padId);
|
||||
|
||||
/**
|
||||
* Removes the pad from database and unloads it.
|
||||
*/
|
||||
exports.removePad = async (padId) => {
|
||||
exports.removePad = async (padId: string) => {
|
||||
const p = db.remove(`pad:${padId}`);
|
||||
exports.unloadPad(padId);
|
||||
padList.removePad(padId);
|
||||
|
@ -191,6 +201,6 @@ exports.removePad = async (padId) => {
|
|||
};
|
||||
|
||||
// removes a pad from the cache
|
||||
exports.unloadPad = (padId) => {
|
||||
exports.unloadPad = (padId: string) => {
|
||||
globalPads.remove(padId);
|
||||
};
|
|
@ -29,14 +29,14 @@ const randomString = require('../utils/randomstring');
|
|||
* @param {String} id the pad's id
|
||||
* @return {Boolean} true if the id is readonly
|
||||
*/
|
||||
exports.isReadOnlyId = (id) => id.startsWith('r.');
|
||||
exports.isReadOnlyId = (id:string) => 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) => {
|
||||
exports.getReadOnlyId = async (padId:string) => {
|
||||
// check if there is a pad2readonly entry
|
||||
let readOnlyId = await db.get(`pad2readonly:${padId}`);
|
||||
|
||||
|
@ -57,14 +57,14 @@ exports.getReadOnlyId = async (padId) => {
|
|||
* @param {String} readOnlyId read only id
|
||||
* @return {String} the padId
|
||||
*/
|
||||
exports.getPadId = async (readOnlyId) => await db.get(`readonly2pad:${readOnlyId}`);
|
||||
exports.getPadId = async (readOnlyId:string) => await db.get(`readonly2pad:${readOnlyId}`);
|
||||
|
||||
/**
|
||||
* returns the padId and readonlyPadId in an object for any id
|
||||
* @param {String} id read only id or real pad id
|
||||
* @return {Object} an object with the padId and readonlyPadId
|
||||
*/
|
||||
exports.getIds = async (id) => {
|
||||
exports.getIds = async (id:string) => {
|
||||
const readonly = exports.isReadOnlyId(id);
|
||||
|
||||
// Might be null, if this is an unknown read-only id
|
|
@ -19,6 +19,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {UserSettingsObject} from "../types/UserSettingsObject";
|
||||
|
||||
const authorManager = require('./AuthorManager');
|
||||
const hooks = require('../../static/js/pluginfw/hooks.js');
|
||||
const padManager = require('./PadManager');
|
||||
|
@ -55,7 +57,7 @@ const DENY = Object.freeze({accessStatus: 'deny'});
|
|||
* @param {Object} userSettings
|
||||
* @return {DENY|{accessStatus: String, authorID: String}}
|
||||
*/
|
||||
exports.checkAccess = async (padID, sessionCookie, token, userSettings) => {
|
||||
exports.checkAccess = async (padID:string, sessionCookie:string, token:string, userSettings:UserSettingsObject) => {
|
||||
if (!padID) {
|
||||
authLogger.debug('access denied: missing padID');
|
||||
return DENY;
|
||||
|
@ -95,7 +97,7 @@ exports.checkAccess = async (padID, sessionCookie, token, userSettings) => {
|
|||
}
|
||||
|
||||
// allow plugins to deny access
|
||||
const isFalse = (x) => x === false;
|
||||
const isFalse = (x:boolean) => x === false;
|
||||
if (hooks.callAll('onAccessCheck', {padID, token, sessionCookie}).some(isFalse)) {
|
||||
authLogger.debug('access denied: an onAccessCheck hook function returned false');
|
||||
return DENY;
|
|
@ -36,7 +36,7 @@ const authorManager = require('./AuthorManager');
|
|||
* sessionCookie, and is bound to a group with the given ID, then this returns the author ID
|
||||
* bound to the session. Otherwise, returns undefined.
|
||||
*/
|
||||
exports.findAuthorID = async (groupID, sessionCookie) => {
|
||||
exports.findAuthorID = async (groupID:string, sessionCookie: string) => {
|
||||
if (!sessionCookie) return undefined;
|
||||
/*
|
||||
* Sometimes, RFC 6265-compliant web servers may send back a cookie whose
|
||||
|
@ -65,7 +65,7 @@ exports.findAuthorID = async (groupID, sessionCookie) => {
|
|||
const sessionInfoPromises = sessionIDs.map(async (id) => {
|
||||
try {
|
||||
return await exports.getSessionInfo(id);
|
||||
} catch (err) {
|
||||
} catch (err:any) {
|
||||
if (err.message === 'sessionID does not exist') {
|
||||
console.debug(`SessionManager getAuthorID: no session exists with ID ${id}`);
|
||||
} else {
|
||||
|
@ -75,7 +75,10 @@ exports.findAuthorID = async (groupID, sessionCookie) => {
|
|||
return undefined;
|
||||
});
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const isMatch = (si) => (si != null && si.groupID === groupID && now < si.validUntil);
|
||||
const isMatch = (si: {
|
||||
groupID: string;
|
||||
validUntil: number;
|
||||
}|null) => (si != null && si.groupID === groupID && now < si.validUntil);
|
||||
const sessionInfo = await promises.firstSatisfies(sessionInfoPromises, isMatch);
|
||||
if (sessionInfo == null) return undefined;
|
||||
return sessionInfo.authorID;
|
||||
|
@ -86,7 +89,7 @@ exports.findAuthorID = async (groupID, sessionCookie) => {
|
|||
* @param {String} sessionID The id of the session
|
||||
* @return {Promise<boolean>} Resolves to true if the session exists
|
||||
*/
|
||||
exports.doesSessionExist = async (sessionID) => {
|
||||
exports.doesSessionExist = async (sessionID: string) => {
|
||||
// check if the database entry of this session exists
|
||||
const session = await db.get(`session:${sessionID}`);
|
||||
return (session != null);
|
||||
|
@ -99,7 +102,7 @@ exports.doesSessionExist = async (sessionID) => {
|
|||
* @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) => {
|
||||
exports.createSession = async (groupID: string, authorID: string, validUntil: number) => {
|
||||
// check if the group exists
|
||||
const groupExists = await groupManager.doesGroupExist(groupID);
|
||||
if (!groupExists) {
|
||||
|
@ -160,7 +163,7 @@ exports.createSession = async (groupID, authorID, validUntil) => {
|
|||
* @param {String} sessionID The id of the session
|
||||
* @return {Promise<Object>} the sessioninfos
|
||||
*/
|
||||
exports.getSessionInfo = async (sessionID) => {
|
||||
exports.getSessionInfo = async (sessionID:string) => {
|
||||
// check if the database entry of this session exists
|
||||
const session = await db.get(`session:${sessionID}`);
|
||||
|
||||
|
@ -178,7 +181,7 @@ exports.getSessionInfo = async (sessionID) => {
|
|||
* @param {String} sessionID The id of the session
|
||||
* @return {Promise<void>} Resolves when the session is deleted
|
||||
*/
|
||||
exports.deleteSession = async (sessionID) => {
|
||||
exports.deleteSession = async (sessionID:string) => {
|
||||
// ensure that the session exists
|
||||
const session = await db.get(`session:${sessionID}`);
|
||||
if (session == null) {
|
||||
|
@ -207,7 +210,7 @@ exports.deleteSession = async (sessionID) => {
|
|||
* @param {String} groupID The id of the group
|
||||
* @return {Promise<Object>} The sessioninfos of all sessions of this group
|
||||
*/
|
||||
exports.listSessionsOfGroup = async (groupID) => {
|
||||
exports.listSessionsOfGroup = async (groupID: string) => {
|
||||
// check that the group exists
|
||||
const exists = await groupManager.doesGroupExist(groupID);
|
||||
if (!exists) {
|
||||
|
@ -223,7 +226,7 @@ exports.listSessionsOfGroup = async (groupID) => {
|
|||
* @param {String} authorID The id of the author
|
||||
* @return {Promise<Object>} The sessioninfos of all sessions of this author
|
||||
*/
|
||||
exports.listSessionsOfAuthor = async (authorID) => {
|
||||
exports.listSessionsOfAuthor = async (authorID: string) => {
|
||||
// check that the author exists
|
||||
const exists = await authorManager.doesAuthorExist(authorID);
|
||||
if (!exists) {
|
||||
|
@ -240,7 +243,7 @@ exports.listSessionsOfAuthor = async (authorID) => {
|
|||
* @param {String} dbkey The db key to use to get the sessions
|
||||
* @return {Promise<*>}
|
||||
*/
|
||||
const listSessionsWithDBKey = async (dbkey) => {
|
||||
const listSessionsWithDBKey = async (dbkey: string) => {
|
||||
// get the group2sessions entry
|
||||
const sessionObject = await db.get(dbkey);
|
||||
const sessions = sessionObject ? sessionObject.sessionIDs : null;
|
||||
|
@ -249,7 +252,7 @@ const listSessionsWithDBKey = async (dbkey) => {
|
|||
for (const sessionID of Object.keys(sessions || {})) {
|
||||
try {
|
||||
sessions[sessionID] = await exports.getSessionInfo(sessionID);
|
||||
} catch (err) {
|
||||
} catch (err:any) {
|
||||
if (err.name === 'apierror') {
|
||||
console.warn(`Found bad session ${sessionID} in ${dbkey}`);
|
||||
sessions[sessionID] = null;
|
||||
|
@ -262,9 +265,11 @@ const listSessionsWithDBKey = async (dbkey) => {
|
|||
return sessions;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
// @ts-ignore
|
||||
const isInt = (value:number|string): boolean => (parseFloat(value) === parseInt(value)) && !isNaN(value);
|
Loading…
Add table
Add a link
Reference in a new issue