bdy 1.7.46-dev

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.
Files changed (96) hide show
  1. package/.eslintrc.yml +23 -0
  2. package/LICENSE +21 -0
  3. package/bin/cli.js +5 -0
  4. package/dockerfile +15 -0
  5. package/link.sh +3 -0
  6. package/package.json +39 -0
  7. package/src/agent/linux.js +127 -0
  8. package/src/agent/manager.js +404 -0
  9. package/src/agent/osx.js +150 -0
  10. package/src/agent/socket/tunnel.js +232 -0
  11. package/src/agent/socket.js +260 -0
  12. package/src/agent/system.js +205 -0
  13. package/src/agent/wait.js +20 -0
  14. package/src/agent/windows.js +168 -0
  15. package/src/agent.js +248 -0
  16. package/src/api/agent.js +95 -0
  17. package/src/api/buddy.js +131 -0
  18. package/src/api/socket.js +142 -0
  19. package/src/cfg.js +228 -0
  20. package/src/command/agent/disable.js +37 -0
  21. package/src/command/agent/enable.js +117 -0
  22. package/src/command/agent/restart.js +28 -0
  23. package/src/command/agent/run.js +16 -0
  24. package/src/command/agent/start.js +28 -0
  25. package/src/command/agent/status.js +45 -0
  26. package/src/command/agent/stop.js +28 -0
  27. package/src/command/agent/tunnel/http.js +47 -0
  28. package/src/command/agent/tunnel/list.js +27 -0
  29. package/src/command/agent/tunnel/start.js +38 -0
  30. package/src/command/agent/tunnel/status.js +32 -0
  31. package/src/command/agent/tunnel/stop.js +30 -0
  32. package/src/command/agent/tunnel/tcp.js +47 -0
  33. package/src/command/agent/tunnel/tls.js +47 -0
  34. package/src/command/agent/tunnel.js +21 -0
  35. package/src/command/agent/update.js +43 -0
  36. package/src/command/agent/version.js +23 -0
  37. package/src/command/agent.js +27 -0
  38. package/src/command/config/add/http.js +33 -0
  39. package/src/command/config/add/tcp.js +33 -0
  40. package/src/command/config/add/tls.js +33 -0
  41. package/src/command/config/add.js +13 -0
  42. package/src/command/config/get/region.js +13 -0
  43. package/src/command/config/get/timeout.js +13 -0
  44. package/src/command/config/get/token.js +13 -0
  45. package/src/command/config/get/tunnel.js +21 -0
  46. package/src/command/config/get/tunnels.js +13 -0
  47. package/src/command/config/get/whitelist.js +13 -0
  48. package/src/command/config/get.js +19 -0
  49. package/src/command/config/remove/tunnel.js +22 -0
  50. package/src/command/config/remove.js +9 -0
  51. package/src/command/config/set/region.js +19 -0
  52. package/src/command/config/set/timeout.js +22 -0
  53. package/src/command/config/set/token.js +18 -0
  54. package/src/command/config/set/whitelist.js +19 -0
  55. package/src/command/config/set.js +15 -0
  56. package/src/command/config.js +15 -0
  57. package/src/command/http.js +34 -0
  58. package/src/command/pre.js +47 -0
  59. package/src/command/start.js +31 -0
  60. package/src/command/tcp.js +32 -0
  61. package/src/command/tls.js +32 -0
  62. package/src/command/version.js +10 -0
  63. package/src/format.js +171 -0
  64. package/src/index.js +32 -0
  65. package/src/input.js +283 -0
  66. package/src/logger.js +87 -0
  67. package/src/output/interactive/tunnel.js +871 -0
  68. package/src/output/noninteractive/agent/tunnels.js +32 -0
  69. package/src/output/noninteractive/config/tunnel.js +52 -0
  70. package/src/output/noninteractive/config/tunnels.js +19 -0
  71. package/src/output/noninteractive/tunnel.js +79 -0
  72. package/src/output.js +136 -0
  73. package/src/server/cert.js +51 -0
  74. package/src/server/http1.js +79 -0
  75. package/src/server/http2.js +79 -0
  76. package/src/server/sftp.js +474 -0
  77. package/src/server/ssh.js +107 -0
  78. package/src/server/tls.js +41 -0
  79. package/src/ssh/client.js +196 -0
  80. package/src/texts.js +447 -0
  81. package/src/tunnel/agent.js +100 -0
  82. package/src/tunnel/compression.js +32 -0
  83. package/src/tunnel/dns.js +55 -0
  84. package/src/tunnel/html/404.html +129 -0
  85. package/src/tunnel/html/503.html +136 -0
  86. package/src/tunnel/html.js +32 -0
  87. package/src/tunnel/http/log.js +204 -0
  88. package/src/tunnel/http/serve.js +127 -0
  89. package/src/tunnel/http/stream.js +46 -0
  90. package/src/tunnel/http.js +406 -0
  91. package/src/tunnel/identification.js +95 -0
  92. package/src/tunnel/latency.js +63 -0
  93. package/src/tunnel/tcp.js +71 -0
  94. package/src/tunnel.js +696 -0
  95. package/src/utils.js +496 -0
  96. package/unlink.sh +3 -0
@@ -0,0 +1,95 @@
1
+ const logger = require('../logger.js');
2
+ const {
3
+ ERR_FAILED_TO_CONNECT_TO_AGENT,
4
+ ERR_NOT_FOUND,
5
+ ERR_SWW,
6
+ LOG_ERROR
7
+ } = require('../texts.js');
8
+ const { WebSocket } = require('ws');
9
+
10
+ const TIMEOUT = 120000;
11
+
12
+ const openSocket = (port, path) => {
13
+ return new Promise((resolve, reject) => {
14
+ const ws = new WebSocket(`ws://localhost:${port}${path}`);
15
+ ws.on('error', () => {
16
+ reject(new Error(ERR_FAILED_TO_CONNECT_TO_AGENT));
17
+ });
18
+ ws.on('open', () => {
19
+ resolve(ws);
20
+ });
21
+ });
22
+ };
23
+
24
+ const makeRequest = async (port, path, body) => {
25
+ const c = new AbortController();
26
+ setTimeout(() => {
27
+ c.abort();
28
+ }, TIMEOUT);
29
+ const response = await fetch(`http://localhost:${port}${path}`, {
30
+ body: body ? JSON.stringify(body) : null,
31
+ headers: { 'Content-Type': 'application/json' },
32
+ method: 'POST',
33
+ signal: c.signal,
34
+ });
35
+ if (response.status === 404) {
36
+ throw new Error(ERR_NOT_FOUND);
37
+ }
38
+ if (response.status === 400) {
39
+ const data = await response.json();
40
+ throw new Error(data.message);
41
+ }
42
+ if (response.status !== 200) {
43
+ throw new Error(ERR_SWW);
44
+ }
45
+ let data;
46
+ try {
47
+ data = await response.json();
48
+ } catch (err) {
49
+ logger.error(LOG_ERROR);
50
+ logger.error(err);
51
+ throw new Error(ERR_FAILED_TO_CONNECT_TO_AGENT);
52
+ }
53
+ return data;
54
+ };
55
+
56
+ class ApiAgent {
57
+ constructor(port) {
58
+ this.port = port;
59
+ }
60
+ async fetchStatus() {
61
+ return makeRequest(this.port,'/status');
62
+ }
63
+
64
+ async addTunnel(data) {
65
+ return makeRequest(this.port,'/tunnel/add', data);
66
+ }
67
+
68
+ async fetchTunnels() {
69
+ return makeRequest(this.port,'/tunnels');
70
+ }
71
+
72
+ async stopTunnel(id) {
73
+ return makeRequest(this.port, '/tunnel/stop', {
74
+ id
75
+ });
76
+ }
77
+
78
+ async startAgent() {
79
+ return makeRequest(this.port,'/agent/start');
80
+ }
81
+
82
+ async restartAgent() {
83
+ return makeRequest(this.port,'/agent/restart');
84
+ }
85
+
86
+ async stopAgent() {
87
+ return makeRequest(this.port,'/agent/stop');
88
+ }
89
+
90
+ async socketTunnel(id) {
91
+ return openSocket(this.port, `/tunnel?id=${encodeURIComponent(id)}`);
92
+ }
93
+ }
94
+
95
+ module.exports = ApiAgent;
@@ -0,0 +1,131 @@
1
+ const { Agent: HttpsAgent } = require('https');
2
+ const Tunnel = require('../tunnel.js');
3
+ const logger = require('../logger.js');
4
+ const Agent = require('../agent.js');
5
+ const {
6
+ apiErrorCodeToClass,
7
+ getHostname,
8
+ getPlatform,
9
+ getVersion,
10
+ ApiErrorFailedToConnect,
11
+ } = require('../utils');
12
+ const {
13
+ LOG_AGENT_REGISTERED,
14
+ LOG_GETTING_AGENT,
15
+ LOG_REGION_DETECTED,
16
+ LOG_REGISTERING_AGENT,
17
+ LOG_REGISTERING_TUNNEL,
18
+ LOG_REMOVING_TUNNEL,
19
+ LOG_TUNNEL_REGISTERED,
20
+ LOG_UNREGISTERING_AGENT
21
+ } = require('../texts.js');
22
+
23
+ const TIMEOUT = 120000;
24
+
25
+ const nodeFetch = (url, opts) => {
26
+ return new Promise((resolve, reject) => {
27
+ import('node-fetch').then(({ default: fetch }) => {
28
+ fetch(url, opts).then(resolve).catch(reject);
29
+ }).catch(reject);
30
+ });
31
+ };
32
+
33
+ const makeRequest = async (host, path, body, method = 'POST', respAsJson = true, timeout = TIMEOUT) => {
34
+ let data;
35
+ try {
36
+ const c = new AbortController();
37
+ setTimeout(() => {
38
+ c.abort();
39
+ }, timeout);
40
+ const response = await nodeFetch(`${host}${path}`, {
41
+ body: body ? JSON.stringify(body) : null,
42
+ headers: body ? { 'Content-Type': 'application/json' } : null,
43
+ method,
44
+ signal: c.signal,
45
+ agent: new HttpsAgent({
46
+ rejectUnauthorized: false,
47
+ }),
48
+ });
49
+ if (respAsJson) data = await response.json();
50
+ else data = await response.text();
51
+ } catch (err) {
52
+ throw new ApiErrorFailedToConnect(host);
53
+ }
54
+ if (respAsJson) {
55
+ if (data.code !== 200) {
56
+ throw apiErrorCodeToClass(data.result.code, host);
57
+ }
58
+ return data.result;
59
+ } else {
60
+ return data;
61
+ }
62
+ };
63
+
64
+ class ApiBuddyClass {
65
+ async register(service, host, token, onDefaultRegion) {
66
+ const version = getVersion();
67
+ const hostname = getHostname();
68
+ const platform = getPlatform();
69
+ logger.info(LOG_REGISTERING_AGENT);
70
+ const r = await makeRequest(host, '/tunnel/agent/add', {
71
+ token,
72
+ version,
73
+ hostname,
74
+ platform,
75
+ service
76
+ });
77
+ logger.info(LOG_AGENT_REGISTERED(r.id));
78
+ logger.info(LOG_REGION_DETECTED(r.region));
79
+ if (onDefaultRegion) onDefaultRegion(r.region);
80
+ return new Agent(r.id, host, r.token, service, this);
81
+ }
82
+
83
+ async unregister(id, host, token) {
84
+ logger.info(LOG_UNREGISTERING_AGENT);
85
+ await makeRequest(host, '/tunnel/agent/remove', {
86
+ token,
87
+ id
88
+ });
89
+ return true;
90
+ }
91
+
92
+ async fetchAgent(id, host, token) {
93
+ logger.info(LOG_GETTING_AGENT);
94
+ const r = await makeRequest(host, '/tunnel/agent/fetch', {
95
+ token,
96
+ id
97
+ });
98
+ return new Agent(r.id, host, token, r.service, this);
99
+ }
100
+
101
+ async addTunnel(agentId, host, token, prepared, sshHostKey) {
102
+ logger.info(LOG_REGISTERING_TUNNEL);
103
+ const config = await makeRequest(host, '/tunnel/add', {
104
+ ...prepared,
105
+ token,
106
+ agentId
107
+ });
108
+ logger.info(LOG_TUNNEL_REGISTERED(config.id));
109
+ return new Tunnel({
110
+ ...config,
111
+ sshHostKey
112
+ });
113
+ }
114
+
115
+ async removeTunnel(agentId, tunnelId, host, token) {
116
+ logger.info(LOG_REMOVING_TUNNEL);
117
+ await makeRequest(host, '/tunnel/remove', {
118
+ agentId,
119
+ tunnelId,
120
+ token
121
+ });
122
+ }
123
+
124
+ async fetchMyIp() {
125
+ return makeRequest('https://es.buddy.works', '/ip', null, 'GET', false);
126
+ }
127
+ }
128
+
129
+ const ApiBuddy = new ApiBuddyClass();
130
+
131
+ module.exports = ApiBuddy;
@@ -0,0 +1,142 @@
1
+ const { io } = require('socket.io-client');
2
+ const { Agent: HttpsAgent } = require('https');
3
+ const EventEmitter = require('events');
4
+ const logger = require('../logger.js');
5
+ const {
6
+ LOG_SOCKET_CONNECTED,
7
+ LOG_SOCKET_DISCONNECTED
8
+ } = require('../texts');
9
+ const {
10
+ apiErrorCodeToClass,
11
+ getHostname,
12
+ getPlatform,
13
+ getVersion,
14
+ SOCKET_IO_EVENT_FETCH_FAILED,
15
+ SOCKET_IO_EVENT_FETCH_SUCCESS,
16
+ SOCKET_IO_EVENT_CONNECTED,
17
+ SOCKET_IO_EVENT_DISCONNECTED,
18
+ SOCKET_IO_EVENT_AGENT,
19
+ SOCKET_IO_EVENT_TUNNEL,
20
+ EVENT_TUNNEL_HTTP_NEW_RESPONSE_END
21
+ } = require('../utils');
22
+
23
+ const MAX_REQUESTS_SYNC_WINDOW = 30000;
24
+ const MAX_REQUESTS_SYNC_IN_WINDOW = 100;
25
+
26
+ class ApiSocketClass extends EventEmitter {
27
+ fetch(activate = true, action = null, resetFirstHeard = false, tunnels) {
28
+ this.socket.emit('fetchTunnelAgent', {
29
+ id: this.id,
30
+ token: this.token,
31
+ hostname: this.hostname,
32
+ platform: this.platform,
33
+ version: this.version,
34
+ activate,
35
+ action,
36
+ resetFirstHeard,
37
+ tunnels
38
+ });
39
+ }
40
+
41
+ update(activate, tunnels, force = false) {
42
+ const now = Date.now();
43
+ // nie robimy update jak byl mniej niz 5s temu
44
+ if (!force && this.lastUpdate && now - this.lastUpdate < 5000) return;
45
+ this.lastUpdate = now;
46
+ this.socket.emit('updateTunnelAgent', {
47
+ id: this.id,
48
+ token: this.token,
49
+ hostname: this.hostname,
50
+ platform: this.platform,
51
+ version: this.version,
52
+ activate,
53
+ tunnels
54
+ });
55
+ }
56
+
57
+ emitRequest(tunnelId, logRequest) {
58
+ this.socket.emit('tunnelRequest', {
59
+ id: this.id,
60
+ token: this.token,
61
+ tunnelId,
62
+ request: logRequest.toSocket()
63
+ });
64
+ }
65
+
66
+ request(tunnelId, logRequest) {
67
+ if (this.tunnelRequests > MAX_REQUESTS_SYNC_IN_WINDOW) return;
68
+ this.tunnelRequests += 1;
69
+ logRequest.once(EVENT_TUNNEL_HTTP_NEW_RESPONSE_END, () => {
70
+ this.emitRequest(tunnelId, logRequest);
71
+ });
72
+ this.emitRequest(tunnelId, logRequest);
73
+ }
74
+
75
+ onSyncAgent(data, action) {
76
+ this.emit(SOCKET_IO_EVENT_AGENT, data, action);
77
+ }
78
+
79
+ onSyncTunnel(data, action) {
80
+ this.emit(SOCKET_IO_EVENT_TUNNEL, data, action);
81
+ }
82
+
83
+ onSync(data) {
84
+ try {
85
+ const json = JSON.parse(data);
86
+ if (json.payloadType === 'TunnelAgentFront') this.onSyncAgent(json.payload, json.action);
87
+ else if (json.payloadType === 'TunnelFront') this.onSyncTunnel(json.payload, json.action);
88
+ } catch {
89
+ // do nothing
90
+ }
91
+ }
92
+
93
+ constructor(host, id, token) {
94
+ super();
95
+ this.id = id;
96
+ this.token = token;
97
+ this.connected = false;
98
+ this.hostname = getHostname();
99
+ this.platform = getPlatform();
100
+ this.version = getVersion();
101
+ this.lastUpdate = null;
102
+ this.tunnelRequests = 0;
103
+ setInterval(() => {
104
+ this.tunnelRequests = 0;
105
+ }, MAX_REQUESTS_SYNC_WINDOW);
106
+ this.socket = io(host, {
107
+ forceNew: true,
108
+ autoConnect: true,
109
+ autoUnref: true,
110
+ forceBase64: true,
111
+ transports: ['websocket'],
112
+ reconnection: true,
113
+ rejectUnauthorized: false,
114
+ agent: new HttpsAgent({
115
+ rejectUnauthorized: false,
116
+ }),
117
+ maxHttpBufferSize: 3e6,
118
+ extraHeaders: {
119
+ cookie: 'a=b'
120
+ }
121
+ });
122
+ this.socket.on('connect', () => {
123
+ this.connected = true;
124
+ logger.info(LOG_SOCKET_CONNECTED);
125
+ this.emit(SOCKET_IO_EVENT_CONNECTED);
126
+ });
127
+ this.socket.on('disconnect', () => {
128
+ this.connected = false;
129
+ logger.info(LOG_SOCKET_DISCONNECTED);
130
+ this.emit(SOCKET_IO_EVENT_DISCONNECTED);
131
+ });
132
+ this.socket.on('fetchTunnelAgentSuccess', (data) => {
133
+ this.emit(SOCKET_IO_EVENT_FETCH_SUCCESS, data);
134
+ });
135
+ this.socket.on('fetchTunnelAgentFailed', (code) => {
136
+ this.emit(SOCKET_IO_EVENT_FETCH_FAILED, apiErrorCodeToClass(code, host));
137
+ });
138
+ this.socket.on('sync', (data) => this.onSync(data));
139
+ }
140
+ }
141
+
142
+ module.exports = ApiSocketClass;
package/src/cfg.js ADDED
@@ -0,0 +1,228 @@
1
+ const { resolve } = require('path');
2
+ const {
3
+ mkdirSync,
4
+ readFileSync,
5
+ statSync,
6
+ writeFileSync
7
+ } = require('fs');
8
+ const { decode } = require('jsonwebtoken');
9
+ const {
10
+ DEFAULT_TIMEOUT,
11
+ getHomeDirectory,
12
+ TUNNEL_HTTP,
13
+ TUNNEL_TLS
14
+ } = require('./utils.js');
15
+ const Input = require('./input.js');
16
+ const {
17
+ ERR_CANT_CREATE_DIR_IN_HOME,
18
+ ERR_CONFIG_CORRUPTED,
19
+ ERR_TOKEN_NOT_PROVIDED,
20
+ ERR_WRONG_TOKEN
21
+ } = require('./texts.js');
22
+
23
+ class Cfg {
24
+ constructor() {
25
+ this.dir = getHomeDirectory();
26
+ this.file = resolve(this.dir, 'cfg.json');
27
+ this.json = {};
28
+ this.load();
29
+ }
30
+
31
+ createDir() {
32
+ try {
33
+ mkdirSync(this.dir, {
34
+ recursive: true
35
+ });
36
+ } catch (err) {
37
+ throw new Error(ERR_CANT_CREATE_DIR_IN_HOME('.bdy'));
38
+ }
39
+ }
40
+
41
+ createEmptyFile() {
42
+ try {
43
+ writeFileSync(this.file, '{}', 'utf-8');
44
+ } catch (err) {
45
+ throw new Error(ERR_CANT_CREATE_DIR_IN_HOME('.bdy/cfg.json'));
46
+ }
47
+ }
48
+
49
+ ensureDir() {
50
+ try {
51
+ statSync(this.dir);
52
+ } catch(err) {
53
+ this.createDir();
54
+ }
55
+ }
56
+
57
+ ensureFile() {
58
+ this.ensureDir();
59
+ try {
60
+ statSync(this.file);
61
+ } catch (err) {
62
+ this.createEmptyFile();
63
+ }
64
+ }
65
+
66
+ ensureTunnels() {
67
+ if (!this.json.tunnels) this.json.tunnels = {};
68
+ }
69
+
70
+ async prepareTunnel(tunnelType, target, options, useDefaults, myIp) {
71
+ const type = Input.type(tunnelType);
72
+ const tunnel = {
73
+ type,
74
+ target: Input.target(target, type)
75
+ };
76
+ if (options.region !== undefined) tunnel.region = Input.region(options.region);
77
+ else if (useDefaults) tunnel.region = this.getRegion();
78
+ if (options.whitelist !== undefined) tunnel.whitelist = Input.whitelist(options.whitelist);
79
+ else if (useDefaults) {
80
+ tunnel.whitelist = this.getWhitelist();
81
+ if (!tunnel.whitelist.length) {
82
+ tunnel.whitelist.push(myIp);
83
+ }
84
+ }
85
+ if (options.timeout !== undefined) tunnel.timeout = Input.timeout(options.timeout);
86
+ else if (useDefaults) tunnel.timeout = this.getTimeout();
87
+ if (options.domain !== undefined) tunnel.domain = Input.domain(options.domain);
88
+ if (options.subdomain !== undefined) tunnel.subdomain = Input.subdomain(options.subdomain);
89
+ if (type === TUNNEL_HTTP) {
90
+ if (options.host !== undefined) tunnel.host = options.host;
91
+ if (options.auth !== undefined) {
92
+ const { password, login } = Input.auth(options.auth);
93
+ tunnel.login = login;
94
+ tunnel.password = password;
95
+ }
96
+ if (options.ca !== undefined) tunnel.ca = Input.ca(options.ca);
97
+ if (options.serve !== undefined) tunnel.serve = Input.serve(options.serve);
98
+ if (options.useragent !== undefined) tunnel.useragents = Input.useragents(options.useragent);
99
+ if (options.header !== undefined) tunnel.headers = Input.headers(options.header);
100
+ if (options.responseHeader !== undefined) tunnel.responseHeaders = Input.headers(options.responseHeader);
101
+ if (options.circuitBreaker !== undefined) tunnel.circuitBreaker = Input.circuitBreaker(options.circuitBreaker);
102
+ tunnel.log = !!options.log;
103
+ tunnel.verify = !!options.verify;
104
+ tunnel.http2 = !!options.http2;
105
+ tunnel.compression = !!options.compression;
106
+ } else if (type === TUNNEL_TLS) {
107
+ tunnel.terminate = Input.terminate(options.terminate);
108
+ if (options.key !== undefined || options.cert !== undefined){
109
+ const { key, cert } = Input.keyCert(options.key, options.cert);
110
+ tunnel.key = key;
111
+ tunnel.cert = cert;
112
+ }
113
+ if (options.ca !== undefined) tunnel.ca = Input.ca(options.ca);
114
+ }
115
+ if (options.name !== undefined) tunnel.name = Input.name(options.name);
116
+ return tunnel;
117
+ }
118
+
119
+ async addTunnel(name, type, target, options, myIp) {
120
+ this.ensureTunnels();
121
+ this.json.tunnels[name] = await this.prepareTunnel(type, target, {
122
+ name,
123
+ ...options
124
+ }, false, myIp);
125
+ this.save();
126
+ }
127
+
128
+ removeTunnel(name) {
129
+ this.ensureTunnels();
130
+ delete this.json.tunnels[name];
131
+ this.save();
132
+ }
133
+
134
+ getTunnels() {
135
+ this.ensureTunnels();
136
+ return this.json.tunnels;
137
+ }
138
+
139
+ hasTunnel(name) {
140
+ this.ensureTunnels();
141
+ return !!this.json.tunnels[name];
142
+ }
143
+
144
+ getTunnel(name) {
145
+ this.ensureTunnels();
146
+ return this.json.tunnels[name];
147
+ }
148
+
149
+ setToken(token) {
150
+ if (!token) delete this.json.token;
151
+ else this.json.token = token;
152
+ this.save();
153
+ }
154
+
155
+ setWhitelist(whitelist) {
156
+ if (!whitelist || !whitelist.length) delete this.json.whitelist;
157
+ else this.json.whitelist = whitelist;
158
+ this.save();
159
+ }
160
+
161
+ setTimeout(timeout) {
162
+ if (!timeout) delete this.json.timeout;
163
+ else this.json.timeout = timeout;
164
+ this.save();
165
+ }
166
+
167
+ getToken() {
168
+ return this.json.token || '';
169
+ }
170
+
171
+ getTokenHost() {
172
+ const token = this.getToken();
173
+ if (!token) {
174
+ throw new Error(ERR_TOKEN_NOT_PROVIDED);
175
+ }
176
+ const d = decode(token);
177
+ if (d === null) {
178
+ throw new Error(ERR_WRONG_TOKEN);
179
+ }
180
+ if (!d.host) {
181
+ throw new Error(ERR_WRONG_TOKEN);
182
+ }
183
+ return d.host;
184
+ }
185
+
186
+ getRegion() {
187
+ return (this.json.region || '').toUpperCase();
188
+ }
189
+
190
+ getTimeout() {
191
+ return this.json.timeout || DEFAULT_TIMEOUT;
192
+ }
193
+
194
+ getWhitelist() {
195
+ return this.json.whitelist || [];
196
+ }
197
+
198
+ setRegion(region) {
199
+ this.json.region = region;
200
+ this.save();
201
+ }
202
+
203
+ setRegionIfNotSet(region) {
204
+ if (!this.json.region && region) this.json.region = region.toUpperCase();
205
+ this.save();
206
+ }
207
+
208
+ load() {
209
+ this.ensureFile();
210
+ try {
211
+ const txt = readFileSync(this.file, 'utf-8');
212
+ this.json = JSON.parse(txt);
213
+ } catch (err) {
214
+ throw new Error(ERR_CONFIG_CORRUPTED);
215
+ }
216
+ }
217
+
218
+ save() {
219
+ this.ensureDir();
220
+ try {
221
+ writeFileSync(this.file, JSON.stringify(this.json, null, 4), 'utf-8');
222
+ } catch (err) {
223
+ throw new Error(ERR_CANT_CREATE_DIR_IN_HOME('.bdy/cfg.json'));
224
+ }
225
+ }
226
+ }
227
+
228
+ module.exports = new Cfg();
@@ -0,0 +1,37 @@
1
+ const { Command } = require('commander');
2
+ const Output = require('../../output.js');
3
+ const {
4
+ DESC_COMMAND_AGENT_DISABLE,
5
+ TXT_AGENT_DISABLED
6
+ } = require('../../texts.js');
7
+ const AgentManager = require('../../agent/manager.js');
8
+ const ApiBuddy = require('../../api/buddy.js');
9
+ const { ERR_AGENT_ADMIN_RIGHTS } = require('../../texts');
10
+
11
+ const commandAgentDisable = new Command('disable');
12
+ commandAgentDisable.description(DESC_COMMAND_AGENT_DISABLE);
13
+ commandAgentDisable.action(async () => {
14
+ const hasAdminRights = await AgentManager.system.hasAdminRights();
15
+ if (!hasAdminRights) {
16
+ Output.exitError(ERR_AGENT_ADMIN_RIGHTS);
17
+ }
18
+ try {
19
+ await AgentManager.system.disable();
20
+ } catch {
21
+ // do nothing
22
+ }
23
+ try {
24
+ const json = AgentManager.system.loadSystemConfig();
25
+ await ApiBuddy.unregister(json.id, json.host, json.token);
26
+ } catch {
27
+ // do nothing
28
+ }
29
+ try {
30
+ AgentManager.system.clearSystemFiles();
31
+ } catch {
32
+ // do nothing
33
+ }
34
+ Output.exitSuccess(TXT_AGENT_DISABLED);
35
+ });
36
+
37
+ module.exports = commandAgentDisable;