]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/server/plugin.ts
Add external login buttons
[github/Chocobozzz/PeerTube.git] / server / models / server / plugin.ts
CommitLineData
ad91e700
C
1import { AllowNull, Column, CreatedAt, DataType, DefaultScope, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
2import { getSort, throwIfNotValid } from '../utils'
345da516 3import {
b5f919ac
C
4 isPluginDescriptionValid,
5 isPluginHomepage,
345da516
C
6 isPluginNameValid,
7 isPluginTypeValid,
8 isPluginVersionValid
9} from '../../helpers/custom-validators/plugins'
ad91e700
C
10import { PluginType } from '../../../shared/models/plugins/plugin.type'
11import { PeerTubePlugin } from '../../../shared/models/plugins/peertube-plugin.model'
b2195faf 12import { FindAndCountOptions, json } from 'sequelize'
ba211e73 13import { RegisterServerSettingOptions } from '../../../shared/models/plugins/register-server-setting.model'
453e83ea 14import * as Bluebird from 'bluebird'
1ca9f7c3 15import { MPlugin, MPluginFormattable } from '@server/typings/models'
ad91e700
C
16
17@DefaultScope(() => ({
18 attributes: {
19 exclude: [ 'storage' ]
20 }
21}))
345da516
C
22
23@Table({
24 tableName: 'plugin',
25 indexes: [
26 {
dba85a1e 27 fields: [ 'name', 'type' ],
345da516
C
28 unique: true
29 }
30 ]
31})
32export class PluginModel extends Model<PluginModel> {
33
34 @AllowNull(false)
35 @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name'))
36 @Column
37 name: string
38
39 @AllowNull(false)
40 @Is('PluginType', value => throwIfNotValid(value, isPluginTypeValid, 'type'))
41 @Column
42 type: number
43
44 @AllowNull(false)
45 @Is('PluginVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version'))
46 @Column
47 version: string
48
b5f919ac
C
49 @AllowNull(true)
50 @Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version'))
51 @Column
52 latestVersion: string
53
345da516
C
54 @AllowNull(false)
55 @Column
56 enabled: boolean
57
58 @AllowNull(false)
59 @Column
60 uninstalled: boolean
61
62 @AllowNull(false)
345da516
C
63 @Column
64 peertubeEngine: string
65
66 @AllowNull(true)
67 @Is('PluginDescription', value => throwIfNotValid(value, isPluginDescriptionValid, 'description'))
68 @Column
69 description: string
70
dba85a1e
C
71 @AllowNull(false)
72 @Is('PluginHomepage', value => throwIfNotValid(value, isPluginHomepage, 'homepage'))
73 @Column
74 homepage: string
75
345da516
C
76 @AllowNull(true)
77 @Column(DataType.JSONB)
78 settings: any
79
80 @AllowNull(true)
81 @Column(DataType.JSONB)
82 storage: any
83
84 @CreatedAt
85 createdAt: Date
86
87 @UpdatedAt
88 updatedAt: Date
89
453e83ea 90 static listEnabledPluginsAndThemes (): Bluebird<MPlugin[]> {
345da516
C
91 const query = {
92 where: {
93 enabled: true,
94 uninstalled: false
95 }
96 }
97
98 return PluginModel.findAll(query)
99 }
100
453e83ea 101 static loadByNpmName (npmName: string): Bluebird<MPlugin> {
dba85a1e
C
102 const name = this.normalizePluginName(npmName)
103 const type = this.getTypeFromNpmName(npmName)
104
2c053942
C
105 const query = {
106 where: {
dba85a1e
C
107 name,
108 type
2c053942
C
109 }
110 }
111
112 return PluginModel.findOne(query)
113 }
114
b5f919ac 115 static getSetting (pluginName: string, pluginType: PluginType, settingName: string) {
ad91e700
C
116 const query = {
117 attributes: [ 'settings' ],
118 where: {
b5f919ac
C
119 name: pluginName,
120 type: pluginType
ad91e700
C
121 }
122 }
123
124 return PluginModel.findOne(query)
b5f919ac
C
125 .then(p => {
126 if (!p || !p.settings) return undefined
ad91e700 127
b5f919ac 128 return p.settings[settingName]
ad91e700
C
129 })
130 }
131
055cfb11
C
132 static getSettings (pluginName: string, pluginType: PluginType, settingNames: string[]) {
133 const query = {
134 attributes: [ 'settings' ],
135 where: {
136 name: pluginName,
137 type: pluginType
138 }
139 }
140
141 return PluginModel.findOne(query)
142 .then(p => {
143 if (!p || !p.settings) return {}
144
145 const result: { [settingName: string ]: string } = {}
146
147 for (const key of Object.keys(p.settings)) {
148 if (settingNames.includes(key)) {
149 result[key] = p.settings[key]
150 }
151 }
152
153 return result
154 })
155 }
156
b5f919ac 157 static setSetting (pluginName: string, pluginType: PluginType, settingName: string, settingValue: string) {
f023a19c
C
158 const query = {
159 where: {
b5f919ac
C
160 name: pluginName,
161 type: pluginType
f023a19c
C
162 }
163 }
164
ad91e700
C
165 const toSave = {
166 [`settings.${settingName}`]: settingValue
167 }
168
169 return PluginModel.update(toSave, query)
170 .then(() => undefined)
171 }
172
b2195faf
C
173 static getData (pluginName: string, pluginType: PluginType, key: string) {
174 const query = {
175 raw: true,
176 attributes: [ [ json('storage.' + key), 'value' ] as any ], // FIXME: typings
177 where: {
178 name: pluginName,
179 type: pluginType
180 }
181 }
182
183 return PluginModel.findOne(query)
109d893f 184 .then((c: any) => {
b2195faf 185 if (!c) return undefined
9fa6ca16
C
186 const value = c.value
187
188 if (typeof value === 'string' && value.startsWith('{')) {
189 try {
190 return JSON.parse(value)
191 } catch {
192 return value
193 }
194 }
b2195faf
C
195
196 return c.value
197 })
198 }
199
200 static storeData (pluginName: string, pluginType: PluginType, key: string, data: any) {
201 const query = {
202 where: {
203 name: pluginName,
204 type: pluginType
205 }
206 }
207
208 const toSave = {
209 [`storage.${key}`]: data
210 }
211
212 return PluginModel.update(toSave, query)
213 .then(() => undefined)
214 }
215
ad91e700 216 static listForApi (options: {
a1587156
C
217 pluginType?: PluginType
218 uninstalled?: boolean
219 start: number
220 count: number
ad91e700
C
221 sort: string
222 }) {
8d2be0ed 223 const { uninstalled = false } = options
ad91e700
C
224 const query: FindAndCountOptions = {
225 offset: options.start,
226 limit: options.count,
227 order: getSort(options.sort),
8d2be0ed
C
228 where: {
229 uninstalled
230 }
ad91e700
C
231 }
232
6702a1b2 233 if (options.pluginType) query.where['type'] = options.pluginType
ad91e700
C
234
235 return PluginModel
453e83ea 236 .findAndCountAll<MPlugin>(query)
ad91e700
C
237 .then(({ rows, count }) => {
238 return { total: count, data: rows }
239 })
240 }
241
453e83ea 242 static listInstalled (): Bluebird<MPlugin[]> {
6702a1b2
C
243 const query = {
244 where: {
245 uninstalled: false
246 }
247 }
248
249 return PluginModel.findAll(query)
250 }
251
252 static normalizePluginName (npmName: string) {
253 return npmName.replace(/^peertube-((theme)|(plugin))-/, '')
dba85a1e
C
254 }
255
256 static getTypeFromNpmName (npmName: string) {
257 return npmName.startsWith('peertube-plugin-')
258 ? PluginType.PLUGIN
259 : PluginType.THEME
260 }
261
b5f919ac
C
262 static buildNpmName (name: string, type: PluginType) {
263 if (type === PluginType.THEME) return 'peertube-theme-' + name
264
265 return 'peertube-plugin-' + name
266 }
267
ba211e73
C
268 getPublicSettings (registeredSettings: RegisterServerSettingOptions[]) {
269 const result: { [ name: string ]: string } = {}
270 const settings = this.settings || {}
271
272 for (const r of registeredSettings) {
273 if (r.private !== false) continue
274
275 result[r.name] = settings[r.name] || r.default || null
276 }
277
278 return result
279 }
280
1ca9f7c3 281 toFormattedJSON (this: MPluginFormattable): PeerTubePlugin {
ad91e700
C
282 return {
283 name: this.name,
284 type: this.type,
285 version: this.version,
b5f919ac 286 latestVersion: this.latestVersion,
ad91e700
C
287 enabled: this.enabled,
288 uninstalled: this.uninstalled,
289 peertubeEngine: this.peertubeEngine,
290 description: this.description,
dba85a1e 291 homepage: this.homepage,
ad91e700
C
292 settings: this.settings,
293 createdAt: this.createdAt,
294 updatedAt: this.updatedAt
295 }
f023a19c
C
296 }
297
345da516 298}