feat: improve email validation
This commit is contained in:
		
							parent
							
								
									a28c515ef6
								
							
						
					
					
						commit
						68192126e6
					
				
					 9 changed files with 188 additions and 26 deletions
				
			
		|  | @ -11,6 +11,7 @@ | |||
| 
 | ||||
| ### Improvements | ||||
| - フォロー/フォロワーを非公開にできるように | ||||
| - メールアドレスのバリデーションを強化 | ||||
| 
 | ||||
| ### Bugfixes | ||||
| - クライアント: 長いメニューが画面からはみ出す問題を修正 | ||||
|  |  | |||
|  | @ -807,6 +807,13 @@ unmuteThread: "スレッドのミュートを解除" | |||
| ffVisibility: "つながりの公開範囲" | ||||
| ffVisibilityDescription: "自分のフォロー/フォロワー情報の公開範囲を設定できます。" | ||||
| 
 | ||||
| _emailUnavailable: | ||||
|   used: "既に使用されています" | ||||
|   format: "形式が正しくありません" | ||||
|   disposable: "恒久的に使用可能なアドレスではありません" | ||||
|   mx: "正しいメールサーバーではありません" | ||||
|   smtp: "メールサーバーが応答しません" | ||||
| 
 | ||||
| _ffVisibility: | ||||
|   public: "公開" | ||||
|   followers: "フォロワーだけに公開" | ||||
|  |  | |||
|  | @ -130,6 +130,7 @@ | |||
| 		"cssnano": "5.0.8", | ||||
| 		"date-fns": "2.25.0", | ||||
| 		"dateformat": "4.5.1", | ||||
| 		"deep-email-validator": "0.1.18", | ||||
| 		"escape-regexp": "0.0.1", | ||||
| 		"eslint": "8.1.0", | ||||
| 		"eslint-plugin-vue": "7.20.0", | ||||
|  |  | |||
|  | @ -19,12 +19,17 @@ | |||
| 				<span v-else-if="usernameState === 'max-range'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.tooLong }}</span> | ||||
| 			</template> | ||||
| 		</MkInput> | ||||
| 		<MkInput v-if="meta.emailRequiredForSignup" class="_formBlock" v-model="email" type="email" :autocomplete="Math.random()" spellcheck="false" required @update:modelValue="onChangeEmail" data-cy-signup-email> | ||||
| 		<MkInput v-if="meta.emailRequiredForSignup" class="_formBlock" v-model="email" :debounce="true" type="email" :autocomplete="Math.random()" spellcheck="false" required @update:modelValue="onChangeEmail" data-cy-signup-email> | ||||
| 			<template #label>{{ $ts.emailAddress }} <div class="_button _help" v-tooltip:dialog="$ts._signup.emailAddressInfo"><i class="far fa-question-circle"></i></div></template> | ||||
| 			<template #prefix><i class="fas fa-envelope"></i></template> | ||||
| 			<template #caption> | ||||
| 				<span v-if="emailState === 'wait'" style="color:#999"><i class="fas fa-spinner fa-pulse fa-fw"></i> {{ $ts.checking }}</span> | ||||
| 				<span v-else-if="emailState === 'ok'" style="color: var(--success)"><i class="fas fa-check fa-fw"></i> {{ $ts.available }}</span> | ||||
| 				<span v-else-if="emailState === 'unavailable:used'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts._emailUnavailable.used }}</span> | ||||
| 				<span v-else-if="emailState === 'unavailable:format'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts._emailUnavailable.format }}</span> | ||||
| 				<span v-else-if="emailState === 'unavailable:disposable'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts._emailUnavailable.disposable }}</span> | ||||
| 				<span v-else-if="emailState === 'unavailable:mx'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts._emailUnavailable.mx }}</span> | ||||
| 				<span v-else-if="emailState === 'unavailable:smtp'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts._emailUnavailable.smtp }}</span> | ||||
| 				<span v-else-if="emailState === 'unavailable'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.unavailable }}</span> | ||||
| 				<span v-else-if="emailState === 'error'" style="color: var(--error)"><i class="fas fa-exclamation-triangle fa-fw"></i> {{ $ts.error }}</span> | ||||
| 			</template> | ||||
|  | @ -171,7 +176,13 @@ export default defineComponent({ | |||
| 			os.api('email-address/available', { | ||||
| 				emailAddress: this.email | ||||
| 			}).then(result => { | ||||
| 				this.emailState = result.available ? 'ok' : 'unavailable'; | ||||
| 				this.emailState = result.available ? 'ok' : | ||||
| 					result.reason === 'used' ? 'unavailable:used' : | ||||
| 					result.reason === 'format' ? 'unavailable:format' : | ||||
| 					result.reason === 'disposable' ? 'unavailable:disposable' : | ||||
| 					result.reason === 'mx' ? 'unavailable:mx' : | ||||
| 					result.reason === 'smtp' ? 'unavailable:smtp' : | ||||
| 					'unavailable'; | ||||
| 			}).catch(err => { | ||||
| 				this.emailState = 'error'; | ||||
| 			}); | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import $ from 'cafy'; | ||||
| import define from '../../define'; | ||||
| import { UserProfiles } from '@/models/index'; | ||||
| import { validateEmailForAccount } from '@/services/validate-email-for-account'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	tags: ['users'], | ||||
|  | @ -20,18 +20,15 @@ export const meta = { | |||
| 			available: { | ||||
| 				type: 'boolean' as const, | ||||
| 				optional: false as const, nullable: false as const, | ||||
| 			} | ||||
| 			}, | ||||
| 			reason: { | ||||
| 				type: 'string' as const, | ||||
| 				optional: false as const, nullable: true as const, | ||||
| 			}, | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| export default define(meta, async (ps) => { | ||||
| 	const exist = await UserProfiles.count({ | ||||
| 		emailVerified: true, | ||||
| 		email: ps.emailAddress, | ||||
| 	}); | ||||
| 
 | ||||
| 	return { | ||||
| 		available: exist === 0 | ||||
| 	}; | ||||
| 	return await validateEmailForAccount(ps.emailAddress); | ||||
| }); | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import * as bcrypt from 'bcryptjs'; | |||
| import { Users, UserProfiles } from '@/models/index'; | ||||
| import { sendEmail } from '@/services/send-email'; | ||||
| import { ApiError } from '../../error'; | ||||
| import { validateEmailForAccount } from '@/services/validate-email-for-account'; | ||||
| 
 | ||||
| export const meta = { | ||||
| 	requireCredential: true as const, | ||||
|  | @ -35,6 +36,12 @@ export const meta = { | |||
| 			code: 'INCORRECT_PASSWORD', | ||||
| 			id: 'e54c1d7e-e7d6-4103-86b6-0a95069b4ad3' | ||||
| 		}, | ||||
| 
 | ||||
| 		unavailable: { | ||||
| 			message: 'Unavailable email address.', | ||||
| 			code: 'UNAVAILABLE', | ||||
| 			id: 'a2defefb-f220-8849-0af6-17f816099323' | ||||
| 		}, | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
|  | @ -48,6 +55,13 @@ export default define(meta, async (ps, user) => { | |||
| 		throw new ApiError(meta.errors.incorrectPassword); | ||||
| 	} | ||||
| 
 | ||||
| 	if (ps.email != null) { | ||||
| 		const available = await validateEmailForAccount(ps.email); | ||||
| 		if (!available) { | ||||
| 			throw new ApiError(meta.errors.unavailable); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	await UserProfiles.update(user.id, { | ||||
| 		email: ps.email, | ||||
| 		emailVerified: false, | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import { signup } from '../common/signup'; | |||
| import config from '@/config'; | ||||
| import { sendEmail } from '@/services/send-email'; | ||||
| import { genId } from '@/misc/gen-id'; | ||||
| import { validateEmailForAccount } from '@/services/validate-email-for-account'; | ||||
| 
 | ||||
| export default async (ctx: Koa.Context) => { | ||||
| 	const body = ctx.request.body; | ||||
|  | @ -41,6 +42,12 @@ export default async (ctx: Koa.Context) => { | |||
| 			ctx.status = 400; | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		const available = await validateEmailForAccount(emailAddress); | ||||
| 		if (!available) { | ||||
| 			ctx.status = 400; | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (instance.disableRegistration) { | ||||
|  |  | |||
							
								
								
									
										34
									
								
								src/services/validate-email-for-account.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/services/validate-email-for-account.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| import validateEmail from 'deep-email-validator'; | ||||
| import { UserProfiles } from '@/models'; | ||||
| 
 | ||||
| export async function validateEmailForAccount(emailAddress: string): Promise<{ | ||||
| 	available: boolean; | ||||
| 	reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp'; | ||||
| }> { | ||||
| 	const exist = await UserProfiles.count({ | ||||
| 		emailVerified: true, | ||||
| 		email: emailAddress, | ||||
| 	}); | ||||
| 
 | ||||
| 	const validated = await validateEmail({ | ||||
| 		email: emailAddress, | ||||
| 		validateRegex: true, | ||||
| 		validateMx: true, | ||||
| 		validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
 | ||||
| 		validateDisposable: true, // 捨てアドかどうかチェック
 | ||||
| 		validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
 | ||||
| 	}); | ||||
| 
 | ||||
| 	const available = exist === 0 && validated.valid; | ||||
| 
 | ||||
| 	return { | ||||
| 		available, | ||||
| 		reason: available ? null : | ||||
| 			exist !== 0 ? 'used' : | ||||
| 			validated.reason === 'regex' ? 'format' : | ||||
| 			validated.reason === 'disposable' ? 'disposable' : | ||||
| 			validated.reason === 'mx' ? 'mx' : | ||||
| 			validated.reason === 'smtp' ? 'smtp' : | ||||
| 			null, | ||||
| 	}; | ||||
| } | ||||
							
								
								
									
										118
									
								
								yarn.lock
									
										
									
									
									
								
							
							
						
						
									
										118
									
								
								yarn.lock
									
										
									
									
									
								
							|  | @ -513,6 +513,11 @@ | |||
|   resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-3.0.1.tgz#98d747a2e5e9a56070c6bf14e27bff56204e34cc" | ||||
|   integrity sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g== | ||||
| 
 | ||||
| "@types/disposable-email-domains@^1.0.1": | ||||
|   version "1.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/@types/disposable-email-domains/-/disposable-email-domains-1.0.2.tgz#0280f6b38fa7f14e54b056a434135ecd254483b1" | ||||
|   integrity sha512-SDKwyYTjk3y5aZBxxc38yRecpJPjsqn57STz1bNxYYlv4k11bBe7QB8w4llXDTmQXKT1mFvgGmJv+8Zdu3YmJw== | ||||
| 
 | ||||
| "@types/escape-regexp@0.0.0": | ||||
|   version "0.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/@types/escape-regexp/-/escape-regexp-0.0.0.tgz#bff0225f9ef30d0dbdbe0e2a24283ee5342990c3" | ||||
|  | @ -2081,6 +2086,13 @@ aws4@^1.8.0: | |||
|   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" | ||||
|   integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== | ||||
| 
 | ||||
| axios@^0.19.2: | ||||
|   version "0.19.2" | ||||
|   resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" | ||||
|   integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== | ||||
|   dependencies: | ||||
|     follow-redirects "1.5.10" | ||||
| 
 | ||||
| axios@^0.21.1: | ||||
|   version "0.21.1" | ||||
|   resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" | ||||
|  | @ -2310,6 +2322,13 @@ browserslist@^4.16.6: | |||
|     escalade "^3.1.1" | ||||
|     node-releases "^1.1.71" | ||||
| 
 | ||||
| bs-logger@0.x: | ||||
|   version "0.2.6" | ||||
|   resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" | ||||
|   integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== | ||||
|   dependencies: | ||||
|     fast-json-stable-stringify "2.x" | ||||
| 
 | ||||
| buffer-alloc-unsafe@^1.1.0: | ||||
|   version "1.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" | ||||
|  | @ -2343,6 +2362,11 @@ buffer-fill@^1.0.0: | |||
|   resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" | ||||
|   integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= | ||||
| 
 | ||||
| buffer-from@1.x: | ||||
|   version "1.1.2" | ||||
|   resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" | ||||
|   integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== | ||||
| 
 | ||||
| buffer-from@^1.0.0, buffer-from@^1.1.1: | ||||
|   version "1.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" | ||||
|  | @ -3631,6 +3655,13 @@ debug@4.3.2, debug@^4.3.2: | |||
|   dependencies: | ||||
|     ms "2.1.2" | ||||
| 
 | ||||
| debug@=3.1.0, debug@~3.1.0: | ||||
|   version "3.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" | ||||
|   integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== | ||||
|   dependencies: | ||||
|     ms "2.0.0" | ||||
| 
 | ||||
| debug@^3.1.0: | ||||
|   version "3.2.7" | ||||
|   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" | ||||
|  | @ -3645,13 +3676,6 @@ debug@^3.2.6: | |||
|   dependencies: | ||||
|     ms "^2.1.1" | ||||
| 
 | ||||
| debug@~3.1.0: | ||||
|   version "3.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" | ||||
|   integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== | ||||
|   dependencies: | ||||
|     ms "2.0.0" | ||||
| 
 | ||||
| debuglog@^1.0.0: | ||||
|   version "1.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" | ||||
|  | @ -3691,6 +3715,18 @@ decompress-response@^6.0.0: | |||
|   dependencies: | ||||
|     mimic-response "^3.1.0" | ||||
| 
 | ||||
| deep-email-validator@0.1.18: | ||||
|   version "0.1.18" | ||||
|   resolved "https://registry.yarnpkg.com/deep-email-validator/-/deep-email-validator-0.1.18.tgz#a072a93f28e11863cc6b9ca3ae964e0e45b3ece8" | ||||
|   integrity sha512-eo2WEUidQvppg6Qdek8iwOqmXvaxRJ2D2VJKbIOwUgLZNFveDDdJMBsFc+yq0S+lILEUcmzrJRrCWbyoe7QUzQ== | ||||
|   dependencies: | ||||
|     "@types/disposable-email-domains" "^1.0.1" | ||||
|     axios "^0.19.2" | ||||
|     disposable-email-domains "^1.0.53" | ||||
|     lodash "^4.17.15" | ||||
|     mailcheck "^1.1.1" | ||||
|     ts-jest "^25.2.1" | ||||
| 
 | ||||
| deep-equal@~1.0.1: | ||||
|   version "1.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" | ||||
|  | @ -3842,6 +3878,11 @@ dir-glob@^3.0.1: | |||
|   dependencies: | ||||
|     path-type "^4.0.0" | ||||
| 
 | ||||
| disposable-email-domains@^1.0.53: | ||||
|   version "1.0.58" | ||||
|   resolved "https://registry.yarnpkg.com/disposable-email-domains/-/disposable-email-domains-1.0.58.tgz#ac9c879c02c4f0898bfb6c0c80b959c0b0b7bc51" | ||||
|   integrity sha512-frnNCPqTjk6t/sosPoco6EIFHbP9SazHQkeltJNfZeUyNgewaVf+kFjEfVkVDVd436Vln43YElJPb8JozhBs7Q== | ||||
| 
 | ||||
| doctrine@^3.0.0: | ||||
|   version "3.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" | ||||
|  | @ -4609,7 +4650,7 @@ fast-glob@^3.1.1: | |||
|     micromatch "^4.0.2" | ||||
|     picomatch "^2.2.1" | ||||
| 
 | ||||
| fast-json-stable-stringify@^2.0.0: | ||||
| fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: | ||||
|   version "2.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" | ||||
|   integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== | ||||
|  | @ -4824,6 +4865,13 @@ flush-write-stream@^1.0.2: | |||
|     inherits "^2.0.3" | ||||
|     readable-stream "^2.3.6" | ||||
| 
 | ||||
| follow-redirects@1.5.10: | ||||
|   version "1.5.10" | ||||
|   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" | ||||
|   integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== | ||||
|   dependencies: | ||||
|     debug "=3.1.0" | ||||
| 
 | ||||
| follow-redirects@^1.10.0: | ||||
|   version "1.14.1" | ||||
|   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.1.tgz#d9114ded0a1cfdd334e164e6662ad02bfd91ff43" | ||||
|  | @ -6386,7 +6434,7 @@ json5-loader@4.0.1: | |||
|     loader-utils "^2.0.0" | ||||
|     schema-utils "^3.0.0" | ||||
| 
 | ||||
| json5@2.2.0: | ||||
| json5@2.2.0, json5@2.x: | ||||
|   version "2.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" | ||||
|   integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== | ||||
|  | @ -6912,7 +6960,7 @@ lodash.map@^4.4.0: | |||
|   resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" | ||||
|   integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= | ||||
| 
 | ||||
| lodash.memoize@^4.1.2: | ||||
| lodash.memoize@4.x, lodash.memoize@^4.1.2: | ||||
|   version "4.1.2" | ||||
|   resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" | ||||
|   integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= | ||||
|  | @ -6957,7 +7005,7 @@ lodash.uniq@^4.5.0: | |||
|   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" | ||||
|   integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= | ||||
| 
 | ||||
| lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0: | ||||
| lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0: | ||||
|   version "4.17.21" | ||||
|   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" | ||||
|   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== | ||||
|  | @ -7014,7 +7062,12 @@ magic-string@^0.25.7: | |||
|   dependencies: | ||||
|     sourcemap-codec "^1.4.4" | ||||
| 
 | ||||
| make-error@^1.1.1: | ||||
| mailcheck@^1.1.1: | ||||
|   version "1.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/mailcheck/-/mailcheck-1.1.1.tgz#d87cf6ba0b64ba512199dbf93f1489f479591e34" | ||||
|   integrity sha1-2Hz2ugtkulEhmdv5PxSJ9HlZHjQ= | ||||
| 
 | ||||
| make-error@1.x, make-error@^1.1.1: | ||||
|   version "1.3.6" | ||||
|   resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" | ||||
|   integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== | ||||
|  | @ -7152,6 +7205,14 @@ mfm-js@0.20.0: | |||
|   dependencies: | ||||
|     twemoji-parser "13.1.x" | ||||
| 
 | ||||
| micromatch@4.x: | ||||
|   version "4.0.4" | ||||
|   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" | ||||
|   integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== | ||||
|   dependencies: | ||||
|     braces "^3.0.1" | ||||
|     picomatch "^2.2.3" | ||||
| 
 | ||||
| micromatch@^3.0.4, micromatch@^3.1.4: | ||||
|   version "3.1.10" | ||||
|   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" | ||||
|  | @ -7321,7 +7382,7 @@ mkdirp-classic@^0.5.3: | |||
|   resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" | ||||
|   integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== | ||||
| 
 | ||||
| mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@~0.5.1: | ||||
| mkdirp@0.x, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@~0.5.1: | ||||
|   version "0.5.5" | ||||
|   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" | ||||
|   integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== | ||||
|  | @ -8234,6 +8295,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7, picomatch@^2.2.1: | |||
|   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" | ||||
|   integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== | ||||
| 
 | ||||
| picomatch@^2.2.3: | ||||
|   version "2.3.0" | ||||
|   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" | ||||
|   integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== | ||||
| 
 | ||||
| pify@^2.0.0, pify@^2.2.0: | ||||
|   version "2.3.0" | ||||
|   resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" | ||||
|  | @ -9825,7 +9891,7 @@ semver-greatest-satisfied-range@^1.1.0: | |||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" | ||||
|   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== | ||||
| 
 | ||||
| semver@^6.3.0: | ||||
| semver@6.x, semver@^6.3.0: | ||||
|   version "6.3.0" | ||||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" | ||||
|   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== | ||||
|  | @ -10904,6 +10970,22 @@ tree-kill@^1.2.2: | |||
|   resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" | ||||
|   integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== | ||||
| 
 | ||||
| ts-jest@^25.2.1: | ||||
|   version "25.5.1" | ||||
|   resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-25.5.1.tgz#2913afd08f28385d54f2f4e828be4d261f4337c7" | ||||
|   integrity sha512-kHEUlZMK8fn8vkxDjwbHlxXRB9dHYpyzqKIGDNxbzs+Rz+ssNDSDNusEK8Fk/sDd4xE6iKoQLfFkFVaskmTJyw== | ||||
|   dependencies: | ||||
|     bs-logger "0.x" | ||||
|     buffer-from "1.x" | ||||
|     fast-json-stable-stringify "2.x" | ||||
|     json5 "2.x" | ||||
|     lodash.memoize "4.x" | ||||
|     make-error "1.x" | ||||
|     micromatch "4.x" | ||||
|     mkdirp "0.x" | ||||
|     semver "6.x" | ||||
|     yargs-parser "18.x" | ||||
| 
 | ||||
| ts-loader@9.2.6: | ||||
|   version "9.2.6" | ||||
|   resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" | ||||
|  | @ -11934,6 +12016,14 @@ yargonaut@^1.1.4: | |||
|     figlet "^1.1.1" | ||||
|     parent-require "^1.0.0" | ||||
| 
 | ||||
| yargs-parser@18.x: | ||||
|   version "18.1.3" | ||||
|   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" | ||||
|   integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== | ||||
|   dependencies: | ||||
|     camelcase "^5.0.0" | ||||
|     decamelize "^1.2.0" | ||||
| 
 | ||||
| yargs-parser@20.2.4, yargs-parser@^20.2.2: | ||||
|   version "20.2.4" | ||||
|   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue