estatehelm 1.0.3 → 1.0.5
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/index.js +61 -145
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1454,99 +1454,21 @@ function prompt(question) {
|
|
|
1454
1454
|
});
|
|
1455
1455
|
});
|
|
1456
1456
|
}
|
|
1457
|
-
var ALLOWED_CALLBACK_PORTS = [11033, 11034, 11035];
|
|
1458
1457
|
async function findAvailablePort() {
|
|
1459
|
-
for (const port of ALLOWED_CALLBACK_PORTS) {
|
|
1460
|
-
const available = await isPortAvailable(port);
|
|
1461
|
-
if (available) {
|
|
1462
|
-
return port;
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
throw new Error(
|
|
1466
|
-
`No available ports for CLI callback. Ports ${ALLOWED_CALLBACK_PORTS.join(", ")} are all in use.`
|
|
1467
|
-
);
|
|
1468
|
-
}
|
|
1469
|
-
function isPortAvailable(port) {
|
|
1470
|
-
return new Promise((resolve) => {
|
|
1471
|
-
const server = http.createServer();
|
|
1472
|
-
server.listen(port, "127.0.0.1", () => {
|
|
1473
|
-
server.close(() => resolve(true));
|
|
1474
|
-
});
|
|
1475
|
-
server.on("error", () => resolve(false));
|
|
1476
|
-
});
|
|
1477
|
-
}
|
|
1478
|
-
function waitForCallback(port) {
|
|
1479
1458
|
return new Promise((resolve, reject) => {
|
|
1480
|
-
const server = http.createServer(
|
|
1481
|
-
|
|
1482
|
-
const
|
|
1483
|
-
const
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
<title>Authentication Failed</title>
|
|
1492
|
-
<style>
|
|
1493
|
-
body { font-family: system-ui, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #fef2f2; }
|
|
1494
|
-
.card { background: white; padding: 2rem; border-radius: 1rem; box-shadow: 0 10px 25px rgba(0,0,0,0.1); text-align: center; max-width: 400px; }
|
|
1495
|
-
h1 { color: #dc2626; margin: 0 0 0.5rem; }
|
|
1496
|
-
p { color: #6b7280; margin: 0.5rem 0; }
|
|
1497
|
-
.error { font-family: monospace; background: #f3f4f6; padding: 0.5rem; border-radius: 0.25rem; font-size: 0.875rem; }
|
|
1498
|
-
</style>
|
|
1499
|
-
</head>
|
|
1500
|
-
<body>
|
|
1501
|
-
<div class="card">
|
|
1502
|
-
<h1>Authentication Failed</h1>
|
|
1503
|
-
<p>${errorDescription || error || "An error occurred during authentication."}</p>
|
|
1504
|
-
<p class="error">${error}</p>
|
|
1505
|
-
</div>
|
|
1506
|
-
</body>
|
|
1507
|
-
</html>
|
|
1508
|
-
`);
|
|
1509
|
-
server.close();
|
|
1510
|
-
reject(new Error(errorDescription || error || "Authentication failed"));
|
|
1511
|
-
return;
|
|
1512
|
-
}
|
|
1513
|
-
if (sessionToken) {
|
|
1514
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1515
|
-
res.end(`
|
|
1516
|
-
<!DOCTYPE html>
|
|
1517
|
-
<html>
|
|
1518
|
-
<head>
|
|
1519
|
-
<title>CLI Authentication Successful</title>
|
|
1520
|
-
<style>
|
|
1521
|
-
body { font-family: system-ui, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: linear-gradient(115deg, #fff1be 28%, #ee87cb 70%, #b060ff 100%); }
|
|
1522
|
-
.card { background: white; padding: 2rem; border-radius: 1rem; box-shadow: 0 10px 25px rgba(0,0,0,0.1); text-align: center; }
|
|
1523
|
-
h1 { color: #059669; margin: 0 0 0.5rem; }
|
|
1524
|
-
p { color: #6b7280; margin: 0; }
|
|
1525
|
-
</style>
|
|
1526
|
-
</head>
|
|
1527
|
-
<body>
|
|
1528
|
-
<div class="card">
|
|
1529
|
-
<h1>\u2713 Authentication Successful</h1>
|
|
1530
|
-
<p>You can close this window and return to your terminal.</p>
|
|
1531
|
-
</div>
|
|
1532
|
-
</body>
|
|
1533
|
-
</html>
|
|
1534
|
-
`);
|
|
1535
|
-
server.close();
|
|
1536
|
-
resolve(sessionToken);
|
|
1537
|
-
} else {
|
|
1538
|
-
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
1539
|
-
res.end("Not found");
|
|
1540
|
-
}
|
|
1541
|
-
});
|
|
1542
|
-
server.listen(port, "127.0.0.1", () => {
|
|
1543
|
-
console.log(`Callback server listening on http://127.0.0.1:${port}`);
|
|
1459
|
+
const server = http.createServer();
|
|
1460
|
+
server.listen(0, "127.0.0.1", () => {
|
|
1461
|
+
const address = server.address();
|
|
1462
|
+
const port = typeof address === "object" && address ? address.port : 0;
|
|
1463
|
+
server.close(() => {
|
|
1464
|
+
if (port > 0) {
|
|
1465
|
+
resolve(port);
|
|
1466
|
+
} else {
|
|
1467
|
+
reject(new Error("Failed to find available port"));
|
|
1468
|
+
}
|
|
1469
|
+
});
|
|
1544
1470
|
});
|
|
1545
1471
|
server.on("error", reject);
|
|
1546
|
-
setTimeout(() => {
|
|
1547
|
-
server.close();
|
|
1548
|
-
reject(new Error("Authentication timed out. Please try again."));
|
|
1549
|
-
}, 5 * 60 * 1e3);
|
|
1550
1472
|
});
|
|
1551
1473
|
}
|
|
1552
1474
|
function createApiClient(token) {
|
|
@@ -1618,53 +1540,50 @@ async function decryptDeviceCredentials(encryptedPayload) {
|
|
|
1618
1540
|
);
|
|
1619
1541
|
return new Uint8Array(plaintext);
|
|
1620
1542
|
}
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1543
|
+
function waitForCallback(port) {
|
|
1544
|
+
return new Promise((resolve, reject) => {
|
|
1545
|
+
const server = http.createServer((req, res) => {
|
|
1546
|
+
const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
|
|
1547
|
+
const sessionToken = url.searchParams.get("session_token");
|
|
1548
|
+
const error = url.searchParams.get("error");
|
|
1549
|
+
if (error) {
|
|
1550
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
1551
|
+
res.end(`
|
|
1552
|
+
<!DOCTYPE html>
|
|
1553
|
+
<html>
|
|
1554
|
+
<head><title>Authentication Failed</title>
|
|
1555
|
+
<style>body{font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#fef2f2}.card{background:white;padding:2rem;border-radius:1rem;box-shadow:0 10px 25px rgba(0,0,0,0.1);text-align:center}h1{color:#dc2626}</style></head>
|
|
1556
|
+
<body><div class="card"><h1>Authentication Failed</h1><p>${url.searchParams.get("error_description") || error}</p></div></body>
|
|
1557
|
+
</html>
|
|
1558
|
+
`);
|
|
1559
|
+
server.close();
|
|
1560
|
+
reject(new Error(url.searchParams.get("error_description") || error));
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
if (sessionToken) {
|
|
1564
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1565
|
+
res.end(`
|
|
1566
|
+
<!DOCTYPE html>
|
|
1567
|
+
<html>
|
|
1568
|
+
<head><title>Authentication Successful</title>
|
|
1569
|
+
<style>body{font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:linear-gradient(115deg,#fff1be 28%,#ee87cb 70%,#b060ff 100%)}.card{background:white;padding:2rem;border-radius:1rem;box-shadow:0 10px 25px rgba(0,0,0,0.1);text-align:center}h1{color:#059669}</style></head>
|
|
1570
|
+
<body><div class="card"><h1>\u2713 Authentication Successful</h1><p>You can close this window and return to your terminal.</p></div></body>
|
|
1571
|
+
</html>
|
|
1572
|
+
`);
|
|
1573
|
+
server.close();
|
|
1574
|
+
resolve(sessionToken);
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
res.writeHead(404);
|
|
1578
|
+
res.end();
|
|
1579
|
+
});
|
|
1580
|
+
server.listen(port, "127.0.0.1");
|
|
1581
|
+
server.on("error", reject);
|
|
1582
|
+
setTimeout(() => {
|
|
1583
|
+
server.close();
|
|
1584
|
+
reject(new Error("Authentication timed out"));
|
|
1585
|
+
}, 5 * 60 * 1e3);
|
|
1651
1586
|
});
|
|
1652
|
-
if (response.status === 422) {
|
|
1653
|
-
const data = await response.json();
|
|
1654
|
-
const redirectUrl = data.redirect_browser_to;
|
|
1655
|
-
if (redirectUrl) {
|
|
1656
|
-
return redirectUrl;
|
|
1657
|
-
}
|
|
1658
|
-
throw new Error("No redirect URL in OIDC response");
|
|
1659
|
-
}
|
|
1660
|
-
if (response.ok) {
|
|
1661
|
-
const data = await response.json();
|
|
1662
|
-
if (data.session_token) {
|
|
1663
|
-
return data.session_token;
|
|
1664
|
-
}
|
|
1665
|
-
}
|
|
1666
|
-
const error = await response.text();
|
|
1667
|
-
throw new Error(`Failed to initiate OIDC flow: ${response.status} - ${error}`);
|
|
1668
1587
|
}
|
|
1669
1588
|
async function login() {
|
|
1670
1589
|
console.log("\nEstateHelm Login");
|
|
@@ -1672,18 +1591,15 @@ async function login() {
|
|
|
1672
1591
|
console.log("Starting authentication server...");
|
|
1673
1592
|
const port = await findAvailablePort();
|
|
1674
1593
|
const callbackUrl = `http://127.0.0.1:${port}/callback`;
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
console.log(
|
|
1678
|
-
|
|
1679
|
-
console.log(`
|
|
1680
|
-
Opening browser for Google authentication...`);
|
|
1681
|
-
console.log(`If the browser doesn't open, visit: ${oauthUrl}
|
|
1594
|
+
const loginUrl = `${APP_URL}/cli-auth?callback=${encodeURIComponent(callbackUrl)}`;
|
|
1595
|
+
console.log("\nOpening browser for authentication...");
|
|
1596
|
+
console.log(`If the browser doesn't open, visit:
|
|
1597
|
+
${loginUrl}
|
|
1682
1598
|
`);
|
|
1683
|
-
const
|
|
1684
|
-
await (0, import_open.default)(
|
|
1599
|
+
const tokenPromise = waitForCallback(port);
|
|
1600
|
+
await (0, import_open.default)(loginUrl);
|
|
1685
1601
|
console.log("Waiting for authentication...");
|
|
1686
|
-
const sessionToken = await
|
|
1602
|
+
const sessionToken = await tokenPromise;
|
|
1687
1603
|
console.log("Authentication successful!");
|
|
1688
1604
|
console.log(`Token: ${sanitizeToken(sessionToken)}`);
|
|
1689
1605
|
await saveBearerToken(sessionToken);
|