]>
Commit | Line | Data |
---|---|---|
1 | commit ffb4a59047a014d6bb050b67a2fc7bc116be4682 | |
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 3260c62fc..dcce721b9 100644 | |
9 | --- a/config/default.yaml | |
10 | +++ b/config/default.yaml | |
11 | @@ -51,6 +51,19 @@ redis: | |
12 | auth: null | |
13 | db: 0 | |
14 | ||
15 | +auth: | |
16 | + local: | |
17 | + enabled: true | |
18 | + ldap: | |
19 | + enabled: true | |
20 | + url: ldap://localhost:389/dc=example,dc=com | |
21 | + insecure_tls: false | |
22 | + bind_dn: cn=admin,dc=example,dc=com | |
23 | + bind_password: adminPass | |
24 | + base: dc=example,dc=com | |
25 | + mail_entry: "mail" | |
26 | + user_filter: "(|(email=%username%)(uid=%username%))" | |
27 | + | |
28 | smtp: | |
29 | hostname: null | |
30 | port: 465 | |
31 | diff --git a/config/production.yaml.example b/config/production.yaml.example | |
32 | index 30cd2ffe0..c56691bf4 100644 | |
33 | --- a/config/production.yaml.example | |
34 | +++ b/config/production.yaml.example | |
35 | @@ -51,6 +51,19 @@ redis: | |
36 | auth: null | |
37 | db: 0 | |
38 | ||
39 | +auth: | |
40 | + local: | |
41 | + enabled: true | |
42 | + ldap: | |
43 | + enabled: true | |
44 | + url: ldap://localhost:389/dc=example,dc=com | |
45 | + insecure_tls: false | |
46 | + bind_dn: cn=admin,dc=example,dc=com | |
47 | + bind_password: adminPass | |
48 | + base: dc=example,dc=com | |
49 | + mail_entry: "mail" | |
50 | + user_filter: "(|(email=%username%)(uid=%username%))" | |
51 | + | |
52 | # SMTP server to send emails | |
53 | smtp: | |
54 | hostname: null | |
55 | diff --git a/package.json b/package.json | |
56 | index 49d9faf97..31eccf797 100644 | |
57 | --- a/package.json | |
58 | +++ b/package.json | |
59 | @@ -112,6 +112,7 @@ | |
60 | "iso-639-3": "^1.0.1", | |
61 | "js-yaml": "^3.5.4", | |
62 | "jsonld": "~2.0.1", | |
63 | + "ldapjs": "^1.0.2", | |
64 | "lodash": "^4.17.10", | |
65 | "lru-cache": "^5.1.1", | |
66 | "magnet-uri": "^5.1.4", | |
67 | diff --git a/server/initializers/config.ts b/server/initializers/config.ts | |
68 | index 7fd77f3e8..45a667826 100644 | |
69 | --- a/server/initializers/config.ts | |
70 | +++ b/server/initializers/config.ts | |
71 | @@ -34,6 +34,21 @@ const CONFIG = { | |
72 | AUTH: config.has('redis.auth') ? config.get<string>('redis.auth') : null, | |
73 | DB: config.has('redis.db') ? config.get<number>('redis.db') : null | |
74 | }, | |
75 | + AUTH: { | |
76 | + LOCAL: { | |
77 | + ENABLED: config.has('auth.local.enabled') ? config.get<boolean>('auth.local.enabled') : true, | |
78 | + }, | |
79 | + LDAP: { | |
80 | + ENABLED: config.has('auth.ldap.enabled') ? config.get<boolean>('auth.ldap.enabled') : false, | |
81 | + URL: config.has('auth.ldap.url') ? config.get<string>('auth.ldap.url') : null, | |
82 | + INSECURE_TLS: config.has('auth.ldap.insecure_tls') ? config.get<boolean>('auth.ldap.insecure_tls') : false, | |
83 | + BIND_DN: config.has('auth.ldap.bind_dn') ? config.get<string>('auth.ldap.bind_dn') : null, | |
84 | + BIND_PASSWORD: config.has('auth.ldap.bind_password') ? config.get<string>('auth.ldap.bind_password') : null, | |
85 | + BASE: config.has('auth.ldap.base') ? config.get<string>('auth.ldap.base') : null, | |
86 | + MAIL_ENTRY: config.has('auth.ldap.mail_entry') ? config.get<string>('auth.ldap.mail_entry') : 'mail', | |
87 | + USER_FILTER: config.has('auth.ldap.user_filter') ? config.get<string>('auth.ldap.user_filter') : null | |
88 | + }, | |
89 | + }, | |
90 | SMTP: { | |
91 | HOSTNAME: config.get<string>('smtp.hostname'), | |
92 | PORT: config.get<number>('smtp.port'), | |
93 | diff --git a/server/initializers/migrations/0375-user-ldap-dn.ts b/server/initializers/migrations/0375-user-ldap-dn.ts | |
94 | new file mode 100644 | |
95 | index 000000000..a9d68124b | |
96 | --- /dev/null | |
97 | +++ b/server/initializers/migrations/0375-user-ldap-dn.ts | |
98 | @@ -0,0 +1,26 @@ | |
99 | +import * as Sequelize from 'sequelize' | |
100 | + | |
101 | +async function up (utils: { | |
102 | + transaction: Sequelize.Transaction, | |
103 | + queryInterface: Sequelize.QueryInterface, | |
104 | + sequelize: Sequelize.Sequelize | |
105 | +}): Promise<void> { | |
106 | + | |
107 | + { | |
108 | + const data = { | |
109 | + type: Sequelize.STRING, | |
110 | + allowNull: true, | |
111 | + defaultValue: null | |
112 | + } | |
113 | + await utils.queryInterface.addColumn('user', 'ldapDn', data) | |
114 | + } | |
115 | +} | |
116 | + | |
117 | +function down (options) { | |
118 | + throw new Error('Not implemented.') | |
119 | +} | |
120 | + | |
121 | +export { | |
122 | + up, | |
123 | + down | |
124 | +} | |
125 | diff --git a/server/lib/ldap.ts b/server/lib/ldap.ts | |
126 | new file mode 100644 | |
127 | index 000000000..e6601e5cb | |
128 | --- /dev/null | |
129 | +++ b/server/lib/ldap.ts | |
130 | @@ -0,0 +1,89 @@ | |
131 | +import * as express from 'express' | |
132 | +import { createClient, Client, parseFilter } from 'ldapjs' | |
133 | +import { logger } from '../helpers/logger' | |
134 | +import { CONFIG } from '../initializers/config' | |
135 | + | |
136 | +class Ldap { | |
137 | + | |
138 | + private static instance: Ldap | |
139 | + private initialized = false | |
140 | + private client: Client | |
141 | + private prefix: string | |
142 | + | |
143 | + private constructor () {} | |
144 | + | |
145 | + init () { | |
146 | + // Already initialized | |
147 | + if (this.initialized === true) return | |
148 | + this.initialized = true | |
149 | + | |
150 | + this.client = createClient(Ldap.getLdapClientOptions()) | |
151 | + } | |
152 | + | |
153 | + static getLdapClientOptions () { | |
154 | + return Object.assign({}, { | |
155 | + url: CONFIG.AUTH.LDAP.URL, | |
156 | + reconnect: true, | |
157 | + tlsOptions: { rejectUnauthorized: !CONFIG.AUTH.LDAP.INSECURE_TLS } | |
158 | + }) | |
159 | + } | |
160 | + | |
161 | + getClient () { | |
162 | + this.init() | |
163 | + return this.client | |
164 | + } | |
165 | + | |
166 | + findUser (username: string) { | |
167 | + const filter = parseFilter(CONFIG.AUTH.LDAP.USER_FILTER) | |
168 | + filter.forEach(function (element) { | |
169 | + if (element.value === '%username%') element.value = username | |
170 | + }) | |
171 | + const opts = { | |
172 | + filter, | |
173 | + scope: 'sub', | |
174 | + attributes: [ CONFIG.AUTH.LDAP.MAIL_ENTRY, 'dn' ] | |
175 | + } | |
176 | + | |
177 | + const client = this.getClient() | |
178 | + | |
179 | + return new Promise(function (resolve, reject) { | |
180 | + client.bind(CONFIG.AUTH.LDAP.BIND_DN, CONFIG.AUTH.LDAP.BIND_PASSWORD, function (err) { | |
181 | + if (err) reject(err) | |
182 | + let entries = [] | |
183 | + client.search(CONFIG.AUTH.LDAP.BASE, opts, function (err, search) { | |
184 | + if (err) reject(err) | |
185 | + search.on('searchEntry', function (entry) { | |
186 | + entries.push(entry.object) | |
187 | + }) | |
188 | + search.on('end', function (result) { | |
189 | + if (entries.length === 1) { | |
190 | + resolve(entries[0]) | |
191 | + } else { | |
192 | + reject("No user found corresponding to this username") | |
193 | + } | |
194 | + }) | |
195 | + }) | |
196 | + }) | |
197 | + }) | |
198 | + } | |
199 | + | |
200 | + checkUser (dn: string, password: string) { | |
201 | + const client = this.getClient() | |
202 | + return new Promise(function (resolve, reject) { | |
203 | + client.bind(dn, password, function (err) { | |
204 | + resolve(!err) | |
205 | + }) | |
206 | + }) | |
207 | + } | |
208 | + | |
209 | + | |
210 | + static get Instance () { | |
211 | + return this.instance || (this.instance = new this()) | |
212 | + } | |
213 | +} | |
214 | + | |
215 | +// --------------------------------------------------------------------------- | |
216 | + | |
217 | +export { | |
218 | + Ldap | |
219 | +} | |
220 | diff --git a/server/lib/oauth-model.ts b/server/lib/oauth-model.ts | |
221 | index 086856f41..ab10effd0 100644 | |
222 | --- a/server/lib/oauth-model.ts | |
223 | +++ b/server/lib/oauth-model.ts | |
224 | @@ -9,6 +9,7 @@ import { Transaction } from 'sequelize' | |
225 | import { CONFIG } from '../initializers/config' | |
226 | import * as LRUCache from 'lru-cache' | |
227 | import { MOAuthTokenUser } from '@server/typings/models/oauth/oauth-token' | |
228 | +import { MUserDefault } from '@server/typings/models' | |
229 | ||
230 | type TokenInfo = { accessToken: string, refreshToken: string, accessTokenExpiresAt: Date, refreshTokenExpiresAt: Date } | |
231 | ||
232 | @@ -74,7 +75,13 @@ function getRefreshToken (refreshToken: string) { | |
233 | async function getUser (usernameOrEmail: string, password: string) { | |
234 | logger.debug('Getting User (username/email: ' + usernameOrEmail + ', password: ******).') | |
235 | ||
236 | - const user = await UserModel.loadByUsernameOrEmail(usernameOrEmail) | |
237 | + let user : MUserDefault | |
238 | + if (CONFIG.AUTH.LDAP.ENABLED) { | |
239 | + user = await UserModel.findOrCreateLDAPUser(usernameOrEmail) | |
240 | + } | |
241 | + if (!user && CONFIG.AUTH.LOCAL.ENABLED) { | |
242 | + user = await UserModel.loadByUsernameOrEmail(usernameOrEmail) | |
243 | + } | |
244 | if (!user) return null | |
245 | ||
246 | const passwordMatch = await user.isPasswordMatch(password) | |
247 | diff --git a/server/models/account/user.ts b/server/models/account/user.ts | |
248 | index 4c2c5e278..0b38f7cb2 100644 | |
249 | --- a/server/models/account/user.ts | |
250 | +++ b/server/models/account/user.ts | |
251 | @@ -1,4 +1,5 @@ | |
252 | import { FindOptions, literal, Op, QueryTypes, where, fn, col } from 'sequelize' | |
253 | +import { Ldap } from '../../lib/ldap' | |
254 | import { | |
255 | AfterDestroy, | |
256 | AfterUpdate, | |
257 | @@ -50,7 +51,9 @@ import { AccountModel } from './account' | |
258 | import { NSFWPolicyType } from '../../../shared/models/videos/nsfw-policy.type' | |
259 | import { values } from 'lodash' | |
260 | import { DEFAULT_THEME_NAME, DEFAULT_USER_THEME_NAME, NSFW_POLICY_TYPES } from '../../initializers/constants' | |
261 | +import { CONFIG } from '../../initializers/config' | |
262 | import { clearCacheByUserId } from '../../lib/oauth-model' | |
263 | +import { createUserAccountAndChannelAndPlaylist } from '../../lib/user' | |
264 | import { UserNotificationSettingModel } from './user-notification-setting' | |
265 | import { VideoModel } from '../video/video' | |
266 | import { ActorModel } from '../activitypub/actor' | |
267 | @@ -149,6 +152,11 @@ export class UserModel extends Model<UserModel> { | |
268 | @Column(DataType.STRING(400)) | |
269 | pendingEmail: string | |
270 | ||
271 | + @AllowNull(true) | |
272 | + @Default(null) | |
273 | + @Column | |
274 | + ldapDn: string | |
275 | + | |
276 | @AllowNull(true) | |
277 | @Default(null) | |
278 | @Is('UserEmailVerified', value => throwIfNotValid(value, isUserEmailVerifiedValid, 'email verified boolean', true)) | |
279 | @@ -440,6 +448,48 @@ export class UserModel extends Model<UserModel> { | |
280 | return UserModel.findOne(query) | |
281 | } | |
282 | ||
283 | + static loadByLdapDn (ldapDn: string) { | |
284 | + const query = { | |
285 | + where: { | |
286 | + ldapDn | |
287 | + } | |
288 | + } | |
289 | + | |
290 | + return UserModel.findOne(query) | |
291 | + } | |
292 | + | |
293 | + static async findOrCreateLDAPUser (username: string) { | |
294 | + try { | |
295 | + const userInfos = await Ldap.Instance.findUser(username) | |
296 | + const user = await UserModel.loadByLdapDn(userInfos['dn']) | |
297 | + if (user) { | |
298 | + return user | |
299 | + } else { | |
300 | + return await UserModel.createLDAPUser(username, userInfos) | |
301 | + } | |
302 | + } catch (e) { | |
303 | + return null | |
304 | + } | |
305 | + } | |
306 | + | |
307 | + static async createLDAPUser (username: string, userInfos: {}) { | |
308 | + const userToCreate = new UserModel({ | |
309 | + username, | |
310 | + password: 'SomeInvalidPassword', | |
311 | + email: userInfos[CONFIG.AUTH.LDAP.MAIL_ENTRY], | |
312 | + ldapDn: userInfos['dn'], | |
313 | + nsfwPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY, | |
314 | + autoPlayVideo: true, | |
315 | + role: UserRole.USER, | |
316 | + videoQuota: CONFIG.USER.VIDEO_QUOTA, | |
317 | + videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY, | |
318 | + emailVerified: true, | |
319 | + adminFlags: UserAdminFlag.NONE | |
320 | + }) | |
321 | + const { user } = await createUserAccountAndChannelAndPlaylist({ userToCreate }) | |
322 | + return user | |
323 | + } | |
324 | + | |
325 | static loadForMeAPI (username: string): Bluebird<MUserNotifSettingChannelDefault> { | |
326 | const query = { | |
327 | where: { | |
328 | @@ -627,7 +677,11 @@ export class UserModel extends Model<UserModel> { | |
329 | } | |
330 | ||
331 | isPasswordMatch (password: string) { | |
332 | - return comparePassword(password, this.password) | |
333 | + if (this.ldapDn === null) { | |
334 | + return comparePassword(password, this.password) | |
335 | + } else { | |
336 | + return Ldap.Instance.checkUser(this.ldapDn, password) | |
337 | + } | |
338 | } | |
339 | ||
340 | toFormattedJSON (this: MUserFormattable, parameters: { withAdminFlags?: boolean } = {}): User { | |
341 | diff --git a/yarn.lock b/yarn.lock | |
342 | index 76ce7ed27..f087746df 100644 | |
343 | --- a/yarn.lock | |
344 | +++ b/yarn.lock | |
345 | @@ -616,6 +616,11 @@ arraybuffer.slice@~0.0.7: | |
346 | resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" | |
347 | integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== | |
348 | ||
349 | +asn1@0.2.3: | |
350 | + version "0.2.3" | |
351 | + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" | |
352 | + integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y= | |
353 | + | |
354 | asn1@~0.2.3: | |
355 | version "0.2.4" | |
356 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" | |
357 | @@ -623,6 +628,11 @@ asn1@~0.2.3: | |
358 | dependencies: | |
359 | safer-buffer "~2.1.0" | |
360 | ||
361 | +assert-plus@0.1.5: | |
362 | + version "0.1.5" | |
363 | + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160" | |
364 | + integrity sha1-7nQAlBMALYTOxyGcasgRgS5yMWA= | |
365 | + | |
366 | assert-plus@1.0.0, assert-plus@^1.0.0: | |
367 | version "1.0.0" | |
368 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" | |
369 | @@ -692,6 +702,13 @@ backo2@1.0.2: | |
370 | resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" | |
371 | integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= | |
372 | ||
373 | +backoff@^2.5.0: | |
374 | + version "2.5.0" | |
375 | + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" | |
376 | + integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8= | |
377 | + dependencies: | |
378 | + precond "0.2" | |
379 | + | |
380 | balanced-match@^1.0.0: | |
381 | version "1.0.0" | |
382 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" | |
383 | @@ -1001,6 +1018,16 @@ bull@^3.4.2: | |
384 | util.promisify "^1.0.0" | |
385 | uuid "^3.3.3" | |
386 | ||
387 | +bunyan@^1.8.3: | |
388 | + version "1.8.12" | |
389 | + resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797" | |
390 | + integrity sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c= | |
391 | + optionalDependencies: | |
392 | + dtrace-provider "~0.8" | |
393 | + moment "^2.10.6" | |
394 | + mv "~2" | |
395 | + safe-json-stringify "~1" | |
396 | + | |
397 | busboy@^0.2.11: | |
398 | version "0.2.14" | |
399 | resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453" | |
400 | @@ -1619,7 +1646,7 @@ d@1, d@^1.0.1: | |
401 | es5-ext "^0.10.50" | |
402 | type "^1.0.1" | |
403 | ||
404 | -dashdash@^1.12.0: | |
405 | +dashdash@^1.12.0, dashdash@^1.14.0: | |
406 | version "1.14.1" | |
407 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" | |
408 | integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= | |
409 | @@ -1845,6 +1872,13 @@ double-ended-queue@^2.1.0-0: | |
410 | resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" | |
411 | integrity sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw= | |
412 | ||
413 | +dtrace-provider@~0.8: | |
414 | + version "0.8.8" | |
415 | + resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" | |
416 | + integrity sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg== | |
417 | + dependencies: | |
418 | + nan "^2.14.0" | |
419 | + | |
420 | duplexer3@^0.1.4: | |
421 | version "0.1.4" | |
422 | resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" | |
423 | @@ -2228,6 +2262,11 @@ extend@^3.0.0, extend@~3.0.0, extend@~3.0.2: | |
424 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" | |
425 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== | |
426 | ||
427 | +extsprintf@1.2.0: | |
428 | + version "1.2.0" | |
429 | + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.2.0.tgz#5ad946c22f5b32ba7f8cd7426711c6e8a3fc2529" | |
430 | + integrity sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk= | |
431 | + | |
432 | extsprintf@1.3.0: | |
433 | version "1.3.0" | |
434 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" | |
435 | @@ -2567,6 +2606,17 @@ glob@7.1.3: | |
436 | once "^1.3.0" | |
437 | path-is-absolute "^1.0.0" | |
438 | ||
439 | +glob@^6.0.1: | |
440 | + version "6.0.4" | |
441 | + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" | |
442 | + integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= | |
443 | + dependencies: | |
444 | + inflight "^1.0.4" | |
445 | + inherits "2" | |
446 | + minimatch "2 || 3" | |
447 | + once "^1.3.0" | |
448 | + path-is-absolute "^1.0.0" | |
449 | + | |
450 | glob@^7.0.3, glob@^7.1.1, glob@^7.1.3: | |
451 | version "7.1.6" | |
452 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" | |
453 | @@ -3356,6 +3406,30 @@ latest-version@^3.0.0: | |
454 | dependencies: | |
455 | package-json "^4.0.0" | |
456 | ||
457 | +ldap-filter@0.2.2: | |
458 | + version "0.2.2" | |
459 | + resolved "https://registry.yarnpkg.com/ldap-filter/-/ldap-filter-0.2.2.tgz#f2b842be0b86da3352798505b31ebcae590d77d0" | |
460 | + integrity sha1-8rhCvguG2jNSeYUFsx68rlkNd9A= | |
461 | + dependencies: | |
462 | + assert-plus "0.1.5" | |
463 | + | |
464 | +ldapjs@^1.0.2: | |
465 | + version "1.0.2" | |
466 | + resolved "https://registry.yarnpkg.com/ldapjs/-/ldapjs-1.0.2.tgz#544ff7032b7b83c68f0701328d9297aa694340f9" | |
467 | + integrity sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk= | |
468 | + dependencies: | |
469 | + asn1 "0.2.3" | |
470 | + assert-plus "^1.0.0" | |
471 | + backoff "^2.5.0" | |
472 | + bunyan "^1.8.3" | |
473 | + dashdash "^1.14.0" | |
474 | + ldap-filter "0.2.2" | |
475 | + once "^1.4.0" | |
476 | + vasync "^1.6.4" | |
477 | + verror "^1.8.1" | |
478 | + optionalDependencies: | |
479 | + dtrace-provider "~0.8" | |
480 | + | |
481 | libxmljs@0.19.7: | |
482 | version "0.19.7" | |
483 | resolved "https://registry.yarnpkg.com/libxmljs/-/libxmljs-0.19.7.tgz#96c2151b0b73f33dd29917edec82902587004e5a" | |
484 | @@ -3724,7 +3798,7 @@ mimic-response@^2.0.0: | |
485 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" | |
486 | integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== | |
487 | ||
488 | -minimatch@3.0.4, minimatch@^3.0.4: | |
489 | +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: | |
490 | version "3.0.4" | |
491 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" | |
492 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== | |
493 | @@ -3825,7 +3899,7 @@ moment-timezone@^0.5.21, moment-timezone@^0.5.25: | |
494 | dependencies: | |
495 | moment ">= 2.9.0" | |
496 | ||
497 | -"moment@>= 2.9.0", moment@^2.24.0: | |
498 | +"moment@>= 2.9.0", moment@^2.10.6, moment@^2.24.0: | |
499 | version "2.24.0" | |
500 | resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" | |
501 | integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== | |
502 | @@ -3898,6 +3972,15 @@ mute-stream@~0.0.4: | |
503 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" | |
504 | integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== | |
505 | ||
506 | +mv@~2: | |
507 | + version "2.1.1" | |
508 | + resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" | |
509 | + integrity sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI= | |
510 | + dependencies: | |
511 | + mkdirp "~0.5.1" | |
512 | + ncp "~2.0.0" | |
513 | + rimraf "~2.4.0" | |
514 | + | |
515 | nan@2.14.0, nan@^2.14.0, nan@~2.14.0: | |
516 | version "2.14.0" | |
517 | resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" | |
518 | @@ -3913,6 +3996,11 @@ ncp@1.0.x: | |
519 | resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" | |
520 | integrity sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY= | |
521 | ||
522 | +ncp@~2.0.0: | |
523 | + version "2.0.0" | |
524 | + resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" | |
525 | + integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= | |
526 | + | |
527 | needle@^2.2.1: | |
528 | version "2.4.0" | |
529 | resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" | |
530 | @@ -4597,6 +4685,11 @@ prebuild-install@^5.3.3: | |
531 | tunnel-agent "^0.6.0" | |
532 | which-pm-runs "^1.0.0" | |
533 | ||
534 | +precond@0.2: | |
535 | + version "0.2.3" | |
536 | + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" | |
537 | + integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= | |
538 | + | |
539 | prepend-http@^1.0.1: | |
540 | version "1.0.4" | |
541 | resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" | |
542 | @@ -5032,6 +5125,13 @@ rimraf@^3.0.0: | |
543 | dependencies: | |
544 | glob "^7.1.3" | |
545 | ||
546 | +rimraf@~2.4.0: | |
547 | + version "2.4.5" | |
548 | + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" | |
549 | + integrity sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto= | |
550 | + dependencies: | |
551 | + glob "^6.0.1" | |
552 | + | |
553 | run-parallel-limit@^1.0.3: | |
554 | version "1.0.5" | |
555 | resolved "https://registry.yarnpkg.com/run-parallel-limit/-/run-parallel-limit-1.0.5.tgz#c29a4fd17b4df358cb52a8a697811a63c984f1b7" | |
556 | @@ -5069,6 +5169,11 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, | |
557 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" | |
558 | integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== | |
559 | ||
560 | +safe-json-stringify@~1: | |
561 | + version "1.2.0" | |
562 | + resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" | |
563 | + integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== | |
564 | + | |
565 | "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: | |
566 | version "2.1.2" | |
567 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" | |
568 | @@ -6337,7 +6442,14 @@ vary@^1, vary@~1.1.2: | |
569 | resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" | |
570 | integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= | |
571 | ||
572 | -verror@1.10.0: | |
573 | +vasync@^1.6.4: | |
574 | + version "1.6.4" | |
575 | + resolved "https://registry.yarnpkg.com/vasync/-/vasync-1.6.4.tgz#dfe93616ad0e7ae801b332a9d88bfc5cdc8e1d1f" | |
576 | + integrity sha1-3+k2Fq0OeugBszKp2Iv8XNyOHR8= | |
577 | + dependencies: | |
578 | + verror "1.6.0" | |
579 | + | |
580 | +verror@1.10.0, verror@^1.8.1: | |
581 | version "1.10.0" | |
582 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" | |
583 | integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= | |
584 | @@ -6346,6 +6458,13 @@ verror@1.10.0: | |
585 | core-util-is "1.0.2" | |
586 | extsprintf "^1.2.0" | |
587 | ||
588 | +verror@1.6.0: | |
589 | + version "1.6.0" | |
590 | + resolved "https://registry.yarnpkg.com/verror/-/verror-1.6.0.tgz#7d13b27b1facc2e2da90405eb5ea6e5bdd252ea5" | |
591 | + integrity sha1-fROyex+swuLakEBetepuW90lLqU= | |
592 | + dependencies: | |
593 | + extsprintf "1.2.0" | |
594 | + | |
595 | videostream@^3.2.0: | |
596 | version "3.2.1" | |
597 | resolved "https://registry.yarnpkg.com/videostream/-/videostream-3.2.1.tgz#643688ad4bfbf37570d421e3196b7e0ad38eeebc" |