diff options
-rw-r--r-- | client/src/app/core/server/server.service.ts | 3 | ||||
-rw-r--r-- | client/src/app/menu/menu.component.ts | 3 | ||||
-rw-r--r-- | config/default.yaml | 4 | ||||
-rw-r--r-- | config/production.yaml.example | 4 | ||||
-rw-r--r-- | package.json | 2 | ||||
-rw-r--r-- | server/controllers/api/config.ts | 6 | ||||
-rw-r--r-- | server/controllers/api/users.ts | 2 | ||||
-rw-r--r-- | server/helpers/utils.ts | 36 | ||||
-rw-r--r-- | server/initializers/checker.ts | 4 | ||||
-rw-r--r-- | server/initializers/constants.ts | 8 | ||||
-rw-r--r-- | server/middlewares/validators/users.ts | 19 | ||||
-rw-r--r-- | shared/models/server/server-config.model.ts | 3 | ||||
-rw-r--r-- | yarn.lock | 20 |
13 files changed, 105 insertions, 9 deletions
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index c5353023b..ccae5a151 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts | |||
@@ -34,7 +34,8 @@ export class ServerService { | |||
34 | }, | 34 | }, |
35 | serverVersion: 'Unknown', | 35 | serverVersion: 'Unknown', |
36 | signup: { | 36 | signup: { |
37 | allowed: false | 37 | allowed: false, |
38 | allowedForCurrentIP: false | ||
38 | }, | 39 | }, |
39 | transcoding: { | 40 | transcoding: { |
40 | enabledResolutions: [] | 41 | enabledResolutions: [] |
diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts index 4c35bb3a5..69216e215 100644 --- a/client/src/app/menu/menu.component.ts +++ b/client/src/app/menu/menu.component.ts | |||
@@ -52,7 +52,8 @@ export class MenuComponent implements OnInit { | |||
52 | } | 52 | } |
53 | 53 | ||
54 | isRegistrationAllowed () { | 54 | isRegistrationAllowed () { |
55 | return this.serverService.getConfig().signup.allowed | 55 | return this.serverService.getConfig().signup.allowed && |
56 | this.serverService.getConfig().signup.allowedForCurrentIP | ||
56 | } | 57 | } |
57 | 58 | ||
58 | getFirstAdminRightAvailable () { | 59 | getFirstAdminRightAvailable () { |
diff --git a/config/default.yaml b/config/default.yaml index 387acf43d..f43cbaf4b 100644 --- a/config/default.yaml +++ b/config/default.yaml | |||
@@ -60,6 +60,10 @@ admin: | |||
60 | signup: | 60 | signup: |
61 | enabled: false | 61 | enabled: false |
62 | limit: 10 # When the limit is reached, registrations are disabled. -1 == unlimited | 62 | limit: 10 # When the limit is reached, registrations are disabled. -1 == unlimited |
63 | filters: | ||
64 | cidr: # You can specify CIDR ranges to whitelist (empty = no filtering) or blacklist | ||
65 | whitelist: [] | ||
66 | blacklist: [] | ||
63 | 67 | ||
64 | user: | 68 | user: |
65 | # Default value of maximum video BYTES the user can upload (does not take into account transcoded files). | 69 | # Default value of maximum video BYTES the user can upload (does not take into account transcoded files). |
diff --git a/config/production.yaml.example b/config/production.yaml.example index 2f80beede..a9d2c3b80 100644 --- a/config/production.yaml.example +++ b/config/production.yaml.example | |||
@@ -76,6 +76,10 @@ admin: | |||
76 | signup: | 76 | signup: |
77 | enabled: false | 77 | enabled: false |
78 | limit: 10 # When the limit is reached, registrations are disabled. -1 == unlimited | 78 | limit: 10 # When the limit is reached, registrations are disabled. -1 == unlimited |
79 | filters: | ||
80 | cidr: # You can specify CIDR ranges to whitelist (empty = no filtering) or blacklist | ||
81 | whitelist: [] | ||
82 | blacklist: [] | ||
79 | 83 | ||
80 | user: | 84 | user: |
81 | # Default value of maximum video BYTES the user can upload (does not take into account transcoded files). | 85 | # Default value of maximum video BYTES the user can upload (does not take into account transcoded files). |
diff --git a/package.json b/package.json index 4123c55ec..bf69c4ce0 100644 --- a/package.json +++ b/package.json | |||
@@ -84,6 +84,8 @@ | |||
84 | "express-rate-limit": "^2.11.0", | 84 | "express-rate-limit": "^2.11.0", |
85 | "express-validator": "^5.0.0", | 85 | "express-validator": "^5.0.0", |
86 | "fluent-ffmpeg": "^2.1.0", | 86 | "fluent-ffmpeg": "^2.1.0", |
87 | "ipaddr.js": "https://github.com/whitequark/ipaddr.js.git#8e69afeb4053ee32447a101845f860848280eca5", | ||
88 | "is-cidr": "^2.0.5", | ||
87 | "iso-639-3": "^1.0.1", | 89 | "iso-639-3": "^1.0.1", |
88 | "js-yaml": "^3.5.4", | 90 | "js-yaml": "^3.5.4", |
89 | "jsonld": "^1.0.1", | 91 | "jsonld": "^1.0.1", |
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 12074a80e..f678e3c4a 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -4,7 +4,7 @@ import { ServerConfig, UserRight } from '../../../shared' | |||
4 | import { About } from '../../../shared/models/server/about.model' | 4 | import { About } from '../../../shared/models/server/about.model' |
5 | import { CustomConfig } from '../../../shared/models/server/custom-config.model' | 5 | import { CustomConfig } from '../../../shared/models/server/custom-config.model' |
6 | import { unlinkPromise, writeFilePromise } from '../../helpers/core-utils' | 6 | import { unlinkPromise, writeFilePromise } from '../../helpers/core-utils' |
7 | import { isSignupAllowed } from '../../helpers/utils' | 7 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/utils' |
8 | import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers' | 8 | import { CONFIG, CONSTRAINTS_FIELDS, reloadConfig } from '../../initializers' |
9 | import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' | 9 | import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../middlewares' |
10 | import { customConfigUpdateValidator } from '../../middlewares/validators/config' | 10 | import { customConfigUpdateValidator } from '../../middlewares/validators/config' |
@@ -36,6 +36,7 @@ configRouter.delete('/custom', | |||
36 | 36 | ||
37 | async function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) { | 37 | async function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) { |
38 | const allowed = await isSignupAllowed() | 38 | const allowed = await isSignupAllowed() |
39 | const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip) | ||
39 | 40 | ||
40 | const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS) | 41 | const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS) |
41 | .filter(key => CONFIG.TRANSCODING.RESOLUTIONS[key] === true) | 42 | .filter(key => CONFIG.TRANSCODING.RESOLUTIONS[key] === true) |
@@ -54,7 +55,8 @@ async function getConfig (req: express.Request, res: express.Response, next: exp | |||
54 | }, | 55 | }, |
55 | serverVersion: packageJSON.version, | 56 | serverVersion: packageJSON.version, |
56 | signup: { | 57 | signup: { |
57 | allowed | 58 | allowed, |
59 | allowedForCurrentIP | ||
58 | }, | 60 | }, |
59 | transcoding: { | 61 | transcoding: { |
60 | enabledResolutions | 62 | enabledResolutions |
diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts index 0a591f11d..8dff4b87c 100644 --- a/server/controllers/api/users.ts +++ b/server/controllers/api/users.ts | |||
@@ -19,6 +19,7 @@ import { | |||
19 | authenticate, | 19 | authenticate, |
20 | ensureUserHasRight, | 20 | ensureUserHasRight, |
21 | ensureUserRegistrationAllowed, | 21 | ensureUserRegistrationAllowed, |
22 | ensureUserRegistrationAllowedForIP, | ||
22 | paginationValidator, | 23 | paginationValidator, |
23 | setDefaultPagination, | 24 | setDefaultPagination, |
24 | setDefaultSort, | 25 | setDefaultSort, |
@@ -106,6 +107,7 @@ usersRouter.post('/', | |||
106 | 107 | ||
107 | usersRouter.post('/register', | 108 | usersRouter.post('/register', |
108 | asyncMiddleware(ensureUserRegistrationAllowed), | 109 | asyncMiddleware(ensureUserRegistrationAllowed), |
110 | ensureUserRegistrationAllowedForIP, | ||
109 | asyncMiddleware(usersRegisterValidator), | 111 | asyncMiddleware(usersRegisterValidator), |
110 | asyncMiddleware(registerUserRetryWrapper) | 112 | asyncMiddleware(registerUserRetryWrapper) |
111 | ) | 113 | ) |
diff --git a/server/helpers/utils.ts b/server/helpers/utils.ts index 058c3211e..e4556fa12 100644 --- a/server/helpers/utils.ts +++ b/server/helpers/utils.ts | |||
@@ -1,4 +1,6 @@ | |||
1 | import { Model } from 'sequelize-typescript' | 1 | import { Model } from 'sequelize-typescript' |
2 | import * as ipaddr from 'ipaddr.js' | ||
3 | const isCidr = require('is-cidr') | ||
2 | import { ResultList } from '../../shared' | 4 | import { ResultList } from '../../shared' |
3 | import { VideoResolution } from '../../shared/models/videos' | 5 | import { VideoResolution } from '../../shared/models/videos' |
4 | import { CONFIG } from '../initializers' | 6 | import { CONFIG } from '../initializers' |
@@ -48,6 +50,39 @@ async function isSignupAllowed () { | |||
48 | return totalUsers < CONFIG.SIGNUP.LIMIT | 50 | return totalUsers < CONFIG.SIGNUP.LIMIT |
49 | } | 51 | } |
50 | 52 | ||
53 | function isSignupAllowedForCurrentIP (ip: string) { | ||
54 | const addr = ipaddr.parse(ip) | ||
55 | let excludeList = [ 'blacklist' ] | ||
56 | let matched: string | ||
57 | |||
58 | // if there is a valid, non-empty whitelist, we exclude all unknown adresses too | ||
59 | if (CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr(cidr)).length > 0) { | ||
60 | excludeList.push('unknown') | ||
61 | } | ||
62 | |||
63 | if (addr.kind() === 'ipv4') { | ||
64 | const addrV4 = ipaddr.IPv4.parse(ip) | ||
65 | const rangeList = { | ||
66 | whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v4(cidr)) | ||
67 | .map(cidr => ipaddr.IPv4.parseCIDR(cidr)), | ||
68 | blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v4(cidr)) | ||
69 | .map(cidr => ipaddr.IPv4.parseCIDR(cidr)) | ||
70 | } | ||
71 | matched = ipaddr.subnetMatch(addrV4, rangeList, 'unknown') | ||
72 | } else if (addr.kind() === 'ipv6') { | ||
73 | const addrV6 = ipaddr.IPv6.parse(ip) | ||
74 | const rangeList = { | ||
75 | whitelist: CONFIG.SIGNUP.FILTERS.CIDR.WHITELIST.filter(cidr => isCidr.v6(cidr)) | ||
76 | .map(cidr => ipaddr.IPv6.parseCIDR(cidr)), | ||
77 | blacklist: CONFIG.SIGNUP.FILTERS.CIDR.BLACKLIST.filter(cidr => isCidr.v6(cidr)) | ||
78 | .map(cidr => ipaddr.IPv6.parseCIDR(cidr)) | ||
79 | } | ||
80 | matched = ipaddr.subnetMatch(addrV6, rangeList, 'unknown') | ||
81 | } | ||
82 | |||
83 | return !excludeList.includes(matched) | ||
84 | } | ||
85 | |||
51 | function computeResolutionsToTranscode (videoFileHeight: number) { | 86 | function computeResolutionsToTranscode (videoFileHeight: number) { |
52 | const resolutionsEnabled: number[] = [] | 87 | const resolutionsEnabled: number[] = [] |
53 | const configResolutions = CONFIG.TRANSCODING.RESOLUTIONS | 88 | const configResolutions = CONFIG.TRANSCODING.RESOLUTIONS |
@@ -99,6 +134,7 @@ export { | |||
99 | generateRandomString, | 134 | generateRandomString, |
100 | getFormattedObjects, | 135 | getFormattedObjects, |
101 | isSignupAllowed, | 136 | isSignupAllowed, |
137 | isSignupAllowedForCurrentIP, | ||
102 | computeResolutionsToTranscode, | 138 | computeResolutionsToTranscode, |
103 | resetSequelizeInstance, | 139 | resetSequelizeInstance, |
104 | getServerActor, | 140 | getServerActor, |
diff --git a/server/initializers/checker.ts b/server/initializers/checker.ts index 5a9c603b5..6259c7b6c 100644 --- a/server/initializers/checker.ts +++ b/server/initializers/checker.ts | |||
@@ -27,7 +27,9 @@ function checkMissedConfig () { | |||
27 | 'storage.avatars', 'storage.videos', 'storage.logs', 'storage.previews', 'storage.thumbnails', 'storage.torrents', 'storage.cache', | 27 | 'storage.avatars', 'storage.videos', 'storage.logs', 'storage.previews', 'storage.thumbnails', 'storage.torrents', 'storage.cache', |
28 | 'log.level', | 28 | 'log.level', |
29 | 'user.video_quota', | 29 | 'user.video_quota', |
30 | 'cache.previews.size', 'admin.email', 'signup.enabled', 'signup.limit', 'transcoding.enabled', 'transcoding.threads', | 30 | 'cache.previews.size', 'admin.email', |
31 | 'signup.enabled', 'signup.limit', 'signup.filters.cidr.whitelist', 'signup.filters.cidr.blacklist', | ||
32 | 'transcoding.enabled', 'transcoding.threads', | ||
31 | 'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route', | 33 | 'instance.name', 'instance.short_description', 'instance.description', 'instance.terms', 'instance.default_client_route', |
32 | 'instance.default_nsfw_policy', 'instance.robots', | 34 | 'instance.default_nsfw_policy', 'instance.robots', |
33 | 'services.twitter.username', 'services.twitter.whitelisted' | 35 | 'services.twitter.username', 'services.twitter.whitelisted' |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 424947590..a35306730 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -150,7 +150,13 @@ const CONFIG = { | |||
150 | }, | 150 | }, |
151 | SIGNUP: { | 151 | SIGNUP: { |
152 | get ENABLED () { return config.get<boolean>('signup.enabled') }, | 152 | get ENABLED () { return config.get<boolean>('signup.enabled') }, |
153 | get LIMIT () { return config.get<number>('signup.limit') } | 153 | get LIMIT () { return config.get<number>('signup.limit') }, |
154 | FILTERS: { | ||
155 | CIDR: { | ||
156 | get WHITELIST () { return config.get<string[]>('signup.filters.cidr.whitelist') }, | ||
157 | get BLACKLIST () { return config.get<string[]>('signup.filters.cidr.blacklist') } | ||
158 | } | ||
159 | } | ||
154 | }, | 160 | }, |
155 | USER: { | 161 | USER: { |
156 | get VIDEO_QUOTA () { return config.get<number>('user.video_quota') } | 162 | get VIDEO_QUOTA () { return config.get<number>('user.video_quota') } |
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index 247b704c4..4ad0e33da 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts | |||
@@ -16,8 +16,8 @@ import { | |||
16 | } from '../../helpers/custom-validators/users' | 16 | } from '../../helpers/custom-validators/users' |
17 | import { isVideoExist } from '../../helpers/custom-validators/videos' | 17 | import { isVideoExist } from '../../helpers/custom-validators/videos' |
18 | import { logger } from '../../helpers/logger' | 18 | import { logger } from '../../helpers/logger' |
19 | import { isSignupAllowed } from '../../helpers/utils' | 19 | import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../helpers/utils' |
20 | import { CONSTRAINTS_FIELDS } from '../../initializers' | 20 | import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers' |
21 | import { Redis } from '../../lib/redis' | 21 | import { Redis } from '../../lib/redis' |
22 | import { UserModel } from '../../models/account/user' | 22 | import { UserModel } from '../../models/account/user' |
23 | import { areValidationErrors } from './utils' | 23 | import { areValidationErrors } from './utils' |
@@ -177,6 +177,20 @@ const ensureUserRegistrationAllowed = [ | |||
177 | } | 177 | } |
178 | ] | 178 | ] |
179 | 179 | ||
180 | const ensureUserRegistrationAllowedForIP = [ | ||
181 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
182 | const allowed = isSignupAllowedForCurrentIP(req.ip) | ||
183 | |||
184 | if (allowed === false) { | ||
185 | return res.status(403) | ||
186 | .send({ error: 'You are not on a network authorized for registration.' }) | ||
187 | .end() | ||
188 | } | ||
189 | |||
190 | return next() | ||
191 | } | ||
192 | ] | ||
193 | |||
180 | const usersAskResetPasswordValidator = [ | 194 | const usersAskResetPasswordValidator = [ |
181 | body('email').isEmail().not().isEmpty().withMessage('Should have a valid email'), | 195 | body('email').isEmail().not().isEmpty().withMessage('Should have a valid email'), |
182 | 196 | ||
@@ -230,6 +244,7 @@ export { | |||
230 | usersUpdateMeValidator, | 244 | usersUpdateMeValidator, |
231 | usersVideoRatingValidator, | 245 | usersVideoRatingValidator, |
232 | ensureUserRegistrationAllowed, | 246 | ensureUserRegistrationAllowed, |
247 | ensureUserRegistrationAllowedForIP, | ||
233 | usersGetValidator, | 248 | usersGetValidator, |
234 | usersUpdateMyAvatarValidator, | 249 | usersUpdateMyAvatarValidator, |
235 | usersAskResetPasswordValidator, | 250 | usersAskResetPasswordValidator, |
diff --git a/shared/models/server/server-config.model.ts b/shared/models/server/server-config.model.ts index d1f956163..da0996dae 100644 --- a/shared/models/server/server-config.model.ts +++ b/shared/models/server/server-config.model.ts | |||
@@ -15,7 +15,8 @@ export interface ServerConfig { | |||
15 | } | 15 | } |
16 | 16 | ||
17 | signup: { | 17 | signup: { |
18 | allowed: boolean | 18 | allowed: boolean, |
19 | allowedForCurrentIP: boolean | ||
19 | } | 20 | } |
20 | 21 | ||
21 | transcoding: { | 22 | transcoding: { |
@@ -1294,6 +1294,12 @@ ci-info@^1.0.0: | |||
1294 | version "1.1.3" | 1294 | version "1.1.3" |
1295 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" | 1295 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" |
1296 | 1296 | ||
1297 | cidr-regex@^2.0.8: | ||
1298 | version "2.0.8" | ||
1299 | resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-2.0.8.tgz#c79bae6223d241c0860d93bfde1fb1c1c4fdcab6" | ||
1300 | dependencies: | ||
1301 | ip-regex "^2.1.0" | ||
1302 | |||
1297 | circular-json@^0.3.1: | 1303 | circular-json@^0.3.1: |
1298 | version "0.3.3" | 1304 | version "0.3.3" |
1299 | resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" | 1305 | resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" |
@@ -3671,6 +3677,10 @@ invert-kv@^1.0.0: | |||
3671 | version "1.0.0" | 3677 | version "1.0.0" |
3672 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" | 3678 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" |
3673 | 3679 | ||
3680 | ip-regex@^2.1.0: | ||
3681 | version "2.1.0" | ||
3682 | resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" | ||
3683 | |||
3674 | ip-set@^1.0.0: | 3684 | ip-set@^1.0.0: |
3675 | version "1.0.1" | 3685 | version "1.0.1" |
3676 | resolved "https://registry.yarnpkg.com/ip-set/-/ip-set-1.0.1.tgz#633b66d0bd6c8d0de968d053263c9120d3b6727e" | 3686 | resolved "https://registry.yarnpkg.com/ip-set/-/ip-set-1.0.1.tgz#633b66d0bd6c8d0de968d053263c9120d3b6727e" |
@@ -3693,6 +3703,10 @@ ipaddr.js@1.6.0: | |||
3693 | version "1.7.0" | 3703 | version "1.7.0" |
3694 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.7.0.tgz#2206ed334afc32e01fed3ee838b6b2521068b9d2" | 3704 | resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.7.0.tgz#2206ed334afc32e01fed3ee838b6b2521068b9d2" |
3695 | 3705 | ||
3706 | "ipaddr.js@https://github.com/whitequark/ipaddr.js.git#8e69afeb4053ee32447a101845f860848280eca5": | ||
3707 | version "1.7.0" | ||
3708 | resolved "https://github.com/whitequark/ipaddr.js.git#8e69afeb4053ee32447a101845f860848280eca5" | ||
3709 | |||
3696 | ipv6-normalize@^1.0.1: | 3710 | ipv6-normalize@^1.0.1: |
3697 | version "1.0.1" | 3711 | version "1.0.1" |
3698 | resolved "https://registry.yarnpkg.com/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz#1b3258290d365fa83239e89907dde4592e7620a8" | 3712 | resolved "https://registry.yarnpkg.com/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz#1b3258290d365fa83239e89907dde4592e7620a8" |
@@ -3747,6 +3761,12 @@ is-ci@^1.0.10, is-ci@^1.1.0: | |||
3747 | dependencies: | 3761 | dependencies: |
3748 | ci-info "^1.0.0" | 3762 | ci-info "^1.0.0" |
3749 | 3763 | ||
3764 | is-cidr@^2.0.5: | ||
3765 | version "2.0.5" | ||
3766 | resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-2.0.5.tgz#13227927d71865d1177fe0e5b60e6ddd3dee0034" | ||
3767 | dependencies: | ||
3768 | cidr-regex "^2.0.8" | ||
3769 | |||
3750 | is-data-descriptor@^0.1.4: | 3770 | is-data-descriptor@^0.1.4: |
3751 | version "0.1.4" | 3771 | version "0.1.4" |
3752 | resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" | 3772 | resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" |