moontraze 1.0.6 → 1.0.8
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/lib/auth.js +60 -81
- package/package.json +1 -1
package/lib/auth.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
const prompts = require('prompts');
|
|
2
2
|
const chalk = require('chalk');
|
|
3
|
-
const http = require('http');
|
|
4
|
-
const { URL } = require('url');
|
|
5
3
|
const { getConfig, setConfig } = require('./config');
|
|
6
4
|
|
|
7
5
|
async function login(tokenArg, options = {}) {
|
|
@@ -10,10 +8,8 @@ async function login(tokenArg, options = {}) {
|
|
|
10
8
|
process.env.MOON_API ||
|
|
11
9
|
getConfig().apiUrl ||
|
|
12
10
|
'https://api.moontraze.com';
|
|
13
|
-
|
|
14
11
|
const label = process.env.MOON_LABEL || process.env.MOON_PLATFORM || 'Moontraze';
|
|
15
12
|
|
|
16
|
-
// --token (hidden power user)
|
|
17
13
|
if (tokenArg && String(tokenArg).trim()) {
|
|
18
14
|
return saveAndValidateToken(String(tokenArg).trim(), { apiUrl, label });
|
|
19
15
|
}
|
|
@@ -72,31 +68,47 @@ async function loginWithEmail({ apiUrl, label }) {
|
|
|
72
68
|
});
|
|
73
69
|
|
|
74
70
|
const data = await res.json().catch(() => ({}));
|
|
75
|
-
|
|
76
71
|
if (!res.ok) throw new Error(data.error || 'Invalid email or password');
|
|
77
72
|
if (!data.token) throw new Error('Login succeeded but no token returned');
|
|
78
73
|
|
|
79
74
|
setConfig({ token: data.token, apiUrl });
|
|
80
|
-
|
|
81
75
|
console.log('');
|
|
82
76
|
console.log(chalk.green('✓ Logged in'));
|
|
83
|
-
if (data.user?.email) console.log(chalk.gray(`
|
|
84
|
-
console.log(chalk.gray(`
|
|
77
|
+
if (data.user?.email) console.log(chalk.gray(` ${data.user.email}`));
|
|
78
|
+
console.log(chalk.gray(` Config: ~/.moontraze/config.json`));
|
|
85
79
|
console.log('');
|
|
86
80
|
}
|
|
87
81
|
|
|
88
82
|
async function loginWithMoonID({ apiUrl, label }) {
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
const
|
|
92
|
-
const appId = 'com.moonstorage.app';
|
|
83
|
+
const fetch = require('node-fetch');
|
|
84
|
+
const nonce = Math.random().toString(36).substring(2, 12);
|
|
85
|
+
const state = `${nonce}.login`;
|
|
93
86
|
|
|
87
|
+
// ★ Same flow as website (working)
|
|
88
|
+
const startRes = await fetch(`${apiUrl}/api/platform/moonid/web-start`, {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
headers: { 'Content-Type': 'application/json' },
|
|
91
|
+
body: JSON.stringify({ state, action: 'login' }),
|
|
92
|
+
});
|
|
93
|
+
const startData = await startRes.json().catch(() => ({}));
|
|
94
|
+
if (!startRes.ok) {
|
|
95
|
+
throw new Error(startData.error || 'Could not start MoonID session');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const notifyUrl = `${apiUrl}/api/platform/moonid/web-complete`;
|
|
99
|
+
const redirectUri = `${apiUrl}/api/platform/moonid/done?state=${encodeURIComponent(
|
|
100
|
+
state
|
|
101
|
+
)}`;
|
|
102
|
+
|
|
103
|
+
const appId = 'com.moonstorage.app';
|
|
94
104
|
const deepLink =
|
|
95
105
|
`moonid://auth` +
|
|
96
106
|
`?app_id=${encodeURIComponent(appId)}` +
|
|
97
107
|
`&action=login` +
|
|
98
108
|
`&redirect_uri=${encodeURIComponent(redirectUri)}` +
|
|
99
|
-
`&
|
|
109
|
+
`¬ify_url=${encodeURIComponent(notifyUrl)}` +
|
|
110
|
+
`&state=${encodeURIComponent(state)}` +
|
|
111
|
+
`&source=cli`;
|
|
100
112
|
|
|
101
113
|
const qrImageUrl = `https://api.qrserver.com/v1/create-qr-code/?size=220x220&data=${encodeURIComponent(
|
|
102
114
|
deepLink
|
|
@@ -105,7 +117,7 @@ async function loginWithMoonID({ apiUrl, label }) {
|
|
|
105
117
|
console.log('');
|
|
106
118
|
console.log(chalk.cyan(`${label} — MoonID Login`));
|
|
107
119
|
console.log(chalk.gray('1. Open MoonID app on your phone'));
|
|
108
|
-
console.log(chalk.gray('2. Scan the QR code (open link below in browser)'));
|
|
120
|
+
console.log(chalk.gray('2. Scan the QR code (open the link below in a browser if needed)'));
|
|
109
121
|
console.log(chalk.gray('3. Approve login'));
|
|
110
122
|
console.log('');
|
|
111
123
|
console.log(chalk.yellow('QR code image:'));
|
|
@@ -114,75 +126,45 @@ async function loginWithMoonID({ apiUrl, label }) {
|
|
|
114
126
|
console.log(chalk.gray('Waiting for approval... (Ctrl+C to cancel)'));
|
|
115
127
|
console.log('');
|
|
116
128
|
|
|
117
|
-
const token = await
|
|
129
|
+
const token = await pollWebStatus({ apiUrl, state, timeoutMs: 180000 });
|
|
118
130
|
if (!token) throw new Error('MoonID login timed out or denied');
|
|
119
131
|
|
|
120
132
|
await saveAndValidateToken(token, { apiUrl, label });
|
|
121
133
|
}
|
|
122
134
|
|
|
123
|
-
function
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
143
|
-
res.end(
|
|
144
|
-
'<html><body style="font-family:sans-serif;text-align:center;padding:40px"><h2>Login denied</h2><p>You can close this tab.</p></body></html>'
|
|
145
|
-
);
|
|
146
|
-
server.close();
|
|
147
|
-
resolve(null);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (returnedState && returnedState !== state) {
|
|
152
|
-
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
153
|
-
res.end('Invalid state');
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (!token) {
|
|
158
|
-
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
159
|
-
res.end(
|
|
160
|
-
'<html><body style="font-family:sans-serif;text-align:center;padding:40px"><h2>No token received</h2></body></html>'
|
|
161
|
-
);
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
166
|
-
res.end(
|
|
167
|
-
'<html><body style="font-family:sans-serif;text-align:center;padding:40px"><h2>✓ Login successful</h2><p>You can close this tab.</p></body></html>'
|
|
168
|
-
);
|
|
169
|
-
server.close();
|
|
170
|
-
resolve(token);
|
|
171
|
-
} catch {
|
|
172
|
-
res.writeHead(500);
|
|
173
|
-
res.end('Error');
|
|
135
|
+
async function pollWebStatus({ apiUrl, state, timeoutMs }) {
|
|
136
|
+
const fetch = require('node-fetch');
|
|
137
|
+
const start = Date.now();
|
|
138
|
+
const interval = 2000;
|
|
139
|
+
|
|
140
|
+
while (Date.now() - start < timeoutMs) {
|
|
141
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
142
|
+
try {
|
|
143
|
+
const res = await fetch(
|
|
144
|
+
`${apiUrl}/api/platform/moonid/status?state=${encodeURIComponent(state)}`
|
|
145
|
+
);
|
|
146
|
+
const data = await res.json().catch(() => ({}));
|
|
147
|
+
|
|
148
|
+
// web endpoint returns status: "success"
|
|
149
|
+
if (
|
|
150
|
+
(data.status === 'success' || data.status === 'done') &&
|
|
151
|
+
data.token
|
|
152
|
+
) {
|
|
153
|
+
return data.token;
|
|
174
154
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
155
|
+
if (data.status === 'error' || data.status === 'denied') {
|
|
156
|
+
throw new Error(data.error || 'MoonID login denied');
|
|
157
|
+
}
|
|
158
|
+
} catch (e) {
|
|
159
|
+
if (
|
|
160
|
+
e.message &&
|
|
161
|
+
/denied|failed|not found|mismatch|expired|signup/i.test(e.message)
|
|
162
|
+
) {
|
|
163
|
+
throw e;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
186
168
|
}
|
|
187
169
|
|
|
188
170
|
async function saveAndValidateToken(token, { apiUrl, label }) {
|
|
@@ -190,16 +172,13 @@ async function saveAndValidateToken(token, { apiUrl, label }) {
|
|
|
190
172
|
const res = await fetch(`${apiUrl}/api/hosting/quota`, {
|
|
191
173
|
headers: { Authorization: `Bearer ${token}` },
|
|
192
174
|
});
|
|
193
|
-
|
|
194
175
|
if (res.status === 401) {
|
|
195
176
|
throw new Error('Invalid or expired token');
|
|
196
177
|
}
|
|
197
|
-
|
|
198
178
|
setConfig({ token, apiUrl });
|
|
199
|
-
|
|
200
179
|
console.log('');
|
|
201
180
|
console.log(chalk.green('✓ Logged in'));
|
|
202
|
-
console.log(chalk.gray(`
|
|
181
|
+
console.log(chalk.gray(` Config: ~/.moontraze/config.json`));
|
|
203
182
|
console.log('');
|
|
204
183
|
}
|
|
205
184
|
|