]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/server/plugin.ts
WIP plugins: add storage manager
[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'
ad91e700
C
13
14@DefaultScope(() => ({
15 attributes: {
16 exclude: [ 'storage' ]
17 }
18}))
345da516
C
19
20@Table({
21 tableName: 'plugin',
22 indexes: [
23 {
dba85a1e 24 fields: [ 'name', 'type' ],
345da516
C
25 unique: true
26 }
27 ]
28})
29export class PluginModel extends Model<PluginModel> {
30
31 @AllowNull(false)
32 @Is('PluginName', value => throwIfNotValid(value, isPluginNameValid, 'name'))
33 @Column
34 name: string
35
36 @AllowNull(false)
37 @Is('PluginType', value => throwIfNotValid(value, isPluginTypeValid, 'type'))
38 @Column
39 type: number
40
41 @AllowNull(false)
42 @Is('PluginVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version'))
43 @Column
44 version: string
45
b5f919ac
C
46 @AllowNull(true)
47 @Is('PluginLatestVersion', value => throwIfNotValid(value, isPluginVersionValid, 'version'))
48 @Column
49 latestVersion: string
50
345da516
C
51 @AllowNull(false)
52 @Column
53 enabled: boolean
54
55 @AllowNull(false)
56 @Column
57 uninstalled: boolean
58
59 @AllowNull(false)
345da516
C
60 @Column
61 peertubeEngine: string
62
63 @AllowNull(true)
64 @Is('PluginDescription', value => throwIfNotValid(value, isPluginDescriptionValid, 'description'))
65 @Column
66 description: string
67
dba85a1e
C
68 @AllowNull(false)
69 @Is('PluginHomepage', value => throwIfNotValid(value, isPluginHomepage, 'homepage'))
70 @Column
71 homepage: string
72
345da516
C
73 @AllowNull(true)
74 @Column(DataType.JSONB)
75 settings: any
76
77 @AllowNull(true)
78 @Column(DataType.JSONB)
79 storage: any
80
81 @CreatedAt
82 createdAt: Date
83
84 @UpdatedAt
85 updatedAt: Date
86
87 static listEnabledPluginsAndThemes () {
88 const query = {
89 where: {
90 enabled: true,
91 uninstalled: false
92 }
93 }
94
95 return PluginModel.findAll(query)
96 }
97
dba85a1e
C
98 static loadByNpmName (npmName: string) {
99 const name = this.normalizePluginName(npmName)
100 const type = this.getTypeFromNpmName(npmName)
101
2c053942
C
102 const query = {
103 where: {
dba85a1e
C
104 name,
105 type
2c053942
C
106 }
107 }
108
109 return PluginModel.findOne(query)
110 }
111
b5f919ac 112 static getSetting (pluginName: string, pluginType: PluginType, settingName: string) {
ad91e700
C
113 const query = {
114 attributes: [ 'settings' ],
115 where: {
b5f919ac
C
116 name: pluginName,
117 type: pluginType
ad91e700
C
118 }
119 }
120
121 return PluginModel.findOne(query)
b5f919ac
C
122 .then(p => {
123 if (!p || !p.settings) return undefined
ad91e700 124
b5f919ac 125 return p.settings[settingName]
ad91e700
C
126 })
127 }
128
b5f919ac 129 static setSetting (pluginName: string, pluginType: PluginType, settingName: string, settingValue: string) {
f023a19c
C
130 const query = {
131 where: {
b5f919ac
C
132 name: pluginName,
133 type: pluginType
f023a19c
C
134 }
135 }
136
ad91e700
C
137 const toSave = {
138 [`settings.${settingName}`]: settingValue
139 }
140
141 return PluginModel.update(toSave, query)
142 .then(() => undefined)
143 }
144
b2195faf
C
145 static getData (pluginName: string, pluginType: PluginType, key: string) {
146 const query = {
147 raw: true,
148 attributes: [ [ json('storage.' + key), 'value' ] as any ], // FIXME: typings
149 where: {
150 name: pluginName,
151 type: pluginType
152 }
153 }
154
155 return PluginModel.findOne(query)
156 .then((c: any) => {
157 if (!c) return undefined
158
159 return c.value
160 })
161 }
162
163 static storeData (pluginName: string, pluginType: PluginType, key: string, data: any) {
164 const query = {
165 where: {
166 name: pluginName,
167 type: pluginType
168 }
169 }
170
171 const toSave = {
172 [`storage.${key}`]: data
173 }
174
175 return PluginModel.update(toSave, query)
176 .then(() => undefined)
177 }
178
ad91e700
C
179 static listForApi (options: {
180 type?: PluginType,
181 uninstalled?: boolean,
182 start: number,
183 count: number,
184 sort: string
185 }) {
8d2be0ed 186 const { uninstalled = false } = options
ad91e700
C
187 const query: FindAndCountOptions = {
188 offset: options.start,
189 limit: options.count,
190 order: getSort(options.sort),
8d2be0ed
C
191 where: {
192 uninstalled
193 }
ad91e700
C
194 }
195
196 if (options.type) query.where['type'] = options.type
ad91e700
C
197
198 return PluginModel
199 .findAndCountAll(query)
200 .then(({ rows, count }) => {
201 return { total: count, data: rows }
202 })
203 }
204
dba85a1e
C
205 static normalizePluginName (name: string) {
206 return name.replace(/^peertube-((theme)|(plugin))-/, '')
207 }
208
209 static getTypeFromNpmName (npmName: string) {
210 return npmName.startsWith('peertube-plugin-')
211 ? PluginType.PLUGIN
212 : PluginType.THEME
213 }
214
b5f919ac
C
215 static buildNpmName (name: string, type: PluginType) {
216 if (type === PluginType.THEME) return 'peertube-theme-' + name
217
218 return 'peertube-plugin-' + name
219 }
220
ad91e700
C
221 toFormattedJSON (): PeerTubePlugin {
222 return {
223 name: this.name,
224 type: this.type,
225 version: this.version,
b5f919ac 226 latestVersion: this.latestVersion,
ad91e700
C
227 enabled: this.enabled,
228 uninstalled: this.uninstalled,
229 peertubeEngine: this.peertubeEngine,
230 description: this.description,
dba85a1e 231 homepage: this.homepage,
ad91e700
C
232 settings: this.settings,
233 createdAt: this.createdAt,
234 updatedAt: this.updatedAt
235 }
f023a19c
C
236 }
237
345da516 238}