ag-awsauth 0.0.293 → 0.0.294
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/helpers/browser.js +48 -28
- package/package.json +12 -9
package/dist/helpers/browser.js
CHANGED
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.allowAccessIfRequested = exports.dismissAllowAccessPrompt = exports.allowAccessSelectors = exports.goToPage = exports.launchBrowser = exports.closeBrowser = void 0;
|
|
13
13
|
exports.getMFA = getMFA;
|
|
14
14
|
const log_1 = require("ag-common/dist/common/helpers/log");
|
|
15
|
+
const sleep_1 = require("ag-common/dist/common/helpers/sleep");
|
|
15
16
|
const puppeteer_1 = require("puppeteer");
|
|
16
17
|
const __1 = require("..");
|
|
17
18
|
const config_1 = require("../config");
|
|
@@ -103,9 +104,7 @@ const clickSelectorIfPresent = (page_1, selector_1, ...args_1) => __awaiter(void
|
|
|
103
104
|
catch (_a) {
|
|
104
105
|
// Element may detach between query and click (SPA re-render).
|
|
105
106
|
// Fall back to an in-page click which re-queries the selector.
|
|
106
|
-
yield page
|
|
107
|
-
.$eval(selector, (bn) => bn.click())
|
|
108
|
-
.catch(() => undefined);
|
|
107
|
+
yield page.$eval(selector, (bn) => bn.click()).catch(() => undefined);
|
|
109
108
|
}
|
|
110
109
|
return true;
|
|
111
110
|
}
|
|
@@ -113,24 +112,23 @@ const clickSelectorIfPresent = (page_1, selector_1, ...args_1) => __awaiter(void
|
|
|
113
112
|
return false;
|
|
114
113
|
}
|
|
115
114
|
});
|
|
116
|
-
const clickAllowAccessByText = (page) =>
|
|
115
|
+
const clickAllowAccessByText = (page) => {
|
|
117
116
|
try {
|
|
118
|
-
|
|
117
|
+
const clicked = page.evaluate(() => {
|
|
119
118
|
const isVisible = (el) => {
|
|
120
119
|
const rect = el.getBoundingClientRect();
|
|
121
|
-
return
|
|
122
|
-
rect.height > 0 &&
|
|
123
|
-
getComputedStyle(el).visibility !== 'hidden');
|
|
120
|
+
return rect.width > 0 && rect.height > 0 && getComputedStyle(el).visibility !== 'hidden';
|
|
124
121
|
};
|
|
125
122
|
// Match button, link, or ARIA-button variants: AWS renders the
|
|
126
123
|
// "Allow access" consent action differently across releases
|
|
127
124
|
// (orange button vs link), so don't assume a <button>.
|
|
128
125
|
const candidates = Array.from(document.querySelectorAll('button, a, [role="button"], input[type="submit"], input[type="button"]')).filter((el) => isVisible(el));
|
|
129
126
|
const label = (el) => {
|
|
130
|
-
var _a
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
127
|
+
var _a;
|
|
128
|
+
const inputValue = el.value;
|
|
129
|
+
// oxlint-disable-next-line typescript/no-unnecessary-condition -- value is undefined on non-inputs
|
|
130
|
+
const text = typeof inputValue === 'string' ? inputValue : ((_a = el.textContent) !== null && _a !== void 0 ? _a : '');
|
|
131
|
+
return text.trim().toLowerCase();
|
|
134
132
|
};
|
|
135
133
|
const exact = candidates.find((el) => label(el) === 'allow access');
|
|
136
134
|
const target = exact !== null && exact !== void 0 ? exact : candidates.find((el) => label(el).includes('allow access'));
|
|
@@ -140,17 +138,17 @@ const clickAllowAccessByText = (page) => __awaiter(void 0, void 0, void 0, funct
|
|
|
140
138
|
}
|
|
141
139
|
return false;
|
|
142
140
|
});
|
|
141
|
+
return clicked;
|
|
143
142
|
}
|
|
144
143
|
catch (_a) {
|
|
145
|
-
return false;
|
|
144
|
+
return Promise.resolve(false);
|
|
146
145
|
}
|
|
147
|
-
}
|
|
146
|
+
};
|
|
148
147
|
const dismissAllowAccessPrompt = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, perSelectorTimeout = 1000) {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
148
|
+
const clicked = yield Promise.all(exports.allowAccessSelectors.map((selector) => clickSelectorIfPresent(page, selector, perSelectorTimeout)));
|
|
149
|
+
if (clicked.some(Boolean)) {
|
|
150
|
+
(0, log_1.info)('click allow-access-button');
|
|
151
|
+
return true;
|
|
154
152
|
}
|
|
155
153
|
if (yield clickAllowAccessByText(page)) {
|
|
156
154
|
(0, log_1.info)('click allow-access-button (text match "Allow access")');
|
|
@@ -159,29 +157,40 @@ const dismissAllowAccessPrompt = (page_1, ...args_1) => __awaiter(void 0, [page_
|
|
|
159
157
|
return false;
|
|
160
158
|
});
|
|
161
159
|
exports.dismissAllowAccessPrompt = dismissAllowAccessPrompt;
|
|
160
|
+
const pollDelayMs = 500;
|
|
161
|
+
const sleepUntilDeadline = (deadline) => __awaiter(void 0, void 0, void 0, function* () {
|
|
162
|
+
const remaining = deadline - Date.now();
|
|
163
|
+
if (remaining <= 0) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
yield (0, sleep_1.sleep)(Math.min(pollDelayMs, remaining));
|
|
167
|
+
});
|
|
162
168
|
const allowAccessIfRequested = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, timeout = config_1.timeoutMs) {
|
|
163
169
|
const deadline = Date.now() + timeout;
|
|
164
170
|
// Poll so a slow-rendering consent dialog is not missed, while still
|
|
165
171
|
// returning quickly when the prompt appears (or never appears).
|
|
166
|
-
|
|
172
|
+
// oxlint-disable-next-line no-await-in-loop -- polling must stay sequential to match dialog timing
|
|
173
|
+
for (;;) {
|
|
174
|
+
// oxlint-disable-next-line no-await-in-loop -- each poll depends on the current page state
|
|
167
175
|
if (yield (0, exports.dismissAllowAccessPrompt)(page)) {
|
|
168
176
|
return true;
|
|
169
177
|
}
|
|
170
|
-
if (Date.now()
|
|
171
|
-
|
|
178
|
+
if (Date.now() >= deadline) {
|
|
179
|
+
return false;
|
|
172
180
|
}
|
|
173
|
-
|
|
181
|
+
// oxlint-disable-next-line no-await-in-loop -- delay must elapse before the next poll
|
|
182
|
+
yield sleepUntilDeadline(deadline);
|
|
174
183
|
}
|
|
175
|
-
return false;
|
|
176
184
|
});
|
|
177
185
|
exports.allowAccessIfRequested = allowAccessIfRequested;
|
|
178
186
|
const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page_1, ...args_1], void 0, function* (page, timeout = config_1.timeoutMs) {
|
|
179
|
-
var _a;
|
|
180
187
|
const deadline = Date.now() + timeout;
|
|
181
188
|
let lastError;
|
|
182
|
-
|
|
189
|
+
// oxlint-disable-next-line no-await-in-loop -- success and consent checks are order-dependent
|
|
190
|
+
for (;;) {
|
|
183
191
|
// Success already visible?
|
|
184
192
|
try {
|
|
193
|
+
// oxlint-disable-next-line no-await-in-loop -- must check before dismissing prompts
|
|
185
194
|
const success = yield page.waitForSelector('[data-analytics-alert="success"]', { timeout: 2000 });
|
|
186
195
|
if (success) {
|
|
187
196
|
return;
|
|
@@ -194,6 +203,7 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
|
|
|
194
203
|
// This covers the "Allow <user> to access your data? / Allow access"
|
|
195
204
|
// dialog which otherwise blocks success indefinitely.
|
|
196
205
|
try {
|
|
206
|
+
// oxlint-disable-next-line no-await-in-loop -- prompt check follows the success check
|
|
197
207
|
if (yield (0, exports.dismissAllowAccessPrompt)(page)) {
|
|
198
208
|
(0, log_1.info)('dismissed allow-access prompt while waiting for success');
|
|
199
209
|
continue;
|
|
@@ -204,6 +214,7 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
|
|
|
204
214
|
}
|
|
205
215
|
// Also re-check the other intermediate confirmations while polling.
|
|
206
216
|
try {
|
|
217
|
+
// oxlint-disable-next-line no-await-in-loop -- confirmation check follows the success check
|
|
207
218
|
if (yield clickSelectorIfPresent(page, '[data-analytics="accept-user-code"]', 1000)) {
|
|
208
219
|
(0, log_1.info)('click accept-user-code (while waiting for success)');
|
|
209
220
|
continue;
|
|
@@ -213,6 +224,7 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
|
|
|
213
224
|
(0, log_1.debug)('error clicking accept-user-code while waiting:', e);
|
|
214
225
|
}
|
|
215
226
|
try {
|
|
227
|
+
// oxlint-disable-next-line no-await-in-loop -- auth request check follows the success check
|
|
216
228
|
if (yield clickSelectorIfPresent(page, '#cli_verification_btn', 1000)) {
|
|
217
229
|
(0, log_1.info)('clicking auth request button (while waiting for success)');
|
|
218
230
|
}
|
|
@@ -220,6 +232,11 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
|
|
|
220
232
|
catch (e) {
|
|
221
233
|
(0, log_1.debug)('error clicking auth request button while waiting:', e);
|
|
222
234
|
}
|
|
235
|
+
if (Date.now() >= deadline) {
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
// oxlint-disable-next-line no-await-in-loop -- delay must elapse before the next poll
|
|
239
|
+
yield sleepUntilDeadline(deadline);
|
|
223
240
|
}
|
|
224
241
|
// Final wait to surface a clear TimeoutError if success never arrived.
|
|
225
242
|
try {
|
|
@@ -227,8 +244,11 @@ const waitForSuccessDefensively = (page_1, ...args_1) => __awaiter(void 0, [page
|
|
|
227
244
|
timeout: config_1.timeoutShortMs,
|
|
228
245
|
});
|
|
229
246
|
}
|
|
230
|
-
catch (
|
|
231
|
-
|
|
247
|
+
catch (_a) {
|
|
248
|
+
if (lastError instanceof Error) {
|
|
249
|
+
throw lastError;
|
|
250
|
+
}
|
|
251
|
+
throw new Error('Timed out waiting for success');
|
|
232
252
|
}
|
|
233
253
|
});
|
|
234
254
|
function getMFA(p) {
|
package/package.json
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ag-awsauth",
|
|
3
|
+
"version": "0.0.294",
|
|
4
|
+
"private": false,
|
|
3
5
|
"description": "auth to aws sso/iamv2 easily",
|
|
4
|
-
"main": "dist/index.js",
|
|
5
|
-
"author": "andreigec@hotmail.com",
|
|
6
6
|
"license": "ISC",
|
|
7
|
-
"
|
|
8
|
-
"version": "0.0.293",
|
|
9
|
-
"preferGlobal": true,
|
|
7
|
+
"author": "andreigec@hotmail.com",
|
|
10
8
|
"bin": {
|
|
11
9
|
"ag-awsauth": "./bin/awsauth.js"
|
|
12
10
|
},
|
|
@@ -16,18 +14,21 @@
|
|
|
16
14
|
"README.md",
|
|
17
15
|
"LICENSE.md"
|
|
18
16
|
],
|
|
17
|
+
"main": "dist/index.js",
|
|
19
18
|
"dependencies": {
|
|
20
19
|
"@aws-sdk/client-sso": "3.972.0",
|
|
21
20
|
"@aws-sdk/client-sso-oidc": "3.972.0",
|
|
22
21
|
"@aws-sdk/client-sts": "3.972.0",
|
|
23
22
|
"@aws-sdk/shared-ini-file-loader": "3.374.0",
|
|
24
|
-
"ag-common": "0.0.
|
|
23
|
+
"ag-common": "0.0.911",
|
|
25
24
|
"cli-select": "1.1.2",
|
|
26
25
|
"dotenv": "17.2.3",
|
|
27
26
|
"envfile": "7.1.0",
|
|
28
|
-
"eslint-config-e7npm": "0.1.
|
|
27
|
+
"eslint-config-e7npm": "0.1.68",
|
|
29
28
|
"ini": "5.0.0",
|
|
30
29
|
"node-fetch": "3.3.2",
|
|
30
|
+
"oxfmt": "^0.65.0",
|
|
31
|
+
"oxlint": "^1.83.0",
|
|
31
32
|
"puppeteer": "24.35.0",
|
|
32
33
|
"readline-sync": "1.4.10",
|
|
33
34
|
"typescript": "5.9.3",
|
|
@@ -43,12 +44,14 @@
|
|
|
43
44
|
"resolutions": {
|
|
44
45
|
"ws": ">=8.17.1"
|
|
45
46
|
},
|
|
47
|
+
"preferGlobal": true,
|
|
46
48
|
"engines": {
|
|
47
49
|
"node": ">=20"
|
|
48
50
|
},
|
|
49
51
|
"scripts": {
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
+
"format": "e7-oxfmt --config .oxfmtrc.json --disable-nested-config .",
|
|
53
|
+
"lint": "e7-oxlint --config .oxlintrc.json --deny-warnings src && pnpm run typecheck",
|
|
54
|
+
"typecheck": "tsc --noEmit",
|
|
52
55
|
"test": "tsc && node --test test/*.test.js",
|
|
53
56
|
"start": "tsc && node bin/awsauth.js",
|
|
54
57
|
"build": "tsc"
|