mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +01:00
AuthorManager: New getAuthorId
hook
This commit is contained in:
parent
6d4085f5f0
commit
ae092edf0c
4 changed files with 82 additions and 7 deletions
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
* New `expressPreSession` server-side hook.
|
* New `expressPreSession` server-side hook.
|
||||||
* New `padDefaultContent` server-side hook.
|
* New `padDefaultContent` server-side hook.
|
||||||
|
* New `getAuthorId` server-side hook.
|
||||||
* New APIs for processing attributes: `ep_etherpad-lite/static/js/attributes`
|
* New APIs for processing attributes: `ep_etherpad-lite/static/js/attributes`
|
||||||
(low-level API) and `ep_etherpad-lite/static/js/AttributeMap` (high-level
|
(low-level API) and `ep_etherpad-lite/static/js/AttributeMap` (high-level
|
||||||
API).
|
API).
|
||||||
|
@ -79,6 +80,8 @@
|
||||||
* `appendATextToAssembler()`: Deprecated in favor of the new `opsFromAText()`
|
* `appendATextToAssembler()`: Deprecated in favor of the new `opsFromAText()`
|
||||||
generator function.
|
generator function.
|
||||||
* `newOp()`: Deprecated in favor of the new `Op` class.
|
* `newOp()`: Deprecated in favor of the new `Op` class.
|
||||||
|
* The `AuthorManager.getAuthor4Token()` function is deprecated; use the new
|
||||||
|
`AuthorManager.getAuthorId()` function instead.
|
||||||
|
|
||||||
# 1.8.17
|
# 1.8.17
|
||||||
|
|
||||||
|
|
|
@ -207,6 +207,62 @@ Things in context:
|
||||||
This hook gets called when the access to the concrete pad is being checked.
|
This hook gets called when the access to the concrete pad is being checked.
|
||||||
Return `false` to deny access.
|
Return `false` to deny access.
|
||||||
|
|
||||||
|
## `getAuthorId`
|
||||||
|
|
||||||
|
Called from `src/node/db/AuthorManager.js`
|
||||||
|
|
||||||
|
Called when looking up (or creating) the author ID for a user, except for author
|
||||||
|
IDs obtained via the HTTP API. Registered hook functions are called until one
|
||||||
|
returns a non-`undefined` value. If a truthy value is returned by a hook
|
||||||
|
function, it is used as the user's author ID. Otherwise, the value of the
|
||||||
|
`dbKey` context property is used to look up the author ID. If there is no such
|
||||||
|
author ID at that key, a new author ID is generated and associated with that
|
||||||
|
key.
|
||||||
|
|
||||||
|
Context properties:
|
||||||
|
|
||||||
|
* `dbKey`: Database key to use when looking up the user's author ID if no hook
|
||||||
|
function returns an author ID. This is initialized to the user-supplied token
|
||||||
|
value (see the `token` context property), but hook functions can modify this
|
||||||
|
to control how author IDs are allocated to users. If no author ID is
|
||||||
|
associated with this database key, a new author ID will be randomly generated
|
||||||
|
and associated with the key. For security reasons, if this is modified it
|
||||||
|
should be modified to not look like a valid token (see the `token` context
|
||||||
|
property) unless the plugin intentionally wants the user to be able to
|
||||||
|
impersonate another user.
|
||||||
|
* `token`: The user-supplied token, or nullish for an anonymous user. Tokens are
|
||||||
|
secret values that must not be disclosed to others. If non-null, the token is
|
||||||
|
guaranteed to be a string with the form `t.<base64url>` where `<base64url>` is
|
||||||
|
any valid non-empty base64url string (RFC 4648 section 5 with padding).
|
||||||
|
Example: `t.twim3X2_KGiRj8cJ-3602g==`.
|
||||||
|
* `user`: If the user has authenticated, this is an object from `settings.users`
|
||||||
|
(or similar from an authentication plugin). Etherpad core and all good
|
||||||
|
authentication plugins set the `username` property of this object to a string
|
||||||
|
that uniquely identifies the authenticated user. This object is nullish if the
|
||||||
|
user has not authenticated.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
exports.getAuthorId = async (hookName, context) => {
|
||||||
|
const {username} = context.user || {};
|
||||||
|
// If the user has not authenticated, or has "authenticated" as the guest
|
||||||
|
// user, do the default behavior (try another plugin if any, falling through
|
||||||
|
// to using the token as the database key).
|
||||||
|
if (!username || username === 'guest') return;
|
||||||
|
// The user is authenticated and has a username. Give the user a stable author
|
||||||
|
// ID so that they appear to be the same author even after clearing cookies or
|
||||||
|
// accessing the pad from another device. Note that this string is guaranteed
|
||||||
|
// to never have the form of a valid token; without that guarantee an
|
||||||
|
// unauthenticated user might be able to impersonate an authenticated user.
|
||||||
|
context.dbKey = `username=${username}`;
|
||||||
|
// Return a falsy but non-undefined value to stop Etherpad from calling any
|
||||||
|
// more getAuthorId hook functions and look up the author ID using the
|
||||||
|
// username-derived database key.
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## `padCreate`
|
## `padCreate`
|
||||||
|
|
||||||
Called from: `src/node/db/Pad.js`
|
Called from: `src/node/db/Pad.js`
|
||||||
|
|
|
@ -21,7 +21,8 @@
|
||||||
|
|
||||||
const db = require('./DB');
|
const db = require('./DB');
|
||||||
const CustomError = require('../utils/customError');
|
const CustomError = require('../utils/customError');
|
||||||
const randomString = require('../../static/js/pad_utils').randomString;
|
const hooks = require('../../static/js/pluginfw/hooks.js');
|
||||||
|
const {randomString, padutils: {warnDeprecated}} = require('../../static/js/pad_utils');
|
||||||
|
|
||||||
exports.getColorPalette = () => [
|
exports.getColorPalette = () => [
|
||||||
'#ffc7c7',
|
'#ffc7c7',
|
||||||
|
@ -102,17 +103,32 @@ exports.doesAuthorExist = async (authorID) => {
|
||||||
/* exported for backwards compatibility */
|
/* exported for backwards compatibility */
|
||||||
exports.doesAuthorExists = exports.doesAuthorExist;
|
exports.doesAuthorExists = exports.doesAuthorExist;
|
||||||
|
|
||||||
/**
|
const getAuthor4Token = async (token) => {
|
||||||
* Returns the AuthorID for a token.
|
|
||||||
* @param {String} token The token
|
|
||||||
*/
|
|
||||||
exports.getAuthor4Token = async (token) => {
|
|
||||||
const author = await mapAuthorWithDBKey('token2author', token);
|
const author = await mapAuthorWithDBKey('token2author', token);
|
||||||
|
|
||||||
// return only the sub value authorID
|
// return only the sub value authorID
|
||||||
return author ? author.authorID : author;
|
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.
|
* Returns the AuthorID for a mapper.
|
||||||
* @param {String} token The mapper
|
* @param {String} token The mapper
|
||||||
|
|
|
@ -115,7 +115,7 @@ exports.checkAccess = async (padID, sessionCookie, token, userSettings) => {
|
||||||
|
|
||||||
const grant = {
|
const grant = {
|
||||||
accessStatus: 'grant',
|
accessStatus: 'grant',
|
||||||
authorID: sessionAuthorID || await authorManager.getAuthor4Token(token),
|
authorID: sessionAuthorID || await authorManager.getAuthorId(token, userSettings),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!padID.includes('$')) {
|
if (!padID.includes('$')) {
|
||||||
|
|
Loading…
Reference in a new issue