@mytmpvpn/mytmpvpn-cli 4.2.0 → 6.0.0
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/mytmpvpn.js +62 -75
- package/package.json +6 -6
- package/src/mytmpvpn.ts +35 -51
package/dist/mytmpvpn.js
CHANGED
|
@@ -33,18 +33,21 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
return result;
|
|
34
34
|
};
|
|
35
35
|
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
36
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
40
|
// Use NODE_NO_WARNINGS=1 to get rid of the fetch node deprecated API
|
|
38
41
|
// https://github.com/netlify/cli/issues/4608 -- but it hangs the process: https://github.com/nodejs/node/issues/21960
|
|
39
42
|
const fs = __importStar(require("fs"));
|
|
40
43
|
const path = __importStar(require("path"));
|
|
41
44
|
const commander_1 = require("commander");
|
|
42
|
-
const
|
|
43
|
-
|
|
45
|
+
const loglevel_1 = __importDefault(require("loglevel"));
|
|
46
|
+
loglevel_1.default.setDefaultLevel("info");
|
|
44
47
|
const vpnlib = __importStar(require("@mytmpvpn/mytmpvpn-common/models/vpn"));
|
|
45
48
|
const mytmpvpn_client_1 = require("@mytmpvpn/mytmpvpn-client");
|
|
46
49
|
const appconfig = __importStar(require("@mytmpvpn/mytmpvpn-client/appconfig"));
|
|
47
|
-
const
|
|
50
|
+
const userprofiles = __importStar(require("@mytmpvpn/mytmpvpn-client/userprofiles"));
|
|
48
51
|
const client = __importStar(require("@mytmpvpn/mytmpvpn-client/client"));
|
|
49
52
|
const program = new commander_1.Command();
|
|
50
53
|
function handleError(error, verbose = false) {
|
|
@@ -52,24 +55,24 @@ function handleError(error, verbose = false) {
|
|
|
52
55
|
// The request was made and the server responded with a status code
|
|
53
56
|
// that falls out of the range of 2xx
|
|
54
57
|
try {
|
|
55
|
-
|
|
58
|
+
loglevel_1.default.error(`[${error.response.status}] - ${JSON.stringify(error.response.data)}`);
|
|
56
59
|
}
|
|
57
60
|
catch (Error) {
|
|
58
|
-
|
|
61
|
+
loglevel_1.default.error(`[${error.response.status}] - ${JSON.stringify(error.message)}`);
|
|
59
62
|
}
|
|
60
|
-
|
|
63
|
+
loglevel_1.default.debug(error.response.headers);
|
|
61
64
|
}
|
|
62
65
|
else if (error.request) {
|
|
63
66
|
// The request was made but no response was received
|
|
64
67
|
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
|
65
68
|
// http.ClientRequest in node.js
|
|
66
|
-
|
|
69
|
+
loglevel_1.default.error(`No reponse received. Check your profile and your appConfig`);
|
|
67
70
|
}
|
|
68
71
|
else {
|
|
69
72
|
// Something happened in setting up the request that triggered an Error
|
|
70
|
-
|
|
73
|
+
loglevel_1.default.error(`Error while setting up the request ${JSON.stringify(error)}`);
|
|
71
74
|
}
|
|
72
|
-
|
|
75
|
+
loglevel_1.default.trace(`Stack trace: ${error}`);
|
|
73
76
|
}
|
|
74
77
|
program
|
|
75
78
|
.name('mytmpvpn-cli')
|
|
@@ -77,10 +80,10 @@ program
|
|
|
77
80
|
.version('0.0.1')
|
|
78
81
|
.option('--verbose', 'Produce more logs')
|
|
79
82
|
.option('--appConfig <file>', 'Path to the application config file', appconfig.getDefaultAppConfigFile())
|
|
80
|
-
.option('--
|
|
81
|
-
.option('--profile <name>', 'Name of the profile in the user
|
|
83
|
+
.option('--userProfiles <file>', 'Path to the user profiles file', userprofiles.getDefaultUserProfilesFile())
|
|
84
|
+
.option('--profile <name>', 'Name of the profile in the user profiles file to use', userprofiles.getDefaultUsername());
|
|
82
85
|
program.on('option:verbose', function () {
|
|
83
|
-
|
|
86
|
+
loglevel_1.default.setDefaultLevel("trace");
|
|
84
87
|
});
|
|
85
88
|
program.command('list-peanuts-packs')
|
|
86
89
|
.description(`Returns the list of peanuts packs you can purchase. A peanuts pack contains a given number of peanuts.`)
|
|
@@ -91,7 +94,7 @@ program.command('list-peanuts-packs')
|
|
|
91
94
|
const clientImpl = new client.MyTmpVpnClientImpl(appConfig.apiUrl);
|
|
92
95
|
clientImpl.listPeanutsPacks()
|
|
93
96
|
.then(((packs) => {
|
|
94
|
-
|
|
97
|
+
loglevel_1.default.info(JSON.stringify(packs, null, 2));
|
|
95
98
|
}))
|
|
96
99
|
.catch((err) => handleError(err));
|
|
97
100
|
});
|
|
@@ -99,14 +102,14 @@ program.command('get-peanuts-balance')
|
|
|
99
102
|
.description('Get the current peanuts balance')
|
|
100
103
|
.action((_, command) => {
|
|
101
104
|
const options = command.optsWithGlobals();
|
|
102
|
-
|
|
105
|
+
loglevel_1.default.debug(`Get peanuts balance`);
|
|
103
106
|
(0, mytmpvpn_client_1.getLoggedInClientFromFiles)({
|
|
104
107
|
appConfigFile: options.appConfig,
|
|
105
|
-
userConfigFile: options.
|
|
108
|
+
userConfigFile: options.userProfiles,
|
|
106
109
|
profileName: options.profile
|
|
107
110
|
}).then(client => {
|
|
108
111
|
client.getPeanutsBalance().then(balance => {
|
|
109
|
-
|
|
112
|
+
loglevel_1.default.info(balance);
|
|
110
113
|
}).catch((err) => {
|
|
111
114
|
handleError(err);
|
|
112
115
|
});
|
|
@@ -114,61 +117,45 @@ program.command('get-peanuts-balance')
|
|
|
114
117
|
handleError(err, options.verbose);
|
|
115
118
|
});
|
|
116
119
|
});
|
|
117
|
-
program.command('list-
|
|
118
|
-
.description('Returns the list of all
|
|
120
|
+
program.command('list-locations')
|
|
121
|
+
.description('Returns the list of all locations where vpn can be created')
|
|
119
122
|
.action((_, command) => {
|
|
120
123
|
const options = command.optsWithGlobals();
|
|
121
124
|
const appConfig = appconfig.loadAppConfig(options.appConfig);
|
|
122
125
|
// We don't need authenticated user to call this API
|
|
123
126
|
const clientImpl = new client.MyTmpVpnClientImpl(appConfig.apiUrl);
|
|
124
|
-
clientImpl.
|
|
125
|
-
.then(((
|
|
126
|
-
|
|
127
|
-
}))
|
|
128
|
-
.catch((err) => handleError(err));
|
|
129
|
-
});
|
|
130
|
-
program.command('list-regions-detailed')
|
|
131
|
-
.description('Returns the detailed list of all regions where vpn can be created')
|
|
132
|
-
.action((_, command) => {
|
|
133
|
-
const options = command.optsWithGlobals();
|
|
134
|
-
const appConfig = appconfig.loadAppConfig(options.appConfig);
|
|
135
|
-
// We don't need authenticated user to call this API
|
|
136
|
-
const clientImpl = new client.MyTmpVpnClientImpl(appConfig.apiUrl);
|
|
137
|
-
clientImpl.listRegionsDetailed()
|
|
138
|
-
.then(((regions) => {
|
|
139
|
-
log.info(JSON.stringify(regions, null, 2));
|
|
127
|
+
clientImpl.listLocations()
|
|
128
|
+
.then(((locations) => {
|
|
129
|
+
loglevel_1.default.info(JSON.stringify(locations, null, 2));
|
|
140
130
|
}))
|
|
141
131
|
.catch((err) => handleError(err));
|
|
142
132
|
});
|
|
143
133
|
program.command('create')
|
|
144
134
|
.description('Create a new vpn')
|
|
145
|
-
.argument('<
|
|
135
|
+
.argument('<geonameId>', 'geonameId where the vpn should be created, as returned by list-locations')
|
|
146
136
|
.option('--sync', 'wait for vpn creation completion')
|
|
147
|
-
.addOption(new commander_1.Option('--type <type>', 'Type of VPN')
|
|
148
|
-
.choices(vpnlib.getVpnConfigTypes())
|
|
149
|
-
.default(vpnlib.VpnType.WireGuard))
|
|
150
137
|
.option('--peanuts <nb>', 'Max number of peanuts to use (specify -1 for maximum)', '-1')
|
|
151
138
|
.option('--deleteAfter seconds', 'Number of seconds after which the vpn will be terminated')
|
|
152
|
-
.action((
|
|
139
|
+
.action((geonameId, _, command) => {
|
|
153
140
|
const options = command.optsWithGlobals();
|
|
154
141
|
const syncStr = options.sync ? "synchronously" : "asynchronously";
|
|
155
142
|
const deleteAfter = options.deleteAfter ? options.deleteAfter : undefined;
|
|
156
|
-
|
|
143
|
+
loglevel_1.default.debug(`Creating new ${options.type} vpn into ${geonameId} ${syncStr}`);
|
|
157
144
|
(0, mytmpvpn_client_1.getLoggedInClientFromFiles)({
|
|
158
145
|
appConfigFile: options.appConfig,
|
|
159
|
-
userConfigFile: options.
|
|
146
|
+
userConfigFile: options.userProfiles,
|
|
160
147
|
profileName: options.profile
|
|
161
148
|
}).then(client => {
|
|
162
|
-
client.createVpn(
|
|
149
|
+
client.createVpn(Number.parseInt(geonameId), {
|
|
163
150
|
type: options.type,
|
|
164
151
|
maxPeanuts: options.peanuts, deleteAfter
|
|
165
152
|
}).then(vpn => {
|
|
166
153
|
if (!options.sync) {
|
|
167
|
-
|
|
154
|
+
loglevel_1.default.info(vpn);
|
|
168
155
|
return;
|
|
169
156
|
}
|
|
170
157
|
client.waitUntilVpnStateIs(vpn.vpnId, vpnlib.VpnState.Running).then(updatedVpn => {
|
|
171
|
-
|
|
158
|
+
loglevel_1.default.info(updatedVpn);
|
|
172
159
|
}).catch(err => {
|
|
173
160
|
handleError(err);
|
|
174
161
|
});
|
|
@@ -186,20 +173,20 @@ program.command('delete')
|
|
|
186
173
|
.action((vpnId, _, command) => {
|
|
187
174
|
const options = command.optsWithGlobals();
|
|
188
175
|
const syncStr = options.sync ? "synchronously" : "asynchronously";
|
|
189
|
-
|
|
176
|
+
loglevel_1.default.debug(`Deleting vpn ${vpnId} ${syncStr}`);
|
|
190
177
|
(0, mytmpvpn_client_1.getLoggedInClientFromFiles)({
|
|
191
178
|
appConfigFile: options.appConfig,
|
|
192
|
-
userConfigFile: options.
|
|
179
|
+
userConfigFile: options.userProfiles,
|
|
193
180
|
profileName: options.profile
|
|
194
181
|
}).then(client => {
|
|
195
182
|
client.deleteVpn(vpnId).then(vpn => {
|
|
196
183
|
if (!options.sync) {
|
|
197
|
-
|
|
184
|
+
loglevel_1.default.info(JSON.stringify(vpn));
|
|
198
185
|
return;
|
|
199
186
|
}
|
|
200
187
|
client.waitUntilVpnStateIs(vpnId, vpnlib.VpnState.Deleted)
|
|
201
188
|
.then(updatedVpn => {
|
|
202
|
-
|
|
189
|
+
loglevel_1.default.info(updatedVpn);
|
|
203
190
|
return;
|
|
204
191
|
}).catch(err => {
|
|
205
192
|
handleError(err.response?.data || JSON.stringify(err));
|
|
@@ -216,11 +203,11 @@ program.command('get')
|
|
|
216
203
|
const options = command.optsWithGlobals();
|
|
217
204
|
(0, mytmpvpn_client_1.getLoggedInClientFromFiles)({
|
|
218
205
|
appConfigFile: options.appConfig,
|
|
219
|
-
userConfigFile: options.
|
|
206
|
+
userConfigFile: options.userProfiles,
|
|
220
207
|
profileName: options.profile
|
|
221
208
|
}).then(client => {
|
|
222
209
|
client.getVpn(vpnId)
|
|
223
|
-
.then(result =>
|
|
210
|
+
.then(result => loglevel_1.default.info(result))
|
|
224
211
|
.catch(err => handleError(err));
|
|
225
212
|
}).catch(err => {
|
|
226
213
|
handleError(err);
|
|
@@ -230,27 +217,27 @@ program.command('download-config')
|
|
|
230
217
|
.description('Download configuration of the given vpn to the given file')
|
|
231
218
|
.argument('<vpnId>', 'vpnId to get config file from')
|
|
232
219
|
.option('--file <file>', 'file where the config should be downloaded to. Default is <vpnId>.conf')
|
|
233
|
-
.option('--path <path>', 'path where the config file should be written to',
|
|
220
|
+
.option('--path <path>', 'path where the config file should be written to', userprofiles.getDefaultUserProfilesDir())
|
|
234
221
|
.action((vpnId, _, command) => {
|
|
235
222
|
const options = command.optsWithGlobals();
|
|
236
223
|
const file = options.file ? options.file : `${vpnId}.conf`;
|
|
237
224
|
const fullpath = path.join(options.path, file);
|
|
238
225
|
(0, mytmpvpn_client_1.getLoggedInClientFromFiles)({
|
|
239
226
|
appConfigFile: options.appConfig,
|
|
240
|
-
userConfigFile: options.
|
|
227
|
+
userConfigFile: options.userProfiles,
|
|
241
228
|
profileName: options.profile
|
|
242
229
|
}).then(client => {
|
|
243
230
|
client.getVpnConfig(vpnId)
|
|
244
231
|
.then(b64 => {
|
|
245
232
|
const vpnConfig = Buffer.from(b64, 'base64');
|
|
246
|
-
|
|
233
|
+
loglevel_1.default.debug(`Writing config file to ${fullpath}`);
|
|
247
234
|
// Write the config file to the given path
|
|
248
235
|
fs.writeFile(fullpath, vpnConfig, (err) => {
|
|
249
236
|
if (err) {
|
|
250
237
|
handleError(err);
|
|
251
238
|
return;
|
|
252
239
|
}
|
|
253
|
-
|
|
240
|
+
loglevel_1.default.info(`Config file written to ${fullpath}`);
|
|
254
241
|
});
|
|
255
242
|
}).catch(err => handleError(err));
|
|
256
243
|
}).catch(err => {
|
|
@@ -259,20 +246,20 @@ program.command('download-config')
|
|
|
259
246
|
});
|
|
260
247
|
program.command('list')
|
|
261
248
|
.description('List all vpns')
|
|
262
|
-
.option('--
|
|
249
|
+
.option('--geonameId <geonameId>', 'geonameId to list vpns from')
|
|
263
250
|
.option('--include-state [<state>, ...]', 'Comma separated list of states to include', Object.values(vpnlib.VpnState))
|
|
264
251
|
.option('--exclude-state [<state>, ...]', 'Comma separated list of states to exclude from', [vpnlib.VpnState.Deleted])
|
|
265
252
|
.action((_, command) => {
|
|
266
253
|
const options = command.optsWithGlobals();
|
|
267
254
|
(0, mytmpvpn_client_1.getLoggedInClientFromFiles)({
|
|
268
255
|
appConfigFile: options.appConfig,
|
|
269
|
-
userConfigFile: options.
|
|
256
|
+
userConfigFile: options.userProfiles,
|
|
270
257
|
profileName: options.profile
|
|
271
258
|
}).then(client => {
|
|
272
259
|
client.listVpns(options.state)
|
|
273
260
|
.then(vpns => {
|
|
274
|
-
if (options.
|
|
275
|
-
vpns = vpns.filter((vpn) => vpn.
|
|
261
|
+
if (options.location) {
|
|
262
|
+
vpns = vpns.filter((vpn) => vpn.geonamesId === options.geonameId);
|
|
276
263
|
}
|
|
277
264
|
if (options.includeState) {
|
|
278
265
|
vpns = vpns.filter((vpn) => options.includeState.includes(vpn.state));
|
|
@@ -280,7 +267,7 @@ program.command('list')
|
|
|
280
267
|
if (options.excludeState) {
|
|
281
268
|
vpns = vpns.filter((vpn) => !options.excludeState.includes(vpn.state));
|
|
282
269
|
}
|
|
283
|
-
|
|
270
|
+
loglevel_1.default.info(JSON.stringify(vpns, null, 2));
|
|
284
271
|
})
|
|
285
272
|
.catch(err => handleError(err));
|
|
286
273
|
}).catch(err => {
|
|
@@ -298,15 +285,15 @@ program.command('wait')
|
|
|
298
285
|
handleError(`Unknown state: ${state}. Valid states: ${Object.values(vpnlib.VpnState)}`);
|
|
299
286
|
return;
|
|
300
287
|
}
|
|
301
|
-
|
|
288
|
+
loglevel_1.default.debug(`Waiting for ${vpnId} state to be (at least) ${state}`);
|
|
302
289
|
(0, mytmpvpn_client_1.getLoggedInClientFromFiles)({
|
|
303
290
|
appConfigFile: options.appConfig,
|
|
304
|
-
userConfigFile: options.
|
|
291
|
+
userConfigFile: options.userProfiles,
|
|
305
292
|
profileName: options.profile
|
|
306
293
|
}).then(client => {
|
|
307
294
|
client.waitUntilVpnStateIs(vpnId, actualState)
|
|
308
295
|
.then(vpn => {
|
|
309
|
-
|
|
296
|
+
loglevel_1.default.info(vpn);
|
|
310
297
|
})
|
|
311
298
|
.catch(err => handleError(err));
|
|
312
299
|
}).catch(err => {
|
|
@@ -320,10 +307,10 @@ program.command('register')
|
|
|
320
307
|
.action((username, password, _, command) => {
|
|
321
308
|
const options = command.optsWithGlobals();
|
|
322
309
|
var userConfigData;
|
|
323
|
-
if (fs.existsSync(options.
|
|
324
|
-
userConfigData =
|
|
310
|
+
if (fs.existsSync(options.userProfiles)) {
|
|
311
|
+
userConfigData = userprofiles.loadUserProfiles(options.userProfiles);
|
|
325
312
|
if (userConfigData.profiles[options.profile]) {
|
|
326
|
-
handleError(`Profile ${options.profile} already exists in ${options.
|
|
313
|
+
handleError(`Profile ${options.profile} already exists in ${options.userProfiles}, specify another profile name using --profile`);
|
|
327
314
|
return;
|
|
328
315
|
}
|
|
329
316
|
userConfigData.profiles[options.profile] = {
|
|
@@ -344,20 +331,20 @@ program.command('register')
|
|
|
344
331
|
}
|
|
345
332
|
(0, mytmpvpn_client_1.registerUser)(options.appConfig, { username, password })
|
|
346
333
|
.then(user => {
|
|
347
|
-
|
|
348
|
-
fs.mkdir(path.dirname(options.
|
|
334
|
+
loglevel_1.default.info(`Please confirm your identity with the code sent to ${username}`);
|
|
335
|
+
fs.mkdir(path.dirname(options.userProfiles), { recursive: true }, (err, path) => {
|
|
349
336
|
if (err) {
|
|
350
337
|
handleError(err);
|
|
351
338
|
return;
|
|
352
339
|
}
|
|
353
|
-
|
|
354
|
-
fs.writeFile(options.
|
|
340
|
+
loglevel_1.default.debug(`Directory: ${path} created`);
|
|
341
|
+
fs.writeFile(options.userProfiles, JSON.stringify(userConfigData, null, 2), (err) => {
|
|
355
342
|
if (err) {
|
|
356
343
|
handleError(err);
|
|
357
344
|
return;
|
|
358
345
|
}
|
|
359
346
|
});
|
|
360
|
-
|
|
347
|
+
loglevel_1.default.info(`A new profile has been created for ${options.profile} in ${options.userProfiles}`);
|
|
361
348
|
});
|
|
362
349
|
}).catch(err => {
|
|
363
350
|
handleError(err);
|
|
@@ -371,8 +358,8 @@ program.command('confirm-registration')
|
|
|
371
358
|
const options = command.optsWithGlobals();
|
|
372
359
|
(0, mytmpvpn_client_1.confirmUser)(options.appConfig, username, code)
|
|
373
360
|
.then(result => {
|
|
374
|
-
|
|
375
|
-
|
|
361
|
+
loglevel_1.default.debug(result);
|
|
362
|
+
loglevel_1.default.info(`User ${username} confirmed!`);
|
|
376
363
|
})
|
|
377
364
|
.catch(err => {
|
|
378
365
|
handleError(err);
|
|
@@ -399,11 +386,11 @@ Examples:
|
|
|
399
386
|
|
|
400
387
|
# Then you can use the following command at will:
|
|
401
388
|
|
|
402
|
-
# List available
|
|
403
|
-
$ mytmpvpn list-
|
|
389
|
+
# List available locations:
|
|
390
|
+
$ mytmpvpn list-locations
|
|
404
391
|
|
|
405
392
|
# Create a new vpn in Paris:
|
|
406
|
-
$ mytmpvpn create '
|
|
393
|
+
$ mytmpvpn create '2988507' --sync # This takes several minutes, please be patient or remove --sync
|
|
407
394
|
|
|
408
395
|
# List all my vpns:
|
|
409
396
|
$ mytmpvpn list
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mytmpvpn/mytmpvpn-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.0",
|
|
4
4
|
"description": "MyTmpVpn CLI",
|
|
5
5
|
"main": "./dist/mytmpvpn.js",
|
|
6
6
|
"bin": {
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
},
|
|
31
31
|
"license": "GNU GPL",
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@mytmpvpn/mytmpvpn-client": "^
|
|
34
|
-
"@mytmpvpn/mytmpvpn-common": "^
|
|
33
|
+
"@mytmpvpn/mytmpvpn-client": "^10.0.2",
|
|
34
|
+
"@mytmpvpn/mytmpvpn-common": "^13.0.0",
|
|
35
35
|
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
36
|
-
"commander": "^14.0.
|
|
36
|
+
"commander": "^14.0.3",
|
|
37
37
|
"eslint": "^8.57.1",
|
|
38
38
|
"eslint-config-standard-with-typescript": "^39.1.1",
|
|
39
39
|
"eslint-plugin-import": "^2.32.0",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/jest": "^29.5.14",
|
|
46
|
-
"@types/node": "^24.
|
|
46
|
+
"@types/node": "^24.10.13",
|
|
47
47
|
"jest": "^29.7.0",
|
|
48
|
-
"ts-jest": "^29.4.
|
|
48
|
+
"ts-jest": "^29.4.6",
|
|
49
49
|
"typescript": "^5.9.3"
|
|
50
50
|
}
|
|
51
51
|
}
|
package/src/mytmpvpn.ts
CHANGED
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
import * as fs from 'fs'
|
|
5
5
|
import * as path from 'path'
|
|
6
6
|
import { Command, Option } from 'commander'
|
|
7
|
-
import
|
|
7
|
+
import log from 'loglevel'
|
|
8
8
|
log.setDefaultLevel("info")
|
|
9
9
|
|
|
10
10
|
import * as vpnlib from '@mytmpvpn/mytmpvpn-common/models/vpn'
|
|
11
11
|
import * as peanuts from '@mytmpvpn/mytmpvpn-common/models/peanuts'
|
|
12
12
|
import { confirmUser, getLoggedInClientFromFiles, registerUser } from '@mytmpvpn/mytmpvpn-client'
|
|
13
13
|
import * as appconfig from '@mytmpvpn/mytmpvpn-client/appconfig'
|
|
14
|
-
import * as
|
|
14
|
+
import * as userprofiles from '@mytmpvpn/mytmpvpn-client/userprofiles'
|
|
15
15
|
import * as client from '@mytmpvpn/mytmpvpn-client/client'
|
|
16
|
+
import { ListLocationsResponse } from '@mytmpvpn/mytmpvpn-common/models/location'
|
|
16
17
|
|
|
17
18
|
const program = new Command()
|
|
18
19
|
|
|
@@ -45,8 +46,8 @@ program
|
|
|
45
46
|
.version('0.0.1')
|
|
46
47
|
.option('--verbose', 'Produce more logs')
|
|
47
48
|
.option('--appConfig <file>', 'Path to the application config file', appconfig.getDefaultAppConfigFile())
|
|
48
|
-
.option('--
|
|
49
|
-
.option('--profile <name>', 'Name of the profile in the user
|
|
49
|
+
.option('--userProfiles <file>', 'Path to the user profiles file', userprofiles.getDefaultUserProfilesFile())
|
|
50
|
+
.option('--profile <name>', 'Name of the profile in the user profiles file to use', userprofiles.getDefaultUsername())
|
|
50
51
|
|
|
51
52
|
program.on('option:verbose', function () {
|
|
52
53
|
log.setDefaultLevel("trace")
|
|
@@ -73,7 +74,7 @@ program.command('get-peanuts-balance')
|
|
|
73
74
|
log.debug(`Get peanuts balance`)
|
|
74
75
|
getLoggedInClientFromFiles({
|
|
75
76
|
appConfigFile: options.appConfig,
|
|
76
|
-
userConfigFile: options.
|
|
77
|
+
userConfigFile: options.userProfiles,
|
|
77
78
|
profileName: options.profile
|
|
78
79
|
}).then(client => {
|
|
79
80
|
client.getPeanutsBalance().then(balance => {
|
|
@@ -86,54 +87,37 @@ program.command('get-peanuts-balance')
|
|
|
86
87
|
})
|
|
87
88
|
})
|
|
88
89
|
|
|
89
|
-
program.command('list-
|
|
90
|
-
.description('Returns the list of all
|
|
90
|
+
program.command('list-locations')
|
|
91
|
+
.description('Returns the list of all locations where vpn can be created')
|
|
91
92
|
.action((_, command) => {
|
|
92
93
|
const options = command.optsWithGlobals()
|
|
93
94
|
const appConfig = appconfig.loadAppConfig(options.appConfig)
|
|
94
95
|
// We don't need authenticated user to call this API
|
|
95
96
|
const clientImpl = new client.MyTmpVpnClientImpl(appConfig.apiUrl)
|
|
96
|
-
clientImpl.
|
|
97
|
-
.then(((
|
|
98
|
-
log.info(JSON.stringify(
|
|
99
|
-
}))
|
|
100
|
-
.catch((err: any) => handleError(err))
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
program.command('list-regions-detailed')
|
|
104
|
-
.description('Returns the detailed list of all regions where vpn can be created')
|
|
105
|
-
.action((_, command) => {
|
|
106
|
-
const options = command.optsWithGlobals()
|
|
107
|
-
const appConfig = appconfig.loadAppConfig(options.appConfig)
|
|
108
|
-
// We don't need authenticated user to call this API
|
|
109
|
-
const clientImpl = new client.MyTmpVpnClientImpl(appConfig.apiUrl)
|
|
110
|
-
clientImpl.listRegionsDetailed()
|
|
111
|
-
.then(((regions: any) => {
|
|
112
|
-
log.info(JSON.stringify(regions, null, 2))
|
|
97
|
+
clientImpl.listLocations()
|
|
98
|
+
.then(((locations: ListLocationsResponse) => {
|
|
99
|
+
log.info(JSON.stringify(locations, null, 2))
|
|
113
100
|
}))
|
|
114
101
|
.catch((err: any) => handleError(err))
|
|
115
102
|
})
|
|
116
103
|
|
|
117
104
|
program.command('create')
|
|
118
105
|
.description('Create a new vpn')
|
|
119
|
-
.argument('<
|
|
106
|
+
.argument('<geonameId>', 'geonameId where the vpn should be created, as returned by list-locations')
|
|
120
107
|
.option('--sync', 'wait for vpn creation completion')
|
|
121
|
-
.addOption(new Option('--type <type>', 'Type of VPN')
|
|
122
|
-
.choices(vpnlib.getVpnConfigTypes())
|
|
123
|
-
.default(vpnlib.VpnType.WireGuard))
|
|
124
108
|
.option('--peanuts <nb>', 'Max number of peanuts to use (specify -1 for maximum)', '-1')
|
|
125
109
|
.option('--deleteAfter seconds', 'Number of seconds after which the vpn will be terminated')
|
|
126
|
-
.action((
|
|
110
|
+
.action((geonameId: string, _, command) => {
|
|
127
111
|
const options = command.optsWithGlobals()
|
|
128
112
|
const syncStr = options.sync ? "synchronously" : "asynchronously"
|
|
129
113
|
const deleteAfter = options.deleteAfter ? options.deleteAfter : undefined
|
|
130
|
-
log.debug(`Creating new ${options.type} vpn into ${
|
|
114
|
+
log.debug(`Creating new ${options.type} vpn into ${geonameId} ${syncStr}`)
|
|
131
115
|
getLoggedInClientFromFiles({
|
|
132
116
|
appConfigFile: options.appConfig,
|
|
133
|
-
userConfigFile: options.
|
|
117
|
+
userConfigFile: options.userProfiles,
|
|
134
118
|
profileName: options.profile
|
|
135
119
|
}).then(client => {
|
|
136
|
-
client.createVpn(
|
|
120
|
+
client.createVpn(Number.parseInt(geonameId), {
|
|
137
121
|
type: options.type,
|
|
138
122
|
maxPeanuts: options.peanuts, deleteAfter
|
|
139
123
|
}).then(vpn => {
|
|
@@ -164,7 +148,7 @@ program.command('delete')
|
|
|
164
148
|
log.debug(`Deleting vpn ${vpnId} ${syncStr}`)
|
|
165
149
|
getLoggedInClientFromFiles({
|
|
166
150
|
appConfigFile: options.appConfig,
|
|
167
|
-
userConfigFile: options.
|
|
151
|
+
userConfigFile: options.userProfiles,
|
|
168
152
|
profileName: options.profile
|
|
169
153
|
}).then(client => {
|
|
170
154
|
client.deleteVpn(vpnId).then(vpn => {
|
|
@@ -192,7 +176,7 @@ program.command('get')
|
|
|
192
176
|
const options = command.optsWithGlobals()
|
|
193
177
|
getLoggedInClientFromFiles({
|
|
194
178
|
appConfigFile: options.appConfig,
|
|
195
|
-
userConfigFile: options.
|
|
179
|
+
userConfigFile: options.userProfiles,
|
|
196
180
|
profileName: options.profile
|
|
197
181
|
}).then(client => {
|
|
198
182
|
client.getVpn(vpnId)
|
|
@@ -207,14 +191,14 @@ program.command('download-config')
|
|
|
207
191
|
.description('Download configuration of the given vpn to the given file')
|
|
208
192
|
.argument('<vpnId>', 'vpnId to get config file from')
|
|
209
193
|
.option('--file <file>', 'file where the config should be downloaded to. Default is <vpnId>.conf')
|
|
210
|
-
.option('--path <path>', 'path where the config file should be written to',
|
|
194
|
+
.option('--path <path>', 'path where the config file should be written to', userprofiles.getDefaultUserProfilesDir())
|
|
211
195
|
.action((vpnId, _, command) => {
|
|
212
196
|
const options = command.optsWithGlobals()
|
|
213
197
|
const file = options.file ? options.file : `${vpnId}.conf`
|
|
214
198
|
const fullpath = path.join(options.path, file)
|
|
215
199
|
getLoggedInClientFromFiles({
|
|
216
200
|
appConfigFile: options.appConfig,
|
|
217
|
-
userConfigFile: options.
|
|
201
|
+
userConfigFile: options.userProfiles,
|
|
218
202
|
profileName: options.profile
|
|
219
203
|
}).then(client => {
|
|
220
204
|
client.getVpnConfig(vpnId)
|
|
@@ -237,20 +221,20 @@ program.command('download-config')
|
|
|
237
221
|
|
|
238
222
|
program.command('list')
|
|
239
223
|
.description('List all vpns')
|
|
240
|
-
.option('--
|
|
224
|
+
.option('--geonameId <geonameId>', 'geonameId to list vpns from')
|
|
241
225
|
.option('--include-state [<state>, ...]', 'Comma separated list of states to include', Object.values(vpnlib.VpnState))
|
|
242
226
|
.option('--exclude-state [<state>, ...]', 'Comma separated list of states to exclude from', [vpnlib.VpnState.Deleted])
|
|
243
227
|
.action((_, command) => {
|
|
244
228
|
const options = command.optsWithGlobals()
|
|
245
229
|
getLoggedInClientFromFiles({
|
|
246
230
|
appConfigFile: options.appConfig,
|
|
247
|
-
userConfigFile: options.
|
|
231
|
+
userConfigFile: options.userProfiles,
|
|
248
232
|
profileName: options.profile
|
|
249
233
|
}).then(client => {
|
|
250
234
|
client.listVpns(options.state)
|
|
251
235
|
.then(vpns => {
|
|
252
|
-
if (options.
|
|
253
|
-
vpns = vpns.filter((vpn: vpnlib.Vpn) => vpn.
|
|
236
|
+
if (options.location) {
|
|
237
|
+
vpns = vpns.filter((vpn: vpnlib.Vpn) => vpn.geonamesId === options.geonameId)
|
|
254
238
|
}
|
|
255
239
|
if (options.includeState) {
|
|
256
240
|
vpns = vpns.filter((vpn: vpnlib.Vpn) => options.includeState.includes(vpn.state))
|
|
@@ -280,7 +264,7 @@ program.command('wait')
|
|
|
280
264
|
log.debug(`Waiting for ${vpnId} state to be (at least) ${state}`)
|
|
281
265
|
getLoggedInClientFromFiles({
|
|
282
266
|
appConfigFile: options.appConfig,
|
|
283
|
-
userConfigFile: options.
|
|
267
|
+
userConfigFile: options.userProfiles,
|
|
284
268
|
profileName: options.profile
|
|
285
269
|
}).then(client => {
|
|
286
270
|
client.waitUntilVpnStateIs(vpnId, actualState)
|
|
@@ -299,11 +283,11 @@ program.command('register')
|
|
|
299
283
|
.argument('<password>', 'a password')
|
|
300
284
|
.action((username, password, _, command) => {
|
|
301
285
|
const options = command.optsWithGlobals()
|
|
302
|
-
var userConfigData:
|
|
303
|
-
if (fs.existsSync(options.
|
|
304
|
-
userConfigData =
|
|
286
|
+
var userConfigData: userprofiles.UserProfiles
|
|
287
|
+
if (fs.existsSync(options.userProfiles)) {
|
|
288
|
+
userConfigData = userprofiles.loadUserProfiles(options.userProfiles)
|
|
305
289
|
if (userConfigData.profiles[options.profile]) {
|
|
306
|
-
handleError(`Profile ${options.profile} already exists in ${options.
|
|
290
|
+
handleError(`Profile ${options.profile} already exists in ${options.userProfiles}, specify another profile name using --profile`)
|
|
307
291
|
return
|
|
308
292
|
}
|
|
309
293
|
userConfigData.profiles[options.profile] = {
|
|
@@ -325,19 +309,19 @@ program.command('register')
|
|
|
325
309
|
{ username, password })
|
|
326
310
|
.then(user => {
|
|
327
311
|
log.info(`Please confirm your identity with the code sent to ${username}`)
|
|
328
|
-
fs.mkdir(path.dirname(options.
|
|
312
|
+
fs.mkdir(path.dirname(options.userProfiles), { recursive: true }, (err, path?) => {
|
|
329
313
|
if (err) {
|
|
330
314
|
handleError(err)
|
|
331
315
|
return
|
|
332
316
|
}
|
|
333
317
|
log.debug(`Directory: ${path} created`)
|
|
334
|
-
fs.writeFile(options.
|
|
318
|
+
fs.writeFile(options.userProfiles, JSON.stringify(userConfigData, null, 2), (err) => {
|
|
335
319
|
if (err) {
|
|
336
320
|
handleError(err)
|
|
337
321
|
return
|
|
338
322
|
}
|
|
339
323
|
})
|
|
340
|
-
log.info(`A new profile has been created for ${options.profile} in ${options.
|
|
324
|
+
log.info(`A new profile has been created for ${options.profile} in ${options.userProfiles}`)
|
|
341
325
|
})
|
|
342
326
|
}).catch(err => {
|
|
343
327
|
handleError(err)
|
|
@@ -382,11 +366,11 @@ Examples:
|
|
|
382
366
|
|
|
383
367
|
# Then you can use the following command at will:
|
|
384
368
|
|
|
385
|
-
# List available
|
|
386
|
-
$ mytmpvpn list-
|
|
369
|
+
# List available locations:
|
|
370
|
+
$ mytmpvpn list-locations
|
|
387
371
|
|
|
388
372
|
# Create a new vpn in Paris:
|
|
389
|
-
$ mytmpvpn create '
|
|
373
|
+
$ mytmpvpn create '2988507' --sync # This takes several minutes, please be patient or remove --sync
|
|
390
374
|
|
|
391
375
|
# List all my vpns:
|
|
392
376
|
$ mytmpvpn list
|