kalvium-worklog 1.4.1 → 1.4.3
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/capture-token.js +92 -38
- package/package.json +1 -1
package/dist/capture-token.js
CHANGED
|
@@ -61,10 +61,9 @@ async function captureTokenViaBrowser() {
|
|
|
61
61
|
console.log("\n ========================================");
|
|
62
62
|
console.log(" Browser-based token capture (no Playwright)");
|
|
63
63
|
console.log(" ========================================\n");
|
|
64
|
-
// Start local HTTP server
|
|
64
|
+
// Start local HTTP server
|
|
65
65
|
const tokenPromise = new Promise((resolve) => {
|
|
66
66
|
const server = createServer((req, res) => {
|
|
67
|
-
// Handle CORS + token capture
|
|
68
67
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
69
68
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
70
69
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
@@ -78,15 +77,14 @@ async function captureTokenViaBrowser() {
|
|
|
78
77
|
body += chunk;
|
|
79
78
|
});
|
|
80
79
|
req.on("end", () => {
|
|
80
|
+
// Token capture endpoint
|
|
81
81
|
if (req.url?.startsWith("/capture")) {
|
|
82
82
|
try {
|
|
83
|
-
// Try parsing as JSON first (POST body)
|
|
84
83
|
let data;
|
|
85
84
|
if (body) {
|
|
86
85
|
data = JSON.parse(body);
|
|
87
86
|
}
|
|
88
87
|
else {
|
|
89
|
-
// Try query param
|
|
90
88
|
const url = new URL(req.url, `http://localhost:${PORT}`);
|
|
91
89
|
const tokenParam = url.searchParams.get("token");
|
|
92
90
|
if (!tokenParam) {
|
|
@@ -98,69 +96,125 @@ async function captureTokenViaBrowser() {
|
|
|
98
96
|
}
|
|
99
97
|
if (data.refresh_token) {
|
|
100
98
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
101
|
-
res.end("<html><body><h2
|
|
99
|
+
res.end("<html><body style='font-family:sans-serif;text-align:center;padding:40px'><h2>✓ Token captured!</h2><p>You can close this tab and go back to Termux.</p></body></html>");
|
|
102
100
|
resolve(data);
|
|
103
101
|
}
|
|
104
102
|
else {
|
|
105
|
-
res.writeHead(400);
|
|
106
|
-
res.end("Invalid token — missing refresh_token");
|
|
103
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
104
|
+
res.end("<html><body><h2>Invalid token — missing refresh_token</h2></body></html>");
|
|
107
105
|
resolve(null);
|
|
108
106
|
}
|
|
109
107
|
}
|
|
110
108
|
catch {
|
|
111
|
-
res.writeHead(400);
|
|
112
|
-
res.end("Invalid JSON");
|
|
109
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
110
|
+
res.end("<html><body><h2>Invalid JSON</h2></body></html>");
|
|
113
111
|
resolve(null);
|
|
114
112
|
}
|
|
113
|
+
return;
|
|
115
114
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
// Main page — serves instructions + manual paste form
|
|
116
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
117
|
+
res.end(`<!DOCTYPE html>
|
|
118
|
+
<html>
|
|
119
|
+
<head>
|
|
120
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
121
|
+
<title>Kalvium Worklog — Login</title>
|
|
122
|
+
<style>
|
|
123
|
+
* { box-sizing: border-box; }
|
|
124
|
+
body { font-family: -apple-system, sans-serif; max-width: 600px; margin: 0 auto; padding: 16px; line-height: 1.6; color: #333; }
|
|
125
|
+
h2 { color: #1a73e8; }
|
|
126
|
+
.step { background: #f0f4ff; border-radius: 12px; padding: 16px; margin: 12px 0; }
|
|
127
|
+
.step h3 { margin-top: 0; color: #1a73e8; }
|
|
128
|
+
.btn { display: block; text-align: center; background: #4285f4; color: white; padding: 14px; border-radius: 8px; text-decoration: none; font-size: 18px; font-weight: bold; margin: 12px 0; }
|
|
129
|
+
.btn-green { background: #34a853; }
|
|
130
|
+
.btn:active { opacity: 0.8; }
|
|
131
|
+
.code-box { background: #1e1e1e; color: #0f0; padding: 12px; border-radius: 8px; font-family: monospace; font-size: 12px; word-break: break-all; white-space: pre-wrap; user-select: all; }
|
|
132
|
+
.note { background: #fff8e1; border-radius: 8px; padding: 12px; margin: 12px 0; font-size: 14px; }
|
|
133
|
+
.warn { background: #fce4ec; border-radius: 8px; padding: 12px; margin: 12px 0; font-size: 14px; }
|
|
134
|
+
textarea { width: 100%; height: 120px; font-family: monospace; font-size: 12px; border: 2px solid #4285f4; border-radius: 8px; padding: 8px; }
|
|
135
|
+
#result { font-weight: bold; padding: 12px; border-radius: 8px; margin: 8px 0; display: none; }
|
|
136
|
+
.success { background: #e8f5e9; color: #2e7d32; }
|
|
137
|
+
.error { background: #ffebee; color: #c62828; }
|
|
138
|
+
</style>
|
|
139
|
+
</head>
|
|
140
|
+
<body>
|
|
141
|
+
<h2>Kalvium Worklog — Login</h2>
|
|
142
|
+
|
|
143
|
+
<div class="step">
|
|
144
|
+
<h3>Step 1: Log in to Kalvium</h3>
|
|
145
|
+
<p>Tap below, log in with Google (2FA if asked).</p>
|
|
146
|
+
<a class="btn btn-green" href="https://kalvium.community/internships" target="_blank">Open Kalvium →</a>
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<div class="step">
|
|
150
|
+
<h3>Step 2: Extract token</h3>
|
|
151
|
+
<p>After logging in, go to the Kalvium tab.<br>
|
|
152
|
+
<b>Type</b> this in the address bar (don't paste — type <code>javascript:</code> yourself, then paste the rest):</p>
|
|
153
|
+
<div class="code-box" id="jscode">javascript:void(function(){var t;for(var i=0;i<localStorage.length;i++){var k=localStorage.key(i),v=localStorage.getItem(i);if(v&&v.includes('refresh_token')){t=v}}if(!t){for(var i=0;i<sessionStorage.length;i++){var k=sessionStorage.key(i),v=sessionStorage.getItem(i);if(v&&v.includes('refresh_token')){t=v}}}if(t){fetch('http://localhost:${PORT}/capture',{method:'POST',body:t}).then(function(r){alert(r.ok?'Token sent! Go back to Termux':'Failed: '+r.status)}).catch(function(e){alert('Error: '+e)})}else{alert('No token found. Are you logged in?')}})()</div>
|
|
154
|
+
<p><small>👆 Long-press the code above → "Copy", then go to Kalvium tab, type <code>javascript:</code> in address bar, paste the rest after it, press Enter.</small></p>
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
<div class="warn">
|
|
158
|
+
<b>Brave users:</b> Brave strips <code>javascript:</code> when pasting. You must <b>type</b> <code>javascript:</code> manually, then paste only the code after <code>javascript:</code>.
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<div class="step">
|
|
162
|
+
<h3>Or: Paste token manually</h3>
|
|
163
|
+
<p>If the above doesn't work, extract the token another way and paste it here:</p>
|
|
164
|
+
<textarea id="manualToken" placeholder='Paste token JSON here (starts with {"access_token"...'></textarea>
|
|
165
|
+
<button class="btn" onclick="sendManual()">Send Token</button>
|
|
166
|
+
<div id="result"></div>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<script>
|
|
170
|
+
function sendManual() {
|
|
171
|
+
var val = document.getElementById('manualToken').value.trim();
|
|
172
|
+
var result = document.getElementById('result');
|
|
173
|
+
result.style.display = 'block';
|
|
174
|
+
if (!val) { result.className = 'error'; result.textContent = 'Paste token JSON first'; return; }
|
|
175
|
+
fetch('http://localhost:${PORT}/capture', { method: 'POST', body: val })
|
|
176
|
+
.then(function(r) {
|
|
177
|
+
if (r.ok) { result.className = 'success'; result.textContent = '✓ Token sent! Go back to Termux.'; }
|
|
178
|
+
else { result.className = 'error'; result.textContent = 'Failed: ' + r.status; }
|
|
179
|
+
})
|
|
180
|
+
.catch(function(e) { result.className = 'error'; result.textContent = 'Error: ' + e; });
|
|
181
|
+
}
|
|
182
|
+
</script>
|
|
183
|
+
|
|
184
|
+
</body>
|
|
185
|
+
</html>`);
|
|
126
186
|
});
|
|
127
187
|
});
|
|
128
188
|
server.listen(PORT, () => {
|
|
129
189
|
console.log(` Local server running on http://localhost:${PORT}`);
|
|
130
190
|
});
|
|
131
|
-
// Timeout after 5 minutes
|
|
132
191
|
setTimeout(() => {
|
|
133
192
|
server.close();
|
|
134
193
|
resolve(null);
|
|
135
194
|
}, 300000);
|
|
136
195
|
});
|
|
137
|
-
// Open
|
|
138
|
-
const
|
|
196
|
+
// Open the localhost page in the browser
|
|
197
|
+
const localUrl = `http://localhost:${PORT}`;
|
|
139
198
|
try {
|
|
140
199
|
if (process.platform === "android") {
|
|
141
|
-
|
|
142
|
-
execSync(`termux-open-url ${url}`, { stdio: "ignore" });
|
|
200
|
+
execSync(`termux-open-url ${localUrl}`, { stdio: "ignore" });
|
|
143
201
|
}
|
|
144
202
|
else {
|
|
145
|
-
|
|
146
|
-
|
|
203
|
+
execSync(`xdg-open ${localUrl} || open ${localUrl}`, {
|
|
204
|
+
stdio: "ignore",
|
|
205
|
+
});
|
|
147
206
|
}
|
|
148
|
-
console.log(` Opened ${
|
|
207
|
+
console.log(` Opened ${localUrl} in your browser.`);
|
|
149
208
|
}
|
|
150
209
|
catch {
|
|
151
|
-
console.log(` Could not auto-open browser. Please open: ${
|
|
210
|
+
console.log(` Could not auto-open browser. Please open: ${localUrl}`);
|
|
152
211
|
}
|
|
153
212
|
console.log("\n ────────────────────────────────────────────");
|
|
154
|
-
console.log("
|
|
155
|
-
console.log("
|
|
156
|
-
console.log("
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const jsSnippet = `javascript:void(function(){var t=localStorage.getItem('kc-token')||localStorage.getItem('keycloak-token');if(!t){for(var i=0;i<localStorage.length;i++){var k=localStorage.key(i),v=localStorage.getItem(k);if(v&&v.includes('refresh_token')){t=v;break}}}if(!t){for(var i=0;i<sessionStorage.length;i++){var k=sessionStorage.key(i),v=sessionStorage.getItem(k);if(v&&v.includes('refresh_token')){t=v;break}}}if(t){fetch('http://localhost:${PORT}/capture',{method:'POST',headers:{'Content-Type':'text/plain'},body:t}).then(function(r){if(r.ok)alert('Token sent! You can close this tab.');else alert('Failed: '+r.status)}).catch(function(e){alert('Error: '+e)})}else{alert('No token found in storage. Make sure you are logged in.')}})()`;
|
|
160
|
-
console.log(` ${jsSnippet}\n`);
|
|
161
|
-
console.log(" 3. Paste it in the browser ADDRESS BAR (where you type URLs)");
|
|
162
|
-
console.log(" and press Enter. (Remove any leading 'javascript:' that");
|
|
163
|
-
console.log(" the browser strips, then type it manually if needed.)");
|
|
213
|
+
console.log(" A page opened in your browser with instructions:");
|
|
214
|
+
console.log(" 1. Click 'Open Kalvium' and log in");
|
|
215
|
+
console.log(" 2. Long-press 'Capture Token' → Bookmark it");
|
|
216
|
+
console.log(" 3. Go to Kalvium tab → open the bookmark");
|
|
217
|
+
console.log(" ────────────────────────────────────────────");
|
|
164
218
|
console.log("\n Waiting for token (up to 5 minutes)...\n");
|
|
165
219
|
const data = await tokenPromise;
|
|
166
220
|
if (data) {
|