mybase 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mybase.js.map +1 -0
- package/package.json +16 -1
- package/ts/funcs/Geoip2Paths.js.map +1 -0
- package/ts/funcs/MaxRuntimeHours.js.map +1 -0
- package/ts/funcs/asJSON.js.map +1 -0
- package/ts/funcs/deepCopy.js.map +1 -0
- package/ts/funcs/ensureFolder.js.map +1 -0
- package/ts/funcs/fileCacheIsValid.js.map +1 -0
- package/ts/funcs/getMysql1.js.map +1 -0
- package/ts/funcs/getMysql2.js.map +1 -0
- package/ts/funcs/getWeekNumber.js.map +1 -0
- package/ts/funcs/hash_sha512.js.map +1 -0
- package/ts/funcs/initMysql2Pool.js.map +1 -0
- package/ts/funcs/int2ip.js.map +1 -0
- package/ts/funcs/ip2int.js.map +1 -0
- package/ts/funcs/isLANIp.js.map +1 -0
- package/ts/funcs/isLocal.js.map +1 -0
- package/ts/funcs/isLoopbackIP.js.map +1 -0
- package/ts/funcs/knexConnection.js.map +1 -0
- package/ts/funcs/promiseTimeout.js.map +1 -0
- package/ts/funcs/randomIP.js.map +1 -0
- package/ts/funcs/randomIP6.js.map +1 -0
- package/ts/funcs/randomString.js.map +1 -0
- package/ts/funcs/randomTCPPort.js.map +1 -0
- package/ts/funcs/randomUTFString.js.map +1 -0
- package/ts/funcs/utcnow.js.map +1 -0
- package/ts/funcs/validEmail.js.map +1 -0
- package/ts/funcs/validIp.js.map +1 -0
- package/ts/funcs/vaultFill.js.map +1 -0
- package/ts/funcs/vaultRead.js.map +1 -0
- package/ts/funcs/wait.js.map +1 -0
- package/ts/global.js.map +1 -0
- package/ts/index.js.map +1 -0
- package/ts/models/DateIterator.js.map +1 -0
- package/ts/models/IPAddress.js.map +1 -0
- package/ts/models/Interfaces.js.map +1 -0
- package/ts/models/OTPGenerator.js.map +1 -0
- package/ts/models/Timespan.js.map +1 -0
- package/ts/models/Unixtime.js.map +1 -0
- package/ts/types.js.map +1 -0
- package/jest/isLANIp.test.js +0 -36
- package/jest/isLoopbackIP.test.js +0 -31
- package/jest.config.js +0 -13
- package/mybase.test.ts +0 -647
- package/mybase.ts +0 -397
- package/ts/funcs/Geoip2Paths.test.ts +0 -11
- package/ts/funcs/Geoip2Paths.ts +0 -28
- package/ts/funcs/MaxRuntimeHours.ts +0 -7
- package/ts/funcs/asJSON.test.js +0 -72
- package/ts/funcs/asJSON.ts +0 -9
- package/ts/funcs/deepCopy.test.ts +0 -108
- package/ts/funcs/deepCopy.ts +0 -34
- package/ts/funcs/ensureFolder.test.ts +0 -79
- package/ts/funcs/ensureFolder.ts +0 -21
- package/ts/funcs/fileCacheIsValid.ts +0 -13
- package/ts/funcs/getMysql1.ts +0 -41
- package/ts/funcs/getMysql2.ts +0 -42
- package/ts/funcs/getWeekNumber.test.ts +0 -9
- package/ts/funcs/getWeekNumber.ts +0 -31
- package/ts/funcs/hash_sha512.ts +0 -6
- package/ts/funcs/initMysql2Pool.ts +0 -11
- package/ts/funcs/int2ip.test.js +0 -33
- package/ts/funcs/int2ip.ts +0 -9
- package/ts/funcs/ip2int.test.js +0 -30
- package/ts/funcs/ip2int.ts +0 -10
- package/ts/funcs/isLANIp.test.ts +0 -58
- package/ts/funcs/isLANIp.ts +0 -34
- package/ts/funcs/isLocal.test.ts +0 -16
- package/ts/funcs/isLocal.ts +0 -5
- package/ts/funcs/isLoopbackIP.test.ts +0 -72
- package/ts/funcs/isLoopbackIP.ts +0 -30
- package/ts/funcs/knexConnection.ts +0 -42
- package/ts/funcs/promiseTimeout.test.js +0 -104
- package/ts/funcs/promiseTimeout.ts +0 -19
- package/ts/funcs/randomIP.test.ts +0 -16
- package/ts/funcs/randomIP.ts +0 -10
- package/ts/funcs/randomIP6.test.js +0 -18
- package/ts/funcs/randomIP6.ts +0 -12
- package/ts/funcs/randomString.test.ts +0 -15
- package/ts/funcs/randomString.ts +0 -5
- package/ts/funcs/randomTCPPort.test.ts +0 -62
- package/ts/funcs/randomTCPPort.ts +0 -58
- package/ts/funcs/randomUTFString.test.ts +0 -44
- package/ts/funcs/randomUTFString.ts +0 -33
- package/ts/funcs/utcnow.ts +0 -5
- package/ts/funcs/validEmail.test.js +0 -31
- package/ts/funcs/validEmail.ts +0 -11
- package/ts/funcs/validIp.test.ts +0 -33
- package/ts/funcs/validIp.ts +0 -5
- package/ts/funcs/vaultFill.ts +0 -89
- package/ts/funcs/vaultRead.ts +0 -50
- package/ts/funcs/wait.ts +0 -7
- package/ts/global.ts +0 -10
- package/ts/index.test.ts +0 -7
- package/ts/index.ts +0 -39
- package/ts/models/DateIterator.test.ts +0 -149
- package/ts/models/DateIterator.ts +0 -80
- package/ts/models/IPAddress.test.ts +0 -393
- package/ts/models/IPAddress.ts +0 -272
- package/ts/models/Interfaces.ts +0 -58
- package/ts/models/OTPGenerator.test.ts +0 -42
- package/ts/models/OTPGenerator.ts +0 -43
- package/ts/models/Timespan.ts +0 -80
- package/ts/models/Unixtime.test.ts +0 -168
- package/ts/models/Unixtime.ts +0 -208
- package/ts/types.ts +0 -42
- package/tsconfig.jest.json +0 -11
- package/tsconfig.json +0 -37
- package/types/third-party.d.ts +0 -21
package/ts/models/IPAddress.ts
DELETED
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
/// <reference path="./../../ip6addr.d.ts" />
|
|
2
|
-
import debug from 'debug'
|
|
3
|
-
import { randomIP, randomIP6, } from "./../"
|
|
4
|
-
import ip6addr, { Addr, CIDR, ToStringOpts } from '@7c/node-ip6addr'
|
|
5
|
-
import net from 'net'
|
|
6
|
-
const ip6 = require('ip6') // "url": "https://github.com/elgs/ip6"
|
|
7
|
-
const dbg = debug('_IPAddress')
|
|
8
|
-
dbg.enabled = true
|
|
9
|
-
// need version "ip6": "0.2.7",!!
|
|
10
|
-
|
|
11
|
-
export class IPAddress {
|
|
12
|
-
private _ip: Addr
|
|
13
|
-
|
|
14
|
-
public static loopback_cidrs4 = [
|
|
15
|
-
ip6addr.createCIDR('127.0.0.0/8'),
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
public static loopback_cidrs6 = [
|
|
19
|
-
ip6addr.createCIDR('::1/128') // yes ipv6 has single address
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
public static loopback_cidrs = IPAddress.loopback_cidrs4.concat(IPAddress.loopback_cidrs6)
|
|
23
|
-
|
|
24
|
-
public static lan_cidrs4 = [
|
|
25
|
-
ip6addr.createCIDR('10.0.0.0/8'),
|
|
26
|
-
ip6addr.createCIDR('172.16.0.0/12'),
|
|
27
|
-
ip6addr.createCIDR('192.168.0.0/16'),
|
|
28
|
-
]
|
|
29
|
-
|
|
30
|
-
public static lan_cidrs6 = [
|
|
31
|
-
ip6addr.createCIDR('fd00::/8'), // Reserved by IETF for future use, but not currently in active use.
|
|
32
|
-
ip6addr.createCIDR('fc00::/8'), // The range currently in use for local communications within a site or organization.
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
public static lan_cidrs = IPAddress.lan_cidrs4.concat(IPAddress.lan_cidrs6)
|
|
36
|
-
|
|
37
|
-
public static local_cidrs = IPAddress.loopback_cidrs.concat(IPAddress.lan_cidrs)
|
|
38
|
-
public static local_cidrs4 = IPAddress.loopback_cidrs4.concat(IPAddress.lan_cidrs4)
|
|
39
|
-
public static local_cidrs6 = IPAddress.loopback_cidrs6.concat(IPAddress.lan_cidrs6)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
constructor(ip: string) { // may throw
|
|
43
|
-
if (ip === '-') ip = '0.0.0.0' // is this really required?
|
|
44
|
-
try {
|
|
45
|
-
this._ip = ip6addr.parse(ip)
|
|
46
|
-
if (this._ip._attrs.ipv4Mapped) {
|
|
47
|
-
// we wany to convert it to ipv4
|
|
48
|
-
this._ip = ip6addr.parse(this._ip.toString({ format: 'v4' }))
|
|
49
|
-
}
|
|
50
|
-
} catch (err) {
|
|
51
|
-
if (err instanceof Error)
|
|
52
|
-
throw new Error(`IPAddress: '${ip}' Error: ${err.message}`)
|
|
53
|
-
throw err
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
public abbreviated(): string {
|
|
59
|
-
return this.toString() // default behaviour of ip6addr
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
public toString(opts: ToStringOpts = { format: 'auto', zeroElide: false, zeroPad: false }): string {
|
|
63
|
-
return this._ip.toString()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
public static validate(ip: string): boolean {
|
|
67
|
-
try {
|
|
68
|
-
new IPAddress(ip)
|
|
69
|
-
return true
|
|
70
|
-
} catch (_) {
|
|
71
|
-
return false
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public static try(ip: string): IPAddress | undefined {
|
|
76
|
-
try {
|
|
77
|
-
return new IPAddress(ip)
|
|
78
|
-
} catch (_) {
|
|
79
|
-
return undefined
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public static fromString(ip: string): IPAddress {
|
|
84
|
-
return new IPAddress(ip)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
public static get Empty(): IPAddress {
|
|
88
|
-
//The IP address 0.0.0.0 is a non-routable meta-address used to denote an invalid, unknown,
|
|
89
|
-
// or non-applicable target. It's not assigned to any individual device.
|
|
90
|
-
// It is used in different contexts to mean "any IPv4-enabled network interface" or as a default route
|
|
91
|
-
return new IPAddress('0.0.0.0')
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
public isLoopbackIP(): boolean {
|
|
95
|
-
return this.partOfCIDR(IPAddress.loopback_cidrs)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
public isLANIP(): boolean {
|
|
99
|
-
return this.partOfCIDR(IPAddress.lan_cidrs)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public isLocalIP(): boolean {
|
|
103
|
-
return this.partOfCIDR(IPAddress.local_cidrs)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
partOfCIDR(cidr_networks: CIDR[]): boolean {
|
|
107
|
-
const ipNormalized = this.toString()
|
|
108
|
-
let ipVersion = net.isIPv4(ipNormalized) ? 'ipv4' : 'ipv6'
|
|
109
|
-
for (let cidr of cidr_networks) {
|
|
110
|
-
if (!cidr) continue
|
|
111
|
-
let first = cidr.first()
|
|
112
|
-
if (first.kind() !== ipVersion) continue
|
|
113
|
-
if (cidr.contains(ipNormalized))
|
|
114
|
-
return true
|
|
115
|
-
}
|
|
116
|
-
return false
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
static partOfCIDR(_ip: string, cidr_networks: CIDR[]): boolean {
|
|
120
|
-
const ip = IPAddress.try(_ip)
|
|
121
|
-
if (ip === undefined) return false
|
|
122
|
-
return ip.partOfCIDR(cidr_networks)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
public isPublicIP(): boolean {
|
|
126
|
-
return this.toString() !== '0.0.0.0' && !this.isLoopbackIP() && !this.isLANIP()
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
public static unserialize(serializedIpString: string): IPAddress {
|
|
130
|
-
if (serializedIpString.length === 32) {
|
|
131
|
-
// we have possible ipv6
|
|
132
|
-
let ip = serializedIpString.match(/.{1,4}/g)?.join(':')
|
|
133
|
-
if (ip) return new IPAddress(ip)
|
|
134
|
-
}
|
|
135
|
-
// we have possible ipv4
|
|
136
|
-
let ip = serializedIpString.match(/.{1,3}/g)?.join('.')
|
|
137
|
-
if (ip)
|
|
138
|
-
try { return new IPAddress(ip) } catch (_) { }
|
|
139
|
-
|
|
140
|
-
throw new Error(`Invalid SerializationString: ${serializedIpString}`)
|
|
141
|
-
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
public static randomIP4(): IPAddress {
|
|
145
|
-
return new IPAddress(randomIP())
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
public static randomIP6(): IPAddress {
|
|
150
|
-
return new IPAddress(randomIP6())
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
public static randomCIDRIp(cidr: CIDR[] | 'loopback' | 'lan' | 'local' | 'loopback4' | 'loopback6' | 'lan4' | 'lan6' | 'local4' | 'local6'): IPAddress {
|
|
155
|
-
if (cidr === 'loopback') cidr = IPAddress.loopback_cidrs
|
|
156
|
-
if (cidr === 'loopback4') cidr = IPAddress.loopback_cidrs4
|
|
157
|
-
if (cidr === 'loopback6') cidr = IPAddress.loopback_cidrs6
|
|
158
|
-
if (cidr === 'lan') cidr = IPAddress.lan_cidrs
|
|
159
|
-
if (cidr === 'lan4') cidr = IPAddress.lan_cidrs4
|
|
160
|
-
if (cidr === 'lan6') cidr = IPAddress.lan_cidrs6
|
|
161
|
-
if (cidr === 'local') cidr = IPAddress.local_cidrs
|
|
162
|
-
if (cidr === 'local4') cidr = IPAddress.local_cidrs4
|
|
163
|
-
if (cidr === 'local6') cidr = IPAddress.local_cidrs6
|
|
164
|
-
// dbg('randomCIDRIp', cidr)
|
|
165
|
-
if (cidr.length === 0) throw new Error('CIDR array is empty')
|
|
166
|
-
// Pick a random CIDR network
|
|
167
|
-
const network = cidr[Math.floor(Math.random() * cidr.length)];
|
|
168
|
-
// dbg('randomCIDRIp:network', network)
|
|
169
|
-
// Get the range of IPs in this CIDR
|
|
170
|
-
const start = network.first().toBigInt()
|
|
171
|
-
// dbg('randomCIDRIp:first', network.first().toString(),start)
|
|
172
|
-
const end = network.last().toBigInt();
|
|
173
|
-
// dbg('randomCIDRIp:last', network.last().toString(),end)
|
|
174
|
-
let range : any = end-start
|
|
175
|
-
// dbg('randomCIDRIp:first:last', start, end)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// Generate a random Long between the start and end
|
|
179
|
-
// if start-end > Maximum integer number
|
|
180
|
-
// we need to use BigInt
|
|
181
|
-
if (range > BigInt(Number.MAX_SAFE_INTEGER)) range=(Number.MAX_SAFE_INTEGER)
|
|
182
|
-
|
|
183
|
-
const randomBigInt = BigInt(Math.floor(Math.random() * (Number(range) + 1))) + start;
|
|
184
|
-
// dbg('randomBigInt', randomBigInt)
|
|
185
|
-
|
|
186
|
-
// Convert the BigInt back to an IP address
|
|
187
|
-
const randomIp = ip6addr.parse(randomBigInt)
|
|
188
|
-
// dbg('randomCIDRIp', randomIp.toString())
|
|
189
|
-
|
|
190
|
-
return new IPAddress(randomIp.toString())
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
public serialize(): string {
|
|
194
|
-
if (this.kind() === 4) {
|
|
195
|
-
// zero pad ipv4
|
|
196
|
-
return this._ip.toString().split('.').map((octet) => {
|
|
197
|
-
return octet.padStart(3, '0')
|
|
198
|
-
}).join('.').replace(/\./g, '')
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// zero pad ipv6
|
|
202
|
-
return ip6.normalize(this._ip.toString()).split(':').map((hextet: string) => {
|
|
203
|
-
return hextet.padStart(4, '0')
|
|
204
|
-
}).join(':').replace(/:/g, '')
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
public kind(): number {
|
|
208
|
-
return this._ip.kind() === 'ipv6' ? 6 : 4
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
public equals(secondIp: IPAddress): boolean {
|
|
212
|
-
return this._ip.compare(secondIp._ip) === 0
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
public randomPad(): string {
|
|
216
|
-
if (this.kind() === 4) return this.padIp4()
|
|
217
|
-
return this.padIp6()
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
public normalized(): string {
|
|
221
|
-
if (this.kind() === 4) return this._ip.toString()
|
|
222
|
-
return ip6.normalize(this._ip.toString())
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
private padIp6(): string {
|
|
227
|
-
const hextets = this.normalized().split(':') // we need to have the full form
|
|
228
|
-
const paddedHextets = hextets.map(hextet => {
|
|
229
|
-
const cleanHextet = Number(`0x${hextet}`).toString(16)
|
|
230
|
-
const padLength = Math.floor(Math.random() * (4 - cleanHextet.length))
|
|
231
|
-
return cleanHextet.padStart(padLength + cleanHextet.length, '0')
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
return paddedHextets.join(':')
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
private padIp4(): string {
|
|
238
|
-
const octets = this._ip.toString().split('.')
|
|
239
|
-
const paddedOctets = octets.map(octet => {
|
|
240
|
-
const cleanOctet = String(Number(octet))
|
|
241
|
-
const padLength = Math.floor(Math.random() * (3 - cleanOctet.length))
|
|
242
|
-
return cleanOctet.padStart(padLength + cleanOctet.length, '0')
|
|
243
|
-
});
|
|
244
|
-
return paddedOctets.join('.')
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
asciiChecksum(): string {
|
|
248
|
-
// support ipv4 and ipv6
|
|
249
|
-
// FNV-1a hash parameters
|
|
250
|
-
const FNV_PRIME = 0x01000193;
|
|
251
|
-
const FNV_OFFSET_BASIS = 0x811c9dc5;
|
|
252
|
-
const CHAR_SET = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
253
|
-
|
|
254
|
-
let hash = FNV_OFFSET_BASIS;
|
|
255
|
-
const ip = this.normalized()
|
|
256
|
-
for (let i = 0; i < ip.length; i++) {
|
|
257
|
-
hash ^= ip.charCodeAt(i);
|
|
258
|
-
hash *= FNV_PRIME;
|
|
259
|
-
hash >>>= 0; // Ensure hash is always a positive 32-bit integer
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Map the hash to a character in the CHAR_SET
|
|
263
|
-
const index = hash % CHAR_SET.length;
|
|
264
|
-
return CHAR_SET.charAt(index);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
checksum1(): string {
|
|
268
|
-
// this shall check that the ip is ipv4 and return the last octet as checksum
|
|
269
|
-
if (this.kind() !== 4) return 'x'
|
|
270
|
-
return this._ip.toString().split('.').pop() || '-'
|
|
271
|
-
}
|
|
272
|
-
}
|
package/ts/models/Interfaces.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { networkInterfaces } from 'os';
|
|
2
|
-
|
|
3
|
-
interface NetworkInterfaceInfo {
|
|
4
|
-
name: string;
|
|
5
|
-
ipv4: string[];
|
|
6
|
-
ipv6: string[];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export class Interfaces {
|
|
11
|
-
|
|
12
|
-
static findByName(name: string): NetworkInterfaceInfo | null {
|
|
13
|
-
const ifaces = this.getInterfaces()
|
|
14
|
-
const iface = ifaces.find(iface => iface.name === name)
|
|
15
|
-
return iface || null
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
static findByNamePrefix(prefix: string): NetworkInterfaceInfo[] {
|
|
19
|
-
const ifaces = this.getInterfaces()
|
|
20
|
-
return ifaces.filter(iface => iface.name.startsWith(prefix))
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
static findByIp(ip: string): NetworkInterfaceInfo | null {
|
|
24
|
-
const ifaces = this.getInterfaces()
|
|
25
|
-
const iface = ifaces.find(iface => iface.ipv4.includes(ip) || iface.ipv6.includes(ip))
|
|
26
|
-
return iface || null
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
static asApiServerConfig(ifaces:string[], port:number): {ip:string,port:number}[] {
|
|
30
|
-
const ret: {ip:string,port:number}[] = []
|
|
31
|
-
for (const iface of ifaces) {
|
|
32
|
-
const i = this.findByName(iface)
|
|
33
|
-
if (i) ret.push({ip:i.ipv4[0],port:port})
|
|
34
|
-
}
|
|
35
|
-
return ret
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
static getInterfaces(): NetworkInterfaceInfo[] {
|
|
39
|
-
const interfaces = networkInterfaces();
|
|
40
|
-
const result: NetworkInterfaceInfo[] = [];
|
|
41
|
-
|
|
42
|
-
for (const name of Object.keys(interfaces)) {
|
|
43
|
-
const networkInterface = interfaces[name];
|
|
44
|
-
if (networkInterface) {
|
|
45
|
-
const ipv4 = networkInterface.filter(info => info.family === 'IPv4').map(info => info.address);
|
|
46
|
-
const ipv6 = networkInterface.filter(info => info.family === 'IPv6').map(info => info.address);
|
|
47
|
-
|
|
48
|
-
result.push({
|
|
49
|
-
name,
|
|
50
|
-
ipv4,
|
|
51
|
-
ipv6
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return result;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { OTPGenerator } from './OTPGenerator';
|
|
2
|
-
import { wait } from './../funcs/wait';
|
|
3
|
-
import { Timespan } from './Timespan';
|
|
4
|
-
|
|
5
|
-
const passkey = 'hiowi3rmpewr34';
|
|
6
|
-
describe('OTPGenerator', () => {
|
|
7
|
-
it('should generate OTP', () => {
|
|
8
|
-
const otpGenerator = new OTPGenerator(passkey, 5);
|
|
9
|
-
const otp = otpGenerator.generateOTP();
|
|
10
|
-
// length should be 5 + 13
|
|
11
|
-
expect(otp.length).toBe(18);
|
|
12
|
-
// console.log(otp);
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('should generate different OTPs in milliseconds', async () => {
|
|
16
|
-
const otpGenerator = new OTPGenerator(passkey, 5);
|
|
17
|
-
const otp1 = otpGenerator.generateOTP()
|
|
18
|
-
await wait(3/1000);
|
|
19
|
-
const otp2 = otpGenerator.generateOTP();
|
|
20
|
-
expect(otp1).not.toBe(otp2);
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
it('should generate different OTPs in milliseconds per password', async () => {
|
|
24
|
-
const otpGenerator1 = new OTPGenerator(passkey+'1', 5);
|
|
25
|
-
const otpGenerator2 = new OTPGenerator(passkey+'2', 5);
|
|
26
|
-
for(let i=0; i<10000; i++) {
|
|
27
|
-
const otp1 = otpGenerator1.generateOTP()
|
|
28
|
-
const otp2 = otpGenerator2.generateOTP();
|
|
29
|
-
expect(otp1).not.toBe(otp2);
|
|
30
|
-
}
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('age should be milliseconds since generation', async () => {
|
|
34
|
-
const otpGenerator = new OTPGenerator(passkey, 5);
|
|
35
|
-
const otp = otpGenerator.generateOTP();
|
|
36
|
-
await wait(1/1000);
|
|
37
|
-
const age = otpGenerator.age(otp);
|
|
38
|
-
expect(age).toBeInstanceOf(Timespan);
|
|
39
|
-
expect(age.miliseconds).toBeGreaterThan(0);
|
|
40
|
-
expect(age.miliseconds).toBeLessThan(100);
|
|
41
|
-
})
|
|
42
|
-
});
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import * as crypto from 'crypto';
|
|
2
|
-
import { Timespan } from './Timespan';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export class OTPGenerator {
|
|
6
|
-
constructor(private passkey: string, private length: number = 4) {}
|
|
7
|
-
|
|
8
|
-
// Generate OTP with the current timestamp as nonce
|
|
9
|
-
public generateOTP(): string {
|
|
10
|
-
return this.generateOTPWithNonce(Date.now());
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Validate if the OTP matches by extracting the nonce and regenerating OTP
|
|
14
|
-
public validateOTP(otp: string): boolean {
|
|
15
|
-
if (!this.isValid(otp)) return false; // Validate plausibility of OTP
|
|
16
|
-
const nonce = this.extractNonce(otp);
|
|
17
|
-
return otp === this.generateOTPWithNonce(nonce);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Get the age of the OTP compared to now
|
|
21
|
-
public age(otp: string): Timespan {
|
|
22
|
-
if (!this.isValid(otp)) throw new Error('Invalid OTP');
|
|
23
|
-
const nonce = this.extractNonce(otp);
|
|
24
|
-
return new Timespan(Date.now() - nonce)
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
public generateOTPWithNonce(nonce: number): string { // lets keep it public for testing
|
|
28
|
-
const hash = crypto.createHmac('sha256', this.passkey).update(nonce.toString()).digest('hex');
|
|
29
|
-
const otp = [...hash.slice(0, this.length)].map(char => String.fromCharCode((parseInt(char, 16) % 26) + 97)).join('');
|
|
30
|
-
return `${otp}${nonce.toString(16).padStart(13, '0')}`;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Private helper to validate plausibility of OTP
|
|
34
|
-
private isValid(otp: string): boolean {
|
|
35
|
-
return otp.length === this.length + 13;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Private helper to extract the nonce from the OTP
|
|
39
|
-
private extractNonce(otp: string): number {
|
|
40
|
-
const nonceHex = otp.slice(-13);
|
|
41
|
-
return parseInt(nonceHex, 16);
|
|
42
|
-
}
|
|
43
|
-
}
|
package/ts/models/Timespan.ts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
export class Timespan {
|
|
2
|
-
constructor(private readonly ms: number){
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
get miliseconds() : number {
|
|
6
|
-
return this.ms
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
get seconds() : number {
|
|
10
|
-
return this.ms / 1000
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
get minutes() : number {
|
|
14
|
-
return this.ms / 1000 / 60
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
get hours() : number {
|
|
18
|
-
return this.ms / 1000 / 60 / 60
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
get days() : number {
|
|
22
|
-
return this.ms / 1000 / 60 / 60 / 24
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get weeks() : number {
|
|
26
|
-
return this.ms / 1000 / 60 / 60 / 24 / 7
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get months() : number {
|
|
30
|
-
return this.ms / 1000 / 60 / 60 / 24 / 30
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
static miliseconds(amount: number): Timespan {
|
|
34
|
-
return new Timespan(amount)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static seconds(amount: number): Timespan {
|
|
38
|
-
return new Timespan(amount * 1000)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static minutes(mins: number): Timespan {
|
|
42
|
-
return new Timespan(mins * 60 * 1000)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static hours(hours: number): Timespan {
|
|
46
|
-
return new Timespan(hours * 60 * 60 * 1000)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static days(days: number): Timespan {
|
|
50
|
-
return new Timespan(days * 24 * 60 * 60 * 1000)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static weeks(weeks: number): Timespan {
|
|
54
|
-
return new Timespan(weeks * 7 * 24 * 60 * 60 * 1000)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
static months(months: number): Timespan {
|
|
58
|
-
return new Timespan(months * 30 * 24 * 60 * 60 * 1000)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
static years(years: number): Timespan {
|
|
62
|
-
return new Timespan(years * 365 * 24 * 60 * 60 * 1000)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
add(timespan: Timespan): Timespan {
|
|
66
|
-
return new Timespan(this.ms + timespan.ms)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
subtract(timespan: Timespan): Timespan {
|
|
70
|
-
return new Timespan(this.ms - timespan.ms)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
toJSON() {
|
|
75
|
-
return {
|
|
76
|
-
__type:'Timespan',
|
|
77
|
-
value:this.ms
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
import { Timespan } from './Timespan';
|
|
2
|
-
import { Unixtime } from './Unixtime';
|
|
3
|
-
|
|
4
|
-
describe('Unixtime', () => {
|
|
5
|
-
it('should create Unixtime object from Date', () => {
|
|
6
|
-
const date = new Date();
|
|
7
|
-
const unixtime = new Unixtime(date);
|
|
8
|
-
expect(unixtime.toDate()).toEqual(date);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('create invalid date should throw error', () => {
|
|
12
|
-
expect(() => new Unixtime('invalid date')).toThrow();
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
it('should create Unixtime object from string', () => {
|
|
16
|
-
const dateString = '2022-01-01T00:00:00Z';
|
|
17
|
-
const date = new Date(dateString);
|
|
18
|
-
const unixtime = new Unixtime(dateString);
|
|
19
|
-
expect(unixtime.toDate()).toEqual(date);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should create Unixtime object from number (short form)', () => {
|
|
23
|
-
const timestamp = 1640995200; // January 1, 2022 00:00:00 UTC
|
|
24
|
-
const date = new Date(timestamp * 1000);
|
|
25
|
-
const unixtime = new Unixtime(timestamp);
|
|
26
|
-
expect(unixtime.toDate()).toEqual(date);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it('should create Unixtime object from number (long form)', () => {
|
|
30
|
-
const timestamp = 1640995200000; // January 1, 2022 00:00:00 UTC
|
|
31
|
-
const date = new Date(timestamp);
|
|
32
|
-
const unixtime = new Unixtime(timestamp);
|
|
33
|
-
expect(unixtime.toDate()).toEqual(date);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('should convert Unixtime to short Unixtime', () => {
|
|
37
|
-
const date = new Date();
|
|
38
|
-
const unixtime = new Unixtime(date);
|
|
39
|
-
const shortUnixtime = Math.round(date.getTime() / 1000);
|
|
40
|
-
expect(unixtime.toShortUnixtime()).toEqual(shortUnixtime);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('should convert Unixtime to long Unixtime', () => {
|
|
44
|
-
const date = new Date();
|
|
45
|
-
const unixtime = new Unixtime(date);
|
|
46
|
-
expect(unixtime.toLongUnixtime()).toEqual(date.getTime());
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should convert Unixtime to ISO string', () => {
|
|
50
|
-
const date = new Date();
|
|
51
|
-
const unixtime = new Unixtime(date);
|
|
52
|
-
expect(unixtime.toISOString()).toEqual(date.toISOString());
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should add miliseconds to Unixtime', () => {
|
|
56
|
-
const date = new Date();
|
|
57
|
-
const unixtime = new Unixtime(date);
|
|
58
|
-
const addedUnixtime = unixtime.addMiliseconds(1000);
|
|
59
|
-
expect(addedUnixtime.toDate()).toEqual(new Date(date.getTime() + 1000));
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should add seconds to Unixtime', () => {
|
|
63
|
-
const date = new Date();
|
|
64
|
-
const unixtime = new Unixtime(date);
|
|
65
|
-
const addedUnixtime = unixtime.addSeconds(1);
|
|
66
|
-
expect(addedUnixtime.toDate()).toEqual(new Date(date.getTime() + 1000));
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it('should add minutes to Unixtime', () => {
|
|
70
|
-
const date = new Date();
|
|
71
|
-
const unixtime = new Unixtime(date);
|
|
72
|
-
const addedUnixtime = unixtime.addMinutes(1);
|
|
73
|
-
expect(addedUnixtime.toDate()).toEqual(new Date(date.getTime() + 60000));
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should add hours to Unixtime', () => {
|
|
77
|
-
const date = new Date();
|
|
78
|
-
const unixtime = new Unixtime(date);
|
|
79
|
-
const addedUnixtime = unixtime.addHours(1);
|
|
80
|
-
expect(addedUnixtime.toDate()).toEqual(new Date(date.getTime() + 3600000));
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('should add days to Unixtime', () => {
|
|
84
|
-
const date = new Date();
|
|
85
|
-
const unixtime = new Unixtime(date);
|
|
86
|
-
const addedUnixtime = unixtime.addDays(1);
|
|
87
|
-
expect(addedUnixtime.toDate()).toEqual(new Date(date.getTime() + 86400000));
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should add months to Unixtime', () => {
|
|
91
|
-
const date = new Date();
|
|
92
|
-
const unixtime = new Unixtime(date);
|
|
93
|
-
const addedUnixtime = unixtime.addMonths(1);
|
|
94
|
-
expect(addedUnixtime.toDate()).toEqual(new Date(date.setMonth(date.getMonth() + 1)));
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('should add years to Unixtime', () => {
|
|
98
|
-
const date = new Date();
|
|
99
|
-
const unixtime = new Unixtime(date);
|
|
100
|
-
const addedUnixtime = unixtime.addYears(1);
|
|
101
|
-
expect(addedUnixtime.toDate()).toEqual(new Date(date.setFullYear(date.getFullYear() + 1)));
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('clone should create brand new object', () => {
|
|
105
|
-
const unixtime0 = new Unixtime(new Date())
|
|
106
|
-
const unixtime1 = unixtime0.clone();
|
|
107
|
-
expect(unixtime1).not.toBe(unixtime0);
|
|
108
|
-
expect(unixtime0.toDate()).toEqual(unixtime1.toDate());
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
it('day,month,year should return correct values', () => {
|
|
113
|
-
const unixtime = new Unixtime("2024-10-11T12:13:14Z");
|
|
114
|
-
expect(unixtime.day).toEqual(11);
|
|
115
|
-
expect(unixtime.month).toEqual(10);
|
|
116
|
-
expect(unixtime.year).toEqual(2024);
|
|
117
|
-
expect(unixtime.minutes).toEqual(13);
|
|
118
|
-
expect(unixtime.seconds).toEqual(14);
|
|
119
|
-
expect(unixtime.hours).toEqual(12);
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
it('fromYYYYMMDD should create Unixtime object from string', () => {
|
|
123
|
-
const unixtime = Unixtime.fromYYYYMMDD('20241011');
|
|
124
|
-
expect(unixtime.toISOString()).toEqual('2024-10-11T00:00:00.000Z');
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('yyyymmddhh should return correct values',() => {
|
|
128
|
-
const unixtime = new Unixtime("2024-10-11T12:13:14Z");
|
|
129
|
-
expect(unixtime.yyyymmdd()).toEqual('20241011');
|
|
130
|
-
expect(unixtime.yyyymmddhh()).toEqual('2024101112');
|
|
131
|
-
// should also work with optional seperators
|
|
132
|
-
expect(unixtime.yyyymmddhh('-')).toEqual('2024-10-11-12');
|
|
133
|
-
})
|
|
134
|
-
|
|
135
|
-
it('randomPast should return random time in the past', () => {
|
|
136
|
-
const end = Unixtime.now()
|
|
137
|
-
const begin = end.clone().addYears(-1)
|
|
138
|
-
for(let i=0;i<100000;i++) {
|
|
139
|
-
const rand = Unixtime.randomPast(Timespan.years(1))
|
|
140
|
-
expect(rand.toLongUnixtime()).toBeGreaterThan(begin.toLongUnixtime());
|
|
141
|
-
expect(rand.toLongUnixtime()).toBeLessThan(end.toLongUnixtime());
|
|
142
|
-
}
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
it('randomFuture should return random time in the future within given timespan of 1 year', () => {
|
|
146
|
-
const begin = Unixtime.now()
|
|
147
|
-
const end = begin.clone().addYears(1)
|
|
148
|
-
for(let i=0;i<100000;i++) {
|
|
149
|
-
const rand = Unixtime.randomFuture(Timespan.years(1))
|
|
150
|
-
expect(rand.toLongUnixtime()).toBeGreaterThan(begin.toLongUnixtime());
|
|
151
|
-
expect(rand.toLongUnixtime()).toBeLessThan(end.toLongUnixtime());
|
|
152
|
-
}
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
it('yyyymmdd should work as designed',() => {
|
|
156
|
-
const unixtime = new Unixtime("2024-10-11T12:13:14Z");
|
|
157
|
-
expect(unixtime.yyyymmdd()).toEqual('20241011');
|
|
158
|
-
expect(unixtime.yyyymmdd('-')).toEqual('2024-10-11');
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
it('fromYYYYMMDD should throw error when invalid date', () => {
|
|
162
|
-
expect(() => Unixtime.fromYYYYMMDD('20243131')).toThrow('Invalid month');
|
|
163
|
-
expect(() => Unixtime.fromYYYYMMDD('20241233')).toThrow('Invalid day');
|
|
164
|
-
expect(() => Unixtime.fromYYYYMMDD('xx')).toThrow('Invalid yyyymmdd value');
|
|
165
|
-
//@ts-ignore
|
|
166
|
-
expect(() => Unixtime.fromYYYYMMDD([])).toThrow('Invalid yyyymmdd value');
|
|
167
|
-
})
|
|
168
|
-
});
|