bdy 1.16.15-dev → 1.16.16-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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.16.15-dev",
4
+ "version": "1.16.16-dev",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "scripts": {
@@ -31,6 +31,7 @@
31
31
  "eventsource": "4.0.0",
32
32
  "fastify": "4.28.1",
33
33
  "fdir": "6.5.0",
34
+ "open": "11.0.0",
34
35
  "fflate": "0.8.2",
35
36
  "human-id": "^4.1.3",
36
37
  "isbinaryfile": "5.0.2",
@@ -21,18 +21,24 @@ class ApiClient {
21
21
  },
22
22
  });
23
23
  }
24
- async request(method, path, body, parseResponseBody = false, rawResponseBody = false) {
25
- const headers = {
26
- authorization: `Bearer ${this.token}`,
27
- };
24
+ async request(method, path, body, parseResponseBody = false, rawResponseBody = false, httpUrlEncoded = false) {
25
+ const headers = {};
26
+ if (this.token)
27
+ headers.authorization = `Bearer ${this.token}`;
28
28
  let bodyParsed = undefined;
29
29
  if (body) {
30
30
  if (body instanceof undici_1.FormData) {
31
31
  bodyParsed = body;
32
32
  }
33
33
  else {
34
- headers['content-type'] = 'application/json; charset=utf-8';
35
- bodyParsed = JSON.stringify(body);
34
+ if (httpUrlEncoded) {
35
+ headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8';
36
+ bodyParsed = new URLSearchParams(body).toString();
37
+ }
38
+ else {
39
+ headers['content-type'] = 'application/json; charset=utf-8';
40
+ bodyParsed = JSON.stringify(body);
41
+ }
36
42
  }
37
43
  }
38
44
  const opts = {
@@ -172,6 +178,28 @@ class ApiClient {
172
178
  async stopSandbox(workspace, sandboxId) {
173
179
  return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/stop`, {}, true);
174
180
  }
181
+ async registerApp(name, redirectUrl) {
182
+ return await this.request('POST', '/auth/register', {
183
+ redirect_uris: [redirectUrl],
184
+ client_name: name,
185
+ grant_types: ['authorization_code', 'refresh_token'],
186
+ response_types: ['code'],
187
+ token_endpoint_auth_method: "client_secret_basic",
188
+ token_expires_in: 3600
189
+ }, true);
190
+ }
191
+ async getApp(clientId) {
192
+ return await this.request('GET', `/auth/register/${encodeURIComponent(clientId)}`, null, true);
193
+ }
194
+ async exchangeAppToken(code, clientId, clientSecret, redirectUrl) {
195
+ return await this.request('POST', '/oauth2/token', {
196
+ grant_type: 'authorization_code',
197
+ code,
198
+ client_id: clientId,
199
+ client_secret: clientSecret,
200
+ redirect_uri: redirectUrl
201
+ }, true, false, true);
202
+ }
175
203
  async restartSandbox(workspace, sandboxId) {
176
204
  return await this.request('POST', `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/restart`, {}, true);
177
205
  }
@@ -6,21 +6,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const cfg_1 = __importDefault(require("../tunnel/cfg"));
7
7
  const output_1 = __importDefault(require("../output"));
8
8
  const client_1 = __importDefault(require("../api/client"));
9
+ const node_http_1 = __importDefault(require("node:http"));
10
+ const open_1 = __importDefault(require("open"));
9
11
  const texts_1 = require("../texts");
10
12
  const utils_1 = require("../utils");
11
13
  const input_1 = __importDefault(require("../input"));
12
- function getSecurityUrl(region, baseUrl) {
13
- switch (region) {
14
- case utils_1.REST_API_REGION.US:
15
- return 'https://app.buddy.works/security';
16
- case utils_1.REST_API_REGION.EU:
17
- return 'https://eu.buddy.works/security';
18
- case utils_1.REST_API_REGION.AS:
19
- return 'https://asia.buddy.works/security';
20
- default:
21
- return `https://${baseUrl}/security`;
22
- }
23
- }
14
+ const OAUTH_CLIENT_APP_PORT = 7596;
15
+ const OAUTH_CLIENT_APP_HOST = 'localhost';
16
+ const OAUTH_CLIENT_APP_REDIRECT_URL = `http://localhost:${OAUTH_CLIENT_APP_PORT}`;
17
+ const OAUTH_CLIENT_APP_SCOPES = 'WORKSPACE USER_INFO EXECUTION_MANAGE SANDBOX_MANAGE';
24
18
  function normalizeBaseUrl(url) {
25
19
  let normalized = url.trim();
26
20
  normalized = normalized.replace(/^https?:\/\//i, '');
@@ -52,10 +46,96 @@ async function restApiBaseUrl() {
52
46
  }
53
47
  return `${normalized}/api`;
54
48
  }
55
- async function inputToken(region, baseUrl) {
56
- const securityUrl = getSecurityUrl(region, baseUrl);
57
- output_1.default.normal((0, texts_1.TXT_LOGIN_ENTER_TOKEN)(securityUrl));
58
- return await output_1.default.inputString();
49
+ async function oauthServer(api, clientId, clientSecret) {
50
+ return new Promise((resolve, reject) => {
51
+ const s = node_http_1.default.createServer(async (req, res) => {
52
+ const url = new URL(req.url || '', `http://${OAUTH_CLIENT_APP_HOST}`);
53
+ const urlCode = url.searchParams.get('code');
54
+ if (!urlCode) {
55
+ res.end(texts_1.ERR_LOGIN_HTTP_FAILED);
56
+ s.close();
57
+ reject(new Error(texts_1.ERR_LOGIN_HTTP_FAILED));
58
+ return;
59
+ }
60
+ const client = new client_1.default(new URL(`https://${api}`));
61
+ try {
62
+ const response = await client.exchangeAppToken(urlCode, clientId, clientSecret, OAUTH_CLIENT_APP_REDIRECT_URL);
63
+ res.end(texts_1.ERR_LOGIN_HTTP_SUCCESS);
64
+ s.close();
65
+ resolve(response.access_token);
66
+ }
67
+ catch {
68
+ res.end(texts_1.ERR_LOGIN_HTTP_FAILED);
69
+ s.close();
70
+ reject(new Error(texts_1.ERR_LOGIN_HTTP_FAILED));
71
+ return;
72
+ }
73
+ });
74
+ s.on('error', () => {
75
+ s.close();
76
+ reject(texts_1.ERR_LOGIN_HTTP_SERVER_PORT_TAKEN);
77
+ });
78
+ s.listen(OAUTH_CLIENT_APP_PORT, OAUTH_CLIENT_APP_HOST);
79
+ (0, open_1.default)(`https://${api}/oauth2/authorize?type=web_server&client_id=${encodeURIComponent(clientId)}&redirect_uri=${encodeURIComponent(OAUTH_CLIENT_APP_REDIRECT_URL)}&response_type=code&scope=${encodeURIComponent(OAUTH_CLIENT_APP_SCOPES)}`);
80
+ });
81
+ }
82
+ async function getOrCreateApp(api) {
83
+ const client = new client_1.default(new URL(`https://${api}`));
84
+ let clientId = cfg_1.default.getApiClientId();
85
+ let clientSecret = cfg_1.default.getApiClientSecret();
86
+ if (clientId && clientSecret) {
87
+ try {
88
+ await client.getApp(clientId);
89
+ }
90
+ catch {
91
+ clientId = null;
92
+ clientSecret = null;
93
+ }
94
+ }
95
+ if (!clientId || !clientSecret) {
96
+ const app = await client.registerApp('bdy cli app', OAUTH_CLIENT_APP_REDIRECT_URL);
97
+ clientId = app.client_id;
98
+ clientSecret = app.client_secret;
99
+ cfg_1.default.setApiClient(clientId, clientSecret);
100
+ }
101
+ return {
102
+ clientId,
103
+ clientSecret,
104
+ };
105
+ }
106
+ async function authorizeOAuth(api) {
107
+ const { clientId, clientSecret } = await getOrCreateApp(api);
108
+ return await oauthServer(api, clientId, clientSecret);
109
+ }
110
+ async function authorizeToken(api, token, workspace, project) {
111
+ const client = new client_1.default(new URL(`https://${api}`), token);
112
+ const w = await client.getWorkspaces();
113
+ if (!w.workspaces?.length) {
114
+ output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACES);
115
+ }
116
+ if (workspace) {
117
+ const found = w.workspaces.find((w) => w.domain === workspace);
118
+ if (!found) {
119
+ output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACE_FOUND);
120
+ }
121
+ }
122
+ else {
123
+ workspace = await output_1.default.selectWorkspace(w.workspaces);
124
+ }
125
+ cfg_1.default.setApiToken(token);
126
+ cfg_1.default.setWorkspace(workspace);
127
+ const p = await client.getProjects(workspace);
128
+ if (project) {
129
+ const found = p.projects.find((p) => p.name === project);
130
+ if (!found) {
131
+ output_1.default.exitError(texts_1.ERR_LOGIN_NO_PROJECT_FOUND);
132
+ }
133
+ }
134
+ else {
135
+ project = await output_1.default.selectProject(p.projects);
136
+ }
137
+ cfg_1.default.setProject(project);
138
+ output_1.default.exitSuccess(texts_1.TXT_LOGIN_SUCCESS);
59
139
  }
60
140
  const commandLogin = (0, utils_1.newCommand)('login', texts_1.DESC_COMMAND_LOGIN);
61
141
  commandLogin.option('--token <token>', texts_1.OPTION_REST_API_TOKEN);
@@ -68,9 +148,9 @@ commandLogin.action(async (options) => {
68
148
  cfg_1.default.clearLogin();
69
149
  let api = options.api || process.env.BUDDY_API_ENDPOINT;
70
150
  let region = options.region || process.env.BUDDY_REGION;
71
- let token = options.token || process.env.BUDDY_TOKEN;
72
- let workspace = options.workspace || process.env.BUDDY_WORKSPACE;
73
- let project = options.project || process.env.BUDDY_PROJECT;
151
+ const token = options.token || process.env.BUDDY_TOKEN;
152
+ const workspace = options.workspace || process.env.BUDDY_WORKSPACE;
153
+ const project = options.project || process.env.BUDDY_PROJECT;
74
154
  if (api) {
75
155
  region = utils_1.REST_API_REGION.ONPREM;
76
156
  }
@@ -96,35 +176,12 @@ commandLogin.action(async (options) => {
96
176
  }
97
177
  cfg_1.default.setBaseUrl(api);
98
178
  if (!token) {
99
- token = await inputToken(region, api);
100
- }
101
- const client = new client_1.default(new URL(`https://${api}`), token);
102
- const w = await client.getWorkspaces();
103
- if (!w.workspaces?.length) {
104
- output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACES);
105
- }
106
- if (workspace) {
107
- const found = w.workspaces.find((w) => w.domain === workspace);
108
- if (!found) {
109
- output_1.default.exitError(texts_1.ERR_LOGIN_NO_WORKSPACE_FOUND);
110
- }
179
+ output_1.default.normal(texts_1.TXT_LOGIN_OAUTH);
180
+ const token = await authorizeOAuth(api);
181
+ await authorizeToken(api, token, workspace, project);
111
182
  }
112
183
  else {
113
- workspace = await output_1.default.selectWorkspace(w.workspaces);
184
+ await authorizeToken(api, token, workspace, project);
114
185
  }
115
- cfg_1.default.setApiToken(token);
116
- cfg_1.default.setWorkspace(workspace);
117
- const p = await client.getProjects(workspace);
118
- if (project) {
119
- const found = p.projects.find((p) => p.name === project);
120
- if (!found) {
121
- output_1.default.exitError(texts_1.ERR_LOGIN_NO_PROJECT_FOUND);
122
- }
123
- }
124
- else {
125
- project = await output_1.default.selectProject(p.projects);
126
- }
127
- cfg_1.default.setProject(project);
128
- output_1.default.exitSuccess(texts_1.TXT_LOGIN_SUCCESS);
129
186
  });
130
187
  exports.default = commandLogin;
@@ -9,7 +9,7 @@ exports.LOG_SOCKET_DISCONNECTED = exports.LOG_SOCKET_CONNECTED = exports.LOG_AGE
9
9
  exports.DEBUG_AUTO_SCROLL = exports.DEBUG_RESOURCE_SCRAPPING_URL = exports.DEBUG_SNAPSHOT_PROCESSING = exports.DEBUG_SNAPSHOTS_PROCESSING = exports.DEBUG_EXEC_COMMAND = exports.DEBUG_EXEC_TEST_COMMAND = exports.LOG_INSTALLED_BROWSER = exports.LOG_SESSION_LINK = exports.LOG_SENDING_DATA = exports.LOG_SENDING_REQUEST = exports.LOG_PROCESSING_SNAPSHOTS = exports.LOG_RUNNING_EXEC_COMMAND = exports.LOG_TUNNEL_SSH_STREAM = exports.LOG_TUNNEL_TLS_AGENT_STREAM = exports.LOG_TUNNEL_TLS_REGION_STREAM = exports.LOG_TUNNEL_TLS_TARGET_STREAM = exports.LOG_TUNNEL_HTTP2_STREAM = exports.LOG_TUNNEL_HTTP1_STREAM = exports.LOG_TUNNEL_TCP_STREAM = exports.LOG_TUNNEL_HTTP_WRONG_USER_AGENTS = exports.LOG_TUNNEL_HTTP_CIRCUIT_BREAKER_OPEN = exports.LOG_TUNNEL_HTTP_RATE_LIMIT = exports.LOG_TUNNEL_HTTP_WRON_AUTH = exports.LOG_TUNNEL_IDENTIFIED = exports.LOG_TUNNEL_DISCONNECTED = exports.LOG_TUNNEL_FAILED = exports.LOG_TUNNEL_CONNECTED = exports.LOG_AGENT_STARTED = exports.LOG_AGENT_SERVER_STARTED = exports.LOG_ERROR_STARTING_AGENT_SERVER = exports.LOG_SSH_CONNECTION = exports.LOG_WRONG_STREAM = exports.LOG_DETECTED_STREAM = exports.LOG_HTTP2_REQUEST = exports.LOG_HTTP2_CONNECTION = exports.LOG_HTTP1_REQUEST = exports.LOG_HTTP1_CONNECTION = exports.LOG_ERROR = exports.LOG_STOPPING_TUNNEL = exports.LOG_STARTING_TUNNEL = exports.LOG_ENABLING_AGENT_TARGET = exports.LOG_DISABLING_AGENT_TARGET = exports.LOG_REMOVING_TUNNEL = exports.LOG_TUNNEL_REGISTERED = exports.LOG_ERROR_WHILE_REFRESHING_AGENT = exports.LOG_REGISTERING_TUNNEL = exports.LOG_GETTING_AGENT = exports.LOG_UNREGISTERING_AGENT = exports.LOG_REGION_DETECTED = exports.LOG_AGENT_REGISTERED = void 0;
10
10
  exports.TXT_SANDBOX_STOPPED = exports.TXT_SANDBOX_STARTED = exports.TXT_SANDBOX_DESTROYED = exports.TXT_SANDBOX_CREATED = exports.TXT_SANDBOX_CREATING = exports.OPTION_SANDBOX_COMMAND_LAST = exports.OPTION_SANDBOX_WAIT_TIMEOUT = exports.OPTION_SANDBOX_WAIT = exports.OPTION_SANDBOX_WAIT_APP = exports.OPTION_SANDBOX_WAIT_CONFIGURED = exports.OPTION_SANDBOX_WAIT_RUNNING = exports.ERR_SANDBOX_STOP_FAILED = exports.ERR_SANDBOX_NO_COMMANDS = exports.ERR_SANDBOX_RUNNING_FAILED = exports.ERR_SANDBOX_STOP_TIMEOUT = exports.ERR_SANDBOX_SNAPSHOT_TIMEOUT = exports.ERR_SANDBOX_RUNNING_TIMEOUT = exports.ERR_SANDBOX_APP_TIMEOUT = exports.ERR_SANDBOX_SETUP_TIMEOUT = exports.ERR_SANDBOX_APP_FAILED = exports.ERR_SANDBOX_SETUP_FAILED = exports.ERR_SANDBOX_INVALID_RUNTIME = exports.ERR_SANDBOX_INVALID_RESOURCES = exports.ERR_SANDBOX_NOT_FOUND = exports.OPTION_SANDBOX_COMMAND = exports.OPTION_SANDBOX_DETACHED = exports.OPTION_SANDBOX_RUNTIME = exports.OPTION_SANDBOX_APP_TYPE = exports.OPTION_SANDBOX_APP_DIR = exports.OPTION_SANDBOX_RUN_COMMAND = exports.OPTION_SANDBOX_TAGS = exports.OPTION_SANDBOX_INSTALL_COMMANDS = exports.OPTION_SANDBOX_RESOURCES = exports.OPTION_SANDBOX_OS = exports.OPTION_SANDBOX_NAME = exports.OPTION_SANDBOX_IDENTIFIER = exports.DESC_COMMAND_SANDBOX_EXEC = exports.DESC_COMMAND_SANDBOX_STATUS = exports.DESC_COMMAND_SANDBOX_RESTART = exports.DESC_COMMAND_SANDBOX_STOP = exports.DESC_COMMAND_SANDBOX_START = exports.DESC_COMMAND_SANDBOX_DESTROY = exports.DESC_COMMAND_SANDBOX_GET = exports.DESC_COMMAND_SANDBOX_LIST = exports.DESC_COMMAND_SANDBOX_CREATE = exports.DESC_COMMAND_SANDBOX = exports.DEBUG_WAIT_FOR_IDLE_TIMEOUT = exports.DEBUG_WAIT_FOR_IDLE = exports.DEBUG_RESOURCE_DISCOVERY_TIMEOUT = exports.DEBUG_AUTO_WIDTH = void 0;
11
11
  exports.TXT_SANDBOX_EXEC_BACKGROUND = exports.TXT_SANDBOX_EXEC_ID = exports.ERR_SANDBOX_CP_INVALID_DEST = exports.ERR_SANDBOX_CP_SOURCE_NOT_FOUND = exports.TXT_SANDBOX_CP_DONE = exports.TXT_SANDBOX_CP_PROGRESS = exports.OPTION_SANDBOX_CP_SILENT = exports.OPTION_SANDBOX_CP_DEST = exports.OPTION_SANDBOX_CP_SOURCE = exports.DESC_COMMAND_SANDBOX_CP = exports.ERR_SANDBOX_ENDPOINTS_NOT_FOUND = exports.ERR_SANDBOX_ENDPOINT_NOT_FOUND = exports.ERR_SANDBOX_ENDPOINT_EXISTS = exports.TXT_SANDBOX_ENDPOINT_DELETED = exports.TXT_SANDBOX_ENDPOINT_ADDED = exports.OPTION_SANDBOX_ENDPOINT_TYPE = exports.OPTION_SANDBOX_ENDPOINT_PORT = exports.OPTION_SANDBOX_ENDPOINT_NAME_ARG = exports.OPTION_SANDBOX_ENDPOINT_NAME = exports.DESC_COMMAND_SANDBOX_ENDPOINT_DELETE = exports.DESC_COMMAND_SANDBOX_ENDPOINT_ADD = exports.DESC_COMMAND_SANDBOX_ENDPOINT_GET = exports.DESC_COMMAND_SANDBOX_ENDPOINT_LIST = exports.DESC_COMMAND_SANDBOX_ENDPOINT = exports.ERR_SANDBOX_SNAPSHOTS_NOT_FOUND = exports.ERR_SANDBOX_SNAPSHOT_NOT_FOUND = exports.ERR_SANDBOX_SNAPSHOT_FAILED = exports.TXT_SANDBOX_SNAPSHOT_WAITING = exports.TXT_SANDBOX_SNAPSHOT_DELETED = exports.TXT_SANDBOX_SNAPSHOT_CREATED = exports.OPTION_SANDBOX_FROM_SNAPSHOT = exports.OPTION_SANDBOX_SNAPSHOT_NAME_ARG = exports.OPTION_SANDBOX_SNAPSHOT_NAME = exports.DESC_COMMAND_SANDBOX_SNAPSHOT_DELETE = exports.DESC_COMMAND_SANDBOX_SNAPSHOT_GET = exports.DESC_COMMAND_SANDBOX_SNAPSHOT_CREATE = exports.DESC_COMMAND_SANDBOX_SNAPSHOT_LIST = exports.DESC_COMMAND_SANDBOX_SNAPSHOT = exports.TXT_SANDBOX_COMMAND_KILLED = exports.OPTION_SANDBOX_COMMAND_FOLLOW = exports.OPTION_SANDBOX_COMMAND_ID = exports.DESC_COMMAND_SANDBOX_EXEC_KILL = exports.DESC_COMMAND_SANDBOX_EXEC_LOGS = exports.DESC_COMMAND_SANDBOX_EXEC_STATUS = exports.DESC_COMMAND_SANDBOX_EXEC_LIST = exports.TXT_SANDBOX_WAITING_START = exports.TXT_SANDBOX_WAITING_STOP = exports.TXT_SANDBOX_WAITING_APP = exports.TXT_SANDBOX_WAITING_SETUP = exports.TXT_SANDBOX_WAITING_RUNNING = void 0;
12
- exports.TXT_PROJECT_NONE = exports.ERR_PROJECT_NO_PROJECTS = exports.ERR_PROJECT_NOT_FOUND = exports.TXT_LOGIN_SELECT_PROJECT = exports.TXT_PROJECT_SET_CLEARED = exports.TXT_PROJECT_SET_SUCCESS = exports.DESC_COMMAND_PROJECT_GET = exports.ARG_COMMAND_PROJECT_NAME = exports.DESC_COMMAND_PROJECT_SET = exports.DESC_COMMAND_PROJECT_LIST = exports.DESC_COMMAND_PROJECT = exports.ERR_LOGIN_INVALID_BASE_URL = exports.ERR_LOGIN_NO_PROJECT_FOUND = exports.ERR_LOGIN_NO_WORKSPACE_FOUND = exports.ERR_LOGIN_NO_WORKSPACES = exports.TXT_LOGIN_SUCCESS = exports.TXT_LOGIN_SELECT_WORKSPACE = exports.TXT_LOGIN_ENTER_TOKEN = exports.TXT_LOGIN_ENTER_BASE_URL = exports.TXT_LOGIN_SELECT_REGION = exports.TXT_WORKSPACE_NONE = exports.TXT_WORKSPACE_SET_SUCCESS = exports.ARG_COMMAND_WORKSPACE = exports.DESC_COMMAND_WORKSPACE_GET = exports.DESC_COMMAND_WORKSPACE_SET = exports.DESC_COMMAND_WORKSPACE_LIST = exports.DESC_COMMAND_WORKSPACE = exports.TXT_LOGOUT_SUCCESS = exports.DESC_COMMAND_LOGOUT = exports.DESC_COMMAND_LOGIN = exports.ERR_WHOAMI_LOGOUT = exports.TXT_WHOAMI_NO_PROJECT = exports.TXT_WHOAMI_NO_WORKSPACE = exports.DESC_COMMAND_WHOAMI = exports.TXT_SANDBOX_EXEC_FAILED = exports.TXT_SANDBOX_EXEC_INPROGRESS = exports.TXT_SANDBOX_EXEC_SUCCESS = void 0;
12
+ exports.TXT_PROJECT_NONE = exports.ERR_PROJECT_NO_PROJECTS = exports.ERR_PROJECT_NOT_FOUND = exports.TXT_LOGIN_SELECT_PROJECT = exports.TXT_PROJECT_SET_CLEARED = exports.TXT_PROJECT_SET_SUCCESS = exports.DESC_COMMAND_PROJECT_GET = exports.ARG_COMMAND_PROJECT_NAME = exports.DESC_COMMAND_PROJECT_SET = exports.DESC_COMMAND_PROJECT_LIST = exports.DESC_COMMAND_PROJECT = exports.ERR_LOGIN_INVALID_BASE_URL = exports.ERR_LOGIN_NO_PROJECT_FOUND = exports.ERR_LOGIN_NO_WORKSPACE_FOUND = exports.ERR_LOGIN_NO_WORKSPACES = exports.ERR_LOGIN_HTTP_SUCCESS = exports.ERR_LOGIN_HTTP_FAILED = exports.TXT_LOGIN_OAUTH = exports.ERR_LOGIN_HTTP_SERVER_PORT_TAKEN = exports.TXT_LOGIN_SUCCESS = exports.TXT_LOGIN_SELECT_WORKSPACE = exports.TXT_LOGIN_ENTER_BASE_URL = exports.TXT_LOGIN_SELECT_REGION = exports.TXT_WORKSPACE_NONE = exports.TXT_WORKSPACE_SET_SUCCESS = exports.ARG_COMMAND_WORKSPACE = exports.DESC_COMMAND_WORKSPACE_GET = exports.DESC_COMMAND_WORKSPACE_SET = exports.DESC_COMMAND_WORKSPACE_LIST = exports.DESC_COMMAND_WORKSPACE = exports.TXT_LOGOUT_SUCCESS = exports.DESC_COMMAND_LOGOUT = exports.DESC_COMMAND_LOGIN = exports.ERR_WHOAMI_LOGOUT = exports.TXT_WHOAMI_NO_PROJECT = exports.TXT_WHOAMI_NO_WORKSPACE = exports.DESC_COMMAND_WHOAMI = exports.TXT_SANDBOX_EXEC_FAILED = exports.TXT_SANDBOX_EXEC_INPROGRESS = exports.TXT_SANDBOX_EXEC_SUCCESS = void 0;
13
13
  const utils_1 = require("./utils");
14
14
  exports.ERR_REST_API_GENERAL_ERROR = 'Something went wrong';
15
15
  exports.ERR_REST_API_CONNECT_ERROR = 'Connection refused. Check selected endpoint';
@@ -583,10 +583,12 @@ exports.TXT_WORKSPACE_SET_SUCCESS = TXT_WORKSPACE_SET_SUCCESS;
583
583
  exports.TXT_WORKSPACE_NONE = 'No workspace configured. Run "bdy login" or "bdy workspace set" first.';
584
584
  exports.TXT_LOGIN_SELECT_REGION = 'Select region:';
585
585
  exports.TXT_LOGIN_ENTER_BASE_URL = 'Enter your Buddy instance URL (e.g., buddy.company.com):';
586
- const TXT_LOGIN_ENTER_TOKEN = (url) => `Enter your personal access token (get your personal access token at: ${url}):`;
587
- exports.TXT_LOGIN_ENTER_TOKEN = TXT_LOGIN_ENTER_TOKEN;
588
586
  exports.TXT_LOGIN_SELECT_WORKSPACE = 'Select workspace:';
589
587
  exports.TXT_LOGIN_SUCCESS = 'Logged in successfully!';
588
+ exports.ERR_LOGIN_HTTP_SERVER_PORT_TAKEN = 'Cant start local http server to authorize';
589
+ exports.TXT_LOGIN_OAUTH = 'Starting authorization process...';
590
+ exports.ERR_LOGIN_HTTP_FAILED = 'Failed to authorize. Try again...';
591
+ exports.ERR_LOGIN_HTTP_SUCCESS = 'Authorized. You can now safely close this browser tab';
590
592
  exports.ERR_LOGIN_NO_WORKSPACES = 'No workspaces found for this token';
591
593
  exports.ERR_LOGIN_NO_WORKSPACE_FOUND = 'Provided workspace has been not found';
592
594
  exports.ERR_LOGIN_NO_PROJECT_FOUND = 'Provided project has been not found';
@@ -172,6 +172,17 @@ class Cfg {
172
172
  this.json.apiToken = token;
173
173
  this.save();
174
174
  }
175
+ setApiClient(clientId, clientSecret) {
176
+ if (!clientId || !clientSecret) {
177
+ delete this.json.apiClientId;
178
+ delete this.json.apiClientSecret;
179
+ }
180
+ else {
181
+ this.json.apiClientId = clientId;
182
+ this.json.apiClientSecret = clientSecret;
183
+ }
184
+ this.save();
185
+ }
175
186
  setWhitelist(whitelist) {
176
187
  if (!whitelist || !whitelist.length)
177
188
  delete this.json.whitelist;
@@ -192,6 +203,12 @@ class Cfg {
192
203
  getApiToken() {
193
204
  return this.json.apiToken || '';
194
205
  }
206
+ getApiClientId() {
207
+ return this.json.apiClientId || '';
208
+ }
209
+ getApiClientSecret() {
210
+ return this.json.apiClientSecret || '';
211
+ }
195
212
  getTokenHost() {
196
213
  const token = this.getToken();
197
214
  if (!token) {
@@ -11,9 +11,11 @@ const texts_1 = require("../../texts");
11
11
  const tunnel_1 = require("../../types/tunnel");
12
12
  class ServerHttp1 extends events_1.default {
13
13
  server;
14
+ host;
14
15
  constructor(host) {
15
16
  super();
16
- this.server = http_1.default.createServer((req, res) => this.processRequest(req, res, host));
17
+ this.host = host;
18
+ this.server = http_1.default.createServer((req, res) => this.processRequest(req, res));
17
19
  this.server.on('connection', (socket) => {
18
20
  socket.id = (0, uuid_1.v4)();
19
21
  this.emit(tunnel_1.TUNNEL_HTTP_SOCKET.OPEN, socket);
@@ -46,7 +48,10 @@ class ServerHttp1 extends events_1.default {
46
48
  method: logRequest.method,
47
49
  setHost: false,
48
50
  path: logRequest.url,
49
- headers: logRequest.headers,
51
+ headers: {
52
+ ...logRequest.headers,
53
+ host: this.host
54
+ },
50
55
  });
51
56
  if (logRequest.requestBody.data.length > 0)
52
57
  req.write(logRequest.requestBody.data);
@@ -60,9 +65,9 @@ class ServerHttp1 extends events_1.default {
60
65
  });
61
66
  req.end();
62
67
  }
63
- checkHostHeader(req, res, host) {
68
+ checkHostHeader(req, res) {
64
69
  const headerHost = (req.headers.host || '').split(':')[0];
65
- if (headerHost === host)
70
+ if (headerHost === this.host)
66
71
  return true;
67
72
  else {
68
73
  res.statusCode = 421;
@@ -70,8 +75,8 @@ class ServerHttp1 extends events_1.default {
70
75
  return false;
71
76
  }
72
77
  }
73
- async processRequest(req, res, host) {
74
- if (!this.checkHostHeader(req, res, host))
78
+ async processRequest(req, res) {
79
+ if (!this.checkHostHeader(req, res))
75
80
  return;
76
81
  logger_1.default.debug((0, texts_1.LOG_HTTP1_REQUEST)(req.method, req.url));
77
82
  this.emit(tunnel_1.TUNNEL_EVENT.HTTP_REQUEST, req, res);
@@ -11,9 +11,11 @@ const texts_1 = require("../../texts");
11
11
  const tunnel_1 = require("../../types/tunnel");
12
12
  class ServerHttp2 extends events_1.default {
13
13
  server;
14
+ host;
14
15
  constructor(host) {
15
16
  super();
16
- this.server = http2_1.default.createServer((req, res) => this.processRequest(req, res, host));
17
+ this.host = host;
18
+ this.server = http2_1.default.createServer((req, res) => this.processRequest(req, res));
17
19
  this.server.on('session', (session) => {
18
20
  session.id = (0, uuid_1.v4)();
19
21
  this.emit(tunnel_1.TUNNEL_EVENT.HTTP_SESSION_OPEN, session);
@@ -43,7 +45,10 @@ class ServerHttp2 extends events_1.default {
43
45
  let client = http2_1.default.connect(`http://localhost:${address.port}`, {
44
46
  maxSessionMemory: 100,
45
47
  });
46
- let req = client.request(logRequest.headers);
48
+ let req = client.request({
49
+ ...logRequest.headers,
50
+ ':authority': this.host
51
+ });
47
52
  if (logRequest.requestBody.data.length > 0)
48
53
  req.write(logRequest.requestBody.data);
49
54
  req.on('response', () => {
@@ -64,9 +69,12 @@ class ServerHttp2 extends events_1.default {
64
69
  });
65
70
  req.end();
66
71
  }
67
- checkHostHeader(req, res, host) {
72
+ checkHostHeader(req, res) {
73
+ logger_js_1.default.info('checkHostHeader');
74
+ logger_js_1.default.info(this.host);
75
+ logger_js_1.default.info(req.headers[':authority']);
68
76
  const headerHost = (req.headers[':authority'] || '').split(':')[0];
69
- if (headerHost === host)
77
+ if (headerHost === this.host)
70
78
  return true;
71
79
  else {
72
80
  res.statusCode = 421;
@@ -74,8 +82,8 @@ class ServerHttp2 extends events_1.default {
74
82
  return false;
75
83
  }
76
84
  }
77
- async processRequest(req, res, host) {
78
- if (!this.checkHostHeader(req, res, host))
85
+ async processRequest(req, res) {
86
+ if (!this.checkHostHeader(req, res))
79
87
  return;
80
88
  logger_js_1.default.debug((0, texts_1.LOG_HTTP2_REQUEST)(req.method, req.url));
81
89
  this.emit(tunnel_1.TUNNEL_EVENT.HTTP_REQUEST, req, res);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bdy",
3
3
  "preferGlobal": false,
4
- "version": "1.16.15-dev",
4
+ "version": "1.16.16-dev",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
7
7
  "scripts": {
@@ -31,6 +31,7 @@
31
31
  "eventsource": "4.0.0",
32
32
  "fastify": "4.28.1",
33
33
  "fdir": "6.5.0",
34
+ "open": "11.0.0",
34
35
  "fflate": "0.8.2",
35
36
  "human-id": "^4.1.3",
36
37
  "isbinaryfile": "5.0.2",