From ba211e7386bb2f25e37a4c5bcdfeb4237e1cd315 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 26 Jul 2019 09:35:43 +0200 Subject: [PATCH] Add public settings endpoint --- .../plugin-show-installed.component.ts | 2 +- .../plugins/shared/plugin-api.service.ts | 4 +-- client/src/app/core/plugins/plugin.service.ts | 7 ++-- server/controllers/api/plugins.ts | 32 ++++++++++++++----- server/models/server/plugin.ts | 15 ++++++++- server/tests/api/check-params/plugins.ts | 10 +++--- server/tests/api/server/plugins.ts | 19 ++++++++--- shared/extra-utils/server/plugins.ts | 18 ++++++++++- .../models/plugins/public-server.setting.ts | 3 ++ .../plugins/register-server-setting.model.ts | 8 ++++- 10 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 shared/models/plugins/public-server.setting.ts diff --git a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts index 569d98482..13d12b145 100644 --- a/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts +++ b/client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts @@ -66,7 +66,7 @@ export class PluginShowInstalledComponent extends FormReactive implements OnInit this.pluginService.getPlugin(npmName) .pipe(switchMap(plugin => { return this.pluginService.getPluginRegisteredSettings(plugin.name, plugin.type) - .pipe(map(data => ({ plugin, registeredSettings: data.settings }))) + .pipe(map(data => ({ plugin, registeredSettings: data.registeredSettings }))) })) .subscribe( ({ plugin, registeredSettings }) => { diff --git a/client/src/app/+admin/plugins/shared/plugin-api.service.ts b/client/src/app/+admin/plugins/shared/plugin-api.service.ts index 343eb57b2..c360fc1b3 100644 --- a/client/src/app/+admin/plugins/shared/plugin-api.service.ts +++ b/client/src/app/+admin/plugins/shared/plugin-api.service.ts @@ -11,7 +11,7 @@ import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model' import { ManagePlugin } from '@shared/models/plugins/manage-plugin.model' import { InstallOrUpdatePlugin } from '@shared/models/plugins/install-plugin.model' import { PeerTubePluginIndex } from '@shared/models/plugins/peertube-plugin-index.model' -import { RegisterServerSettingOptions } from '@shared/models/plugins/register-server-setting.model' +import { RegisteredServerSettings, RegisterServerSettingOptions } from '@shared/models/plugins/register-server-setting.model' import { PluginService } from '@app/core/plugins/plugin.service' @Injectable() @@ -91,7 +91,7 @@ export class PluginApiService { const npmName = this.pluginService.nameToNpmName(pluginName, pluginType) const path = PluginApiService.BASE_PLUGIN_URL + '/' + npmName + '/registered-settings' - return this.authHttp.get<{ settings: RegisterServerSettingOptions[] }>(path) + return this.authHttp.get(path) .pipe(catchError(res => this.restExtractor.handleError(res))) } diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts index 45d8088a4..714abd82d 100644 --- a/client/src/app/core/plugins/plugin.service.ts +++ b/client/src/app/core/plugins/plugin.service.ts @@ -15,6 +15,7 @@ import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model' import { HttpClient } from '@angular/common/http' import { RestExtractor } from '@app/shared/rest' import { PluginType } from '@shared/models/plugins/plugin.type' +import { PublicServerSetting } from '@shared/models/plugins/public-server.setting' interface HookStructValue extends RegisterClientHookOptions { plugin: ServerConfigPlugin @@ -241,11 +242,11 @@ export class PluginService implements ClientHook { getSettings: () => { const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType) - const path = PluginService.BASE_PLUGIN_URL + '/' + npmName + const path = PluginService.BASE_PLUGIN_URL + '/' + npmName + '/public-settings' - return this.authHttp.get(path) + return this.authHttp.get(path) .pipe( - map(p => p.settings), + map(p => p.publicSettings), catchError(res => this.restExtractor.handleError(res)) ) .toPromise() diff --git a/server/controllers/api/plugins.ts b/server/controllers/api/plugins.ts index 86384ee27..6b7562fd3 100644 --- a/server/controllers/api/plugins.ts +++ b/server/controllers/api/plugins.ts @@ -26,6 +26,7 @@ import { logger } from '../../helpers/logger' import { listAvailablePluginsFromIndex } from '../../lib/plugins/plugin-index' import { PeertubePluginIndexList } from '../../../shared/models/plugins/peertube-plugin-index-list.model' import { RegisteredServerSettings } from '../../../shared/models/plugins/register-server-setting.model' +import { PublicServerSetting } from '../../../shared/models/plugins/public-server.setting' const pluginRouter = express.Router() @@ -51,18 +52,16 @@ pluginRouter.get('/', asyncMiddleware(listPlugins) ) -pluginRouter.get('/:npmName', +pluginRouter.get('/:npmName/registered-settings', authenticate, ensureUserHasRight(UserRight.MANAGE_PLUGINS), asyncMiddleware(existingPluginValidator), - getPlugin + getPluginRegisteredSettings ) -pluginRouter.get('/:npmName/registered-settings', - authenticate, - ensureUserHasRight(UserRight.MANAGE_PLUGINS), +pluginRouter.get('/:npmName/public-settings', asyncMiddleware(existingPluginValidator), - getPluginRegisteredSettings + getPublicPluginSettings ) pluginRouter.put('/:npmName/settings', @@ -73,6 +72,13 @@ pluginRouter.put('/:npmName/settings', asyncMiddleware(updatePluginSettings) ) +pluginRouter.get('/:npmName', + authenticate, + ensureUserHasRight(UserRight.MANAGE_PLUGINS), + asyncMiddleware(existingPluginValidator), + getPlugin +) + pluginRouter.post('/install', authenticate, ensureUserHasRight(UserRight.MANAGE_PLUGINS), @@ -161,10 +167,20 @@ async function uninstallPlugin (req: express.Request, res: express.Response) { return res.sendStatus(204) } +function getPublicPluginSettings (req: express.Request, res: express.Response) { + const plugin = res.locals.plugin + const registeredSettings = PluginManager.Instance.getRegisteredSettings(req.params.npmName) + const publicSettings = plugin.getPublicSettings(registeredSettings) + + const json: PublicServerSetting = { publicSettings } + + return res.json(json) +} + function getPluginRegisteredSettings (req: express.Request, res: express.Response) { - const settings = PluginManager.Instance.getRegisteredSettings(req.params.npmName) + const registeredSettings = PluginManager.Instance.getRegisteredSettings(req.params.npmName) - const json: RegisteredServerSettings = { settings } + const json: RegisteredServerSettings = { registeredSettings } return res.json(json) } diff --git a/server/models/server/plugin.ts b/server/models/server/plugin.ts index f39b97ef0..a15f9a7e2 100644 --- a/server/models/server/plugin.ts +++ b/server/models/server/plugin.ts @@ -10,7 +10,7 @@ import { import { PluginType } from '../../../shared/models/plugins/plugin.type' import { PeerTubePlugin } from '../../../shared/models/plugins/peertube-plugin.model' import { FindAndCountOptions, json } from 'sequelize' -import { PeerTubePluginIndex } from '../../../shared/models/plugins/peertube-plugin-index.model' +import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model' @DefaultScope(() => ({ attributes: { @@ -238,6 +238,19 @@ export class PluginModel extends Model { return 'peertube-plugin-' + name } + getPublicSettings (registeredSettings: RegisterServerSettingOptions[]) { + const result: { [ name: string ]: string } = {} + const settings = this.settings || {} + + for (const r of registeredSettings) { + if (r.private !== false) continue + + result[r.name] = settings[r.name] || r.default || null + } + + return result + } + toFormattedJSON (): PeerTubePlugin { return { name: this.name, diff --git a/server/tests/api/check-params/plugins.ts b/server/tests/api/check-params/plugins.ts index 83ce6f451..9553bce17 100644 --- a/server/tests/api/check-params/plugins.ts +++ b/server/tests/api/check-params/plugins.ts @@ -281,7 +281,7 @@ describe('Test server plugins API validators', function () { }) }) - describe('When getting a plugin or the registered settings', function () { + describe('When getting a plugin or the registered settings or public settings', function () { const path = '/api/v1/plugins/' it('Should fail with an invalid token', async function () { @@ -307,7 +307,7 @@ describe('Test server plugins API validators', function () { }) it('Should fail with an invalid npm name', async function () { - for (const suffix of [ 'toto', 'toto/registered-settings' ]) { + for (const suffix of [ 'toto', 'toto/registered-settings', 'toto/public-settings' ]) { await makeGetRequest({ url: server.url, path: path + suffix, @@ -316,7 +316,7 @@ describe('Test server plugins API validators', function () { }) } - for (const suffix of [ 'peertube-plugin-TOTO', 'peertube-plugin-TOTO/registered-settings' ]) { + for (const suffix of [ 'peertube-plugin-TOTO', 'peertube-plugin-TOTO/registered-settings', 'peertube-plugin-TOTO/public-settings' ]) { await makeGetRequest({ url: server.url, path: path + suffix, @@ -327,7 +327,7 @@ describe('Test server plugins API validators', function () { }) it('Should fail with an unknown plugin', async function () { - for (const suffix of [ 'peertube-plugin-toto', 'peertube-plugin-toto/registered-settings' ]) { + for (const suffix of [ 'peertube-plugin-toto', 'peertube-plugin-toto/registered-settings', 'peertube-plugin-toto/public-settings' ]) { await makeGetRequest({ url: server.url, path: path + suffix, @@ -338,7 +338,7 @@ describe('Test server plugins API validators', function () { }) it('Should succeed with the correct parameters', async function () { - for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings` ]) { + for (const suffix of [ npmPlugin, `${npmPlugin}/registered-settings`, `${npmPlugin}/public-settings` ]) { await makeGetRequest({ url: server.url, path: path + suffix, diff --git a/server/tests/api/server/plugins.ts b/server/tests/api/server/plugins.ts index f8b2d78c9..b8a8a2fee 100644 --- a/server/tests/api/server/plugins.ts +++ b/server/tests/api/server/plugins.ts @@ -18,7 +18,7 @@ import { setPluginVersion, uninstallPlugin, updateCustomSubConfig, updateMyUser, updatePluginPackageJSON, updatePlugin, updatePluginSettings, - wait + wait, getPublicSettings } from '../../../../shared/extra-utils' import { PluginType } from '../../../../shared/models/plugins/plugin.type' import { PeerTubePluginIndex } from '../../../../shared/models/plugins/peertube-plugin-index.model' @@ -27,6 +27,7 @@ import { PeerTubePlugin } from '../../../../shared/models/plugins/peertube-plugi import { User } from '../../../../shared/models/users' import { PluginPackageJson } from '../../../../shared/models/plugins/plugin-package-json.model' import { RegisteredServerSettings } from '../../../../shared/models/plugins/register-server-setting.model' +import { PublicServerSetting } from '../../../../shared/models/plugins/public-server.setting' const expect = chai.expect @@ -217,14 +218,24 @@ describe('Test plugins', function () { npmName: 'peertube-plugin-hello-world' }) - const settings = (res.body as RegisteredServerSettings).settings + const registeredSettings = (res.body as RegisteredServerSettings).registeredSettings - expect(settings).to.have.length.at.least(1) + expect(registeredSettings).to.have.length.at.least(1) - const adminNameSettings = settings.find(s => s.name === 'admin-name') + const adminNameSettings = registeredSettings.find(s => s.name === 'admin-name') expect(adminNameSettings).to.not.be.undefined }) + it('Should get public settings', async function () { + const res = await getPublicSettings({ url: server.url, npmName: 'peertube-plugin-hello-world' }) + + const publicSettings = (res.body as PublicServerSetting).publicSettings + + expect(Object.keys(publicSettings)).to.have.lengthOf(1) + expect(Object.keys(publicSettings)).to.deep.equal([ 'user-name' ]) + expect(publicSettings['user-name']).to.be.null + }) + it('Should update the settings', async function () { const settings = { 'admin-name': 'Cid' diff --git a/shared/extra-utils/server/plugins.ts b/shared/extra-utils/server/plugins.ts index 2302208a8..65d37d69f 100644 --- a/shared/extra-utils/server/plugins.ts +++ b/shared/extra-utils/server/plugins.ts @@ -119,6 +119,21 @@ function getPluginRegisteredSettings (parameters: { }) } +function getPublicSettings (parameters: { + url: string, + npmName: string, + expectedStatus?: number +}) { + const { url, npmName, expectedStatus = 200 } = parameters + const path = '/api/v1/plugins/' + npmName + '/public-settings' + + return makeGetRequest({ + url, + path, + statusCodeExpected: expectedStatus + }) +} + function installPlugin (parameters: { url: string, accessToken: string, @@ -218,5 +233,6 @@ export { getPackageJSONPath, updatePluginPackageJSON, getPluginPackageJSON, - getPluginTestPath + getPluginTestPath, + getPublicSettings } diff --git a/shared/models/plugins/public-server.setting.ts b/shared/models/plugins/public-server.setting.ts new file mode 100644 index 000000000..9802c4d7d --- /dev/null +++ b/shared/models/plugins/public-server.setting.ts @@ -0,0 +1,3 @@ +export interface PublicServerSetting { + publicSettings: { [ name: string ]: string } +} diff --git a/shared/models/plugins/register-server-setting.model.ts b/shared/models/plugins/register-server-setting.model.ts index 5dea93c39..78c5abd1b 100644 --- a/shared/models/plugins/register-server-setting.model.ts +++ b/shared/models/plugins/register-server-setting.model.ts @@ -2,9 +2,15 @@ export interface RegisterServerSettingOptions { name: string label: string type: 'input' + + // If the setting is not private, anyone can view its value + // Mainly used by the PeerTube client to get admin config + private: boolean + + // Default setting value default?: string } export interface RegisteredServerSettings { - settings: RegisterServerSettingOptions[] + registeredSettings: RegisterServerSettingOptions[] } -- 2.41.0