]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/models/server/plugin.ts
Merge branch 'release/2.1.0' into develop
[github/Chocobozzz/PeerTube.git] / server / models / server / plugin.ts
index 059a442de5dfe9a96d9206f0b8698d65708aa9d0..95774a4674634bf8609cedc5bdd5ff619054180e 100644 (file)
@@ -2,13 +2,17 @@ import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table,
 import { getSort, throwIfNotValid } from '../utils'
 import {
   isPluginDescriptionValid,
+  isPluginHomepage,
   isPluginNameValid,
   isPluginTypeValid,
   isPluginVersionValid
 } from '../../helpers/custom-validators/plugins'
 import { PluginType } from '../../../shared/models/plugins/plugin.type'
 import { PeerTubePlugin } from '../../../shared/models/plugins/peertube-plugin.model'
-import { FindAndCountOptions } from 'sequelize'
+import { FindAndCountOptions, json } from 'sequelize'
+import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model'
+import * as Bluebird from 'bluebird'
+import { MPlugin, MPluginFormattable } from '@server/typings/models'
 
 @DefaultScope(() => ({
   attributes: {
@@ -20,7 +24,7 @@ import { FindAndCountOptions } from 'sequelize'
   tableName: 'plugin',
   indexes: [
     {
-      fields: [ 'name' ],
+      fields: [ 'name', 'type' ],
       unique: true
     }
   ]
@@ -42,6 +46,11 @@ export class PluginModel extends Model<PluginModel> {
   @Column
   version: string
 
+  @AllowNull(true)
+  @Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version'))
+  @Column
+  latestVersion: string
+
   @AllowNull(false)
   @Column
   enabled: boolean
@@ -59,6 +68,11 @@ export class PluginModel extends Model<PluginModel> {
   @Column
   description: string
 
+  @AllowNull(false)
+  @Is('PluginHomepage', value => throwIfNotValid(value, isPluginHomepage, 'homepage'))
+  @Column
+  homepage: string
+
   @AllowNull(true)
   @Column(DataType.JSONB)
   settings: any
@@ -73,7 +87,7 @@ export class PluginModel extends Model<PluginModel> {
   @UpdatedAt
   updatedAt: Date
 
-  static listEnabledPluginsAndThemes () {
+  static listEnabledPluginsAndThemes (): Bluebird<MPlugin[]> {
     const query = {
       where: {
         enabled: true,
@@ -84,37 +98,42 @@ export class PluginModel extends Model<PluginModel> {
     return PluginModel.findAll(query)
   }
 
-  static load (pluginName: string) {
+  static loadByNpmName (npmName: string): Bluebird<MPlugin> {
+    const name = this.normalizePluginName(npmName)
+    const type = this.getTypeFromNpmName(npmName)
+
     const query = {
       where: {
-        name: pluginName
+        name,
+        type
       }
     }
 
     return PluginModel.findOne(query)
   }
 
-  static getSetting (pluginName: string, settingName: string) {
+  static getSetting (pluginName: string, pluginType: PluginType, settingName: string) {
     const query = {
       attributes: [ 'settings' ],
       where: {
-        name: pluginName
+        name: pluginName,
+        type: pluginType
       }
     }
 
     return PluginModel.findOne(query)
-      .then(p => p.settings)
-      .then(settings => {
-        if (!settings) return undefined
+      .then(p => {
+        if (!p || !p.settings) return undefined
 
-        return settings[settingName]
+        return p.settings[settingName]
       })
   }
 
-  static setSetting (pluginName: string, settingName: string, settingValue: string) {
+  static setSetting (pluginName: string, pluginType: PluginType, settingName: string, settingValue: string) {
     const query = {
       where: {
-        name: pluginName
+        name: pluginName,
+        type: pluginType
       }
     }
 
@@ -126,39 +145,125 @@ export class PluginModel extends Model<PluginModel> {
       .then(() => undefined)
   }
 
+  static getData (pluginName: string, pluginType: PluginType, key: string) {
+    const query = {
+      raw: true,
+      attributes: [ [ json('storage.' + key), 'value' ] as any ], // FIXME: typings
+      where: {
+        name: pluginName,
+        type: pluginType
+      }
+    }
+
+    return PluginModel.findOne(query)
+      .then((c: any) => {
+        if (!c) return undefined
+        const value = c.value
+
+        if (typeof value === 'string' && value.startsWith('{')) {
+          try {
+            return JSON.parse(value)
+          } catch {
+            return value
+          }
+        }
+
+        return c.value
+      })
+  }
+
+  static storeData (pluginName: string, pluginType: PluginType, key: string, data: any) {
+    const query = {
+      where: {
+        name: pluginName,
+        type: pluginType
+      }
+    }
+
+    const toSave = {
+      [`storage.${key}`]: data
+    }
+
+    return PluginModel.update(toSave, query)
+                      .then(() => undefined)
+  }
+
   static listForApi (options: {
-    type?: PluginType,
-    uninstalled?: boolean,
-    start: number,
-    count: number,
+    pluginType?: PluginType
+    uninstalled?: boolean
+    start: number
+    count: number
     sort: string
   }) {
+    const { uninstalled = false } = options
     const query: FindAndCountOptions = {
       offset: options.start,
       limit: options.count,
       order: getSort(options.sort),
-      where: {}
+      where: {
+        uninstalled
+      }
     }
 
-    if (options.type) query.where['type'] = options.type
-    if (options.uninstalled) query.where['uninstalled'] = options.uninstalled
+    if (options.pluginType) query.where['type'] = options.pluginType
 
     return PluginModel
-      .findAndCountAll(query)
+      .findAndCountAll<MPlugin>(query)
       .then(({ rows, count }) => {
         return { total: count, data: rows }
       })
   }
 
-  toFormattedJSON (): PeerTubePlugin {
+  static listInstalled (): Bluebird<MPlugin[]> {
+    const query = {
+      where: {
+        uninstalled: false
+      }
+    }
+
+    return PluginModel.findAll(query)
+  }
+
+  static normalizePluginName (npmName: string) {
+    return npmName.replace(/^peertube-((theme)|(plugin))-/, '')
+  }
+
+  static getTypeFromNpmName (npmName: string) {
+    return npmName.startsWith('peertube-plugin-')
+      ? PluginType.PLUGIN
+      : PluginType.THEME
+  }
+
+  static buildNpmName (name: string, type: PluginType) {
+    if (type === PluginType.THEME) return 'peertube-theme-' + name
+
+    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 (this: MPluginFormattable): PeerTubePlugin {
     return {
       name: this.name,
       type: this.type,
       version: this.version,
+      latestVersion: this.latestVersion,
       enabled: this.enabled,
       uninstalled: this.uninstalled,
       peertubeEngine: this.peertubeEngine,
       description: this.description,
+      homepage: this.homepage,
       settings: this.settings,
       createdAt: this.createdAt,
       updatedAt: this.updatedAt