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