From 5831dbcbc881a2b19fc0c14a328364700dbd7725 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 4 May 2020 16:13:44 +0200 Subject: [PATCH] Add auth plugins guide --- support/doc/plugins/guide.md | 131 ++++++++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 18 deletions(-) diff --git a/support/doc/plugins/guide.md b/support/doc/plugins/guide.md index 81691c8c1..d95b7649b 100644 --- a/support/doc/plugins/guide.md +++ b/support/doc/plugins/guide.md @@ -48,7 +48,7 @@ Themes are exactly the same as plugins, except that: ### Hooks A plugin registers functions in JavaScript to execute when PeerTube (server and client) fires events. There are 3 types of hooks: - * `filter`: used to filter functions parameters or return values. + * `filter`: used to filter functions parameters or return values. For example to replace words in video comments, or change the videos list behaviour * `action`: used to do something after a certain trigger. For example to send a hook every time a video is published * `static`: same than `action` but PeerTube waits their execution @@ -70,14 +70,24 @@ Example: ```js async function register ({ registerHook, + registerSetting, settingsManager, + storageManager, + videoCategoryManager, videoLicenceManager, videoLanguageManager, + peertubeHelpers, - getRouter + + getRouter, + + registerExternalAuth, + unregisterExternalAuth, + registerIdAndPassAuth, + unregisterIdAndPassAuth }) { registerHook({ target: 'action:application.listening', @@ -120,8 +130,8 @@ function register ({ registerHook, peertubeHelpers }) { ### Static files -Plugins can declare static directories that PeerTube will serve (images for example) -from `/plugins/{plugin-name}/{plugin-version}/static/` +Plugins can declare static directories that PeerTube will serve (images for example) +from `/plugins/{plugin-name}/{plugin-version}/static/` or `/themes/{theme-name}/{theme-version}/static/` routes. ### CSS @@ -160,6 +170,10 @@ const adminName = await settingsManager.getSetting('admin-name') const result = await settingsManager.getSettings([ 'admin-name', 'admin-password' ]) result['admin-name] + +settingsManager.onSettingsChange(settings => { + settings['admin-name]) +}) ``` #### Storage @@ -205,6 +219,87 @@ The `ping` route can be accessed using: * Or `/plugins/:pluginName/router/ping` +#### Add external auth methods + +If you want to add a classic username/email and password auth method (like [LDAP](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-ldap) for example): + +```js +registerIdAndPassAuth({ + authName: 'my-auth-method', + + // PeerTube will try all id and pass plugins in the weight DESC order + // Exposing this value in the plugin settings could be interesting + getWeight: () => 60, + + // Optional function called by PeerTube when the user clicked on the logout button + onLogout: user => { + console.log('User %s logged out.', user.username') + }, + + // Optional function called by PeerTube when the access token or refresh token are generated/refreshed + hookTokenValidity: ({ token, type }) => { + if (type === 'access') return { valid: true } + if (type === 'refresh') return { valid: false } + }, + + // Used by PeerTube when the user tries to authenticate + login: ({ id, password }) => { + if (id === 'user' && password === 'super password') { + return { + username: 'user' + email: 'user@example.com' + role: 2 + displayName: 'User display name' + } + } + + // Auth failed + return null + } +}) + +// Unregister this auth method +unregisterIdAndPassAuth('my-auth-method') +``` + +You can also add an external auth method (like [OpenID](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-openid-connect), [SAML2](https://framagit.org/framasoft/peertube/official-plugins/-/tree/master/peertube-plugin-auth-saml2) etc): + +```js +// result contains the userAuthenticated auth method you can call to authenticate a user +const result = registerExternalAuth({ + authName: 'my-auth-method', + + // Will be displayed in a button next to the login form + authDisplayName: () => 'Auth method' + + // If the user click on the auth button, PeerTube will forward the request in this function + onAuthRequest: (req, res) => { + res.redirect('https://external-auth.example.com/auth') + }, + + // Same than registerIdAndPassAuth option + // onLogout: ... + + // Same than registerIdAndPassAuth option + // hookTokenValidity: ... +}) + +router.use('/external-auth-callback', (req, res) => { + // Forward the request to PeerTube + result.userAuthenticated({ + req, + res, + username: 'user' + email: 'user@example.com' + role: 2 + displayName: 'User display name' + }) +}) + +// Unregister this external auth method +unregisterExternalAuth('my-auth-method) +``` + ### Client helpers (themes & plugins) #### Plugin static route @@ -278,10 +373,10 @@ peertubeHelpers.getSettings() console.error('Matomo settings are not set.') return } - + // ... }) -``` +``` ### Publishing @@ -344,9 +439,9 @@ Update the `package.json` fields: * `author` * `bugs` * `engine.peertube` (the PeerTube version compatibility, must be `>=x.y.z` and nothing else) - + **Caution:** Don't update or remove other keys, or PeerTube will not be able to index/install your plugin. -If you don't need static directories, use an empty `object`: +If you don't need static directories, use an empty `object`: ```json { @@ -371,7 +466,7 @@ And if you don't need CSS or client script files, use an empty `array`: Now you can register hooks or settings, write CSS and add static directories to your plugin or your theme :) -**Caution:** It's up to you to check the code you write will be compatible with the PeerTube NodeJS version, +**Caution:** It's up to you to check the code you write will be compatible with the PeerTube NodeJS version, and will be supported by web browsers. If you want to write modern JavaScript, please use a transpiler like [Babel](https://babeljs.io/). @@ -405,27 +500,27 @@ Translation files are just objects, with the english sentence as the key and the ### Test your plugin/theme You'll need to have a local PeerTube instance: - * Follow the [dev prerequisites](https://github.com/Chocobozzz/PeerTube/blob/develop/.github/CONTRIBUTING.md#prerequisites) + * Follow the [dev prerequisites](https://github.com/Chocobozzz/PeerTube/blob/develop/.github/CONTRIBUTING.md#prerequisites) (to clone the repository, install dependencies and prepare the database) - * Build PeerTube (`--light` to only build the english language): + * Build PeerTube (`--light` to only build the english language): ``` $ npm run build -- --light ``` * Build the CLI: - + ``` $ npm run setup:cli ``` - - * Run PeerTube (you can access to your instance on http://localhost:9000): + + * Run PeerTube (you can access to your instance on http://localhost:9000): ``` $ NODE_ENV=test npm start ``` - * Register the instance via the CLI: + * Register the instance via the CLI: ``` $ node ./dist/server/tools/peertube.js auth add -u 'http://localhost:9000' -U 'root' --password 'test' @@ -474,10 +569,10 @@ registerHook({ }) ``` * Don't try to require parent PeerTube modules, only use `peertubeHelpers`. If you need another helper or a specific hook, please [create an issue](https://github.com/Chocobozzz/PeerTube/issues/new) - * Don't use PeerTube dependencies. Use your own :) + * Don't use PeerTube dependencies. Use your own :) If your plugin is broken with a new PeerTube release, update your code and the `peertubeEngine` field of your `package.json` field. -This way, older PeerTube versions will still use your old plugin, and new PeerTube versions will use your updated plugin. +This way, older PeerTube versions will still use your old plugin, and new PeerTube versions will use your updated plugin. ### Spam/moderation plugin @@ -488,7 +583,7 @@ If you want to create an antispam/moderation plugin, you could use the following * `filter:api.video-threads.list.result`: to change/hide the text of threads * `filter:api.video-thread-comments.list.result`: to change/hide the text of replies * `filter:video.auto-blacklist.result`: to automatically blacklist local or remote videos - + ### Other plugin examples You can take a look to "official" PeerTube plugins if you want to take inspiration from them: https://framagit.org/framasoft/peertube/official-plugins