]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - pkgs/webapps/peertube/ldap.patch
Upgrade mastodon
[perso/Immae/Config/Nix.git] / pkgs / webapps / peertube / ldap.patch
1 commit 45a9e4a7b1badbea15d74bd8b3990303a424dfa6
2 Author: Ismaƫl Bouya <ismael.bouya@normalesup.org>
3 Date: Tue Feb 12 18:47:53 2019 +0100
4
5 Add LDAP authentication
6
7 diff --git a/config/default.yaml b/config/default.yaml
8 index e16b8c35..eac0dd3f 100644
9 --- a/config/default.yaml
10 +++ b/config/default.yaml
11 @@ -33,6 +33,9 @@ redis:
12 auth: null
13 db: 0
14
15 +ldap:
16 + enable: false
17 +
18 smtp:
19 hostname: null
20 port: 465
21 diff --git a/config/production.yaml.example b/config/production.yaml.example
22 index 661eac0d..bb5ac251 100644
23 --- a/config/production.yaml.example
24 +++ b/config/production.yaml.example
25 @@ -33,6 +33,17 @@ redis:
26 auth: null
27 db: 0
28
29 +ldap:
30 + enable: true
31 + # Disallow non-ldap users (it also disables root!)
32 + ldap_only: true
33 + url: ldap://localhost:389/dc=example,dc=com
34 + bind_dn: cn=admin,dc=example,dc=com
35 + bind_password: adminPass
36 + base: dc=example,dc=com
37 + mail_entry: "mail"
38 + user_filter: "(|(email=%username%)(uid=%username%))"
39 +
40 # SMTP server to send emails
41 smtp:
42 hostname: null
43 diff --git a/package.json b/package.json
44 index 0cf39c7e..fd1ce3ea 100644
45 --- a/package.json
46 +++ b/package.json
47 @@ -125,6 +125,7 @@
48 "js-yaml": "^3.5.4",
49 "jsonld": "^1.0.1",
50 "jsonld-signatures": "https://github.com/Chocobozzz/jsonld-signatures#rsa2017",
51 + "ldapjs": "^1.0.2",
52 "lodash": "^4.17.10",
53 "magnet-uri": "^5.1.4",
54 "memoizee": "^0.4.14",
55 diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts
56 index 6f3ebb9a..fb21df37 100644
57 --- a/server/initializers/constants.ts
58 +++ b/server/initializers/constants.ts
59 @@ -16,7 +16,7 @@ let config: IConfig = require('config')
60
61 // ---------------------------------------------------------------------------
62
63 -const LAST_MIGRATION_VERSION = 325
64 +const LAST_MIGRATION_VERSION = 326
65
66 // ---------------------------------------------------------------------------
67
68 @@ -177,6 +177,16 @@ const CONFIG = {
69 AUTH: config.has('redis.auth') ? config.get<string>('redis.auth') : null,
70 DB: config.has('redis.db') ? config.get<number>('redis.db') : null
71 },
72 + LDAP: {
73 + ENABLE: config.has('ldap.enable') ? config.get<boolean>('ldap.enable') : false,
74 + LDAP_ONLY: config.has('ldap.ldap_only') ? config.get<boolean>('ldap.ldap_only') : false,
75 + URL: config.has('ldap.url') ? config.get<string>('ldap.url') : null,
76 + BIND_DN: config.has('ldap.bind_dn') ? config.get<string>('ldap.bind_dn') : null,
77 + BIND_PASSWORD: config.has('ldap.bind_password') ? config.get<string>('ldap.bind_password') : null,
78 + BASE: config.has('ldap.base') ? config.get<string>('ldap.base') : null,
79 + MAIL_ENTRY: config.has('ldap.mail_entry') ? config.get<string>('ldap.mail_entry') : 'mail',
80 + USER_FILTER: config.has('ldap.user_filter') ? config.get<string>('ldap.user_filter') : '(|(email=%username%)(uid=%username%))'
81 + },
82 SMTP: {
83 HOSTNAME: config.get<string>('smtp.hostname'),
84 PORT: config.get<number>('smtp.port'),
85 diff --git a/server/initializers/migrations/0326-user-ldap-dn.ts b/server/initializers/migrations/0326-user-ldap-dn.ts
86 new file mode 100644
87 index 00000000..a9d68124
88 --- /dev/null
89 +++ b/server/initializers/migrations/0326-user-ldap-dn.ts
90 @@ -0,0 +1,26 @@
91 +import * as Sequelize from 'sequelize'
92 +
93 +async function up (utils: {
94 + transaction: Sequelize.Transaction,
95 + queryInterface: Sequelize.QueryInterface,
96 + sequelize: Sequelize.Sequelize
97 +}): Promise<void> {
98 +
99 + {
100 + const data = {
101 + type: Sequelize.STRING,
102 + allowNull: true,
103 + defaultValue: null
104 + }
105 + await utils.queryInterface.addColumn('user', 'ldapDn', data)
106 + }
107 +}
108 +
109 +function down (options) {
110 + throw new Error('Not implemented.')
111 +}
112 +
113 +export {
114 + up,
115 + down
116 +}
117 diff --git a/server/lib/oauth-model.ts b/server/lib/oauth-model.ts
118 index 2cd2ae97..3f14b216 100644
119 --- a/server/lib/oauth-model.ts
120 +++ b/server/lib/oauth-model.ts
121 @@ -66,7 +66,13 @@ function getRefreshToken (refreshToken: string) {
122 async function getUser (usernameOrEmail: string, password: string) {
123 logger.debug('Getting User (username/email: ' + usernameOrEmail + ', password: ******).')
124
125 - const user = await UserModel.loadByUsernameOrEmail(usernameOrEmail)
126 + let user
127 + if (CONFIG.LDAP.ENABLE) {
128 + user = await UserModel.findOrCreateLDAPUser(usernameOrEmail)
129 + }
130 + if (!user && (!CONFIG.LDAP.ENABLE || !CONFIG.LDAP.LDAP_ONLY)) {
131 + user = await UserModel.loadByUsernameOrEmail(usernameOrEmail)
132 + }
133 if (!user) return null
134
135 const passwordMatch = await user.isPasswordMatch(password)
136 diff --git a/server/models/account/user.ts b/server/models/account/user.ts
137 index 017a9665..a4d0145c 100644
138 --- a/server/models/account/user.ts
139 +++ b/server/models/account/user.ts
140 @@ -1,3 +1,4 @@
141 +import * as ldap from 'ldapjs'
142 import * as Sequelize from 'sequelize'
143 import {
144 AfterDestroy,
145 @@ -42,8 +43,9 @@ import { VideoChannelModel } from '../video/video-channel'
146 import { AccountModel } from './account'
147 import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type'
148 import { values } from 'lodash'
149 -import { NSFW_POLICY_TYPES } from '../../initializers'
150 +import { CONFIG, NSFW_POLICY_TYPES } from '../../initializers'
151 import { clearCacheByUserId } from '../../lib/oauth-model'
152 +import { createUserAccountAndChannel } from '../../lib/user'
153 import { UserNotificationSettingModel } from './user-notification-setting'
154 import { VideoModel } from '../video/video'
155 import { ActorModel } from '../activitypub/actor'
156 @@ -111,6 +113,11 @@ export class UserModel extends Model<UserModel> {
157 @Column(DataType.STRING(400))
158 email: string
159
160 + @AllowNull(true)
161 + @Default(null)
162 + @Column
163 + ldapDn: string
164 +
165 @AllowNull(true)
166 @Default(null)
167 @Is('UserEmailVerified', value => throwIfNotValid(value, isUserEmailVerifiedValid, 'email verified boolean'))
168 @@ -354,6 +361,90 @@ export class UserModel extends Model<UserModel> {
169 return UserModel.findOne(query)
170 }
171
172 + static loadByLdapDn (ldapDn: string) {
173 + const query = {
174 + where: {
175 + ldapDn
176 + }
177 + }
178 +
179 + return UserModel.findOne(query)
180 + }
181 +
182 + static findOrCreateLDAPUser (username: string) {
183 + let userInfos
184 +
185 + return Promise.resolve(UserModel.findLDAPUser(username))
186 + .then((_userInfos) => {
187 + userInfos = _userInfos
188 + return UserModel.loadByLdapDn(userInfos['dn'])
189 + })
190 + .then((user) => {
191 + if (user) {
192 + return user
193 + } else {
194 + return UserModel.createLDAPUser(username, userInfos)
195 + }
196 + })
197 + .catch(() => { return null })
198 + }
199 +
200 + static findLDAPUser (username: string) {
201 + const client = ldap.createClient({
202 + url: CONFIG.LDAP.URL
203 + })
204 + const filter = ldap.parseFilter(CONFIG.LDAP.USER_FILTER)
205 + filter.forEach(function (element) {
206 + if (element.value === '%username%') element.value = username
207 + })
208 + const opts = {
209 + filter,
210 + scope: 'sub',
211 + attributes: [ CONFIG.LDAP.MAIL_ENTRY, 'dn' ]
212 + }
213 +
214 + return new Promise(function (resolve, reject) {
215 + client.bind(CONFIG.LDAP.BIND_DN, CONFIG.LDAP.BIND_PASSWORD, function (err) {
216 + if (err) reject()
217 + let entries = []
218 + client.search(CONFIG.LDAP.BASE, opts, function (err, search) {
219 + if (err) reject()
220 + search.on('searchEntry', function (entry) {
221 + entries.push(entry.object)
222 + })
223 + search.on('end', function (result) {
224 + if (entries.length === 1) {
225 + resolve(entries[0])
226 + } else {
227 + reject()
228 + }
229 + })
230 + })
231 + })
232 + })
233 + }
234 +
235 + static createLDAPUser (username: string, userInfos: {}) {
236 + return Promise.resolve(userInfos)
237 + .then((userInfos) => {
238 + const userToCreate = new UserModel({
239 + username: username,
240 + password: 'SomeInvalidPassword',
241 + email: userInfos[CONFIG.LDAP.MAIL_ENTRY],
242 + ldapDn: userInfos['dn'],
243 + nsfwPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
244 + autoPlayVideo: true,
245 + role: UserRole.USER,
246 + videoQuota: CONFIG.USER.VIDEO_QUOTA,
247 + videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY,
248 + emailVerified: true
249 + })
250 +
251 + return createUserAccountAndChannel(userToCreate)
252 + })
253 + .then(({ user }) => { return user })
254 + }
255 +
256 static loadByUsernameAndPopulateChannels (username: string) {
257 const query = {
258 where: {
259 @@ -516,8 +607,22 @@ export class UserModel extends Model<UserModel> {
260 return hasUserRight(this.role, right)
261 }
262
263 + static checkLDAPUser (dn: string, password: string) {
264 + const client = ldap.createClient({ url: CONFIG.LDAP.URL })
265 +
266 + return new Promise(function (resolve, reject) {
267 + client.bind(dn, password, function (err) {
268 + resolve(!err)
269 + })
270 + })
271 + }
272 +
273 isPasswordMatch (password: string) {
274 - return comparePassword(password, this.password)
275 + if (this.ldapDn === null) {
276 + return comparePassword(password, this.password)
277 + } else {
278 + return UserModel.checkLDAPUser(this.ldapDn, password)
279 + }
280 }
281
282 toFormattedJSON (): User {
283 diff --git a/yarn.lock b/yarn.lock
284 index 1e759af1..1eb61a9f 100644
285 --- a/yarn.lock
286 +++ b/yarn.lock
287 @@ -674,6 +674,11 @@ asap@^2.0.0:
288 resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
289 integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
290
291 +asn1@0.2.3:
292 + version "0.2.3"
293 + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
294 + integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=
295 +
296 asn1@~0.2.3:
297 version "0.2.4"
298 resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
299 @@ -681,6 +686,11 @@ asn1@~0.2.3:
300 dependencies:
301 safer-buffer "~2.1.0"
302
303 +assert-plus@0.1.5:
304 + version "0.1.5"
305 + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160"
306 + integrity sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=
307 +
308 assert-plus@1.0.0, assert-plus@^1.0.0:
309 version "1.0.0"
310 resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
311 @@ -779,6 +789,13 @@ backo2@1.0.2:
312 resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
313 integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
314
315 +backoff@^2.5.0:
316 + version "2.5.0"
317 + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
318 + integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=
319 + dependencies:
320 + precond "0.2"
321 +
322 balanced-match@^1.0.0:
323 version "1.0.0"
324 resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
325 @@ -1186,6 +1203,16 @@ bull@^3.4.2:
326 semver "^5.6.0"
327 uuid "^3.2.1"
328
329 +bunyan@^1.8.3:
330 + version "1.8.12"
331 + resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797"
332 + integrity sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=
333 + optionalDependencies:
334 + dtrace-provider "~0.8"
335 + moment "^2.10.6"
336 + mv "~2"
337 + safe-json-stringify "~1"
338 +
339 busboy@^0.2.11:
340 version "0.2.14"
341 resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
342 @@ -1966,7 +1993,7 @@ d@1:
343 dependencies:
344 es5-ext "^0.10.9"
345
346 -dashdash@^1.12.0:
347 +dashdash@^1.12.0, dashdash@^1.14.0:
348 version "1.14.1"
349 resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
350 integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
351 @@ -2292,6 +2319,13 @@ double-ended-queue@^2.1.0-0:
352 resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
353 integrity sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=
354
355 +dtrace-provider@~0.8:
356 + version "0.8.7"
357 + resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.7.tgz#dc939b4d3e0620cfe0c1cd803d0d2d7ed04ffd04"
358 + integrity sha1-3JObTT4GIM/gwc2APQ0tftBP/QQ=
359 + dependencies:
360 + nan "^2.10.0"
361 +
362 duplexer3@^0.1.4:
363 version "0.1.4"
364 resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
365 @@ -2864,6 +2898,11 @@ extglob@^2.0.4:
366 snapdragon "^0.8.1"
367 to-regex "^3.0.1"
368
369 +extsprintf@1.2.0:
370 + version "1.2.0"
371 + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.2.0.tgz#5ad946c22f5b32ba7f8cd7426711c6e8a3fc2529"
372 + integrity sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=
373 +
374 extsprintf@1.3.0:
375 version "1.3.0"
376 resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
377 @@ -3350,6 +3389,17 @@ glob@7.1.2:
378 once "^1.3.0"
379 path-is-absolute "^1.0.0"
380
381 +glob@^6.0.1:
382 + version "6.0.4"
383 + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22"
384 + integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=
385 + dependencies:
386 + inflight "^1.0.4"
387 + inherits "2"
388 + minimatch "2 || 3"
389 + once "^1.3.0"
390 + path-is-absolute "^1.0.0"
391 +
392 glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1, glob@~7.1.2:
393 version "7.1.3"
394 resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
395 @@ -4522,6 +4572,30 @@ lcid@^2.0.0:
396 dependencies:
397 invert-kv "^2.0.0"
398
399 +ldap-filter@0.2.2:
400 + version "0.2.2"
401 + resolved "https://registry.yarnpkg.com/ldap-filter/-/ldap-filter-0.2.2.tgz#f2b842be0b86da3352798505b31ebcae590d77d0"
402 + integrity sha1-8rhCvguG2jNSeYUFsx68rlkNd9A=
403 + dependencies:
404 + assert-plus "0.1.5"
405 +
406 +ldapjs@^1.0.2:
407 + version "1.0.2"
408 + resolved "https://registry.yarnpkg.com/ldapjs/-/ldapjs-1.0.2.tgz#544ff7032b7b83c68f0701328d9297aa694340f9"
409 + integrity sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=
410 + dependencies:
411 + asn1 "0.2.3"
412 + assert-plus "^1.0.0"
413 + backoff "^2.5.0"
414 + bunyan "^1.8.3"
415 + dashdash "^1.14.0"
416 + ldap-filter "0.2.2"
417 + once "^1.4.0"
418 + vasync "^1.6.4"
419 + verror "^1.8.1"
420 + optionalDependencies:
421 + dtrace-provider "~0.8"
422 +
423 leven@^2.1.0:
424 version "2.1.0"
425 resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
426 @@ -5186,7 +5260,7 @@ minimalistic-assert@^1.0.1:
427 resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
428 integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
429
430 -minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2:
431 +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4, minimatch@~3.0.2:
432 version "3.0.4"
433 resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
434 integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
435 @@ -5299,6 +5373,11 @@ moment-timezone@^0.5.14, moment-timezone@^0.5.23:
436 resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
437 integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=
438
439 +moment@^2.10.6:
440 + version "2.24.0"
441 + resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
442 + integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
443 +
444 morgan@^1.5.3:
445 version "1.9.1"
446 resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59"
447 @@ -5394,6 +5473,15 @@ mute-stream@~0.0.4:
448 resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
449 integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
450
451 +mv@~2:
452 + version "2.1.1"
453 + resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2"
454 + integrity sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=
455 + dependencies:
456 + mkdirp "~0.5.1"
457 + ncp "~2.0.0"
458 + rimraf "~2.4.0"
459 +
460 nan@2.11.1, nan@^2.10.0, nan@^2.11.1, nan@^2.9.2:
461 version "2.11.1"
462 resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766"
463 @@ -5431,6 +5519,11 @@ ncp@1.0.x:
464 resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246"
465 integrity sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=
466
467 +ncp@~2.0.0:
468 + version "2.0.0"
469 + resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"
470 + integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=
471 +
472 needle@^2.2.1:
473 version "2.2.4"
474 resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e"
475 @@ -6520,6 +6613,11 @@ prebuild-install@^5.2.0:
476 tunnel-agent "^0.6.0"
477 which-pm-runs "^1.0.0"
478
479 +precond@0.2:
480 + version "0.2.3"
481 + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac"
482 + integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=
483 +
484 prelude-ls@~1.1.2:
485 version "1.1.2"
486 resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
487 @@ -7141,6 +7239,13 @@ rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.4.2, rimraf@^2.5.2, rimraf@^2.5
488 dependencies:
489 glob "^7.0.5"
490
491 +rimraf@~2.4.0:
492 + version "2.4.5"
493 + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da"
494 + integrity sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=
495 + dependencies:
496 + glob "^6.0.1"
497 +
498 run-async@^0.1.0:
499 version "0.1.0"
500 resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389"
501 @@ -7197,6 +7302,11 @@ safe-buffer@5.1.2, safe-buffer@^5.0.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, s
502 resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
503 integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
504
505 +safe-json-stringify@~1:
506 + version "1.2.0"
507 + resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd"
508 + integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==
509 +
510 safe-regex@^1.1.0:
511 version "1.1.0"
512 resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
513 @@ -8857,7 +8967,14 @@ vary@~1.0.1:
514 resolved "https://registry.yarnpkg.com/vary/-/vary-1.0.1.tgz#99e4981566a286118dfb2b817357df7993376d10"
515 integrity sha1-meSYFWaihhGN+yuBc1ffeZM3bRA=
516
517 -verror@1.10.0:
518 +vasync@^1.6.4:
519 + version "1.6.4"
520 + resolved "https://registry.yarnpkg.com/vasync/-/vasync-1.6.4.tgz#dfe93616ad0e7ae801b332a9d88bfc5cdc8e1d1f"
521 + integrity sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8=
522 + dependencies:
523 + verror "1.6.0"
524 +
525 +verror@1.10.0, verror@^1.8.1:
526 version "1.10.0"
527 resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
528 integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
529 @@ -8866,6 +8983,13 @@ verror@1.10.0:
530 core-util-is "1.0.2"
531 extsprintf "^1.2.0"
532
533 +verror@1.6.0:
534 + version "1.6.0"
535 + resolved "https://registry.yarnpkg.com/verror/-/verror-1.6.0.tgz#7d13b27b1facc2e2da90405eb5ea6e5bdd252ea5"
536 + integrity sha1-fROyex+swuLakEBetepuW90lLqU=
537 + dependencies:
538 + extsprintf "1.2.0"
539 +
540 videostream@^2.5.1:
541 version "2.6.0"
542 resolved "https://registry.yarnpkg.com/videostream/-/videostream-2.6.0.tgz#7f0b2b84bc457c12cfe599aa2345f5cc06241ab6"