feat(new tool): IPv4/6 in IP Range

This commit is contained in:
sharevb 2024-04-20 22:19:59 +02:00 committed by ShareVB
parent 80e46c9292
commit 9501a60dc0
5 changed files with 127 additions and 7 deletions

View file

@ -62,6 +62,7 @@
"highlight.js": "^11.7.0",
"iarna-toml-esm": "^3.0.5",
"ibantools": "^4.3.3",
"ip-matching": "^2.1.2",
"json5": "^2.2.3",
"jwt-decode": "^3.1.2",
"libphonenumber-js": "^1.10.28",

19
pnpm-lock.yaml generated
View file

@ -86,6 +86,9 @@ dependencies:
ibantools:
specifier: ^4.3.3
version: 4.3.3
ip-matching:
specifier: ^2.1.2
version: 2.1.2
json5:
specifier: ^2.2.3
version: 2.2.3
@ -3374,7 +3377,7 @@ packages:
dependencies:
'@unhead/dom': 0.5.1
'@unhead/schema': 0.5.1
'@vueuse/shared': 10.6.1(vue@3.3.4)
'@vueuse/shared': 10.9.0(vue@3.3.4)
unhead: 0.5.1
vue: 3.3.4
transitivePeerDependencies:
@ -4016,10 +4019,10 @@ packages:
- vue
dev: false
/@vueuse/shared@10.6.1(vue@3.3.4):
resolution: {integrity: sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==}
/@vueuse/shared@10.9.0(vue@3.3.4):
resolution: {integrity: sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==}
dependencies:
vue-demi: 0.14.6(vue@3.3.4)
vue-demi: 0.14.7(vue@3.3.4)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
@ -6203,6 +6206,10 @@ packages:
jsbn: 1.1.0
dev: false
/ip-matching@2.1.2:
resolution: {integrity: sha512-/ok+VhKMasgR5gvTRViwRFQfc0qYt9Vdowg6TO4/pFlDCob5ZjGPkwuOoQVCd5OrMm20zqh+1vA8KLJZTeWudg==}
dev: false
/is-alphabetical@1.0.4:
resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==}
dev: true
@ -9200,8 +9207,8 @@ packages:
vue: 3.3.4
dev: false
/vue-demi@0.14.6(vue@3.3.4):
resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
/vue-demi@0.14.7(vue@3.3.4):
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true

View file

@ -75,6 +75,7 @@ import { tool as urlParser } from './url-parser';
import { tool as uuidGenerator } from './uuid-generator';
import { tool as macAddressLookup } from './mac-address-lookup';
import { tool as xmlFormatter } from './xml-formatter';
import { tool as ipInRange } from './ip-in-range';
export const toolsByCategory: ToolCategory[] = [
{
@ -143,7 +144,15 @@ export const toolsByCategory: ToolCategory[] = [
},
{
name: 'Network',
components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator],
components: [
ipv4SubnetCalculator,
ipv4AddressConverter,
ipInRange,
ipv4RangeExpander,
macAddressLookup,
macAddressGenerator,
ipv6UlaGenerator,
],
},
{
name: 'Math',

View file

@ -0,0 +1,12 @@
import { UnfoldMoreOutlined } from '@vicons/material';
import { defineTool } from '../tool';
export const tool = defineTool({
name: 'IP in Range/CIDR/Mask',
path: '/ip-in-range',
description: 'Given a CIDR/IP Range/Wildcard IP/IP Mask, tell if a given IP is in subnet range',
keywords: ['ip', 'cidr', 'range'],
component: () => import('./ip-in-range.vue'),
icon: UnfoldMoreOutlined,
createdAt: new Date('2024-03-09'),
});

View file

@ -0,0 +1,91 @@
<script setup lang="ts">
import { useStorage } from '@vueuse/core';
import { Check as CheckIcon, LetterX as CrossIcon } from '@vicons/tabler';
import { getMatch } from 'ip-matching';
import { withDefaultOnError } from '@/utils/defaults';
import { isNotThrowing } from '@/utils/boolean';
import SpanCopyable from '@/components/SpanCopyable.vue';
const range = useStorage('ip-in-range:range', '192.168.0.1/24'); // NOSONAR
const ip = useStorage('ip-in-range:ip', '192.168.0.1'); // NOSONAR
const match = computed(() => withDefaultOnError(() => getMatch(range.value), undefined));
const subnets = computed(() => {
return (match.value?.convertToMasks() || []).map((mask) => {
const subnet = mask.convertToSubnet();
if (!subnet) {
return { cidr: '', start: '', end: '' };
}
return {
cidr: subnet.toString(),
start: subnet.getFirst().toString(),
end: subnet.getLast().toString(),
};
}).filter(subnet => subnet.cidr !== '');
});
const ipIsInMatch = computed(() => match.value?.matches(ip.value));
const ipValidationRules = [
{
message: 'We cannot parse this CIDR/IP Range/Mask/Wildcard, check the format',
validator: (value: string) => isNotThrowing(() => getMatch(value)) && getMatch(range.value),
},
];
</script>
<template>
<div>
<c-input-text
v-model:value="range"
label="An IPv4/6 CIDR/Range/Mask/Wildcard"
placeholder="The ipv4/6 CIDR..."
:validation-rules="ipValidationRules"
mb-4
/>
<c-input-text
v-model:value="ip"
label="An IPv4/6 address"
placeholder="The ipv4/6 address..."
:validation-rules="ipValidationRules"
mb-4
/>
<n-divider />
<div flex justify-center>
<span v-if="ipIsInMatch">
<n-icon color="green">
<CheckIcon />
</n-icon>
Match
</span>
<span v-else>
<n-icon color="red">
<CrossIcon />
</n-icon>
Not Match
</span>
</div>
<n-divider />
<c-card title="Subnets">
<n-table>
<tbody>
<tr v-for="{ cidr, start, end } in subnets" :key="cidr">
<td font-bold>
<SpanCopyable :value="cidr" />
</td>
<td>
<SpanCopyable :value="start" />
</td>
<td>
<SpanCopyable :value="end" />
</td>
</tr>
</tbody>
</n-table>
</c-card>
</div>
</template>