@mytmpvpn/mytmpvpn-common 9.0.0 → 10.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/jest.config.d.ts +4 -0
- package/dist/jest.config.js +8 -1
- package/dist/src/models/index.d.ts +2 -0
- package/dist/src/models/index.js +3 -1
- package/dist/src/models/location.d.ts +40 -0
- package/dist/src/models/location.js +18 -0
- package/dist/src/models/uservpn.d.ts +17 -10
- package/dist/src/models/uservpn.js +10 -6
- package/dist/src/models/vpn.d.ts +31 -35
- package/dist/src/models/vpn.js +142 -156
- package/dist/src/models/vpnConfig.d.ts +22 -0
- package/dist/src/models/vpnConfig.js +89 -0
- package/dist/test/models.test.js +64 -56
- package/package.json +3 -2
- package/dist/tsconfig.tsbuildinfo +0 -1
package/dist/jest.config.d.ts
CHANGED
package/dist/jest.config.js
CHANGED
|
@@ -5,5 +5,12 @@ module.exports = {
|
|
|
5
5
|
testMatch: ['**/*.test.ts'],
|
|
6
6
|
transform: {
|
|
7
7
|
'^.+\\.tsx?$': 'ts-jest'
|
|
8
|
-
}
|
|
8
|
+
},
|
|
9
|
+
collectCoverage: true,
|
|
10
|
+
coverageDirectory: 'coverage',
|
|
11
|
+
collectCoverageFrom: [
|
|
12
|
+
'src/**/*.ts',
|
|
13
|
+
'!src/**/*.d.ts'
|
|
14
|
+
],
|
|
15
|
+
coverageReporters: ['text', 'lcov', 'html'],
|
|
9
16
|
};
|
package/dist/src/models/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.referral = exports.uservpn = exports.vpn = void 0;
|
|
3
|
+
exports.location = exports.peanuts = exports.referral = exports.uservpn = exports.vpn = void 0;
|
|
4
4
|
exports.vpn = require("./vpn");
|
|
5
5
|
exports.uservpn = require("./uservpn");
|
|
6
6
|
exports.referral = require("./referral");
|
|
7
|
+
exports.peanuts = require("./peanuts");
|
|
8
|
+
exports.location = require("./location");
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare enum InfrastructureProvider {
|
|
2
|
+
Aws = "Aws",
|
|
3
|
+
GoogleCloud = "GoogleCloud",
|
|
4
|
+
Azure = "Azure"
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Instance types define the bandwidth capabilities of VPN instances
|
|
8
|
+
*/
|
|
9
|
+
export declare enum InstanceType {
|
|
10
|
+
Ultra = "Ultra",
|
|
11
|
+
Fast = "Fast",
|
|
12
|
+
Eco = "Eco"
|
|
13
|
+
}
|
|
14
|
+
export interface PricingRate {
|
|
15
|
+
peanutsPerMinuteMax: number;
|
|
16
|
+
peanutsPerMinuteMin: number;
|
|
17
|
+
}
|
|
18
|
+
export type PricingRates = Partial<Record<InstanceType, PricingRate>>;
|
|
19
|
+
export interface InfraDetails {
|
|
20
|
+
ipv6Supported: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ProviderInfo {
|
|
23
|
+
infraDetails: InfraDetails;
|
|
24
|
+
pricingRates: PricingRates;
|
|
25
|
+
}
|
|
26
|
+
export type ProvidersInfo = Partial<Record<InfrastructureProvider, ProviderInfo>>;
|
|
27
|
+
export interface Location {
|
|
28
|
+
geonamesId: number;
|
|
29
|
+
city: string;
|
|
30
|
+
country: string;
|
|
31
|
+
countryCode: string;
|
|
32
|
+
coordinates: {
|
|
33
|
+
latitude: number;
|
|
34
|
+
longitude: number;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export interface LocationWithProvidersInfo extends Location {
|
|
38
|
+
providersInfo: ProvidersInfo;
|
|
39
|
+
}
|
|
40
|
+
export type ListLocationsResponse = LocationWithProvidersInfo[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InstanceType = exports.InfrastructureProvider = void 0;
|
|
4
|
+
var InfrastructureProvider;
|
|
5
|
+
(function (InfrastructureProvider) {
|
|
6
|
+
InfrastructureProvider["Aws"] = "Aws";
|
|
7
|
+
InfrastructureProvider["GoogleCloud"] = "GoogleCloud";
|
|
8
|
+
InfrastructureProvider["Azure"] = "Azure";
|
|
9
|
+
})(InfrastructureProvider = exports.InfrastructureProvider || (exports.InfrastructureProvider = {}));
|
|
10
|
+
/**
|
|
11
|
+
* Instance types define the bandwidth capabilities of VPN instances
|
|
12
|
+
*/
|
|
13
|
+
var InstanceType;
|
|
14
|
+
(function (InstanceType) {
|
|
15
|
+
InstanceType["Ultra"] = "Ultra";
|
|
16
|
+
InstanceType["Fast"] = "Fast";
|
|
17
|
+
InstanceType["Eco"] = "Eco";
|
|
18
|
+
})(InstanceType = exports.InstanceType || (exports.InstanceType = {}));
|
|
@@ -1,23 +1,30 @@
|
|
|
1
1
|
import * as vpn from './vpn';
|
|
2
|
+
import { VpnConfig } from './vpnConfig';
|
|
3
|
+
export declare enum UserVpnVersion {
|
|
4
|
+
INITIAL = 0,
|
|
5
|
+
LOCATIONS = 1
|
|
6
|
+
}
|
|
2
7
|
export interface UserVpn {
|
|
3
8
|
userId: string;
|
|
4
|
-
version:
|
|
9
|
+
version: UserVpnVersion;
|
|
5
10
|
vpn: vpn.Vpn;
|
|
6
11
|
}
|
|
7
|
-
export interface
|
|
12
|
+
export interface NewUserVpnParams {
|
|
8
13
|
userId: string;
|
|
9
|
-
|
|
10
|
-
version?:
|
|
11
|
-
config:
|
|
14
|
+
geonamesId: number;
|
|
15
|
+
version?: UserVpnVersion;
|
|
16
|
+
config: VpnConfig;
|
|
12
17
|
state: vpn.VpnState;
|
|
13
18
|
}
|
|
14
|
-
export interface
|
|
19
|
+
export interface GetUserVpnFromParams {
|
|
15
20
|
userId: string;
|
|
16
21
|
vpnId: string;
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
createdAt?: Date;
|
|
23
|
+
geonamesId: number;
|
|
24
|
+
version?: UserVpnVersion;
|
|
25
|
+
config: VpnConfig;
|
|
19
26
|
state: vpn.VpnState;
|
|
20
27
|
}
|
|
21
|
-
export declare function newUserVpn({ userId,
|
|
22
|
-
export declare function getUserVpnFrom({ userId, vpnId, version, ...rest }:
|
|
28
|
+
export declare function newUserVpn({ userId, geonamesId, version, ...rest }: NewUserVpnParams): UserVpn;
|
|
29
|
+
export declare function getUserVpnFrom({ userId, vpnId, geonamesId, createdAt, version, ...rest }: GetUserVpnFromParams): UserVpn;
|
|
23
30
|
export declare function jsonToUserVpn(jsonString: any): UserVpn;
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.jsonToUserVpn = exports.getUserVpnFrom = exports.newUserVpn = void 0;
|
|
3
|
+
exports.jsonToUserVpn = exports.getUserVpnFrom = exports.newUserVpn = exports.UserVpnVersion = void 0;
|
|
4
4
|
const vpn = require("./vpn");
|
|
5
|
-
|
|
6
|
-
function
|
|
5
|
+
var UserVpnVersion;
|
|
6
|
+
(function (UserVpnVersion) {
|
|
7
|
+
UserVpnVersion[UserVpnVersion["INITIAL"] = 0] = "INITIAL";
|
|
8
|
+
UserVpnVersion[UserVpnVersion["LOCATIONS"] = 1] = "LOCATIONS"; // This version introduces locations (geonames)
|
|
9
|
+
})(UserVpnVersion = exports.UserVpnVersion || (exports.UserVpnVersion = {}));
|
|
10
|
+
function newUserVpn({ userId, geonamesId, version = UserVpnVersion.LOCATIONS, ...rest }) {
|
|
7
11
|
return {
|
|
8
12
|
userId,
|
|
9
13
|
version,
|
|
10
|
-
vpn: vpn.newVpn(
|
|
14
|
+
vpn: vpn.newVpn(geonamesId, rest.config, rest.state)
|
|
11
15
|
};
|
|
12
16
|
}
|
|
13
17
|
exports.newUserVpn = newUserVpn;
|
|
14
|
-
function getUserVpnFrom({ userId, vpnId, version =
|
|
18
|
+
function getUserVpnFrom({ userId, vpnId, geonamesId, createdAt, version = UserVpnVersion.LOCATIONS, ...rest }) {
|
|
15
19
|
return {
|
|
16
20
|
userId,
|
|
17
21
|
version,
|
|
18
|
-
vpn: vpn.getVpnFrom(vpnId, rest.state, rest.config)
|
|
22
|
+
vpn: vpn.getVpnFrom(vpnId, createdAt, geonamesId, rest.state, rest.config)
|
|
19
23
|
};
|
|
20
24
|
}
|
|
21
25
|
exports.getUserVpnFrom = getUserVpnFrom;
|
package/dist/src/models/vpn.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { UserVpn } from "./uservpn";
|
|
1
|
+
import { UserVpn, UserVpnVersion } from "./uservpn";
|
|
2
|
+
import { VpnConfig } from "./vpnConfig";
|
|
3
|
+
import { Location } from './location';
|
|
2
4
|
export declare enum VpnState {
|
|
3
5
|
Failed = "Failed",
|
|
4
6
|
Creating = "Creating",
|
|
@@ -14,21 +16,6 @@ export declare function fromRank(rank: number): VpnState;
|
|
|
14
16
|
export declare enum VpnType {
|
|
15
17
|
WireGuard = "wireguard"
|
|
16
18
|
}
|
|
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
19
|
export interface VpnMetrics {
|
|
33
20
|
duration: number;
|
|
34
21
|
bytes: number;
|
|
@@ -37,11 +24,10 @@ export interface VpnMetrics {
|
|
|
37
24
|
export interface Vpn {
|
|
38
25
|
vpnId: string;
|
|
39
26
|
createdAt: Date;
|
|
40
|
-
|
|
27
|
+
geonamesId: number;
|
|
41
28
|
config: VpnConfig;
|
|
42
29
|
state: VpnState;
|
|
43
30
|
}
|
|
44
|
-
export type GetVpnConfigLimitsResponse = VpnConfigLimits;
|
|
45
31
|
export type ListVpnsResponse = Vpn[];
|
|
46
32
|
export interface DeleteVpnResponse {
|
|
47
33
|
vpn: {
|
|
@@ -59,33 +45,43 @@ export interface GetVpnResponse {
|
|
|
59
45
|
vpn: Vpn;
|
|
60
46
|
metrics: VpnMetrics;
|
|
61
47
|
}
|
|
62
|
-
export
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
48
|
+
export declare enum ListVpnsSortByCriteria {
|
|
49
|
+
CreatedAt = "createdAt",
|
|
50
|
+
State = "state",
|
|
51
|
+
GeonamesId = "geonamesId",
|
|
52
|
+
VpnId = "vpnId",
|
|
53
|
+
City = "city",
|
|
54
|
+
Country = "country"
|
|
55
|
+
}
|
|
56
|
+
export declare enum ListVpnsSortOrder {
|
|
57
|
+
Asc = "asc",
|
|
58
|
+
Desc = "desc"
|
|
67
59
|
}
|
|
68
|
-
export type GetVpnConfigResponse = string;
|
|
69
|
-
export type ListRegionsResponse = string[];
|
|
70
|
-
export type ListRegionsDetailedResponse = RegionInfo[];
|
|
71
60
|
export type ListVpnsPagingParams = {
|
|
72
|
-
pageSize:
|
|
73
|
-
nextPageToken
|
|
61
|
+
pageSize: number;
|
|
62
|
+
nextPageToken?: string;
|
|
63
|
+
filterCity?: string;
|
|
64
|
+
filterCountry?: string;
|
|
65
|
+
sortBy?: ListVpnsSortByCriteria;
|
|
66
|
+
sortOrder?: ListVpnsSortOrder;
|
|
74
67
|
};
|
|
75
68
|
export type ListVpnsPaginatedResponse = {
|
|
76
|
-
totalVpns: number;
|
|
77
|
-
totalPages: number;
|
|
78
69
|
vpns: Vpn[];
|
|
79
70
|
nextPageToken: string | undefined;
|
|
80
71
|
};
|
|
81
|
-
export declare function
|
|
72
|
+
export declare function validateVpnId(vpnId: string): UserVpnVersion;
|
|
82
73
|
export declare function vpnAgainstQuotaPredicate(uservpn: UserVpn): boolean;
|
|
83
74
|
export declare function validateVpnNbAgainstQuota(vpnNb: number, quota: number): number;
|
|
84
|
-
export
|
|
85
|
-
export declare function
|
|
86
|
-
export declare function
|
|
87
|
-
export declare function
|
|
75
|
+
export type GetLocationByGeonamesId = (geonamesId: number) => Location | undefined;
|
|
76
|
+
export declare function filterVpns(vpns: Vpn[], getLocationByGeonamesId: GetLocationByGeonamesId, filterCity?: string, filterCountry?: string): Vpn[];
|
|
77
|
+
export declare function sortVpns(vpns: Vpn[], getCityByGeonamesId: GetLocationByGeonamesId, sortBy?: ListVpnsSortByCriteria, sortOrder?: ListVpnsSortOrder): Vpn[];
|
|
78
|
+
export declare function newVpn(geonamesId: number, config: VpnConfig, state: VpnState): Vpn;
|
|
79
|
+
export declare function getVpnFrom(vpnId: string, createdAt: Date | undefined, geonamesId: number, state: VpnState, config: VpnConfig): Vpn;
|
|
80
|
+
export declare function dateToId(date: Date): string;
|
|
81
|
+
export declare function idToDate(id: string): Date;
|
|
82
|
+
export declare function vpnIdToWgFileName(vpn: Vpn): string;
|
|
88
83
|
export declare function vpnToClient(vpn: Vpn): Vpn;
|
|
84
|
+
export declare function vpnFromServer(vpn: any): Vpn;
|
|
89
85
|
export declare function metricsToClient(metrics: VpnMetrics | undefined): VpnMetrics;
|
|
90
86
|
/**
|
|
91
87
|
* Extract the creation date from a VPN ID
|
package/dist/src/models/vpn.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getCreationDateFromVpnId = exports.metricsToClient = exports.vpnToClient = exports.vpnIdToWgFileName = exports.getVpnFrom = exports.newVpn = exports.
|
|
3
|
+
exports.getCreationDateFromVpnId = exports.metricsToClient = exports.vpnFromServer = exports.vpnToClient = exports.vpnIdToWgFileName = exports.idToDate = exports.dateToId = exports.getVpnFrom = exports.newVpn = exports.sortVpns = exports.filterVpns = exports.validateVpnNbAgainstQuota = exports.vpnAgainstQuotaPredicate = exports.validateVpnId = exports.ListVpnsSortOrder = exports.ListVpnsSortByCriteria = exports.VpnType = exports.fromRank = exports.toRank = exports.VpnState = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
4
5
|
const errors_1 = require("../errors");
|
|
5
6
|
const peanuts_1 = require("./peanuts");
|
|
6
|
-
const
|
|
7
|
+
const uservpn_1 = require("./uservpn");
|
|
8
|
+
const LEGACY_VPN_ID_FORMAT_REGEX = /\d{4}[01]\d[0-3]\d[0-2]\d[0-5]\d[0-5]\d\d{3}@[a-z]{2}-[a-z]+-\d/;
|
|
7
9
|
var VpnState;
|
|
8
10
|
(function (VpnState) {
|
|
9
11
|
VpnState["Failed"] = "Failed";
|
|
@@ -28,52 +30,29 @@ var VpnType;
|
|
|
28
30
|
(function (VpnType) {
|
|
29
31
|
VpnType["WireGuard"] = "wireguard";
|
|
30
32
|
})(VpnType = exports.VpnType || (exports.VpnType = {}));
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
var ListVpnsSortByCriteria;
|
|
34
|
+
(function (ListVpnsSortByCriteria) {
|
|
35
|
+
ListVpnsSortByCriteria["CreatedAt"] = "createdAt";
|
|
36
|
+
ListVpnsSortByCriteria["State"] = "state";
|
|
37
|
+
ListVpnsSortByCriteria["GeonamesId"] = "geonamesId";
|
|
38
|
+
ListVpnsSortByCriteria["VpnId"] = "vpnId";
|
|
39
|
+
ListVpnsSortByCriteria["City"] = "city";
|
|
40
|
+
ListVpnsSortByCriteria["Country"] = "country";
|
|
41
|
+
})(ListVpnsSortByCriteria = exports.ListVpnsSortByCriteria || (exports.ListVpnsSortByCriteria = {}));
|
|
42
|
+
var ListVpnsSortOrder;
|
|
43
|
+
(function (ListVpnsSortOrder) {
|
|
44
|
+
ListVpnsSortOrder["Asc"] = "asc";
|
|
45
|
+
ListVpnsSortOrder["Desc"] = "desc";
|
|
46
|
+
})(ListVpnsSortOrder = exports.ListVpnsSortOrder || (exports.ListVpnsSortOrder = {}));
|
|
37
47
|
function validateVpnId(vpnId) {
|
|
38
|
-
//
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
function validateMaxPeanuts(peanuts, currentBalance, vpnConfigLimits) {
|
|
45
|
-
// No matter what, if currentBalance is negative, we fail
|
|
46
|
-
if (currentBalance <= 0) {
|
|
47
|
-
throw new errors_1.NegativeBalanceError(currentBalance);
|
|
48
|
-
}
|
|
49
|
-
if (peanuts <= 0) {
|
|
50
|
-
// result = Math.min(currentBalance, vpnConfigLimits.maxPeanutsFieldMaxValue)
|
|
51
|
-
// This is always safe as it means run as long as there are enough peanuts
|
|
52
|
-
return -1;
|
|
53
|
-
}
|
|
54
|
-
if (peanuts > currentBalance) {
|
|
55
|
-
throw new errors_1.NotEnoughPeanutsError(peanuts, currentBalance);
|
|
56
|
-
}
|
|
57
|
-
if (peanuts < vpnConfigLimits.maxPeanutsFieldMinValue) {
|
|
58
|
-
throw new errors_1.MinPeanutsError(vpnConfigLimits.maxPeanutsFieldMinValue, peanuts, currentBalance);
|
|
59
|
-
}
|
|
60
|
-
if (peanuts > vpnConfigLimits.maxPeanutsFieldMaxValue) {
|
|
61
|
-
throw new errors_1.MaxPeanutsError(vpnConfigLimits.maxPeanutsFieldMaxValue, peanuts, currentBalance);
|
|
62
|
-
}
|
|
63
|
-
return peanuts;
|
|
64
|
-
}
|
|
65
|
-
function validateDeleteAfter(deleteAfter, vpnConfigLimits) {
|
|
66
|
-
if (deleteAfter === undefined) {
|
|
67
|
-
return vpnConfigLimits.deleteAfterFieldMaxValue;
|
|
68
|
-
}
|
|
69
|
-
if (deleteAfter < vpnConfigLimits.deleteAfterFieldMinValue) {
|
|
70
|
-
throw new errors_1.MinDeleteAfterError(vpnConfigLimits.deleteAfterFieldMinValue, deleteAfter);
|
|
71
|
-
}
|
|
72
|
-
if (deleteAfter > vpnConfigLimits.deleteAfterFieldMaxValue) {
|
|
73
|
-
throw new errors_1.MaxDeleteAfterError(vpnConfigLimits.deleteAfterFieldMaxValue, deleteAfter);
|
|
74
|
-
}
|
|
75
|
-
return deleteAfter;
|
|
48
|
+
// Parse the string as a uuid
|
|
49
|
+
if ((0, uuid_1.validate)(vpnId))
|
|
50
|
+
return uservpn_1.UserVpnVersion.LOCATIONS;
|
|
51
|
+
if (LEGACY_VPN_ID_FORMAT_REGEX.test(vpnId))
|
|
52
|
+
return uservpn_1.UserVpnVersion.INITIAL;
|
|
53
|
+
throw new errors_1.MyTmpVpnError(`Invalid vpnId format: \'${vpnId}\'`);
|
|
76
54
|
}
|
|
55
|
+
exports.validateVpnId = validateVpnId;
|
|
77
56
|
// Return whether the given vpn should be taken into account when computing
|
|
78
57
|
// whether a given user has reached its quota or not
|
|
79
58
|
function vpnAgainstQuotaPredicate(uservpn) {
|
|
@@ -90,79 +69,113 @@ function validateVpnNbAgainstQuota(vpnNb, quota) {
|
|
|
90
69
|
return vpnNb;
|
|
91
70
|
}
|
|
92
71
|
exports.validateVpnNbAgainstQuota = validateVpnNbAgainstQuota;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if (!type || !Object.values(VpnType).includes(type)) {
|
|
120
|
-
throw new errors_1.InvalidVpnConfigError(`Config type is invalid: ${jsonType}`);
|
|
121
|
-
}
|
|
122
|
-
return type;
|
|
72
|
+
function filterVpns(vpns, getLocationByGeonamesId, filterCity, filterCountry) {
|
|
73
|
+
let filtered = vpns;
|
|
74
|
+
return filtered.filter(vpn => {
|
|
75
|
+
const cityLocation = getLocationByGeonamesId(vpn.geonamesId);
|
|
76
|
+
if (!cityLocation)
|
|
77
|
+
return false;
|
|
78
|
+
// If no filters are applied, include all VPNs
|
|
79
|
+
if (!filterCity && !filterCountry)
|
|
80
|
+
return true;
|
|
81
|
+
const cityMatch = filterCity && cityLocation.city.toLowerCase().includes(filterCity);
|
|
82
|
+
const countryMatch = filterCountry && cityLocation.country.toLowerCase().includes(filterCountry);
|
|
83
|
+
// FilterCity | FilterCountry
|
|
84
|
+
// undefined | undefined -> true (handled above)
|
|
85
|
+
// match | undefined -> cityMatch
|
|
86
|
+
// unmatch | undefined -> false
|
|
87
|
+
// undefined | match -> countryMatch
|
|
88
|
+
// undefined | unmatch -> false
|
|
89
|
+
// match | match -> cityMatch && countryMatch
|
|
90
|
+
// match | unmatch -> cityMatch && false
|
|
91
|
+
// unmatch | match -> false && countryMatch
|
|
92
|
+
// unmatch | unmatch -> false && false
|
|
93
|
+
const bothMatch = cityMatch && countryMatch;
|
|
94
|
+
// Either both city and country match the filter
|
|
95
|
+
// or one of them is undefined and the other matches
|
|
96
|
+
return bothMatch || (!filterCountry && cityMatch) || (!filterCity && countryMatch);
|
|
97
|
+
});
|
|
123
98
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const deleteAfter = Number.parseInt(jsonDeleteAfter);
|
|
129
|
-
if (Number.isNaN(deleteAfter)) {
|
|
130
|
-
throw new errors_1.InvalidVpnConfigError(`Config deleteAfter is invalid: ${jsonDeleteAfter}`);
|
|
99
|
+
exports.filterVpns = filterVpns;
|
|
100
|
+
function sortVpns(vpns, getCityByGeonamesId, sortBy = ListVpnsSortByCriteria.CreatedAt, sortOrder = ListVpnsSortOrder.Desc) {
|
|
101
|
+
if (!sortBy) {
|
|
102
|
+
return vpns;
|
|
131
103
|
}
|
|
132
|
-
|
|
104
|
+
const sorted = [...vpns].sort((a, b) => {
|
|
105
|
+
let compareResult = 0;
|
|
106
|
+
const aCityLocation = getCityByGeonamesId(a.geonamesId);
|
|
107
|
+
const bCityLocation = getCityByGeonamesId(b.geonamesId);
|
|
108
|
+
switch (sortBy) {
|
|
109
|
+
case ListVpnsSortByCriteria.City:
|
|
110
|
+
compareResult = aCityLocation.city.localeCompare(bCityLocation.city);
|
|
111
|
+
break;
|
|
112
|
+
case ListVpnsSortByCriteria.Country:
|
|
113
|
+
compareResult = aCityLocation.country.localeCompare(bCityLocation.country);
|
|
114
|
+
break;
|
|
115
|
+
case ListVpnsSortByCriteria.GeonamesId:
|
|
116
|
+
compareResult = a.geonamesId - b.geonamesId;
|
|
117
|
+
break;
|
|
118
|
+
case ListVpnsSortByCriteria.State:
|
|
119
|
+
compareResult = toRank(a.state) - toRank(b.state);
|
|
120
|
+
break;
|
|
121
|
+
case ListVpnsSortByCriteria.CreatedAt:
|
|
122
|
+
default:
|
|
123
|
+
compareResult = a.createdAt.getTime() - b.createdAt.getTime();
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
return sortOrder === ListVpnsSortOrder.Desc ? -compareResult : compareResult;
|
|
127
|
+
});
|
|
128
|
+
return sorted;
|
|
133
129
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
throw new errors_1.MyTmpVpnError(`Incorrect
|
|
130
|
+
exports.sortVpns = sortVpns;
|
|
131
|
+
function newVpn(geonamesId, config, state) {
|
|
132
|
+
if (!Number.isInteger(geonamesId) || geonamesId <= 0) {
|
|
133
|
+
throw new errors_1.MyTmpVpnError(`Incorrect geonamesId: \'${geonamesId}\'`);
|
|
138
134
|
}
|
|
139
135
|
const createdAt = new Date();
|
|
140
|
-
const vpnId =
|
|
136
|
+
const vpnId = (0, uuid_1.v4)();
|
|
141
137
|
// Assert we will be able to deserialize later on...
|
|
142
138
|
validateVpnId(vpnId);
|
|
143
139
|
return {
|
|
144
140
|
vpnId,
|
|
145
141
|
createdAt,
|
|
146
|
-
|
|
142
|
+
geonamesId,
|
|
147
143
|
config,
|
|
148
144
|
state
|
|
149
145
|
};
|
|
150
146
|
}
|
|
151
147
|
exports.newVpn = newVpn;
|
|
152
|
-
function getVpnFrom(vpnId, state, config) {
|
|
153
|
-
validateVpnId(vpnId);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
148
|
+
function getVpnFrom(vpnId, createdAt, geonamesId, state, config) {
|
|
149
|
+
const version = validateVpnId(vpnId);
|
|
150
|
+
let finalCreatedAt;
|
|
151
|
+
switch (version) {
|
|
152
|
+
case uservpn_1.UserVpnVersion.INITIAL:
|
|
153
|
+
// Legacy vpnId format, the createdAt is given from the vpnId itself
|
|
154
|
+
if (createdAt !== undefined) {
|
|
155
|
+
throw new errors_1.MyTmpVpnError(`Invalid parameter: createdAt must be undefined when vpnId version is INITIAL: vpnId=${vpnId}; createdAt=${createdAt}`);
|
|
156
|
+
}
|
|
157
|
+
const tokens = vpnId.split('@');
|
|
158
|
+
if (tokens.length !== 2) {
|
|
159
|
+
throw new errors_1.MyTmpVpnError(`Incorrect vpnId: ${vpnId}`);
|
|
160
|
+
}
|
|
161
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
162
|
+
finalCreatedAt = idToDate(tokens[0]);
|
|
163
|
+
/* eslint-enable @typescript-eslint/no-non-null-assertion */
|
|
164
|
+
break;
|
|
165
|
+
case uservpn_1.UserVpnVersion.LOCATIONS:
|
|
166
|
+
// New vpnId format
|
|
167
|
+
if (createdAt === undefined) {
|
|
168
|
+
throw new errors_1.MyTmpVpnError(`Invalid parameter: createdAt can't be undefined: vpnId=${vpnId}`);
|
|
169
|
+
}
|
|
170
|
+
finalCreatedAt = createdAt;
|
|
171
|
+
break;
|
|
172
|
+
default:
|
|
173
|
+
throw new errors_1.MyTmpVpnError(`Incorrect version: \'${version}\'`);
|
|
157
174
|
}
|
|
158
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
159
|
-
const createdAt = idToDate(tokens[0]);
|
|
160
|
-
const region = tokens[1];
|
|
161
|
-
/* eslint-enable @typescript-eslint/no-non-null-assertion */
|
|
162
175
|
return {
|
|
163
176
|
vpnId,
|
|
164
|
-
createdAt,
|
|
165
|
-
|
|
177
|
+
createdAt: finalCreatedAt,
|
|
178
|
+
geonamesId,
|
|
166
179
|
config,
|
|
167
180
|
state
|
|
168
181
|
};
|
|
@@ -176,6 +189,7 @@ function dateToId(date) {
|
|
|
176
189
|
// YYYY-MM-DDTHH:mm:ss.uuuZ -> YYYYMMDDHHmmssuuu
|
|
177
190
|
return date.toISOString().replace(/[^\d]/g, '');
|
|
178
191
|
}
|
|
192
|
+
exports.dateToId = dateToId;
|
|
179
193
|
function idToDate(id) {
|
|
180
194
|
// YYYYMMDDHHmmssuuu -> YYYY-MM-DDTHH:mm:ss.uuuZ
|
|
181
195
|
const year = id.substring(0, 4);
|
|
@@ -187,60 +201,25 @@ function idToDate(id) {
|
|
|
187
201
|
const millis = id.substring(14);
|
|
188
202
|
return new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}.${millis}Z`);
|
|
189
203
|
}
|
|
204
|
+
exports.idToDate = idToDate;
|
|
190
205
|
// The WireGuard Mobile Application has requirements for the wireguard configuration file:
|
|
191
206
|
// 1. must have extension '.conf'
|
|
192
207
|
// 2. file name must match the following regexp: "[a-zA-Z0-9_=+.-]{1,15}")
|
|
193
208
|
// https://git.zx2c4.com/wireguard-android/tree/tunnel/src/main/java/com/wireguard/android/backend/Tunnel.java#n19
|
|
194
|
-
// This function is to transform from
|
|
195
|
-
function vpnIdToWgFileName(
|
|
196
|
-
validateVpnId(vpnId);
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
// the
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
switch (seps[1]) {
|
|
209
|
-
case 'north':
|
|
210
|
-
location = 'n';
|
|
211
|
-
break;
|
|
212
|
-
case 'northeast':
|
|
213
|
-
location = 'ne';
|
|
214
|
-
break;
|
|
215
|
-
case 'east':
|
|
216
|
-
location = 'e';
|
|
217
|
-
break;
|
|
218
|
-
case 'southeast':
|
|
219
|
-
location = 'se';
|
|
220
|
-
break;
|
|
221
|
-
case 'south':
|
|
222
|
-
location = 's';
|
|
223
|
-
break;
|
|
224
|
-
case 'southwest':
|
|
225
|
-
location = 'sw';
|
|
226
|
-
break;
|
|
227
|
-
case 'west':
|
|
228
|
-
location = 'w';
|
|
229
|
-
break;
|
|
230
|
-
case 'northwest':
|
|
231
|
-
location = 'nw';
|
|
232
|
-
break;
|
|
233
|
-
case 'central':
|
|
234
|
-
location = 'c';
|
|
235
|
-
break;
|
|
236
|
-
default:
|
|
237
|
-
'';
|
|
238
|
-
break;
|
|
239
|
-
}
|
|
240
|
-
const number = seps[2];
|
|
241
|
-
// Let's make sure the end file is of 15 char max
|
|
242
|
-
const result = `${ddhhmmss}${ccld}${location}${number}`.substring(0, 15);
|
|
243
|
-
loglevel_1.default.info(`Transforming ${vpnId} to ${result}`);
|
|
209
|
+
// This function is to transform from vpnId to Wireguard mobile application requirements
|
|
210
|
+
function vpnIdToWgFileName(vpn) {
|
|
211
|
+
const version = validateVpnId(vpn.vpnId);
|
|
212
|
+
// We will create a file name from the createdAt field and the location so for the end-user
|
|
213
|
+
// it will be easier to distinguish. Also the vpnId is to big anyway.
|
|
214
|
+
// Note that using the createdAt field makes it simpler across versions as
|
|
215
|
+
// all versions must have this field.
|
|
216
|
+
// Let's keep it simple: vpn is mostly temporary, so keeping
|
|
217
|
+
// the year is useless. Also the milliseconds are useless.
|
|
218
|
+
// Return an id from the vpn.createdAt Date object with the following format
|
|
219
|
+
// MMDDHHmmss.conf
|
|
220
|
+
const result = vpn.createdAt.toISOString() // This will create YYYY-MM-DDThh:mm:ss....
|
|
221
|
+
.replace(/[^\d]/g, '') // Remove meanless characters: YYYYMMDDhhmmss
|
|
222
|
+
.substring(4, 14); // Use only MMDDhhmmss
|
|
244
223
|
return result;
|
|
245
224
|
}
|
|
246
225
|
exports.vpnIdToWgFileName = vpnIdToWgFileName;
|
|
@@ -248,20 +227,27 @@ function vpnToClient(vpn) {
|
|
|
248
227
|
return {
|
|
249
228
|
vpnId: vpn.vpnId,
|
|
250
229
|
state: vpn.state,
|
|
251
|
-
|
|
230
|
+
geonamesId: vpn.geonamesId,
|
|
252
231
|
createdAt: vpn.createdAt,
|
|
253
232
|
config: {
|
|
254
233
|
type: vpn.config.type,
|
|
255
234
|
deleteAfter: vpn.config.deleteAfter,
|
|
256
235
|
maxPeanuts: (0, peanuts_1.peanutsToClient)(vpn.config.maxPeanuts),
|
|
257
|
-
// terminationReason: userVpn.vpn.config.terminationReason,
|
|
258
|
-
// terminationMessage: userVpn.vpn.config.terminationMessage,
|
|
259
|
-
// terminationCode: userVpn.vpn.config.terminationCode,
|
|
260
|
-
// terminationType: userVpn.vpn.config.terminationType,
|
|
261
236
|
}
|
|
262
237
|
};
|
|
263
238
|
}
|
|
264
239
|
exports.vpnToClient = vpnToClient;
|
|
240
|
+
function vpnFromServer(vpn) {
|
|
241
|
+
// Transform from JSON to Plain object, especially Date object are not de-serialized automatically
|
|
242
|
+
return {
|
|
243
|
+
vpnId: vpn.vpnId,
|
|
244
|
+
createdAt: new Date(vpn.createdAt),
|
|
245
|
+
geonamesId: vpn.geonamesId,
|
|
246
|
+
config: vpn.config,
|
|
247
|
+
state: vpn.state,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
exports.vpnFromServer = vpnFromServer;
|
|
265
251
|
function metricsToClient(metrics) {
|
|
266
252
|
return (metrics != null)
|
|
267
253
|
? {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare enum VpnType {
|
|
2
|
+
WireGuard = "wireguard"
|
|
3
|
+
}
|
|
4
|
+
export interface VpnConfigLimits {
|
|
5
|
+
deleteAfterFieldMinValue: number;
|
|
6
|
+
deleteAfterFieldMaxValue: number;
|
|
7
|
+
maxPeanutsFieldMinValue: number;
|
|
8
|
+
maxPeanutsFieldMaxValue: number;
|
|
9
|
+
}
|
|
10
|
+
export interface ValidDeleteAfterConfig {
|
|
11
|
+
min: number;
|
|
12
|
+
max: number;
|
|
13
|
+
}
|
|
14
|
+
export interface VpnConfig {
|
|
15
|
+
type: VpnType;
|
|
16
|
+
maxPeanuts: number;
|
|
17
|
+
deleteAfter?: number;
|
|
18
|
+
}
|
|
19
|
+
export type GetVpnConfigLimitsResponse = VpnConfigLimits;
|
|
20
|
+
export type GetVpnConfigResponse = string;
|
|
21
|
+
export declare function getVpnConfigTypes(): VpnType[];
|
|
22
|
+
export declare function checkValidConfig(userId: string, currentBalance: number, vpnConfigLimits: VpnConfigLimits, vpnConfig: any): VpnConfig;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkValidConfig = exports.getVpnConfigTypes = exports.VpnType = void 0;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
const loglevel_1 = require("loglevel");
|
|
6
|
+
var VpnType;
|
|
7
|
+
(function (VpnType) {
|
|
8
|
+
VpnType["WireGuard"] = "wireguard";
|
|
9
|
+
})(VpnType = exports.VpnType || (exports.VpnType = {}));
|
|
10
|
+
function getVpnConfigTypes() {
|
|
11
|
+
return Object.values(VpnType).filter((item) => {
|
|
12
|
+
return isNaN(Number(item));
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
exports.getVpnConfigTypes = getVpnConfigTypes;
|
|
16
|
+
function validateMaxPeanuts(peanuts, currentBalance, vpnConfigLimits) {
|
|
17
|
+
// No matter what, if currentBalance is negative, we fail
|
|
18
|
+
if (currentBalance <= 0) {
|
|
19
|
+
throw new errors_1.NegativeBalanceError(currentBalance);
|
|
20
|
+
}
|
|
21
|
+
if (peanuts <= 0) {
|
|
22
|
+
// result = Math.min(currentBalance, vpnConfigLimits.maxPeanutsFieldMaxValue)
|
|
23
|
+
// This is always safe as it means run as long as there are enough peanuts
|
|
24
|
+
return -1;
|
|
25
|
+
}
|
|
26
|
+
if (peanuts > currentBalance) {
|
|
27
|
+
throw new errors_1.NotEnoughPeanutsError(peanuts, currentBalance);
|
|
28
|
+
}
|
|
29
|
+
if (peanuts < vpnConfigLimits.maxPeanutsFieldMinValue) {
|
|
30
|
+
throw new errors_1.MinPeanutsError(vpnConfigLimits.maxPeanutsFieldMinValue, peanuts, currentBalance);
|
|
31
|
+
}
|
|
32
|
+
if (peanuts > vpnConfigLimits.maxPeanutsFieldMaxValue) {
|
|
33
|
+
throw new errors_1.MaxPeanutsError(vpnConfigLimits.maxPeanutsFieldMaxValue, peanuts, currentBalance);
|
|
34
|
+
}
|
|
35
|
+
return peanuts;
|
|
36
|
+
}
|
|
37
|
+
function validateDeleteAfter(deleteAfter, vpnConfigLimits) {
|
|
38
|
+
if (deleteAfter === undefined) {
|
|
39
|
+
return vpnConfigLimits.deleteAfterFieldMaxValue;
|
|
40
|
+
}
|
|
41
|
+
if (deleteAfter < vpnConfigLimits.deleteAfterFieldMinValue) {
|
|
42
|
+
throw new errors_1.MinDeleteAfterError(vpnConfigLimits.deleteAfterFieldMinValue, deleteAfter);
|
|
43
|
+
}
|
|
44
|
+
if (deleteAfter > vpnConfigLimits.deleteAfterFieldMaxValue) {
|
|
45
|
+
throw new errors_1.MaxDeleteAfterError(vpnConfigLimits.deleteAfterFieldMaxValue, deleteAfter);
|
|
46
|
+
}
|
|
47
|
+
return deleteAfter;
|
|
48
|
+
}
|
|
49
|
+
// vpnConfig is of type any here because it could come from user input such as json
|
|
50
|
+
function checkValidConfig(userId, currentBalance, vpnConfigLimits, vpnConfig) {
|
|
51
|
+
const maxPeanuts = checkValidMaxPeanuts(userId, currentBalance, vpnConfig.maxPeanuts, vpnConfigLimits);
|
|
52
|
+
const type = checkValidVpnType(vpnConfig.type);
|
|
53
|
+
const deleteAfter = checkValidDeleteAfter(vpnConfig.deleteAfter, vpnConfigLimits);
|
|
54
|
+
const result = {
|
|
55
|
+
maxPeanuts,
|
|
56
|
+
type,
|
|
57
|
+
deleteAfter
|
|
58
|
+
};
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
exports.checkValidConfig = checkValidConfig;
|
|
62
|
+
function checkValidMaxPeanuts(userId, currentBalance, maxPeanuts, vpnConfigLimits) {
|
|
63
|
+
const peanuts = maxPeanuts ? Number.parseFloat(maxPeanuts) : -1;
|
|
64
|
+
if (Number.isNaN(peanuts) || !Number.isFinite(peanuts)) {
|
|
65
|
+
throw new errors_1.InvalidVpnConfigError(`Config maxPeanuts is invalid: ${maxPeanuts}`);
|
|
66
|
+
}
|
|
67
|
+
loglevel_1.default.debug(`Validating peanuts for ${userId}, peanuts: ${peanuts}, currentBalance: ${currentBalance}`);
|
|
68
|
+
return validateMaxPeanuts(peanuts, currentBalance, vpnConfigLimits);
|
|
69
|
+
}
|
|
70
|
+
function checkValidVpnType(jsonType) {
|
|
71
|
+
if (!jsonType) {
|
|
72
|
+
throw new errors_1.InvalidVpnConfigError(`Config type is null or undefined: ${jsonType}`);
|
|
73
|
+
}
|
|
74
|
+
const type = jsonType;
|
|
75
|
+
if (!type || !Object.values(VpnType).includes(type)) {
|
|
76
|
+
throw new errors_1.InvalidVpnConfigError(`Config type is invalid: ${jsonType}`);
|
|
77
|
+
}
|
|
78
|
+
return type;
|
|
79
|
+
}
|
|
80
|
+
function checkValidDeleteAfter(jsonDeleteAfter, vpnConfigLimits) {
|
|
81
|
+
if (jsonDeleteAfter === undefined) {
|
|
82
|
+
return validateDeleteAfter(undefined, vpnConfigLimits);
|
|
83
|
+
}
|
|
84
|
+
const deleteAfter = Number.parseInt(jsonDeleteAfter);
|
|
85
|
+
if (Number.isNaN(deleteAfter)) {
|
|
86
|
+
throw new errors_1.InvalidVpnConfigError(`Config deleteAfter is invalid: ${jsonDeleteAfter}`);
|
|
87
|
+
}
|
|
88
|
+
return validateDeleteAfter(deleteAfter, vpnConfigLimits);
|
|
89
|
+
}
|
package/dist/test/models.test.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const uuid_1 = require("uuid");
|
|
3
4
|
const uservpn_1 = require("../src/models/uservpn");
|
|
4
5
|
const errors_1 = require("../src/errors");
|
|
5
6
|
const vpn_1 = require("../src/models/vpn");
|
|
7
|
+
const vpnConfig_1 = require("../src/models/vpnConfig");
|
|
6
8
|
describe('Testing VpnState', () => {
|
|
7
9
|
it('should check that all VpnState are ordered properly', async () => {
|
|
8
10
|
expect((0, vpn_1.toRank)(vpn_1.VpnState.Creating) <= (0, vpn_1.toRank)(vpn_1.VpnState.Created)).toBe(true);
|
|
@@ -19,69 +21,77 @@ describe('Testing VpnState', () => {
|
|
|
19
21
|
});
|
|
20
22
|
});
|
|
21
23
|
describe('Testing Vpn constructors', () => {
|
|
22
|
-
it('Should shout when
|
|
23
|
-
expect(() => (0, vpn_1.newVpn)(
|
|
24
|
-
.toThrow(new errors_1.MyTmpVpnError("Incorrect
|
|
24
|
+
it('Should shout when geonamesId is zero', async () => {
|
|
25
|
+
expect(() => (0, vpn_1.newVpn)(0, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }, vpn_1.VpnState.Created))
|
|
26
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect geonamesId: \'0\'"));
|
|
25
27
|
});
|
|
26
|
-
it('Should shout when
|
|
27
|
-
expect(() => (0, vpn_1.newVpn)(
|
|
28
|
-
.toThrow(new errors_1.MyTmpVpnError("Incorrect
|
|
28
|
+
it('Should shout when geonamesId is negative', async () => {
|
|
29
|
+
expect(() => (0, vpn_1.newVpn)(-1, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }, vpn_1.VpnState.Created))
|
|
30
|
+
.toThrow(new errors_1.MyTmpVpnError("Incorrect geonamesId: \'-1\'"));
|
|
29
31
|
});
|
|
30
32
|
it('Should create vpn with all mandatory fields set', async () => {
|
|
31
|
-
const vpn = (0, vpn_1.newVpn)(
|
|
33
|
+
const vpn = (0, vpn_1.newVpn)(4140963, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }, vpn_1.VpnState.Created);
|
|
32
34
|
expect(vpn.createdAt).toBeDefined();
|
|
33
|
-
expect(vpn.
|
|
35
|
+
expect(vpn.geonamesId).toEqual(4140963);
|
|
34
36
|
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
35
37
|
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard });
|
|
36
38
|
expect(vpn.vpnId).toBeDefined();
|
|
39
|
+
expect((0, vpn_1.validateVpnId)(vpn.vpnId)).toEqual(uservpn_1.UserVpnVersion.LOCATIONS);
|
|
37
40
|
});
|
|
38
41
|
it('Should create vpn with optional fields set', async () => {
|
|
39
|
-
const vpn = (0, vpn_1.newVpn)(
|
|
42
|
+
const vpn = (0, vpn_1.newVpn)(4140963, {
|
|
40
43
|
maxPeanuts: -1,
|
|
41
44
|
type: vpn_1.VpnType.WireGuard,
|
|
42
45
|
deleteAfter: 37,
|
|
43
46
|
}, vpn_1.VpnState.Created);
|
|
44
47
|
expect(vpn.createdAt).toBeDefined();
|
|
45
|
-
expect(vpn.
|
|
48
|
+
expect(vpn.geonamesId).toEqual(4140963);
|
|
46
49
|
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
47
50
|
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: 37 });
|
|
48
51
|
expect(vpn.vpnId).toBeDefined();
|
|
49
52
|
});
|
|
50
53
|
it('Should create vpn with deleteAfter set to NaN', async () => {
|
|
51
54
|
const deleteAfter = Number.NaN;
|
|
52
|
-
const vpn = (0, vpn_1.newVpn)(
|
|
55
|
+
const vpn = (0, vpn_1.newVpn)(4140963, {
|
|
53
56
|
maxPeanuts: -1,
|
|
54
57
|
type: vpn_1.VpnType.WireGuard,
|
|
55
58
|
deleteAfter: deleteAfter
|
|
56
59
|
}, vpn_1.VpnState.Created);
|
|
57
60
|
expect(vpn.createdAt).toBeDefined();
|
|
58
|
-
expect(vpn.
|
|
61
|
+
expect(vpn.geonamesId).toEqual(4140963);
|
|
59
62
|
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
60
63
|
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: deleteAfter });
|
|
61
64
|
expect(vpn.vpnId).toBeDefined();
|
|
62
65
|
});
|
|
63
|
-
it('Should deserialize a vpn with
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
it('Should deserialize a vpn with new format (geonamesId)', async () => {
|
|
67
|
+
const vpnId = (0, uuid_1.v4)();
|
|
68
|
+
const createdAt = new Date();
|
|
69
|
+
const vpn = (0, vpn_1.getVpnFrom)(vpnId, createdAt, 4140963, vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: 37 });
|
|
70
|
+
expect(vpn.createdAt).toEqual(createdAt);
|
|
71
|
+
expect(vpn.geonamesId).toEqual(4140963);
|
|
67
72
|
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
68
73
|
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: 37 });
|
|
69
|
-
expect(vpn.vpnId).
|
|
74
|
+
expect((0, vpn_1.validateVpnId)(vpn.vpnId)).toEqual(uservpn_1.UserVpnVersion.LOCATIONS);
|
|
75
|
+
expect(vpn.vpnId).toEqual(vpnId);
|
|
70
76
|
});
|
|
71
77
|
it('Should deserialize a vpn with deleteAfter set to NaN', async () => {
|
|
72
78
|
const deleteAfter = Number.NaN;
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
const vpnId = (0, uuid_1.v4)();
|
|
80
|
+
const createdAt = new Date();
|
|
81
|
+
const vpn = (0, vpn_1.getVpnFrom)(vpnId, createdAt, 4140963, vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: deleteAfter });
|
|
82
|
+
expect(vpn.createdAt).toEqual(createdAt);
|
|
83
|
+
expect(vpn.geonamesId).toEqual(4140963);
|
|
76
84
|
expect(vpn.state).toEqual(vpn_1.VpnState.Created);
|
|
77
85
|
expect(vpn.config).toEqual({ maxPeanuts: -1, type: vpn_1.VpnType.WireGuard, deleteAfter: deleteAfter });
|
|
78
86
|
expect(vpn.vpnId).toBeDefined();
|
|
87
|
+
expect((0, vpn_1.validateVpnId)(vpn.vpnId)).toEqual(uservpn_1.UserVpnVersion.LOCATIONS);
|
|
88
|
+
expect(vpn.vpnId).toEqual(vpnId);
|
|
79
89
|
});
|
|
80
90
|
it('Should deserialize a json vpn with all fields set', async () => {
|
|
81
91
|
const originalVpn = (0, uservpn_1.newUserVpn)({
|
|
82
92
|
userId: 'myId',
|
|
83
|
-
|
|
84
|
-
version:
|
|
93
|
+
geonamesId: 4140963,
|
|
94
|
+
version: uservpn_1.UserVpnVersion.LOCATIONS,
|
|
85
95
|
config: {
|
|
86
96
|
maxPeanuts: -1,
|
|
87
97
|
type: vpn_1.VpnType.WireGuard,
|
|
@@ -94,35 +104,33 @@ describe('Testing Vpn constructors', () => {
|
|
|
94
104
|
expect(userVpn).toEqual(originalVpn);
|
|
95
105
|
});
|
|
96
106
|
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("
|
|
107
|
+
expect(() => (0, vpn_1.getVpnFrom)('', new Date(), 4140963, vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }))
|
|
108
|
+
.toThrow(new errors_1.MyTmpVpnError("Invalid vpnId format: \'\'"));
|
|
99
109
|
});
|
|
100
110
|
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("
|
|
111
|
+
expect(() => (0, vpn_1.getVpnFrom)('foo', new Date(), 4140963, vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard }))
|
|
112
|
+
.toThrow(new errors_1.MyTmpVpnError("Invalid vpnId format: \'foo\'"));
|
|
103
113
|
});
|
|
104
|
-
it('Should
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
it('Should accept legacy vpnId format with AWS region', async () => {
|
|
115
|
+
const vpn = (0, vpn_1.getVpnFrom)('20030902012345678@us-east-1', undefined, 4140963, vpn_1.VpnState.Created, { maxPeanuts: -1, type: vpn_1.VpnType.WireGuard });
|
|
116
|
+
expect(vpn.vpnId).toEqual('20030902012345678@us-east-1');
|
|
117
|
+
expect(vpn.geonamesId).toEqual(4140963);
|
|
107
118
|
});
|
|
108
119
|
});
|
|
109
120
|
describe('Testing vpnId to Wireguard file name functions ', () => {
|
|
110
|
-
it('Should
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
+
it('Should handle new format with GeoNames ID', async () => {
|
|
122
|
+
const vpn = (0, vpn_1.newVpn)(4140963, {
|
|
123
|
+
maxPeanuts: -1,
|
|
124
|
+
type: vpn_1.VpnType.WireGuard,
|
|
125
|
+
}, vpn_1.VpnState.Created);
|
|
126
|
+
const fileName = (0, vpn_1.vpnIdToWgFileName)(vpn);
|
|
127
|
+
expect(fileName).toBeDefined();
|
|
128
|
+
expect(fileName.length).toBeLessThanOrEqual(15);
|
|
121
129
|
});
|
|
122
130
|
});
|
|
123
131
|
describe('Testing vpn config', () => {
|
|
124
132
|
it('Should keep maxPeanuts to -1 when specified', async () => {
|
|
125
|
-
const validatedConfig = (0,
|
|
133
|
+
const validatedConfig = (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
126
134
|
maxPeanutsFieldMinValue: 0,
|
|
127
135
|
maxPeanutsFieldMaxValue: 1,
|
|
128
136
|
deleteAfterFieldMinValue: 1,
|
|
@@ -139,7 +147,7 @@ describe('Testing vpn config', () => {
|
|
|
139
147
|
});
|
|
140
148
|
});
|
|
141
149
|
it('Should set maxPeanuts to -1 when null', async () => {
|
|
142
|
-
const validatedConfig = (0,
|
|
150
|
+
const validatedConfig = (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
143
151
|
maxPeanutsFieldMinValue: 0,
|
|
144
152
|
maxPeanutsFieldMaxValue: 1,
|
|
145
153
|
deleteAfterFieldMinValue: 1,
|
|
@@ -156,7 +164,7 @@ describe('Testing vpn config', () => {
|
|
|
156
164
|
});
|
|
157
165
|
});
|
|
158
166
|
it('Should set maxPeanuts to -1 when undefined', async () => {
|
|
159
|
-
const validatedConfig = (0,
|
|
167
|
+
const validatedConfig = (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
160
168
|
maxPeanutsFieldMinValue: 0,
|
|
161
169
|
maxPeanutsFieldMaxValue: 1,
|
|
162
170
|
deleteAfterFieldMinValue: 1,
|
|
@@ -173,7 +181,7 @@ describe('Testing vpn config', () => {
|
|
|
173
181
|
});
|
|
174
182
|
});
|
|
175
183
|
it('Should shout when currentBalance is negative', async () => {
|
|
176
|
-
expect(() => (0,
|
|
184
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', -1, {
|
|
177
185
|
maxPeanutsFieldMinValue: 2,
|
|
178
186
|
maxPeanutsFieldMaxValue: 3,
|
|
179
187
|
deleteAfterFieldMinValue: 1,
|
|
@@ -185,7 +193,7 @@ describe('Testing vpn config', () => {
|
|
|
185
193
|
})).toThrow(new errors_1.NegativeBalanceError(-1));
|
|
186
194
|
});
|
|
187
195
|
it('Should shout when currentBalance is zero', async () => {
|
|
188
|
-
expect(() => (0,
|
|
196
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 0, {
|
|
189
197
|
maxPeanutsFieldMinValue: 2,
|
|
190
198
|
maxPeanutsFieldMaxValue: 3,
|
|
191
199
|
deleteAfterFieldMinValue: 1,
|
|
@@ -197,7 +205,7 @@ describe('Testing vpn config', () => {
|
|
|
197
205
|
})).toThrow(new errors_1.NegativeBalanceError(0));
|
|
198
206
|
});
|
|
199
207
|
it('Should shout when maxPeanuts is Infinity', async () => {
|
|
200
|
-
expect(() => (0,
|
|
208
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
201
209
|
maxPeanutsFieldMinValue: 2,
|
|
202
210
|
maxPeanutsFieldMaxValue: 3,
|
|
203
211
|
deleteAfterFieldMinValue: 1,
|
|
@@ -209,7 +217,7 @@ describe('Testing vpn config', () => {
|
|
|
209
217
|
})).toThrow(new errors_1.InvalidVpnConfigError('Config maxPeanuts is invalid: Infinity'));
|
|
210
218
|
});
|
|
211
219
|
it('Should shout when maxPeanuts is -Infinity', async () => {
|
|
212
|
-
expect(() => (0,
|
|
220
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
213
221
|
maxPeanutsFieldMinValue: 2,
|
|
214
222
|
maxPeanutsFieldMaxValue: 3,
|
|
215
223
|
deleteAfterFieldMinValue: 1,
|
|
@@ -221,7 +229,7 @@ describe('Testing vpn config', () => {
|
|
|
221
229
|
})).toThrow(new errors_1.InvalidVpnConfigError('Config maxPeanuts is invalid: -Infinity'));
|
|
222
230
|
});
|
|
223
231
|
it('Should shout when maxPeanuts is not a number', async () => {
|
|
224
|
-
expect(() => (0,
|
|
232
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
225
233
|
maxPeanutsFieldMinValue: 2,
|
|
226
234
|
maxPeanutsFieldMaxValue: 3,
|
|
227
235
|
deleteAfterFieldMinValue: 1,
|
|
@@ -233,7 +241,7 @@ describe('Testing vpn config', () => {
|
|
|
233
241
|
})).toThrow(new errors_1.InvalidVpnConfigError('Config maxPeanuts is invalid: Not a number'));
|
|
234
242
|
});
|
|
235
243
|
it('Should shout when maxPeanuts is below the validPeanutsConfig minimum', async () => {
|
|
236
|
-
expect(() => (0,
|
|
244
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
237
245
|
maxPeanutsFieldMinValue: 2,
|
|
238
246
|
maxPeanutsFieldMaxValue: 3,
|
|
239
247
|
deleteAfterFieldMinValue: 1,
|
|
@@ -245,7 +253,7 @@ describe('Testing vpn config', () => {
|
|
|
245
253
|
})).toThrow(new errors_1.MinPeanutsError(2, 1, 2));
|
|
246
254
|
});
|
|
247
255
|
it('Should shout when maxPeanuts is above the validPeanutsConfig maximum', async () => {
|
|
248
|
-
expect(() => (0,
|
|
256
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 10, {
|
|
249
257
|
maxPeanutsFieldMinValue: 2,
|
|
250
258
|
maxPeanutsFieldMaxValue: 3,
|
|
251
259
|
deleteAfterFieldMinValue: 1,
|
|
@@ -257,7 +265,7 @@ describe('Testing vpn config', () => {
|
|
|
257
265
|
})).toThrow(new errors_1.MaxPeanutsError(3, 5, 10));
|
|
258
266
|
});
|
|
259
267
|
it('Should shout when deleteAfter is below the validPeanutsConfig minimum', async () => {
|
|
260
|
-
expect(() => (0,
|
|
268
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
261
269
|
maxPeanutsFieldMinValue: 1,
|
|
262
270
|
maxPeanutsFieldMaxValue: 3,
|
|
263
271
|
deleteAfterFieldMinValue: 3,
|
|
@@ -269,7 +277,7 @@ describe('Testing vpn config', () => {
|
|
|
269
277
|
})).toThrow(new errors_1.MinDeleteAfterError(3, 1));
|
|
270
278
|
});
|
|
271
279
|
it('Should shout when deleteAfter is greater the validPeanutsConfig maximum', async () => {
|
|
272
|
-
expect(() => (0,
|
|
280
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
273
281
|
maxPeanutsFieldMinValue: 1,
|
|
274
282
|
maxPeanutsFieldMaxValue: 3,
|
|
275
283
|
deleteAfterFieldMinValue: 3,
|
|
@@ -281,7 +289,7 @@ describe('Testing vpn config', () => {
|
|
|
281
289
|
})).toThrow(new errors_1.MaxDeleteAfterError(5, 7));
|
|
282
290
|
});
|
|
283
291
|
it('Should shout when deleteAfter is positive infinity', async () => {
|
|
284
|
-
expect(() => (0,
|
|
292
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
285
293
|
maxPeanutsFieldMinValue: 1,
|
|
286
294
|
maxPeanutsFieldMaxValue: 3,
|
|
287
295
|
deleteAfterFieldMinValue: 3,
|
|
@@ -293,7 +301,7 @@ describe('Testing vpn config', () => {
|
|
|
293
301
|
})).toThrow(new errors_1.InvalidVpnConfigError('Config deleteAfter is invalid: Infinity'));
|
|
294
302
|
});
|
|
295
303
|
it('Should shout when deleteAfter is negative infinity', async () => {
|
|
296
|
-
expect(() => (0,
|
|
304
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
297
305
|
maxPeanutsFieldMinValue: 1,
|
|
298
306
|
maxPeanutsFieldMaxValue: 3,
|
|
299
307
|
deleteAfterFieldMinValue: 3,
|
|
@@ -305,7 +313,7 @@ describe('Testing vpn config', () => {
|
|
|
305
313
|
})).toThrow(new errors_1.InvalidVpnConfigError('Config deleteAfter is invalid: -Infinity'));
|
|
306
314
|
});
|
|
307
315
|
it('Should shout when deleteAfter is not a number', async () => {
|
|
308
|
-
expect(() => (0,
|
|
316
|
+
expect(() => (0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
309
317
|
maxPeanutsFieldMinValue: 1,
|
|
310
318
|
maxPeanutsFieldMaxValue: 3,
|
|
311
319
|
deleteAfterFieldMinValue: 3,
|
|
@@ -317,7 +325,7 @@ describe('Testing vpn config', () => {
|
|
|
317
325
|
})).toThrow(new errors_1.InvalidVpnConfigError('Config deleteAfter is invalid: Not a number'));
|
|
318
326
|
});
|
|
319
327
|
it('Should not shout when deleteAfter is undefined', async () => {
|
|
320
|
-
expect((0,
|
|
328
|
+
expect((0, vpnConfig_1.checkValidConfig)('userId', 2, {
|
|
321
329
|
maxPeanutsFieldMinValue: 1,
|
|
322
330
|
maxPeanutsFieldMaxValue: 3,
|
|
323
331
|
deleteAfterFieldMinValue: 3,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mytmpvpn/mytmpvpn-common",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.2",
|
|
4
4
|
"description": "Common library for all MyTmpVpn related projects",
|
|
5
5
|
"types": "dist/src/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"typescript": "^4.9.5"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"loglevel": "^1.9.2"
|
|
47
|
+
"loglevel": "^1.9.2",
|
|
48
|
+
"uuid": "^11.1.0"
|
|
48
49
|
}
|
|
49
50
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"root":["../.eslintrc.js","../jest.config.js","../src/errors.ts","../src/index.ts","../src/utils.ts","../src/models/index.ts","../src/models/peanuts.ts","../src/models/referral.ts","../src/models/uservpn.ts","../src/models/vpn.ts","../test/models.test.ts"],"version":"5.9.3"}
|