@mytmpvpn/mytmpvpn-common 6.0.0 → 6.0.2
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/dist/.eslintrc.d.ts +24 -0
- package/dist/.eslintrc.js +30 -0
- package/dist/jest.config.d.ts +6 -0
- package/dist/jest.config.js +9 -0
- package/dist/src/errors.d.ts +24 -0
- package/dist/src/errors.js +68 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +6 -0
- package/dist/src/models/index.d.ts +2 -0
- package/dist/src/models/index.js +5 -0
- package/dist/src/models/peanuts.d.ts +9 -0
- package/dist/src/models/peanuts.js +7 -0
- package/dist/src/models/uservpn.d.ts +23 -0
- package/dist/src/models/uservpn.js +36 -0
- package/dist/src/models/vpn.d.ts +52 -0
- package/dist/src/models/vpn.js +272 -0
- package/dist/src/utils.d.ts +3 -0
- package/dist/src/utils.js +23 -0
- package/dist/test/models.test.d.ts +1 -0
- package/dist/test/models.test.js +310 -0
- package/package.json +5 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare namespace env {
|
|
2
|
+
const browser: boolean;
|
|
3
|
+
const es2021: boolean;
|
|
4
|
+
}
|
|
5
|
+
declare const _extends: string[];
|
|
6
|
+
export { _extends as extends };
|
|
7
|
+
export declare const parser: string;
|
|
8
|
+
export declare const plugins: string[];
|
|
9
|
+
export declare const root: boolean;
|
|
10
|
+
export declare const overrides: {
|
|
11
|
+
env: {
|
|
12
|
+
node: boolean;
|
|
13
|
+
};
|
|
14
|
+
files: string[];
|
|
15
|
+
parserOptions: {
|
|
16
|
+
sourceType: string;
|
|
17
|
+
};
|
|
18
|
+
}[];
|
|
19
|
+
export declare namespace parserOptions {
|
|
20
|
+
const ecmaVersion: string;
|
|
21
|
+
const project: string;
|
|
22
|
+
const sourceType: string;
|
|
23
|
+
}
|
|
24
|
+
export declare const rules: {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
module.exports = {
|
|
3
|
+
env: {
|
|
4
|
+
browser: true,
|
|
5
|
+
es2021: true
|
|
6
|
+
},
|
|
7
|
+
extends: ['standard-with-typescript', 'eslint:recommended', 'plugin:@typescript-eslint/recommended'],
|
|
8
|
+
parser: '@typescript-eslint/parser',
|
|
9
|
+
plugins: ['@typescript-eslint'],
|
|
10
|
+
root: true,
|
|
11
|
+
overrides: [
|
|
12
|
+
{
|
|
13
|
+
env: {
|
|
14
|
+
node: true
|
|
15
|
+
},
|
|
16
|
+
files: [
|
|
17
|
+
'.eslintrc.{js,cjs}'
|
|
18
|
+
],
|
|
19
|
+
parserOptions: {
|
|
20
|
+
sourceType: 'script'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
parserOptions: {
|
|
25
|
+
ecmaVersion: 'latest',
|
|
26
|
+
project: './tsconfig.json',
|
|
27
|
+
sourceType: 'module'
|
|
28
|
+
},
|
|
29
|
+
rules: {}
|
|
30
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class MyTmpVpnError extends Error {
|
|
2
|
+
constructor(msg: string);
|
|
3
|
+
}
|
|
4
|
+
export declare class InvalidUserConfigError extends MyTmpVpnError {
|
|
5
|
+
constructor(msg: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class InvalidVpnConfigError extends MyTmpVpnError {
|
|
8
|
+
constructor(msg: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class MinPeanutsError extends InvalidVpnConfigError {
|
|
11
|
+
constructor(min: number, given: number, balance: number);
|
|
12
|
+
}
|
|
13
|
+
export declare class MaxPeanutsError extends InvalidVpnConfigError {
|
|
14
|
+
constructor(max: number, given: number, balance: number);
|
|
15
|
+
}
|
|
16
|
+
export declare class NotEnoughPeanutsError extends InvalidVpnConfigError {
|
|
17
|
+
constructor(given: number, balance: number);
|
|
18
|
+
}
|
|
19
|
+
export declare class MinDeleteAfterError extends InvalidVpnConfigError {
|
|
20
|
+
constructor(min: number, given: number);
|
|
21
|
+
}
|
|
22
|
+
export declare class MaxDeleteAfterError extends InvalidVpnConfigError {
|
|
23
|
+
constructor(max: number, given: number);
|
|
24
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MaxDeleteAfterError = exports.MinDeleteAfterError = exports.NotEnoughPeanutsError = exports.MaxPeanutsError = exports.MinPeanutsError = exports.InvalidVpnConfigError = exports.InvalidUserConfigError = exports.MyTmpVpnError = void 0;
|
|
4
|
+
const peanuts_1 = require("./models/peanuts");
|
|
5
|
+
class MyTmpVpnError extends Error {
|
|
6
|
+
constructor(msg) {
|
|
7
|
+
super(msg); // 'Error' breaks prototype chain here
|
|
8
|
+
// See: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
|
|
9
|
+
Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.MyTmpVpnError = MyTmpVpnError;
|
|
13
|
+
class InvalidUserConfigError extends MyTmpVpnError {
|
|
14
|
+
constructor(msg) {
|
|
15
|
+
super(msg);
|
|
16
|
+
// Set the prototype explicitly.
|
|
17
|
+
Object.setPrototypeOf(this, InvalidUserConfigError.prototype);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.InvalidUserConfigError = InvalidUserConfigError;
|
|
21
|
+
class InvalidVpnConfigError extends MyTmpVpnError {
|
|
22
|
+
constructor(msg) {
|
|
23
|
+
super(msg);
|
|
24
|
+
// Set the prototype explicitly.
|
|
25
|
+
Object.setPrototypeOf(this, InvalidVpnConfigError.prototype);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.InvalidVpnConfigError = InvalidVpnConfigError;
|
|
29
|
+
class MinPeanutsError extends InvalidVpnConfigError {
|
|
30
|
+
constructor(min, given, balance) {
|
|
31
|
+
super(`Minimum number of peanuts should be ${min}, you specified: ${(0, peanuts_1.peanutsToClient)(given)} and you have ${(0, peanuts_1.peanutsToClient)(balance)}.`);
|
|
32
|
+
// Set the prototype explicitly.
|
|
33
|
+
Object.setPrototypeOf(this, MinPeanutsError.prototype);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.MinPeanutsError = MinPeanutsError;
|
|
37
|
+
class MaxPeanutsError extends InvalidVpnConfigError {
|
|
38
|
+
constructor(max, given, balance) {
|
|
39
|
+
super(`Maximum number of peanuts should be ${max}, you specified: ${(0, peanuts_1.peanutsToClient)(given)} and you have ${(0, peanuts_1.peanutsToClient)(balance)}.`);
|
|
40
|
+
// Set the prototype explicitly.
|
|
41
|
+
Object.setPrototypeOf(this, MaxPeanutsError.prototype);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.MaxPeanutsError = MaxPeanutsError;
|
|
45
|
+
class NotEnoughPeanutsError extends InvalidVpnConfigError {
|
|
46
|
+
constructor(given, balance) {
|
|
47
|
+
super(`Not enough peanuts, you specified: ${(0, peanuts_1.peanutsToClient)(given)} and you have ${(0, peanuts_1.peanutsToClient)(balance)}.`);
|
|
48
|
+
// Set the prototype explicitly.
|
|
49
|
+
Object.setPrototypeOf(this, NotEnoughPeanutsError.prototype);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.NotEnoughPeanutsError = NotEnoughPeanutsError;
|
|
53
|
+
class MinDeleteAfterError extends InvalidVpnConfigError {
|
|
54
|
+
constructor(min, given) {
|
|
55
|
+
super(`deleteAfter must be greater than ${min}, you specified: ${given}.`);
|
|
56
|
+
// Set the prototype explicitly.
|
|
57
|
+
Object.setPrototypeOf(this, MinDeleteAfterError.prototype);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.MinDeleteAfterError = MinDeleteAfterError;
|
|
61
|
+
class MaxDeleteAfterError extends InvalidVpnConfigError {
|
|
62
|
+
constructor(max, given) {
|
|
63
|
+
super(`deleteAfter must be lesser than ${max}, you specified: ${given}.`);
|
|
64
|
+
// Set the prototype explicitly.
|
|
65
|
+
Object.setPrototypeOf(this, MaxDeleteAfterError.prototype);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.MaxDeleteAfterError = MaxDeleteAfterError;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as vpn from './vpn';
|
|
2
|
+
export interface UserVpn {
|
|
3
|
+
userId: string;
|
|
4
|
+
version: number;
|
|
5
|
+
vpn: vpn.Vpn;
|
|
6
|
+
}
|
|
7
|
+
export interface newUserVpnParams {
|
|
8
|
+
userId: string;
|
|
9
|
+
region: string;
|
|
10
|
+
version?: number;
|
|
11
|
+
config: vpn.VpnConfig;
|
|
12
|
+
state: vpn.VpnState;
|
|
13
|
+
}
|
|
14
|
+
export interface getUserVpnFromParams {
|
|
15
|
+
userId: string;
|
|
16
|
+
vpnId: string;
|
|
17
|
+
version?: number;
|
|
18
|
+
config: vpn.VpnConfig;
|
|
19
|
+
state: vpn.VpnState;
|
|
20
|
+
}
|
|
21
|
+
export declare function newUserVpn({ userId, region, version, ...rest }: newUserVpnParams): UserVpn;
|
|
22
|
+
export declare function getUserVpnFrom({ userId, vpnId, version, ...rest }: getUserVpnFromParams): UserVpn;
|
|
23
|
+
export declare function jsonToUserVpn(jsonString: any): UserVpn;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jsonToUserVpn = exports.getUserVpnFrom = exports.newUserVpn = void 0;
|
|
4
|
+
const vpn = require("./vpn");
|
|
5
|
+
const INITIAL_VERSION = 0;
|
|
6
|
+
function newUserVpn({ userId, region, version = INITIAL_VERSION, ...rest }) {
|
|
7
|
+
return {
|
|
8
|
+
userId,
|
|
9
|
+
version,
|
|
10
|
+
vpn: vpn.newVpn(region, rest.config, rest.state)
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
exports.newUserVpn = newUserVpn;
|
|
14
|
+
function getUserVpnFrom({ userId, vpnId, version = INITIAL_VERSION, ...rest }) {
|
|
15
|
+
return {
|
|
16
|
+
userId,
|
|
17
|
+
version,
|
|
18
|
+
vpn: vpn.getVpnFrom(vpnId, rest.state, rest.config)
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
exports.getUserVpnFrom = getUserVpnFrom;
|
|
22
|
+
function jsonToUserVpn(jsonString) {
|
|
23
|
+
const parsed = JSON.parse(jsonString, (key, value) => {
|
|
24
|
+
if (key === 'createdAt') {
|
|
25
|
+
return new Date(value);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
});
|
|
29
|
+
const result = {
|
|
30
|
+
userId: parsed.userId,
|
|
31
|
+
version: parsed.version,
|
|
32
|
+
vpn: parsed.vpn
|
|
33
|
+
};
|
|
34
|
+
return parsed;
|
|
35
|
+
}
|
|
36
|
+
exports.jsonToUserVpn = jsonToUserVpn;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { UserVpn } from "./uservpn";
|
|
2
|
+
export declare enum VpnState {
|
|
3
|
+
Failed = "Failed",
|
|
4
|
+
Creating = "Creating",
|
|
5
|
+
Created = "Created",
|
|
6
|
+
Provisioning = "Provisioning",
|
|
7
|
+
Paused = "Paused",
|
|
8
|
+
Running = "Running",
|
|
9
|
+
Deprovisioning = "Deprovisioning",
|
|
10
|
+
Deleted = "Deleted"
|
|
11
|
+
}
|
|
12
|
+
export declare function toRank(state: VpnState): number;
|
|
13
|
+
export declare function fromRank(rank: number): VpnState;
|
|
14
|
+
export declare enum VpnType {
|
|
15
|
+
WireGuard = "wireguard"
|
|
16
|
+
}
|
|
17
|
+
export interface VpnConfigLimits {
|
|
18
|
+
deleteAfterFieldMinValue: number;
|
|
19
|
+
deleteAfterFieldMaxValue: number;
|
|
20
|
+
maxPeanutsFieldMinValue: number;
|
|
21
|
+
maxPeanutsFieldMaxValue: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ValidDeleteAfterConfig {
|
|
24
|
+
min: number;
|
|
25
|
+
max: number;
|
|
26
|
+
}
|
|
27
|
+
export interface VpnConfig {
|
|
28
|
+
type: VpnType;
|
|
29
|
+
maxPeanuts: number;
|
|
30
|
+
deleteAfter?: number;
|
|
31
|
+
}
|
|
32
|
+
export interface VpnMetrics {
|
|
33
|
+
duration: number;
|
|
34
|
+
bytes: number;
|
|
35
|
+
peanuts: number;
|
|
36
|
+
}
|
|
37
|
+
export interface Vpn {
|
|
38
|
+
vpnId: string;
|
|
39
|
+
createdAt: Date;
|
|
40
|
+
region: string;
|
|
41
|
+
config: VpnConfig;
|
|
42
|
+
state: VpnState;
|
|
43
|
+
}
|
|
44
|
+
export declare function getVpnConfigTypes(): VpnType[];
|
|
45
|
+
export declare function vpnAgainstQuotaPredicate(uservpn: UserVpn): boolean;
|
|
46
|
+
export declare function validateVpnNbAgainstQuota(vpnNb: number, quota: number): number;
|
|
47
|
+
export declare function checkValidConfig(userId: string, currentBalance: number, vpnConfigLimits: VpnConfigLimits, vpnConfig: any): VpnConfig;
|
|
48
|
+
export declare function newVpn(region: string, config: VpnConfig, state: VpnState): Vpn;
|
|
49
|
+
export declare function getVpnFrom(vpnId: string, state: VpnState, config: VpnConfig): Vpn;
|
|
50
|
+
export declare function vpnIdToWgFileName(vpnId: string): string;
|
|
51
|
+
export declare function vpnToClient(vpn: Vpn): Vpn;
|
|
52
|
+
export declare function metricsToClient(metrics: VpnMetrics | undefined): VpnMetrics;
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.metricsToClient = exports.vpnToClient = exports.vpnIdToWgFileName = exports.getVpnFrom = exports.newVpn = exports.checkValidConfig = exports.validateVpnNbAgainstQuota = exports.vpnAgainstQuotaPredicate = exports.getVpnConfigTypes = exports.VpnType = exports.fromRank = exports.toRank = exports.VpnState = void 0;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
const peanuts_1 = require("./peanuts");
|
|
6
|
+
var VpnState;
|
|
7
|
+
(function (VpnState) {
|
|
8
|
+
VpnState["Failed"] = "Failed";
|
|
9
|
+
VpnState["Creating"] = "Creating";
|
|
10
|
+
VpnState["Created"] = "Created";
|
|
11
|
+
VpnState["Provisioning"] = "Provisioning";
|
|
12
|
+
VpnState["Paused"] = "Paused";
|
|
13
|
+
VpnState["Running"] = "Running";
|
|
14
|
+
VpnState["Deprovisioning"] = "Deprovisioning";
|
|
15
|
+
VpnState["Deleted"] = "Deleted";
|
|
16
|
+
})(VpnState = exports.VpnState || (exports.VpnState = {}));
|
|
17
|
+
const vpnStateRank = Object.values(VpnState);
|
|
18
|
+
function toRank(state) {
|
|
19
|
+
return vpnStateRank.indexOf(state);
|
|
20
|
+
}
|
|
21
|
+
exports.toRank = toRank;
|
|
22
|
+
function fromRank(rank) {
|
|
23
|
+
return vpnStateRank[rank];
|
|
24
|
+
}
|
|
25
|
+
exports.fromRank = fromRank;
|
|
26
|
+
var VpnType;
|
|
27
|
+
(function (VpnType) {
|
|
28
|
+
VpnType["WireGuard"] = "wireguard";
|
|
29
|
+
})(VpnType = exports.VpnType || (exports.VpnType = {}));
|
|
30
|
+
function getVpnConfigTypes() {
|
|
31
|
+
return Object.values(VpnType).filter((item) => {
|
|
32
|
+
return isNaN(Number(item));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
exports.getVpnConfigTypes = getVpnConfigTypes;
|
|
36
|
+
function validateVpnId(vpnId) {
|
|
37
|
+
// e.g: YYYYMMDDHHmmssmss@az-test-7
|
|
38
|
+
if (!/\d{4}[01]\d[0-3]\d[0-2]\d[0-5]\d[0-5]\d\d{3}@[a-z]{2}-[a-z]+-\d/.test(vpnId)) {
|
|
39
|
+
throw new errors_1.MyTmpVpnError(`Incorrect vpnId: \'${vpnId}\'`);
|
|
40
|
+
}
|
|
41
|
+
return vpnId;
|
|
42
|
+
}
|
|
43
|
+
function validateMaxPeanuts(peanuts, currentBalance, vpnConfigLimits) {
|
|
44
|
+
let result = peanuts;
|
|
45
|
+
if (peanuts <= 0) {
|
|
46
|
+
result = Math.min(currentBalance, vpnConfigLimits.maxPeanutsFieldMaxValue);
|
|
47
|
+
}
|
|
48
|
+
if (result > currentBalance) {
|
|
49
|
+
throw new errors_1.NotEnoughPeanutsError(result, currentBalance);
|
|
50
|
+
}
|
|
51
|
+
if (result < vpnConfigLimits.maxPeanutsFieldMinValue) {
|
|
52
|
+
throw new errors_1.MinPeanutsError(vpnConfigLimits.maxPeanutsFieldMinValue, result, currentBalance);
|
|
53
|
+
}
|
|
54
|
+
if (result > vpnConfigLimits.maxPeanutsFieldMaxValue) {
|
|
55
|
+
throw new errors_1.MaxPeanutsError(vpnConfigLimits.maxPeanutsFieldMaxValue, result, currentBalance);
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
function validateDeleteAfter(deleteAfter, vpnConfigLimits) {
|
|
60
|
+
if (deleteAfter === undefined) {
|
|
61
|
+
return vpnConfigLimits.deleteAfterFieldMaxValue;
|
|
62
|
+
}
|
|
63
|
+
if (deleteAfter < vpnConfigLimits.deleteAfterFieldMinValue) {
|
|
64
|
+
throw new errors_1.MinDeleteAfterError(vpnConfigLimits.deleteAfterFieldMinValue, deleteAfter);
|
|
65
|
+
}
|
|
66
|
+
if (deleteAfter > vpnConfigLimits.deleteAfterFieldMaxValue) {
|
|
67
|
+
throw new errors_1.MaxDeleteAfterError(vpnConfigLimits.deleteAfterFieldMaxValue, deleteAfter);
|
|
68
|
+
}
|
|
69
|
+
return deleteAfter;
|
|
70
|
+
}
|
|
71
|
+
// Return whether the given vpn should be taken into account when computing
|
|
72
|
+
// whether a given user has reached its quota or not
|
|
73
|
+
function vpnAgainstQuotaPredicate(uservpn) {
|
|
74
|
+
// We return true only when the vpn is in a state that is below Running, and not Failed.
|
|
75
|
+
// The idea is that those ones are either already running or will soon, so they have to be
|
|
76
|
+
// part of the quota. Others (Failed, and Deprovisioning, Deleted) are gone, so they should not count.
|
|
77
|
+
return (uservpn.vpn.state !== VpnState.Failed) && (toRank(uservpn.vpn.state) <= toRank(VpnState.Running));
|
|
78
|
+
}
|
|
79
|
+
exports.vpnAgainstQuotaPredicate = vpnAgainstQuotaPredicate;
|
|
80
|
+
function validateVpnNbAgainstQuota(vpnNb, quota) {
|
|
81
|
+
if (vpnNb >= quota) {
|
|
82
|
+
throw new errors_1.InvalidUserConfigError(`User already has ${quota} active vpns. Quota reached.`);
|
|
83
|
+
}
|
|
84
|
+
return vpnNb;
|
|
85
|
+
}
|
|
86
|
+
exports.validateVpnNbAgainstQuota = validateVpnNbAgainstQuota;
|
|
87
|
+
// vpnConfig is of type any here because it could come from user input such as json
|
|
88
|
+
function checkValidConfig(userId, currentBalance, vpnConfigLimits, vpnConfig) {
|
|
89
|
+
const maxPeanuts = checkValidMaxPeanuts(userId, currentBalance, vpnConfig.maxPeanuts, vpnConfigLimits);
|
|
90
|
+
const type = checkValidVpnType(vpnConfig.type);
|
|
91
|
+
const deleteAfter = checkValidDeleteAfter(vpnConfig.deleteAfter, vpnConfigLimits);
|
|
92
|
+
const result = {
|
|
93
|
+
maxPeanuts,
|
|
94
|
+
type,
|
|
95
|
+
deleteAfter
|
|
96
|
+
};
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
exports.checkValidConfig = checkValidConfig;
|
|
100
|
+
function checkValidMaxPeanuts(userId, currentBalance, maxPeanuts, vpnConfigLimits) {
|
|
101
|
+
const peanuts = maxPeanuts ? Number.parseFloat(maxPeanuts) : -1;
|
|
102
|
+
if (Number.isNaN(peanuts) || !Number.isFinite(peanuts)) {
|
|
103
|
+
throw new errors_1.InvalidVpnConfigError(`Config maxPeanuts is invalid: ${maxPeanuts}`);
|
|
104
|
+
}
|
|
105
|
+
console.debug(`Validating peanuts for ${userId}, peanuts: ${peanuts}, currentBalance: ${currentBalance}`);
|
|
106
|
+
return validateMaxPeanuts(peanuts, currentBalance, vpnConfigLimits);
|
|
107
|
+
}
|
|
108
|
+
function checkValidVpnType(jsonType) {
|
|
109
|
+
if (!jsonType) {
|
|
110
|
+
throw new errors_1.InvalidVpnConfigError(`Config type is null or undefined: ${jsonType}`);
|
|
111
|
+
}
|
|
112
|
+
const type = jsonType;
|
|
113
|
+
if (!type || !Object.values(VpnType).includes(type)) {
|
|
114
|
+
throw new errors_1.InvalidVpnConfigError(`Config type is invalid: ${jsonType}`);
|
|
115
|
+
}
|
|
116
|
+
return type;
|
|
117
|
+
}
|
|
118
|
+
function checkValidDeleteAfter(jsonDeleteAfter, vpnConfigLimits) {
|
|
119
|
+
if (jsonDeleteAfter === undefined) {
|
|
120
|
+
return validateDeleteAfter(undefined, vpnConfigLimits);
|
|
121
|
+
}
|
|
122
|
+
const deleteAfter = Number.parseInt(jsonDeleteAfter);
|
|
123
|
+
if (Number.isNaN(deleteAfter)) {
|
|
124
|
+
throw new errors_1.InvalidVpnConfigError(`Config deleteAfter is invalid: ${jsonDeleteAfter}`);
|
|
125
|
+
}
|
|
126
|
+
return validateDeleteAfter(deleteAfter, vpnConfigLimits);
|
|
127
|
+
}
|
|
128
|
+
function newVpn(region, config, state) {
|
|
129
|
+
// e.g: ap-northeast-3
|
|
130
|
+
if (!/[a-z]{2}-[a-z]+-[1-9]+/.test(region)) {
|
|
131
|
+
throw new errors_1.MyTmpVpnError(`Incorrect region: \'${region}\'`);
|
|
132
|
+
}
|
|
133
|
+
const createdAt = new Date();
|
|
134
|
+
const vpnId = `${dateToId(createdAt)}@${region}`;
|
|
135
|
+
// Assert we will be able to deserialize later on...
|
|
136
|
+
validateVpnId(vpnId);
|
|
137
|
+
return {
|
|
138
|
+
vpnId,
|
|
139
|
+
createdAt,
|
|
140
|
+
region,
|
|
141
|
+
config,
|
|
142
|
+
state
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
exports.newVpn = newVpn;
|
|
146
|
+
function getVpnFrom(vpnId, state, config) {
|
|
147
|
+
validateVpnId(vpnId);
|
|
148
|
+
const tokens = vpnId.split('@');
|
|
149
|
+
if (tokens.length !== 2) {
|
|
150
|
+
throw new errors_1.MyTmpVpnError(`Incorrect vpnId: ${vpnId}`);
|
|
151
|
+
}
|
|
152
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
153
|
+
const createdAt = idToDate(tokens[0]);
|
|
154
|
+
const region = tokens[1];
|
|
155
|
+
/* eslint-enable @typescript-eslint/no-non-null-assertion */
|
|
156
|
+
return {
|
|
157
|
+
vpnId,
|
|
158
|
+
createdAt,
|
|
159
|
+
region,
|
|
160
|
+
config,
|
|
161
|
+
state
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
exports.getVpnFrom = getVpnFrom;
|
|
165
|
+
// Using a date from an id is convenient for debugging.
|
|
166
|
+
// We can't use Date.toISOString() because some characters are forbidden
|
|
167
|
+
// E.g: SFn refuse the ':'
|
|
168
|
+
// So we need convertor back and forth
|
|
169
|
+
function dateToId(date) {
|
|
170
|
+
// YYYY-MM-DDTHH:mm:ss.uuuZ -> YYYYMMDDHHmmssuuu
|
|
171
|
+
return date.toISOString().replace(/[^\d]/g, '');
|
|
172
|
+
}
|
|
173
|
+
function idToDate(id) {
|
|
174
|
+
// YYYYMMDDHHmmssuuu -> YYYY-MM-DDTHH:mm:ss.uuuZ
|
|
175
|
+
const year = id.substring(0, 4);
|
|
176
|
+
const month = id.substring(4, 6);
|
|
177
|
+
const day = id.substring(6, 8);
|
|
178
|
+
const hour = id.substring(8, 10);
|
|
179
|
+
const minute = id.substring(10, 12);
|
|
180
|
+
const second = id.substring(12, 14);
|
|
181
|
+
const millis = id.substring(14);
|
|
182
|
+
return new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}.${millis}Z`);
|
|
183
|
+
}
|
|
184
|
+
// The WireGuard Mobile Application has requirements for the wireguard configuration file:
|
|
185
|
+
// 1. must have extension '.conf'
|
|
186
|
+
// 2. file name must match the following regexp: "[a-zA-Z0-9_=+.-]{1,15}")
|
|
187
|
+
// https://git.zx2c4.com/wireguard-android/tree/tunnel/src/main/java/com/wireguard/android/backend/Tunnel.java#n19
|
|
188
|
+
// This function is to transform from vpnIn to Wireguard mobile application requirements
|
|
189
|
+
function vpnIdToWgFileName(vpnId) {
|
|
190
|
+
validateVpnId(vpnId);
|
|
191
|
+
// The vpnId is made of YYYYMMDDHHmmssmss@region
|
|
192
|
+
// Let's keep it simple: vpn is mostly temporary, so keeping
|
|
193
|
+
// the year is useless.
|
|
194
|
+
// Also the milliseconds are useless.
|
|
195
|
+
// Finally, the region itself is of the following format: ap-northeast-3
|
|
196
|
+
// We can compressing with something like:
|
|
197
|
+
// MMDDHHmmssapne3.conf
|
|
198
|
+
const ddhhmmss = vpnId.substring(4, 14);
|
|
199
|
+
const seps = vpnId.substring(18).split(/-/);
|
|
200
|
+
const ccld = seps[0];
|
|
201
|
+
let location;
|
|
202
|
+
switch (seps[1]) {
|
|
203
|
+
case 'north':
|
|
204
|
+
location = 'n';
|
|
205
|
+
break;
|
|
206
|
+
case 'northeast':
|
|
207
|
+
location = 'ne';
|
|
208
|
+
break;
|
|
209
|
+
case 'east':
|
|
210
|
+
location = 'e';
|
|
211
|
+
break;
|
|
212
|
+
case 'southeast':
|
|
213
|
+
location = 'se';
|
|
214
|
+
break;
|
|
215
|
+
case 'south':
|
|
216
|
+
location = 's';
|
|
217
|
+
break;
|
|
218
|
+
case 'southwest':
|
|
219
|
+
location = 'sw';
|
|
220
|
+
break;
|
|
221
|
+
case 'west':
|
|
222
|
+
location = 'w';
|
|
223
|
+
break;
|
|
224
|
+
case 'northwest':
|
|
225
|
+
location = 'nw';
|
|
226
|
+
break;
|
|
227
|
+
case 'central':
|
|
228
|
+
location = 'c';
|
|
229
|
+
break;
|
|
230
|
+
default:
|
|
231
|
+
'';
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
const number = seps[2];
|
|
235
|
+
// Let's make sure the end file is of 15 char max
|
|
236
|
+
const result = `${ddhhmmss}${ccld}${location}${number}`.substring(0, 15);
|
|
237
|
+
console.log(`Transforming ${vpnId} to ${result}`);
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
exports.vpnIdToWgFileName = vpnIdToWgFileName;
|
|
241
|
+
function vpnToClient(vpn) {
|
|
242
|
+
return {
|
|
243
|
+
vpnId: vpn.vpnId,
|
|
244
|
+
state: vpn.state,
|
|
245
|
+
region: vpn.region,
|
|
246
|
+
createdAt: vpn.createdAt,
|
|
247
|
+
config: {
|
|
248
|
+
type: vpn.config.type,
|
|
249
|
+
deleteAfter: vpn.config.deleteAfter,
|
|
250
|
+
maxPeanuts: (0, peanuts_1.peanutsToClient)(vpn.config.maxPeanuts),
|
|
251
|
+
// terminationReason: userVpn.vpn.config.terminationReason,
|
|
252
|
+
// terminationMessage: userVpn.vpn.config.terminationMessage,
|
|
253
|
+
// terminationCode: userVpn.vpn.config.terminationCode,
|
|
254
|
+
// terminationType: userVpn.vpn.config.terminationType,
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
exports.vpnToClient = vpnToClient;
|
|
259
|
+
function metricsToClient(metrics) {
|
|
260
|
+
return (metrics != null)
|
|
261
|
+
? {
|
|
262
|
+
duration: metrics.duration,
|
|
263
|
+
bytes: metrics.bytes,
|
|
264
|
+
peanuts: (0, peanuts_1.peanutsToClient)(metrics.peanuts)
|
|
265
|
+
}
|
|
266
|
+
: {
|
|
267
|
+
duration: Number.NaN,
|
|
268
|
+
bytes: Number.NaN,
|
|
269
|
+
peanuts: Number.NaN,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
exports.metricsToClient = metricsToClient;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sleep = exports.choose = exports.getFromEnvOrThrow = void 0;
|
|
4
|
+
const log = require("loglevel");
|
|
5
|
+
function getFromEnvOrThrow(env) {
|
|
6
|
+
const result = process.env[env];
|
|
7
|
+
if (result === null || result === undefined || result.trim() === '') {
|
|
8
|
+
throw new Error(`${env} unset in environment!`);
|
|
9
|
+
}
|
|
10
|
+
log.debug(`Using ${env} = ${result}`);
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
exports.getFromEnvOrThrow = getFromEnvOrThrow;
|
|
14
|
+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
|
15
|
+
function choose(choices) {
|
|
16
|
+
const index = Math.floor(Math.random() * choices.length);
|
|
17
|
+
return choices[index];
|
|
18
|
+
}
|
|
19
|
+
exports.choose = choose;
|
|
20
|
+
async function sleep(millis) {
|
|
21
|
+
await new Promise(resolve => setTimeout(resolve, millis));
|
|
22
|
+
}
|
|
23
|
+
exports.sleep = sleep;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const uservpn_1 = require("../src/models/uservpn");
|
|
4
|
+
const errors_1 = require("../src/errors");
|
|
5
|
+
const vpn_1 = require("../src/models/vpn");
|
|
6
|
+
describe('Testing VpnState', () => {
|
|
7
|
+
it('should check that all VpnState are ordered properly', async () => {
|
|
8
|
+
expect((0, vpn_1.toRank)(vpn_1.VpnState.Creating) <= (0, vpn_1.toRank)(vpn_1.VpnState.Created)).toBe(true);
|
|
9
|
+
expect((0, vpn_1.toRank)(vpn_1.VpnState.Created) <= (0, vpn_1.toRank)(vpn_1.VpnState.Provisioning)).toBe(true);
|
|
10
|
+
expect((0, vpn_1.toRank)(vpn_1.VpnState.Provisioning) <= (0, vpn_1.toRank)(vpn_1.VpnState.Running)).toBe(true);
|
|
11
|
+
expect((0, vpn_1.toRank)(vpn_1.VpnState.Paused) <= (0, vpn_1.toRank)(vpn_1.VpnState.Running)).toBe(true);
|
|
12
|
+
expect((0, vpn_1.toRank)(vpn_1.VpnState.Running) <= (0, vpn_1.toRank)(vpn_1.VpnState.Deprovisioning)).toBe(true);
|
|
13
|
+
expect((0, vpn_1.toRank)(vpn_1.VpnState.Deprovisioning) <= (0, vpn_1.toRank)(vpn_1.VpnState.Deleted)).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
it('should check that state == fromRank(toRank(state))', async () => {
|
|
16
|
+
Object.values(vpn_1.VpnState).forEach(state => {
|
|
17
|
+
expect(state === (0, vpn_1.fromRank)((0, vpn_1.toRank)(state))).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
describe('Testing Vpn constructors', () => {
|
|
22
|
+
it('Should shout when regions is empty', async () => {
|
|
23
|
+
expect(() => (0, vpn_1.newVpn)('', { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }, vpn_1.VpnState.Created))
|
|
24
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect region: \'\'"));
|
|
25
|
+
});
|
|
26
|
+
it('Should shout when regions is bad format', async () => {
|
|
27
|
+
expect(() => (0, vpn_1.newVpn)('foo', { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }, vpn_1.VpnState.Created))
|
|
28
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect region: \'foo\'"));
|
|
29
|
+
});
|
|
30
|
+
it('Should create vpn with all mandatory fields set', async () => {
|
|
31
|
+
const vpn = (0, vpn_1.newVpn)('az-test-7', { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }, vpn_1.VpnState.Created);
|
|
32
|
+
expect(vpn.createdAt).toBeDefined();
|
|
33
|
+
expect(vpn.region).toEqual('az-test-7');
|
|
34
|
+
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
35
|
+
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard });
|
|
36
|
+
expect(vpn.vpnId).toBeDefined();
|
|
37
|
+
});
|
|
38
|
+
it('Should create vpn with optional fields set', async () => {
|
|
39
|
+
const vpn = (0, vpn_1.newVpn)('az-test-7', {
|
|
40
|
+
maxPeanuts: -1,
|
|
41
|
+
type: vpn_1.VpnType.WireGuard,
|
|
42
|
+
deleteAfter: 37,
|
|
43
|
+
}, vpn_1.VpnState.Created);
|
|
44
|
+
expect(vpn.createdAt).toBeDefined();
|
|
45
|
+
expect(vpn.region).toEqual('az-test-7');
|
|
46
|
+
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
47
|
+
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: 37 });
|
|
48
|
+
expect(vpn.vpnId).toBeDefined();
|
|
49
|
+
});
|
|
50
|
+
it('Should create vpn with deleteAfter set to NaN', async () => {
|
|
51
|
+
const deleteAfter = Number.NaN;
|
|
52
|
+
const vpn = (0, vpn_1.newVpn)('az-test-7', {
|
|
53
|
+
maxPeanuts: -1,
|
|
54
|
+
type: vpn_1.VpnType.WireGuard,
|
|
55
|
+
deleteAfter: deleteAfter
|
|
56
|
+
}, vpn_1.VpnState.Created);
|
|
57
|
+
expect(vpn.createdAt).toBeDefined();
|
|
58
|
+
expect(vpn.region).toEqual('az-test-7');
|
|
59
|
+
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
60
|
+
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: deleteAfter });
|
|
61
|
+
expect(vpn.vpnId).toBeDefined();
|
|
62
|
+
});
|
|
63
|
+
it('Should deserialize a vpn with all mandatory fields set', async () => {
|
|
64
|
+
const vpn = (0, vpn_1.getVpnFrom)('20030902012345678@az-test-7', vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: 37 });
|
|
65
|
+
expect(vpn.createdAt).toEqual(new Date('2003-09-02T01:23:45.678Z'));
|
|
66
|
+
expect(vpn.region).toEqual('az-test-7');
|
|
67
|
+
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
68
|
+
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: 37 });
|
|
69
|
+
expect(vpn.vpnId).toBeDefined();
|
|
70
|
+
});
|
|
71
|
+
it('Should deserialize a vpn with deleteAfter set to NaN', async () => {
|
|
72
|
+
const deleteAfter = Number.NaN;
|
|
73
|
+
const vpn = (0, vpn_1.getVpnFrom)('20030902012345678@az-test-7', vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: deleteAfter });
|
|
74
|
+
expect(vpn.createdAt).toEqual(new Date('2003-09-02T01:23:45.678Z'));
|
|
75
|
+
expect(vpn.region).toEqual('az-test-7');
|
|
76
|
+
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
77
|
+
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: deleteAfter });
|
|
78
|
+
expect(vpn.vpnId).toBeDefined();
|
|
79
|
+
});
|
|
80
|
+
it('Should deserialize a json vpn with all fields set', async () => {
|
|
81
|
+
const originalVpn = (0, uservpn_1.newUserVpn)({
|
|
82
|
+
userId: 'myId',
|
|
83
|
+
region: 'az-test-7',
|
|
84
|
+
version: 1,
|
|
85
|
+
config: {
|
|
86
|
+
maxPeanuts: -1,
|
|
87
|
+
type: vpn_1.VpnType.WireGuard,
|
|
88
|
+
deleteAfter: 37
|
|
89
|
+
},
|
|
90
|
+
state: vpn_1.VpnState.Created,
|
|
91
|
+
});
|
|
92
|
+
const jsonString = JSON.stringify(originalVpn);
|
|
93
|
+
const userVpn = (0, uservpn_1.jsonToUserVpn)(jsonString);
|
|
94
|
+
expect(userVpn).toEqual(originalVpn);
|
|
95
|
+
});
|
|
96
|
+
it('Should shout when vpnId is empty', async () => {
|
|
97
|
+
expect(() => (0, vpn_1.getVpnFrom)('', vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }))
|
|
98
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect vpnId: \'\'"));
|
|
99
|
+
});
|
|
100
|
+
it('Should shout when vpnId has bad format', async () => {
|
|
101
|
+
expect(() => (0, vpn_1.getVpnFrom)('foo', vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }))
|
|
102
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect vpnId: \'foo\'"));
|
|
103
|
+
});
|
|
104
|
+
it('Should shout when vpnId does not hold a region in good format', async () => {
|
|
105
|
+
expect(() => (0, vpn_1.getVpnFrom)('20030902012345678@test', vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }))
|
|
106
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect vpnId: \'20030902012345678@test\'"));
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('Testing vpnId to Wireguard file name functions ', () => {
|
|
110
|
+
it('Should shout when vpnId is empty', async () => {
|
|
111
|
+
expect(() => (0, vpn_1.vpnIdToWgFileName)(''))
|
|
112
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect vpnId: \'\'"));
|
|
113
|
+
});
|
|
114
|
+
it('Should shout when vpnId is bad format', async () => {
|
|
115
|
+
expect(() => (0, vpn_1.vpnIdToWgFileName)('foo'))
|
|
116
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect vpnId: \'foo\'"));
|
|
117
|
+
});
|
|
118
|
+
it('Should shout when region has bad format', async () => {
|
|
119
|
+
expect(() => (0, vpn_1.vpnIdToWgFileName)('20030902012345678@test'))
|
|
120
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect vpnId: \'20030902012345678@test\'"));
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe('Testing vpn config', () => {
|
|
124
|
+
it('Should set maxPeanuts to the validPeanutsConfig maximum when set to negative', async () => {
|
|
125
|
+
const validatedConfig = (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
126
|
+
maxPeanutsFieldMinValue: 0,
|
|
127
|
+
maxPeanutsFieldMaxValue: 1,
|
|
128
|
+
deleteAfterFieldMinValue: 1,
|
|
129
|
+
deleteAfterFieldMaxValue: 3,
|
|
130
|
+
}, {
|
|
131
|
+
maxPeanuts: -1,
|
|
132
|
+
type: vpn_1.VpnType.WireGuard,
|
|
133
|
+
deleteAfter: 1
|
|
134
|
+
});
|
|
135
|
+
expect(validatedConfig).toEqual({
|
|
136
|
+
maxPeanuts: 1,
|
|
137
|
+
type: vpn_1.VpnType.WireGuard,
|
|
138
|
+
deleteAfter: 1
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
it('Should set maxPeanuts to the validPeanutsConfig maximum when null', async () => {
|
|
142
|
+
const validatedConfig = (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
143
|
+
maxPeanutsFieldMinValue: 0,
|
|
144
|
+
maxPeanutsFieldMaxValue: 1,
|
|
145
|
+
deleteAfterFieldMinValue: 1,
|
|
146
|
+
deleteAfterFieldMaxValue: 3,
|
|
147
|
+
}, {
|
|
148
|
+
maxPeanuts: null,
|
|
149
|
+
type: vpn_1.VpnType.WireGuard,
|
|
150
|
+
deleteAfter: 1
|
|
151
|
+
});
|
|
152
|
+
expect(validatedConfig).toEqual({
|
|
153
|
+
maxPeanuts: 1,
|
|
154
|
+
type: vpn_1.VpnType.WireGuard,
|
|
155
|
+
deleteAfter: 1
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
it('Should set maxPeanuts to the validPeanutsConfig maximum when undefined', async () => {
|
|
159
|
+
const validatedConfig = (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
160
|
+
maxPeanutsFieldMinValue: 0,
|
|
161
|
+
maxPeanutsFieldMaxValue: 1,
|
|
162
|
+
deleteAfterFieldMinValue: 1,
|
|
163
|
+
deleteAfterFieldMaxValue: 3,
|
|
164
|
+
}, {
|
|
165
|
+
maxPeanuts: undefined,
|
|
166
|
+
type: vpn_1.VpnType.WireGuard,
|
|
167
|
+
deleteAfter: 1
|
|
168
|
+
});
|
|
169
|
+
expect(validatedConfig).toEqual({
|
|
170
|
+
maxPeanuts: 1,
|
|
171
|
+
type: vpn_1.VpnType.WireGuard,
|
|
172
|
+
deleteAfter: 1
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
it('Should shout when maxPeanuts is Infinity', async () => {
|
|
176
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
177
|
+
maxPeanutsFieldMinValue: 2,
|
|
178
|
+
maxPeanutsFieldMaxValue: 3,
|
|
179
|
+
deleteAfterFieldMinValue: 1,
|
|
180
|
+
deleteAfterFieldMaxValue: 3,
|
|
181
|
+
}, {
|
|
182
|
+
maxPeanuts: Number.POSITIVE_INFINITY,
|
|
183
|
+
type: vpn_1.VpnType.WireGuard,
|
|
184
|
+
deleteAfter: 1
|
|
185
|
+
})).toThrow(new errors_1.InvalidVpnConfigError('Config maxPeanuts is invalid: Infinity'));
|
|
186
|
+
});
|
|
187
|
+
it('Should shout when maxPeanuts is -Infinity', async () => {
|
|
188
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
189
|
+
maxPeanutsFieldMinValue: 2,
|
|
190
|
+
maxPeanutsFieldMaxValue: 3,
|
|
191
|
+
deleteAfterFieldMinValue: 1,
|
|
192
|
+
deleteAfterFieldMaxValue: 3,
|
|
193
|
+
}, {
|
|
194
|
+
maxPeanuts: Number.NEGATIVE_INFINITY,
|
|
195
|
+
type: vpn_1.VpnType.WireGuard,
|
|
196
|
+
deleteAfter: 1
|
|
197
|
+
})).toThrow(new errors_1.InvalidVpnConfigError('Config maxPeanuts is invalid: -Infinity'));
|
|
198
|
+
});
|
|
199
|
+
it('Should shout when maxPeanuts is not a number', async () => {
|
|
200
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
201
|
+
maxPeanutsFieldMinValue: 2,
|
|
202
|
+
maxPeanutsFieldMaxValue: 3,
|
|
203
|
+
deleteAfterFieldMinValue: 1,
|
|
204
|
+
deleteAfterFieldMaxValue: 3,
|
|
205
|
+
}, {
|
|
206
|
+
maxPeanuts: 'Not a number',
|
|
207
|
+
type: vpn_1.VpnType.WireGuard,
|
|
208
|
+
deleteAfter: 1
|
|
209
|
+
})).toThrow(new errors_1.InvalidVpnConfigError('Config maxPeanuts is invalid: Not a number'));
|
|
210
|
+
});
|
|
211
|
+
it('Should shout when maxPeanuts is below the validPeanutsConfig minimum', async () => {
|
|
212
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
213
|
+
maxPeanutsFieldMinValue: 2,
|
|
214
|
+
maxPeanutsFieldMaxValue: 3,
|
|
215
|
+
deleteAfterFieldMinValue: 1,
|
|
216
|
+
deleteAfterFieldMaxValue: 3,
|
|
217
|
+
}, {
|
|
218
|
+
maxPeanuts: 1,
|
|
219
|
+
type: vpn_1.VpnType.WireGuard,
|
|
220
|
+
deleteAfter: 1
|
|
221
|
+
})).toThrow(new errors_1.MinPeanutsError(2, 1, 2));
|
|
222
|
+
});
|
|
223
|
+
it('Should shout when maxPeanuts is above the validPeanutsConfig maximum', async () => {
|
|
224
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 10, {
|
|
225
|
+
maxPeanutsFieldMinValue: 2,
|
|
226
|
+
maxPeanutsFieldMaxValue: 3,
|
|
227
|
+
deleteAfterFieldMinValue: 1,
|
|
228
|
+
deleteAfterFieldMaxValue: 3,
|
|
229
|
+
}, {
|
|
230
|
+
maxPeanuts: 5,
|
|
231
|
+
type: vpn_1.VpnType.WireGuard,
|
|
232
|
+
deleteAfter: 1
|
|
233
|
+
})).toThrow(new errors_1.MaxPeanutsError(3, 5, 10));
|
|
234
|
+
});
|
|
235
|
+
it('Should shout when deleteAfter is below the validPeanutsConfig minimum', async () => {
|
|
236
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
237
|
+
maxPeanutsFieldMinValue: 1,
|
|
238
|
+
maxPeanutsFieldMaxValue: 3,
|
|
239
|
+
deleteAfterFieldMinValue: 3,
|
|
240
|
+
deleteAfterFieldMaxValue: 5,
|
|
241
|
+
}, {
|
|
242
|
+
maxPeanuts: 1,
|
|
243
|
+
type: vpn_1.VpnType.WireGuard,
|
|
244
|
+
deleteAfter: 1
|
|
245
|
+
})).toThrow(new errors_1.MinDeleteAfterError(3, 1));
|
|
246
|
+
});
|
|
247
|
+
it('Should shout when deleteAfter is greater the validPeanutsConfig maximum', async () => {
|
|
248
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
249
|
+
maxPeanutsFieldMinValue: 1,
|
|
250
|
+
maxPeanutsFieldMaxValue: 3,
|
|
251
|
+
deleteAfterFieldMinValue: 3,
|
|
252
|
+
deleteAfterFieldMaxValue: 5,
|
|
253
|
+
}, {
|
|
254
|
+
maxPeanuts: 1,
|
|
255
|
+
type: vpn_1.VpnType.WireGuard,
|
|
256
|
+
deleteAfter: 7
|
|
257
|
+
})).toThrow(new errors_1.MaxDeleteAfterError(5, 7));
|
|
258
|
+
});
|
|
259
|
+
it('Should shout when deleteAfter is positive infinity', async () => {
|
|
260
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
261
|
+
maxPeanutsFieldMinValue: 1,
|
|
262
|
+
maxPeanutsFieldMaxValue: 3,
|
|
263
|
+
deleteAfterFieldMinValue: 3,
|
|
264
|
+
deleteAfterFieldMaxValue: 5,
|
|
265
|
+
}, {
|
|
266
|
+
maxPeanuts: 1,
|
|
267
|
+
type: vpn_1.VpnType.WireGuard,
|
|
268
|
+
deleteAfter: Number.POSITIVE_INFINITY
|
|
269
|
+
})).toThrow(new errors_1.InvalidVpnConfigError('Config deleteAfter is invalid: Infinity'));
|
|
270
|
+
});
|
|
271
|
+
it('Should shout when deleteAfter is negative infinity', async () => {
|
|
272
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
273
|
+
maxPeanutsFieldMinValue: 1,
|
|
274
|
+
maxPeanutsFieldMaxValue: 3,
|
|
275
|
+
deleteAfterFieldMinValue: 3,
|
|
276
|
+
deleteAfterFieldMaxValue: 5,
|
|
277
|
+
}, {
|
|
278
|
+
maxPeanuts: 1,
|
|
279
|
+
type: vpn_1.VpnType.WireGuard,
|
|
280
|
+
deleteAfter: Number.NEGATIVE_INFINITY
|
|
281
|
+
})).toThrow(new errors_1.InvalidVpnConfigError('Config deleteAfter is invalid: -Infinity'));
|
|
282
|
+
});
|
|
283
|
+
it('Should shout when deleteAfter is not a number', async () => {
|
|
284
|
+
expect(() => (0, vpn_1.checkValidConfig)('userId', 2, {
|
|
285
|
+
maxPeanutsFieldMinValue: 1,
|
|
286
|
+
maxPeanutsFieldMaxValue: 3,
|
|
287
|
+
deleteAfterFieldMinValue: 3,
|
|
288
|
+
deleteAfterFieldMaxValue: 5,
|
|
289
|
+
}, {
|
|
290
|
+
maxPeanuts: 1,
|
|
291
|
+
type: vpn_1.VpnType.WireGuard,
|
|
292
|
+
deleteAfter: 'Not a number'
|
|
293
|
+
})).toThrow(new errors_1.InvalidVpnConfigError('Config deleteAfter is invalid: Not a number'));
|
|
294
|
+
});
|
|
295
|
+
it('Should not shout when deleteAfter is undefined', async () => {
|
|
296
|
+
expect((0, vpn_1.checkValidConfig)('userId', 2, {
|
|
297
|
+
maxPeanutsFieldMinValue: 1,
|
|
298
|
+
maxPeanutsFieldMaxValue: 3,
|
|
299
|
+
deleteAfterFieldMinValue: 3,
|
|
300
|
+
deleteAfterFieldMaxValue: 5,
|
|
301
|
+
}, {
|
|
302
|
+
maxPeanuts: 1,
|
|
303
|
+
type: vpn_1.VpnType.WireGuard,
|
|
304
|
+
})).toEqual({
|
|
305
|
+
maxPeanuts: 1,
|
|
306
|
+
type: vpn_1.VpnType.WireGuard,
|
|
307
|
+
deleteAfter: 5
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mytmpvpn/mytmpvpn-common",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.2",
|
|
4
4
|
"description": "Common library for all MyTmpVpn related projects",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -23,7 +23,10 @@
|
|
|
23
23
|
"test": "jest",
|
|
24
24
|
"link-deps": "echo \"No dependencies, noop; that's fine\"",
|
|
25
25
|
"clean": "rm -rf dist/",
|
|
26
|
-
"upgrade": "ncu --target semver --upgrade"
|
|
26
|
+
"upgrade": "ncu --target semver --upgrade",
|
|
27
|
+
"prepublishOnly": "npm ci && npm run build && npm run test",
|
|
28
|
+
"version": "git add -A",
|
|
29
|
+
"postversion": "git push && git push --tags && npm publish"
|
|
27
30
|
},
|
|
28
31
|
"keywords": [],
|
|
29
32
|
"author": "pierre.vigneras@gmail.com",
|