From 4c2f7f9a1131a9af2f914ad381bebe5893152ce3 Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Tue, 26 Oct 2021 01:05:24 -0400 Subject: [PATCH] chat: Rename `userId` to `authorId`, `userName` to `displayName` --- doc/api/hooks_client-side.md | 2 +- src/node/db/Pad.js | 12 ++++----- src/node/handler/PadMessageHandler.js | 6 ++--- src/static/js/ChatMessage.js | 38 ++++++++++++++++++++++++--- src/static/js/chat.js | 12 ++++----- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/doc/api/hooks_client-side.md b/doc/api/hooks_client-side.md index d507459c2..dc5608931 100755 --- a/doc/api/hooks_client-side.md +++ b/doc/api/hooks_client-side.md @@ -299,7 +299,7 @@ Context properties: href="url">url`. (Note that `message.text` is not sanitized or processed in any way.) * `message`: The raw message object as received from the server, except with - time correction and a default `userId` property if missing. Plugins must not + time correction and a default `authorId` property if missing. Plugins must not modify this object. Warning: Unlike `text`, `message.text` is not pre-sanitized or processed in any way. * `rendered` - Used to override the default message rendering. Initially set to diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index 36585426b..2ec573744 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -280,19 +280,19 @@ Pad.prototype.appendText = async function (newText) { * * @param {(ChatMessage|string)} msgOrText - Either a chat message object (recommended) or a string * containing the raw text of the user's chat message (deprecated). - * @param {?string} [userId] - The user's author ID. Deprecated; use `msgOrText.userId` instead. + * @param {?string} [authorId] - The user's author ID. Deprecated; use `msgOrText.authorId` instead. * @param {?number} [time] - Message timestamp (milliseconds since epoch). Deprecated; use * `msgOrText.time` instead. */ -Pad.prototype.appendChatMessage = async function (msgOrText, userId = null, time = null) { +Pad.prototype.appendChatMessage = async function (msgOrText, authorId = null, time = null) { const msg = - msgOrText instanceof ChatMessage ? msgOrText : new ChatMessage(msgOrText, userId, time); + msgOrText instanceof ChatMessage ? msgOrText : new ChatMessage(msgOrText, authorId, time); this.chatHead++; await Promise.all([ // Don't save the display name in the database because the user can change it at any time. The - // `userName` property will be populated with the current value when the message is read from + // `displayName` property will be populated with the current value when the message is read from // the database. - db.set(`pad:${this.id}:chat:${this.chatHead}`, {...msg, userName: undefined}), + db.set(`pad:${this.id}:chat:${this.chatHead}`, {...msg, displayName: undefined}), this.saveToDatabase(), ]); }; @@ -305,7 +305,7 @@ Pad.prototype.getChatMessage = async function (entryNum) { const entry = await db.get(`pad:${this.id}:chat:${entryNum}`); if (entry == null) return null; const message = ChatMessage.fromObject(entry); - message.userName = await authorManager.getAuthorName(message.userId); + message.displayName = await authorManager.getAuthorName(message.authorId); return message; }; diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index 36682abef..64027f6e4 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -345,7 +345,7 @@ const handleChatMessage = async (socket, message) => { const {padId, author: authorId} = sessioninfos[socket.id]; // Don't trust the user-supplied values. chatMessage.time = Date.now(); - chatMessage.userId = authorId; + chatMessage.authorId = authorId; await exports.sendChatMessageToPadClients(chatMessage, padId); }; @@ -364,10 +364,10 @@ exports.sendChatMessageToPadClients = async (mt, puId, text = null, padId = null const message = mt instanceof ChatMessage ? mt : new ChatMessage(text, puId, mt); padId = mt instanceof ChatMessage ? puId : padId; const pad = await padManager.getPad(padId); - // pad.appendChatMessage() ignores the userName property so we don't need to wait for + // pad.appendChatMessage() ignores the displayName property so we don't need to wait for // authorManager.getAuthorName() to resolve before saving the message to the database. const promise = pad.appendChatMessage(message); - message.userName = await authorManager.getAuthorName(message.userId); + message.displayName = await authorManager.getAuthorName(message.userId); socketio.sockets.in(padId).json.send({ type: 'COLLABROOM', data: {type: 'CHAT_MESSAGE', message}, diff --git a/src/static/js/ChatMessage.js b/src/static/js/ChatMessage.js index f6e10c2b5..b4658575e 100644 --- a/src/static/js/ChatMessage.js +++ b/src/static/js/ChatMessage.js @@ -13,10 +13,10 @@ class ChatMessage { /** * @param {?string} [text] - Initial value of the `text` property. - * @param {?string} [userId] - Initial value of the `userId` property. + * @param {?string} [authorId] - Initial value of the `authorId` property. * @param {?number} [time] - Initial value of the `time` property. */ - constructor(text = null, userId = null, time = null) { + constructor(text = null, authorId = null, time = null) { /** * The raw text of the user's chat message (before any rendering or processing). * @@ -29,7 +29,7 @@ class ChatMessage { * * @type {?string} */ - this.userId = userId; + this.authorId = authorId; /** * The message's timestamp, as milliseconds since epoch. @@ -43,7 +43,37 @@ class ChatMessage { * * @type {?string} */ - this.userName = null; + this.displayName = null; + } + + /** + * Alias of `authorId`, for compatibility with old plugins. + * + * @deprecated Use `authorId` instead. + * @type {string} + */ + get userId() { return this.authorId; } + set userId(val) { this.authorId = val; } + + /** + * Alias of `displayName`, for compatibility with old plugins. + * + * @deprecated Use `displayName` instead. + * @type {string} + */ + get userName() { return this.displayName; } + set userName(val) { this.displayName = val; } + + // TODO: Delete this method once users are unlikely to roll back to a version of Etherpad that + // doesn't support authorId and displayName. + toJSON() { + return { + ...this, + authorId: undefined, + displayName: undefined, + userId: this.authorId, + userName: this.displayName, + }; } } diff --git a/src/static/js/chat.js b/src/static/js/chat.js index 62f355499..51da91c6d 100755 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -111,15 +111,15 @@ exports.chat = (() => { // correct the time msg.time += this._pad.clientTimeOffset; - if (!msg.userId) { + if (!msg.authorId) { /* * If, for a bug or a database corruption, the message coming from the - * server does not contain the userId field (see for example #3731), + * server does not contain the authorId field (see for example #3731), * let's be defensive and replace it with "unknown". */ - msg.userId = 'unknown'; + msg.authorId = 'unknown'; console.warn( - 'The "userId" field of a chat message coming from the server was not present. ' + + 'The "authorId" field of a chat message coming from the server was not present. ' + 'Replacing with "unknown". This may be a bug or a database corruption.'); } @@ -130,8 +130,8 @@ exports.chat = (() => { // the hook args const ctx = { - authorName: msg.userName != null ? msg.userName : html10n.get('pad.userlist.unnamed'), - author: msg.userId, + authorName: msg.displayName != null ? msg.displayName : html10n.get('pad.userlist.unnamed'), + author: msg.authorId, text: padutils.escapeHtmlWithClickableLinks(msg.text, '_blank'), message: msg, rendered: null,