@mablhq/mabl-cli 1.19.3 → 1.20.1
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/api/basicApiClient.js +4 -8
- package/api/mablApiClient.js +3 -3
- package/api/mablApiClientFactory.js +9 -9
- package/api/types.js +8 -0
- package/auth/AuthClient.js +1 -0
- package/auth/OktaClient.js +66 -21
- package/browserLauncher/playwrightBrowserLauncher/playwrightDom.js +11 -4
- package/browserLauncher/playwrightBrowserLauncher/playwrightFrame.js +1 -1
- package/browserLauncher/types.js +2 -2
- package/cli.js +1 -3
- package/commands/applications/applications_cmds/list.js +1 -1
- package/commands/auth/auth_cmds/activate-key.js +2 -2
- package/commands/auth/auth_cmds/clear.js +1 -1
- package/commands/auth/auth_cmds/info.js +1 -1
- package/commands/branches/branches_cmds/create.js +1 -1
- package/commands/branches/branches_cmds/describe.js +1 -1
- package/commands/branches/branches_cmds/list.js +1 -1
- package/commands/branches/branches_cmds/merge.js +1 -1
- package/commands/commandUtil/util.js +3 -3
- package/commands/config/config_cmds/configKeys.js +11 -0
- package/commands/config/config_cmds/delete.js +6 -5
- package/commands/config/config_cmds/get.js +6 -5
- package/commands/config/config_cmds/list.js +7 -7
- package/commands/config/config_cmds/set.js +14 -21
- package/commands/credentials/credentials_cmds/list.js +1 -1
- package/commands/deploy/deploy_cmds/create.js +2 -2
- package/commands/deploy/deploy_cmds/list.js +1 -1
- package/commands/environments/environments_cmds/create.js +8 -4
- package/commands/environments/environments_cmds/list.js +1 -1
- package/commands/flows/flows_cmds/list.js +1 -1
- package/commands/link-agents/link-agents_cmds/delete.js +1 -6
- package/commands/plans/plans_cmds/list.js +1 -1
- package/commands/tests/testsUtil.js +8 -8
- package/commands/tests/tests_cmds/create.js +1 -1
- package/commands/tests/tests_cmds/import.js +2 -2
- package/commands/tests/tests_cmds/list.js +1 -1
- package/commands/tests/tests_cmds/run-cloud.js +3 -7
- package/commands/tests/tests_cmds/run.js +8 -4
- package/commands/tests/tests_cmds/trainer_cmds/trainerUtil.js +2 -2
- package/execution/index.js +1 -1
- package/package.json +2 -1
- package/providers/authenticationProvider.js +106 -60
- package/providers/cliConfigProvider.js +159 -61
- package/providers/types.js +9 -0
- package/util/analytics.js +8 -8
- package/util/httpUtil.js +2 -2
- package/utilities.js +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mablhq/mabl-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.1",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
5
5
|
"description": "The official mabl command line interface tool",
|
|
6
6
|
"main": "index.js",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"js-yaml": "4.1.0",
|
|
59
59
|
"jsesc": "3.0.2",
|
|
60
60
|
"jwt-decode": "2.2.0",
|
|
61
|
+
"keytar": "7.7.0",
|
|
61
62
|
"lodash.get": "4.4.2",
|
|
62
63
|
"markdown-table": "2.0.0",
|
|
63
64
|
"mime-types": "2.1.27",
|
|
@@ -3,39 +3,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.isOidcError = exports.AuthenticationProvider = void 0;
|
|
7
7
|
const open_1 = __importDefault(require("open"));
|
|
8
8
|
const axios_1 = __importDefault(require("axios"));
|
|
9
9
|
const env_1 = require("../env/env");
|
|
10
10
|
const cliConfigProvider_1 = require("./cliConfigProvider");
|
|
11
|
-
const
|
|
11
|
+
const types_1 = require("../api/types");
|
|
12
12
|
const mablApiClientFactory_1 = require("../api/mablApiClientFactory");
|
|
13
13
|
const loggingProvider_1 = require("./logging/loggingProvider");
|
|
14
14
|
const pureUtil_1 = require("../util/pureUtil");
|
|
15
15
|
const OktaClient_1 = require("../auth/OktaClient");
|
|
16
16
|
const httpUtil_1 = require("../util/httpUtil");
|
|
17
|
+
const types_2 = require("./types");
|
|
17
18
|
const humanizeDuration = require('humanize-duration');
|
|
18
19
|
const inquirer = require('inquirer');
|
|
19
20
|
const chalk = require('chalk');
|
|
20
|
-
var AuthProviderType;
|
|
21
|
-
(function (AuthProviderType) {
|
|
22
|
-
AuthProviderType["Auth0"] = "auth0";
|
|
23
|
-
AuthProviderType["Mabl"] = "mabl";
|
|
24
|
-
AuthProviderType["Okta"] = "okta";
|
|
25
|
-
})(AuthProviderType = exports.AuthProviderType || (exports.AuthProviderType = {}));
|
|
26
21
|
class AuthenticationProvider {
|
|
27
22
|
constructor() {
|
|
28
23
|
this.verbose = false;
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
}
|
|
25
|
+
async getOktaClient() {
|
|
26
|
+
if (!this.oktaClient) {
|
|
27
|
+
const client = axios_1.default.create(await (0, httpUtil_1.currentProxyConfig)());
|
|
28
|
+
this.oktaClient = new OktaClient_1.OktaClient(client);
|
|
29
|
+
}
|
|
30
|
+
return this.oktaClient;
|
|
31
31
|
}
|
|
32
32
|
async getAuthConfigWithAutoRenew() {
|
|
33
|
-
|
|
33
|
+
const authConfig = (await cliConfigProvider_1.CliConfigProvider.getCliConfig()).authentication;
|
|
34
34
|
if (authConfig.accessToken) {
|
|
35
35
|
if (this.verbose) {
|
|
36
36
|
loggingProvider_1.logger.info('Found existing access token');
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
return this.maybeRenewAuthentication(authConfig);
|
|
39
39
|
}
|
|
40
40
|
return authConfig;
|
|
41
41
|
}
|
|
@@ -46,45 +46,71 @@ class AuthenticationProvider {
|
|
|
46
46
|
}
|
|
47
47
|
return authConfig;
|
|
48
48
|
}
|
|
49
|
-
if (authConfig.authProvider === AuthProviderType.Auth0) {
|
|
49
|
+
if (authConfig.authProvider === types_2.AuthProviderType.Auth0) {
|
|
50
50
|
if (this.verbose) {
|
|
51
51
|
loggingProvider_1.logger.info(`Authentication refresh token ${chalk.yellow.bold('not valid')}`);
|
|
52
52
|
}
|
|
53
53
|
return authConfig;
|
|
54
54
|
}
|
|
55
|
+
const nowMilliseconds = Date.now();
|
|
56
|
+
const refreshTokenValidMilliseconds = authConfig.refreshTokenExpirationTimeMilliseconds
|
|
57
|
+
? authConfig.refreshTokenExpirationTimeMilliseconds - nowMilliseconds
|
|
58
|
+
: undefined;
|
|
59
|
+
if (refreshTokenValidMilliseconds !== undefined &&
|
|
60
|
+
refreshTokenValidMilliseconds <= 0) {
|
|
61
|
+
loggingProvider_1.logger.info(`Login has ${chalk.yellow.bold('expired')}. Please run ${chalk.magenta('mabl auth login')} to log in with your mabl account`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
55
64
|
if (this.verbose) {
|
|
56
|
-
loggingProvider_1.logger.info('Found refresh token');
|
|
65
|
+
loggingProvider_1.logger.info('Found valid refresh token');
|
|
57
66
|
}
|
|
58
|
-
const RefreshAccessTokenWindowMilliseconds =
|
|
59
|
-
const
|
|
60
|
-
const validMilliseconds = authConfig.accessTokenExpirationTimeMilliseconds - nowMilliseconds;
|
|
67
|
+
const RefreshAccessTokenWindowMilliseconds = 10 * 60 * 1000;
|
|
68
|
+
const accessTokenValidMilliseconds = authConfig.accessTokenExpirationTimeMilliseconds - nowMilliseconds;
|
|
61
69
|
if (this.verbose) {
|
|
62
|
-
|
|
70
|
+
if (accessTokenValidMilliseconds > 0) {
|
|
71
|
+
loggingProvider_1.logger.info(`Existing access token expires in [${chalk.magenta.bold(humanizeExpirationTime(accessTokenValidMilliseconds))}]`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
loggingProvider_1.logger.info(`Access token has ${chalk.yellow.bold('expired')}`);
|
|
75
|
+
}
|
|
63
76
|
}
|
|
64
|
-
if (
|
|
77
|
+
if (accessTokenValidMilliseconds < RefreshAccessTokenWindowMilliseconds) {
|
|
65
78
|
if (this.verbose) {
|
|
66
79
|
loggingProvider_1.logger.info(`Renewing authorization...`);
|
|
67
80
|
}
|
|
68
|
-
const
|
|
81
|
+
const oktaClient = await this.getOktaClient();
|
|
82
|
+
let newAuthInfo;
|
|
83
|
+
try {
|
|
84
|
+
newAuthInfo = await oktaClient.exchangeRefreshTokenForAccessToken(authConfig.refreshToken);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
processAuthorizationError(error, true);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
69
90
|
if (newAuthInfo.error) {
|
|
70
91
|
loggingProvider_1.logger.error(chalk.red.bold(`Could not refresh authentication due to error: ${newAuthInfo.error_description}`));
|
|
71
92
|
process.exit(1);
|
|
72
93
|
}
|
|
73
|
-
newAuthInfo.
|
|
74
|
-
|
|
75
|
-
|
|
94
|
+
if (!newAuthInfo.refresh_token_expires_at &&
|
|
95
|
+
authConfig.refreshTokenExpirationTimeMilliseconds) {
|
|
96
|
+
newAuthInfo.refresh_token_expires_at =
|
|
97
|
+
authConfig.refreshTokenExpirationTimeMilliseconds / 1000;
|
|
98
|
+
}
|
|
99
|
+
await cliConfigProvider_1.CliConfigProvider.setCliAuthInfo(newAuthInfo, nowMilliseconds);
|
|
100
|
+
return (await cliConfigProvider_1.CliConfigProvider.getCliConfig()).authentication;
|
|
76
101
|
}
|
|
77
102
|
return authConfig;
|
|
78
103
|
}
|
|
79
|
-
static getAuthType() {
|
|
80
|
-
const config = cliConfigProvider_1.CliConfigProvider.getCliConfig();
|
|
104
|
+
static async getAuthType() {
|
|
105
|
+
const config = await cliConfigProvider_1.CliConfigProvider.getCliConfig();
|
|
81
106
|
return config.authentication.authType;
|
|
82
107
|
}
|
|
83
|
-
displayInfo() {
|
|
108
|
+
async displayInfo() {
|
|
109
|
+
var _a;
|
|
84
110
|
try {
|
|
85
|
-
const config = cliConfigProvider_1.CliConfigProvider.getCliConfig();
|
|
86
|
-
if (config.authentication.authType ===
|
|
87
|
-
loggingProvider_1.logger.info(
|
|
111
|
+
const config = await cliConfigProvider_1.CliConfigProvider.getCliConfig();
|
|
112
|
+
if (config.authentication.authType === types_1.AuthType.ApiKey) {
|
|
113
|
+
loggingProvider_1.logger.info(`You are authenticated by ${chalk.magenta.bold('API key')}`);
|
|
88
114
|
return;
|
|
89
115
|
}
|
|
90
116
|
if (!config.email || config.authentication.authType === undefined) {
|
|
@@ -92,7 +118,7 @@ class AuthenticationProvider {
|
|
|
92
118
|
return;
|
|
93
119
|
}
|
|
94
120
|
loggingProvider_1.logger.info(`Logged in as user [${chalk.magenta.bold(config.email)}]`);
|
|
95
|
-
const expirationMilliseconds = config.authentication.accessTokenExpirationTimeMilliseconds -
|
|
121
|
+
const expirationMilliseconds = ((_a = config.authentication.refreshTokenExpirationTimeMilliseconds) !== null && _a !== void 0 ? _a : config.authentication.accessTokenExpirationTimeMilliseconds) -
|
|
96
122
|
Date.now();
|
|
97
123
|
if (expirationMilliseconds > 0) {
|
|
98
124
|
loggingProvider_1.logger.info(`Login expires in [${chalk.magenta.bold(humanizeExpirationTime(expirationMilliseconds))}]`);
|
|
@@ -106,36 +132,41 @@ class AuthenticationProvider {
|
|
|
106
132
|
process.exit(1);
|
|
107
133
|
}
|
|
108
134
|
}
|
|
109
|
-
clearAuthentication() {
|
|
135
|
+
async clearAuthentication() {
|
|
110
136
|
try {
|
|
111
|
-
const config = cliConfigProvider_1.CliConfigProvider.getCliConfig();
|
|
112
|
-
if (!config.email) {
|
|
137
|
+
const config = await cliConfigProvider_1.CliConfigProvider.getCliConfig();
|
|
138
|
+
if (!config.email && config.authentication.authType !== types_1.AuthType.ApiKey) {
|
|
113
139
|
loggingProvider_1.logger.info('You are not logged in');
|
|
114
140
|
return;
|
|
115
141
|
}
|
|
116
|
-
|
|
117
|
-
|
|
142
|
+
await cliConfigProvider_1.CliConfigProvider.clearAuthConfig();
|
|
143
|
+
if (config.email) {
|
|
144
|
+
loggingProvider_1.logger.info(`Logged out user [${chalk.magenta.bold(config.email)}]`);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
loggingProvider_1.logger.info(`Removed ${chalk.magenta.bold('API key')}`);
|
|
148
|
+
}
|
|
118
149
|
}
|
|
119
150
|
catch (error) {
|
|
120
151
|
loggingProvider_1.logger.error(chalk.red.bold(error));
|
|
121
152
|
process.exit(1);
|
|
122
153
|
}
|
|
123
154
|
}
|
|
124
|
-
activateApiKey(apiKey) {
|
|
155
|
+
async activateApiKey(apiKey) {
|
|
125
156
|
const authInfo = {
|
|
126
|
-
auth_provider: AuthProviderType.Mabl,
|
|
127
|
-
auth_type:
|
|
157
|
+
auth_provider: types_2.AuthProviderType.Mabl,
|
|
158
|
+
auth_type: types_1.AuthType.ApiKey,
|
|
128
159
|
api_key: apiKey,
|
|
129
160
|
};
|
|
130
161
|
const requestTimeMilliseconds = Date.now();
|
|
131
|
-
cliConfigProvider_1.CliConfigProvider.setCliAuthInfo(authInfo, requestTimeMilliseconds);
|
|
162
|
+
await cliConfigProvider_1.CliConfigProvider.setCliAuthInfo(authInfo, requestTimeMilliseconds);
|
|
132
163
|
}
|
|
133
164
|
async authenticate() {
|
|
134
|
-
|
|
165
|
+
const oktaClient = await this.getOktaClient();
|
|
135
166
|
try {
|
|
136
|
-
const { codeChallenge, codeVerifier } =
|
|
167
|
+
const { codeChallenge, codeVerifier } = oktaClient.generateCodeChallenge();
|
|
137
168
|
const redirectUri = `${env_1.BASE_APP_URL}/app-code`;
|
|
138
|
-
const authUrl =
|
|
169
|
+
const authUrl = oktaClient.buildAuthorizationUrl(codeChallenge, redirectUri);
|
|
139
170
|
loggingProvider_1.logger.info(`Your browser has been opened to the following URL for obtaining an authorization code:
|
|
140
171
|
|
|
141
172
|
${authUrl}
|
|
@@ -152,34 +183,23 @@ ${authUrl}
|
|
|
152
183
|
const requestTimeMilliseconds = Date.now();
|
|
153
184
|
let authInfo;
|
|
154
185
|
try {
|
|
155
|
-
authInfo = await
|
|
186
|
+
authInfo = await oktaClient.validateAuthCode(response.authCode, codeVerifier, redirectUri);
|
|
156
187
|
}
|
|
157
188
|
catch (error) {
|
|
158
|
-
|
|
159
|
-
loggingProvider_1.logger.error(chalk.red.bold(error.toString()));
|
|
160
|
-
const data = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data;
|
|
161
|
-
if (isOidcError(data)) {
|
|
162
|
-
loggingProvider_1.logger.error(chalk.red.bold(`Authorization failed: ${data.error_description} [${data.error}]`));
|
|
163
|
-
}
|
|
164
|
-
else if (data) {
|
|
165
|
-
loggingProvider_1.logger.error(chalk.red.bold(`Response data: ${JSON.stringify(data)}`));
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
loggingProvider_1.logger.error(chalk.red.bold('No response data'));
|
|
169
|
-
}
|
|
189
|
+
processAuthorizationError(error, false);
|
|
170
190
|
process.exit(1);
|
|
171
191
|
}
|
|
172
192
|
if (authInfo.error) {
|
|
173
193
|
loggingProvider_1.logger.error(chalk.red.bold(`Could not login due to error: ${authInfo.error_description}`));
|
|
174
194
|
process.exit(1);
|
|
175
195
|
}
|
|
176
|
-
cliConfigProvider_1.CliConfigProvider.setCliAuthInfo(authInfo, requestTimeMilliseconds);
|
|
196
|
+
await cliConfigProvider_1.CliConfigProvider.setCliAuthInfo(authInfo, requestTimeMilliseconds);
|
|
177
197
|
const userData = await AuthenticationProvider.requestUserInfo(authInfo.access_token);
|
|
178
|
-
const config = cliConfigProvider_1.CliConfigProvider.getCliConfig();
|
|
198
|
+
const config = await cliConfigProvider_1.CliConfigProvider.getCliConfig();
|
|
179
199
|
config.userId = userData.id;
|
|
180
200
|
config.email = userData.email;
|
|
181
201
|
config.userFullName = userData.name;
|
|
182
|
-
cliConfigProvider_1.CliConfigProvider.setCliConfig(config);
|
|
202
|
+
await cliConfigProvider_1.CliConfigProvider.setCliConfig(config);
|
|
183
203
|
loggingProvider_1.logger.info(chalk.green.bold(`Login successful for: ${userData.email}`));
|
|
184
204
|
}
|
|
185
205
|
catch (error) {
|
|
@@ -192,11 +212,35 @@ ${authUrl}
|
|
|
192
212
|
return (0, open_1.default)(path);
|
|
193
213
|
}
|
|
194
214
|
static async requestUserInfo(accessToken) {
|
|
195
|
-
const apiClient = mablApiClientFactory_1.MablApiClientFactory.createApiClientForAccessToken(accessToken);
|
|
215
|
+
const apiClient = await mablApiClientFactory_1.MablApiClientFactory.createApiClientForAccessToken(accessToken);
|
|
196
216
|
return apiClient.getSelf();
|
|
197
217
|
}
|
|
198
218
|
}
|
|
199
219
|
exports.AuthenticationProvider = AuthenticationProvider;
|
|
220
|
+
function processAuthorizationError(error, isTokenRefresh) {
|
|
221
|
+
var _a;
|
|
222
|
+
const mainErrorMessage = isTokenRefresh ? 'Token refresh' : 'Authorization';
|
|
223
|
+
loggingProvider_1.logger.error(chalk.red.bold(`${mainErrorMessage} failed.`));
|
|
224
|
+
loggingProvider_1.logger.error(chalk.red.bold(error.toString()));
|
|
225
|
+
let hasResponseData = false;
|
|
226
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
227
|
+
const data = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data;
|
|
228
|
+
if (isOidcError(data)) {
|
|
229
|
+
loggingProvider_1.logger.error(chalk.red.bold(`${mainErrorMessage} failed: ${data.error_description} [${data.error}]`));
|
|
230
|
+
hasResponseData = true;
|
|
231
|
+
}
|
|
232
|
+
else if (data) {
|
|
233
|
+
loggingProvider_1.logger.error(chalk.red.bold(`Response data: ${JSON.stringify(data)}`));
|
|
234
|
+
hasResponseData = true;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!hasResponseData) {
|
|
238
|
+
loggingProvider_1.logger.error(chalk.red.bold('No response data'));
|
|
239
|
+
}
|
|
240
|
+
if (isTokenRefresh) {
|
|
241
|
+
loggingProvider_1.logger.error(`Please try again. If the issue persists authenticate again with ${chalk.magenta('mabl auth login')}.`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
200
244
|
function humanizeExpirationTime(milliseconds) {
|
|
201
245
|
return humanizeDuration(milliseconds, {
|
|
202
246
|
maxDecimalPoints: 0,
|
|
@@ -204,5 +248,7 @@ function humanizeExpirationTime(milliseconds) {
|
|
|
204
248
|
});
|
|
205
249
|
}
|
|
206
250
|
function isOidcError(err) {
|
|
207
|
-
return (0, pureUtil_1.isString)(err === null || err === void 0 ? void 0 : err.error) &&
|
|
251
|
+
return ((0, pureUtil_1.isString)(err === null || err === void 0 ? void 0 : err.error) &&
|
|
252
|
+
(0, pureUtil_1.isString)(err === null || err === void 0 ? void 0 : err.error_description));
|
|
208
253
|
}
|
|
254
|
+
exports.isOidcError = isOidcError;
|
|
@@ -1,15 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
27
|
};
|
|
5
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.CliConfigProvider = exports.getAuthConfigFile = void 0;
|
|
29
|
+
exports.__resetIsKeytarAvailable = exports.CliConfigProvider = exports.getAuthConfigFile = exports.getEncryptionKey = exports.AUTH_KEY_NAMES = exports.IS_CONFIG_ENCRYPTED_KEY_NAME = void 0;
|
|
7
30
|
const env_1 = require("../env/env");
|
|
8
31
|
const conf_1 = __importDefault(require("conf"));
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
32
|
+
const types_1 = require("./types");
|
|
33
|
+
const types_2 = require("../api/types");
|
|
34
|
+
const configKeys_1 = require("../commands/config/config_cmds/configKeys");
|
|
12
35
|
const httpUtil_1 = require("../util/httpUtil");
|
|
36
|
+
const crypto = __importStar(require("crypto"));
|
|
37
|
+
const loggingProvider_1 = require("./logging/loggingProvider");
|
|
38
|
+
const utilities_1 = require("../utilities");
|
|
13
39
|
const USER_ID_NAME = 'userId';
|
|
14
40
|
const USER_FULL_NAME_NAME = 'userFullName';
|
|
15
41
|
const EMAIL_NAME = 'email';
|
|
@@ -19,17 +45,71 @@ const AUTH_TYPE = 'authType';
|
|
|
19
45
|
const ACCESS_TOKEN_NAME = 'accessToken';
|
|
20
46
|
const REFRESH_TOKEN_NAME = 'refreshToken';
|
|
21
47
|
const ACCESS_TOKEN_EXPIRATION_MILLISECONDS_NAME = 'accessTokenExpirationTimeMilliseconds';
|
|
22
|
-
const
|
|
48
|
+
const REFRESH_TOKEN_EXPIRATION_MILLISECONDS_NAME = `${REFRESH_TOKEN_NAME}ExpirationTimeMilliseconds`;
|
|
49
|
+
exports.IS_CONFIG_ENCRYPTED_KEY_NAME = '_isConfigEncrypted';
|
|
50
|
+
exports.AUTH_KEY_NAMES = [
|
|
23
51
|
AUTH_PROVIDER,
|
|
24
52
|
AUTH_TYPE,
|
|
25
53
|
ACCESS_TOKEN_NAME,
|
|
26
54
|
ACCESS_TOKEN_EXPIRATION_MILLISECONDS_NAME,
|
|
27
55
|
REFRESH_TOKEN_NAME,
|
|
56
|
+
REFRESH_TOKEN_EXPIRATION_MILLISECONDS_NAME,
|
|
28
57
|
USER_FULL_NAME_NAME,
|
|
29
58
|
USER_ID_NAME,
|
|
30
59
|
EMAIL_NAME,
|
|
31
60
|
];
|
|
32
|
-
|
|
61
|
+
let isKeytarAvailable = true;
|
|
62
|
+
async function getEncryptionKey() {
|
|
63
|
+
var _a;
|
|
64
|
+
if ((0, utilities_1.areWeTestingInJest)()) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let maybeEncryptionKey;
|
|
68
|
+
if (isKeytarAvailable) {
|
|
69
|
+
try {
|
|
70
|
+
const keytar = require('keytar');
|
|
71
|
+
maybeEncryptionKey =
|
|
72
|
+
(_a = (await keytar.getPassword(env_1.CONF_FILE_PROJECT_NAME, env_1.ENV))) !== null && _a !== void 0 ? _a : undefined;
|
|
73
|
+
if (!maybeEncryptionKey) {
|
|
74
|
+
maybeEncryptionKey = crypto
|
|
75
|
+
.randomFillSync(Buffer.alloc(48))
|
|
76
|
+
.toString('base64');
|
|
77
|
+
await keytar.setPassword(env_1.CONF_FILE_PROJECT_NAME, env_1.ENV, maybeEncryptionKey);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
loggingProvider_1.logger.warn(`Couldn't access the system's key storage. Token renewal will be disabled.`);
|
|
82
|
+
isKeytarAvailable = false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return maybeEncryptionKey;
|
|
86
|
+
}
|
|
87
|
+
exports.getEncryptionKey = getEncryptionKey;
|
|
88
|
+
async function getAuthConfigFile() {
|
|
89
|
+
const maybeEncryptionKey = await getEncryptionKey();
|
|
90
|
+
if (!isKeytarAvailable || (0, utilities_1.areWeTestingInJest)()) {
|
|
91
|
+
return getNonEncryptedConfig();
|
|
92
|
+
}
|
|
93
|
+
const conf = new conf_1.default({
|
|
94
|
+
configName: 'access-enc',
|
|
95
|
+
projectName: env_1.CONF_FILE_PROJECT_NAME,
|
|
96
|
+
projectVersion: env_1.CONF_FILE_VERSION,
|
|
97
|
+
accessPropertiesByDotNotation: false,
|
|
98
|
+
encryptionKey: maybeEncryptionKey,
|
|
99
|
+
});
|
|
100
|
+
if (conf.has(exports.IS_CONFIG_ENCRYPTED_KEY_NAME)) {
|
|
101
|
+
return conf;
|
|
102
|
+
}
|
|
103
|
+
const oldConf = getNonEncryptedConfig();
|
|
104
|
+
copyConf(oldConf, conf);
|
|
105
|
+
conf.set(exports.IS_CONFIG_ENCRYPTED_KEY_NAME, true);
|
|
106
|
+
return conf;
|
|
107
|
+
}
|
|
108
|
+
exports.getAuthConfigFile = getAuthConfigFile;
|
|
109
|
+
function shouldStoreRefreshTokens() {
|
|
110
|
+
return isKeytarAvailable || (0, utilities_1.areWeTestingInJest)();
|
|
111
|
+
}
|
|
112
|
+
function getNonEncryptedConfig() {
|
|
33
113
|
return new conf_1.default({
|
|
34
114
|
configName: 'access',
|
|
35
115
|
projectName: env_1.CONF_FILE_PROJECT_NAME,
|
|
@@ -37,56 +117,62 @@ function getAuthConfigFile() {
|
|
|
37
117
|
accessPropertiesByDotNotation: false,
|
|
38
118
|
});
|
|
39
119
|
}
|
|
40
|
-
|
|
120
|
+
function copyConf(confFrom, confTo) {
|
|
121
|
+
for (const key of [...exports.AUTH_KEY_NAMES, ...configKeys_1.validConfigKeyChoices]) {
|
|
122
|
+
const value = confFrom.get(key);
|
|
123
|
+
if (value !== undefined) {
|
|
124
|
+
confTo.set(key, value);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
41
128
|
class CliConfigProvider {
|
|
42
129
|
static setWorkspace(workspaceId) {
|
|
43
|
-
setValue(WORKSPACE, workspaceId);
|
|
130
|
+
return setValue(WORKSPACE, workspaceId);
|
|
44
131
|
}
|
|
45
132
|
static clearWorkspace() {
|
|
46
|
-
clearValue(WORKSPACE);
|
|
133
|
+
return clearValue(WORKSPACE);
|
|
47
134
|
}
|
|
48
|
-
static getWorkspace() {
|
|
49
|
-
return getAuthConfigFile().get(WORKSPACE);
|
|
135
|
+
static async getWorkspace() {
|
|
136
|
+
return (await getAuthConfigFile()).get(WORKSPACE);
|
|
50
137
|
}
|
|
51
138
|
static getConfigProperty(key) {
|
|
52
|
-
return getValue(
|
|
139
|
+
return getValue(propertyKeyToStoredKey(key));
|
|
53
140
|
}
|
|
54
141
|
static clearConfigProperty(key) {
|
|
55
|
-
return clearValue(
|
|
142
|
+
return clearValue(propertyKeyToStoredKey(key));
|
|
56
143
|
}
|
|
57
144
|
static setConfigProperty(key, value) {
|
|
58
|
-
return setValue(
|
|
145
|
+
return setValue(propertyKeyToStoredKey(key), value);
|
|
59
146
|
}
|
|
60
|
-
static
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const authType = getAuthConfigFile().get(AUTH_TYPE);
|
|
65
|
-
let authProvider = getAuthConfigFile().get(AUTH_PROVIDER);
|
|
147
|
+
static async getCliConfig() {
|
|
148
|
+
const config = await getAuthConfigFile();
|
|
149
|
+
const authType = config.get(AUTH_TYPE);
|
|
150
|
+
let authProvider = config.get(AUTH_PROVIDER);
|
|
66
151
|
if (!authProvider && authType !== undefined) {
|
|
67
152
|
authProvider =
|
|
68
|
-
authType ===
|
|
69
|
-
?
|
|
70
|
-
:
|
|
153
|
+
authType === types_2.AuthType.ApiKey
|
|
154
|
+
? types_1.AuthProviderType.Mabl
|
|
155
|
+
: types_1.AuthProviderType.Auth0;
|
|
71
156
|
}
|
|
72
157
|
const authentication = {
|
|
73
158
|
authProvider,
|
|
74
159
|
authType,
|
|
75
|
-
accessToken:
|
|
76
|
-
refreshToken:
|
|
77
|
-
accessTokenExpirationTimeMilliseconds:
|
|
160
|
+
accessToken: config.get(ACCESS_TOKEN_NAME),
|
|
161
|
+
refreshToken: config.get(REFRESH_TOKEN_NAME),
|
|
162
|
+
accessTokenExpirationTimeMilliseconds: config.get(ACCESS_TOKEN_EXPIRATION_MILLISECONDS_NAME),
|
|
163
|
+
refreshTokenExpirationTimeMilliseconds: config.get(REFRESH_TOKEN_EXPIRATION_MILLISECONDS_NAME),
|
|
78
164
|
};
|
|
79
165
|
const httpConfig = {
|
|
80
166
|
sslVerify: httpUtil_1.EXECUTION_ENGINE_SSL_VERIFY,
|
|
81
167
|
};
|
|
82
|
-
const proxyHostValue = this.getConfigProperty(
|
|
168
|
+
const proxyHostValue = await this.getConfigProperty(configKeys_1.configKeys.proxy);
|
|
83
169
|
if (proxyHostValue) {
|
|
84
170
|
if (typeof proxyHostValue !== 'string') {
|
|
85
171
|
throw new Error('Invalid proxy host value');
|
|
86
172
|
}
|
|
87
173
|
httpConfig.proxyHost = new URL(proxyHostValue);
|
|
88
174
|
}
|
|
89
|
-
const sslVerifyValue = this.getConfigProperty(
|
|
175
|
+
const sslVerifyValue = await this.getConfigProperty(configKeys_1.configKeys.sslVerify);
|
|
90
176
|
if (sslVerifyValue !== undefined) {
|
|
91
177
|
if (typeof sslVerifyValue !== 'boolean') {
|
|
92
178
|
throw new Error(`Invalid proxy sslVerify value`);
|
|
@@ -95,60 +181,72 @@ class CliConfigProvider {
|
|
|
95
181
|
}
|
|
96
182
|
return {
|
|
97
183
|
authentication,
|
|
98
|
-
userId:
|
|
99
|
-
email:
|
|
100
|
-
userFullName:
|
|
101
|
-
workspace:
|
|
184
|
+
userId: config.get(USER_ID_NAME),
|
|
185
|
+
email: config.get(EMAIL_NAME),
|
|
186
|
+
userFullName: config.get(USER_FULL_NAME_NAME),
|
|
187
|
+
workspace: config.get(WORKSPACE),
|
|
102
188
|
http: httpConfig,
|
|
103
189
|
};
|
|
104
190
|
}
|
|
105
191
|
static clearAuthConfig() {
|
|
106
|
-
AUTH_KEY_NAMES.forEach((keyName) => clearValue(keyName));
|
|
192
|
+
exports.AUTH_KEY_NAMES.forEach((keyName) => clearValue(keyName));
|
|
107
193
|
return this.getCliConfig();
|
|
108
194
|
}
|
|
109
|
-
static setCliConfig(config) {
|
|
110
|
-
var _a, _b, _c, _d, _e;
|
|
111
|
-
setValue(AUTH_PROVIDER, (_a = config === null || config === void 0 ? void 0 : config.authentication) === null || _a === void 0 ? void 0 : _a.authProvider);
|
|
112
|
-
setValue(AUTH_TYPE, (_b = config === null || config === void 0 ? void 0 : config.authentication) === null || _b === void 0 ? void 0 : _b.authType);
|
|
113
|
-
setValue(ACCESS_TOKEN_NAME, (_c = config === null || config === void 0 ? void 0 : config.authentication) === null || _c === void 0 ? void 0 : _c.accessToken);
|
|
114
|
-
setValue(REFRESH_TOKEN_NAME, (_d = config === null || config === void 0 ? void 0 : config.authentication) === null || _d === void 0 ? void 0 : _d.refreshToken);
|
|
115
|
-
setValue(ACCESS_TOKEN_EXPIRATION_MILLISECONDS_NAME, (_e = config === null || config === void 0 ? void 0 : config.authentication) === null || _e === void 0 ? void 0 : _e.accessTokenExpirationTimeMilliseconds);
|
|
116
|
-
setValue(
|
|
117
|
-
setValue(
|
|
118
|
-
setValue(
|
|
195
|
+
static async setCliConfig(config) {
|
|
196
|
+
var _a, _b, _c, _d, _e, _f;
|
|
197
|
+
await setValue(AUTH_PROVIDER, (_a = config === null || config === void 0 ? void 0 : config.authentication) === null || _a === void 0 ? void 0 : _a.authProvider);
|
|
198
|
+
await setValue(AUTH_TYPE, (_b = config === null || config === void 0 ? void 0 : config.authentication) === null || _b === void 0 ? void 0 : _b.authType);
|
|
199
|
+
await setValue(ACCESS_TOKEN_NAME, (_c = config === null || config === void 0 ? void 0 : config.authentication) === null || _c === void 0 ? void 0 : _c.accessToken);
|
|
200
|
+
await setValue(REFRESH_TOKEN_NAME, (_d = config === null || config === void 0 ? void 0 : config.authentication) === null || _d === void 0 ? void 0 : _d.refreshToken);
|
|
201
|
+
await setValue(ACCESS_TOKEN_EXPIRATION_MILLISECONDS_NAME, (_e = config === null || config === void 0 ? void 0 : config.authentication) === null || _e === void 0 ? void 0 : _e.accessTokenExpirationTimeMilliseconds);
|
|
202
|
+
await setValue(REFRESH_TOKEN_EXPIRATION_MILLISECONDS_NAME, (_f = config === null || config === void 0 ? void 0 : config.authentication) === null || _f === void 0 ? void 0 : _f.refreshTokenExpirationTimeMilliseconds);
|
|
203
|
+
await setValue(USER_ID_NAME, config.userId);
|
|
204
|
+
await setValue(EMAIL_NAME, config.email);
|
|
205
|
+
await setValue(USER_FULL_NAME_NAME, config.userFullName);
|
|
119
206
|
return config;
|
|
120
207
|
}
|
|
121
|
-
static setCliAuthInfo(authInfo, updateMilliseconds) {
|
|
122
|
-
setValue(AUTH_TYPE, authInfo === null || authInfo === void 0 ? void 0 : authInfo.auth_type);
|
|
208
|
+
static async setCliAuthInfo(authInfo, updateMilliseconds) {
|
|
209
|
+
await setValue(AUTH_TYPE, authInfo === null || authInfo === void 0 ? void 0 : authInfo.auth_type);
|
|
123
210
|
switch (authInfo.auth_type) {
|
|
124
|
-
case
|
|
211
|
+
case types_2.AuthType.Bearer:
|
|
125
212
|
const bearerAuthInfo = authInfo;
|
|
126
213
|
const expirationTimeMilliseconds = updateMilliseconds + bearerAuthInfo.expires_in * 1000;
|
|
127
|
-
setValue(AUTH_PROVIDER, bearerAuthInfo.auth_provider);
|
|
128
|
-
setValue(ACCESS_TOKEN_NAME, bearerAuthInfo === null || bearerAuthInfo === void 0 ? void 0 : bearerAuthInfo.access_token);
|
|
129
|
-
setValue(REFRESH_TOKEN_NAME, bearerAuthInfo === null || bearerAuthInfo === void 0 ? void 0 : bearerAuthInfo.refresh_token);
|
|
130
|
-
setValue(ACCESS_TOKEN_EXPIRATION_MILLISECONDS_NAME, expirationTimeMilliseconds);
|
|
214
|
+
await setValue(AUTH_PROVIDER, bearerAuthInfo.auth_provider);
|
|
215
|
+
await setValue(ACCESS_TOKEN_NAME, bearerAuthInfo === null || bearerAuthInfo === void 0 ? void 0 : bearerAuthInfo.access_token);
|
|
216
|
+
await setValue(REFRESH_TOKEN_NAME, bearerAuthInfo === null || bearerAuthInfo === void 0 ? void 0 : bearerAuthInfo.refresh_token);
|
|
217
|
+
await setValue(ACCESS_TOKEN_EXPIRATION_MILLISECONDS_NAME, expirationTimeMilliseconds);
|
|
218
|
+
if (bearerAuthInfo.refresh_token_expires_at) {
|
|
219
|
+
await setValue(REFRESH_TOKEN_EXPIRATION_MILLISECONDS_NAME, bearerAuthInfo.refresh_token_expires_at * 1000);
|
|
220
|
+
}
|
|
131
221
|
return;
|
|
132
|
-
case
|
|
222
|
+
case types_2.AuthType.ApiKey:
|
|
133
223
|
const apiKeyAuthInfo = authInfo;
|
|
134
|
-
setValue(AUTH_PROVIDER, apiKeyAuthInfo.auth_provider);
|
|
135
|
-
setValue(ACCESS_TOKEN_NAME, apiKeyAuthInfo.api_key);
|
|
224
|
+
await setValue(AUTH_PROVIDER, apiKeyAuthInfo.auth_provider);
|
|
225
|
+
await setValue(ACCESS_TOKEN_NAME, apiKeyAuthInfo.api_key);
|
|
136
226
|
return;
|
|
137
227
|
}
|
|
138
228
|
}
|
|
139
229
|
}
|
|
140
230
|
exports.CliConfigProvider = CliConfigProvider;
|
|
141
|
-
function
|
|
231
|
+
function propertyKeyToStoredKey(key) {
|
|
232
|
+
return `properties.${key}`;
|
|
233
|
+
}
|
|
234
|
+
async function setValue(key, value) {
|
|
142
235
|
if (value === undefined) {
|
|
143
|
-
clearValue(key);
|
|
236
|
+
return clearValue(key);
|
|
144
237
|
}
|
|
145
|
-
|
|
146
|
-
|
|
238
|
+
if (!shouldStoreRefreshTokens() && key.includes(REFRESH_TOKEN_NAME)) {
|
|
239
|
+
return;
|
|
147
240
|
}
|
|
241
|
+
(await getAuthConfigFile()).set(key, value);
|
|
242
|
+
}
|
|
243
|
+
async function getValue(key) {
|
|
244
|
+
return (await getAuthConfigFile()).get(key);
|
|
148
245
|
}
|
|
149
|
-
function
|
|
150
|
-
|
|
246
|
+
async function clearValue(key) {
|
|
247
|
+
(await getAuthConfigFile()).delete(key);
|
|
151
248
|
}
|
|
152
|
-
function
|
|
153
|
-
|
|
249
|
+
function __resetIsKeytarAvailable() {
|
|
250
|
+
isKeytarAvailable = true;
|
|
154
251
|
}
|
|
252
|
+
exports.__resetIsKeytarAvailable = __resetIsKeytarAvailable;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthProviderType = void 0;
|
|
4
|
+
var AuthProviderType;
|
|
5
|
+
(function (AuthProviderType) {
|
|
6
|
+
AuthProviderType["Auth0"] = "auth0";
|
|
7
|
+
AuthProviderType["Mabl"] = "mabl";
|
|
8
|
+
AuthProviderType["Okta"] = "okta";
|
|
9
|
+
})(AuthProviderType = exports.AuthProviderType || (exports.AuthProviderType = {}));
|