Add public settings endpoint
authorChocobozzz <me@florianbigard.com>
Fri, 26 Jul 2019 07:35:43 +0000 (09:35 +0200)
committerChocobozzz <me@florianbigard.com>
Fri, 26 Jul 2019 13:18:29 +0000 (15:18 +0200)
client/src/app/+admin/plugins/plugin-show-installed/plugin-show-installed.component.ts
client/src/app/+admin/plugins/shared/plugin-api.service.ts
client/src/app/core/plugins/plugin.service.ts
server/controllers/api/plugins.ts
server/models/server/plugin.ts
server/tests/api/check-params/plugins.ts
server/tests/api/server/plugins.ts
shared/extra-utils/server/plugins.ts
shared/models/plugins/public-server.setting.ts [new file with mode: 0644]
shared/models/plugins/register-server-setting.model.ts

index 569d9848256256c465a0861aee4d5c6084005792..13d12b145935489a3fffd2a7c6178d4e6023dabb 100644 (file)
@@ -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 }) => {
index 343eb57b28d7a5047018326030b55d13a4026fa7..c360fc1b31951dba87b23ccd1e0252841f13345d 100644 (file)
@@ -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<RegisteredServerSettings>(path)
                .pipe(catchError(res => this.restExtractor.handleError(res)))
   }
 
index 45d8088a48a90bfefe06de64bae6073a380333a1..714abd82dbbc93a201a5d0a33da0b879ee7a259f 100644 (file)
@@ -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<PeerTubePlugin>(path)
+        return this.authHttp.get<PublicServerSetting>(path)
                    .pipe(
-                     map(p => p.settings),
+                     map(p => p.publicSettings),
                      catchError(res => this.restExtractor.handleError(res))
                    )
                    .toPromise()
index 86384ee27bb95eb569939cb8a983f2f58037af2e..6b7562fd3162439b5a15d122d84fb43bcf85120b 100644 (file)
@@ -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)
 }
index f39b97ef00fa9b1059f5bee30793e4a3bd338cc4..a15f9a7e28c905dd94bc3519a6028846baf2d41d 100644 (file)
@@ -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<PluginModel> {
     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,
index 83ce6f4517bf25fdc4439c7aa5981ac7be6b1e34..9553bce17f466d2c06635b56820ed8b2a6f9f9ad 100644 (file)
@@ -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,
index f8b2d78c92570ef5944b9b32d183e03d6e297453..b8a8a2fee00b05e50791c007525a7dc49a3baf65 100644 (file)
@@ -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'
index 2302208a8088e90c86cff0d9d7dae3d9244db9ef..65d37d69f094c5134a509d8cbad3c0ec4049c694 100644 (file)
@@ -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 (file)
index 0000000..9802c4d
--- /dev/null
@@ -0,0 +1,3 @@
+export interface PublicServerSetting {
+  publicSettings: { [ name: string ]: string }
+}
index 5dea93c3989d78492a0d468c1c549995d8146d4d..78c5abd1bca0dad23f8bb8e54d066fff5a2a788f 100644 (file)
@@ -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[]
 }