Skip to content

Commit 31b025b

Browse files
committed
PadMessageHandler: Pass session info to handleMessageSecurity hook
1 parent 1b52c9f commit 31b025b

File tree

4 files changed

+30
-11
lines changed

4 files changed

+30
-11
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
(low-level API) and `ep_etherpad-lite/static/js/AttributeMap` (high-level
3333
API).
3434
* The `import` server-side hook has a new `ImportError` context property.
35+
* The `handleMessageSecurity` and `handleMessage` server-side hooks have a new
36+
`sessionInfo` context property that includes the user's author ID, the pad ID,
37+
and whether the user only has read-only access.
3538

3639
### Compatibility changes
3740

doc/api/hooks_server-side.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,12 @@ then the message will not be subject to further processing.
585585
Context properties:
586586

587587
* `message`: The message being handled.
588+
* `sessionInfo`: Object describing the socket.io session with the following
589+
properties:
590+
* `authorId`: The user's author ID.
591+
* `padId`: The real (not read-only) ID of the pad.
592+
* `readOnly`: Whether the client has read-only access (true) or read/write
593+
access (false).
588594
* `socket`: The socket.io Socket object.
589595
* `client`: (**Deprecated**; use `socket` instead.) Synonym of `socket`.
590596

@@ -620,13 +626,21 @@ Supported return values:
620626
Context properties:
621627

622628
* `message`: The message being handled.
629+
* `sessionInfo`: Object describing the socket.io connection with the following
630+
properties:
631+
* `authorId`: The user's author ID.
632+
* `padId`: The real (not read-only) ID of the pad.
633+
* `readOnly`: Whether the client has read-only access (true) or read/write
634+
access (false).
623635
* `socket`: The socket.io Socket object.
624636
* `client`: (**Deprecated**; use `socket` instead.) Synonym of `socket`.
625637

626638
Example:
627639

628640
```javascript
629-
exports.handleMessageSecurity = async (hookName, {message, socket}) => {
641+
exports.handleMessageSecurity = async (hookName, context) => {
642+
const {message, sessionInfo: {readOnly}, socket} = context;
643+
if (!readOnly || message.type !== 'COLLABROOM') return;
630644
if (shouldGrantWriteAccess(message, socket)) return true;
631645
};
632646
```

src/node/handler/PadMessageHandler.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ exports.handleMessage = async (socket, message) => {
235235
padID: message.padId,
236236
token: message.token,
237237
};
238+
const padIds = await readOnlyManager.getIds(thisSession.auth.padID);
239+
thisSession.padId = padIds.padId;
240+
thisSession.readOnlyPadId = padIds.readOnlyPadId;
241+
thisSession.readonly =
242+
padIds.readonly || !webaccess.userCanModify(thisSession.auth.padID, socket.client.request);
238243
}
239244

240245
const auth = thisSession.auth;
@@ -273,6 +278,11 @@ exports.handleMessage = async (socket, message) => {
273278
// Allow plugins to bypass the readonly message blocker
274279
const context = {
275280
message,
281+
sessionInfo: {
282+
authorId: thisSession.author,
283+
padId: thisSession.padId,
284+
readOnly: thisSession.readonly,
285+
},
276286
socket,
277287
get client() {
278288
padutils.warnDeprecated(
@@ -793,12 +803,6 @@ const handleClientReady = async (socket, message) => {
793803
if (sessionInfo == null) return;
794804
assert(sessionInfo.author);
795805

796-
const padIds = await readOnlyManager.getIds(sessionInfo.auth.padID);
797-
sessionInfo.padId = padIds.padId;
798-
sessionInfo.readOnlyPadId = padIds.readOnlyPadId;
799-
sessionInfo.readonly =
800-
padIds.readonly || !webaccess.userCanModify(sessionInfo.auth.padID, socket.client.request);
801-
802806
await hooks.aCallAll('clientReady', message); // Deprecated due to awkward context.
803807

804808
let {colorId: authorColorId, name: authorName} = message.userInfo || {};

src/node/hooks/express/webaccess.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ exports.userCanModify = (padId, req) => {
3636
if (readOnlyManager.isReadOnlyId(padId)) return false;
3737
if (!settings.requireAuthentication) return true;
3838
const {session: {user} = {}} = req;
39-
assert(user); // If authn required and user == null, the request should have already been denied.
40-
if (user.readOnly) return false;
39+
if (!user || user.readOnly) return false;
4140
assert(user.padAuthorizations); // This is populated even if !settings.requireAuthorization.
4241
const level = exports.normalizeAuthzLevel(user.padAuthorizations[padId]);
43-
assert(level); // If !level, the request should have already been denied.
44-
return level !== 'readOnly';
42+
return level && level !== 'readOnly';
4543
};
4644

4745
// Exported so that tests can set this to 0 to avoid unnecessary test slowness.

0 commit comments

Comments
 (0)