niranzwp 0.8.5 → 0.8.6
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/bin/niranzwp.js +26 -4
- package/lib/auth.js +45 -0
- package/package.json +1 -1
package/bin/niranzwp.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { loginWithAppPassword, loginManual } from '../lib/auth.js';
|
|
2
|
+
import { loginWithAppPassword, loginManual, credentialsFromEnv } from '../lib/auth.js';
|
|
3
3
|
import { saveProfile, saveOAuthProfile, getProfile, listProfiles, deleteProfile, storageKind, configDir } from '../lib/store.js';
|
|
4
4
|
import { discover, registerClient, startDeviceFlow, pollForToken } from '../lib/oauth.js';
|
|
5
5
|
import { CliError } from '../lib/errors.js';
|
|
@@ -257,9 +257,31 @@ async function main() {
|
|
|
257
257
|
// password on its own success page and the user carries it here. The
|
|
258
258
|
// only route that works when the browser cannot reach this machine --
|
|
259
259
|
// SSH, a VPS, a phone browser against a CLI running elsewhere.
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
260
|
+
/*
|
|
261
|
+
* The environment first, and a refusal rather than a hang.
|
|
262
|
+
*
|
|
263
|
+
* Both routes below need a person -- one to approve in a browser, one
|
|
264
|
+
* to type at a prompt -- and neither can tell you that. Given the
|
|
265
|
+
* variables, this skips them entirely; without them, and with no
|
|
266
|
+
* terminal to prompt at, it says so instead of waiting.
|
|
267
|
+
*/
|
|
268
|
+
const fromEnv = credentialsFromEnv();
|
|
269
|
+
let creds;
|
|
270
|
+
|
|
271
|
+
if (fromEnv) {
|
|
272
|
+
const info = await probe(site);
|
|
273
|
+
creds = { siteUrl: site.replace(/\/+$/, ''), ...fromEnv, info };
|
|
274
|
+
} else if (process.stdin.isTTY !== true && flags.manual !== true) {
|
|
275
|
+
throw new CliError(
|
|
276
|
+
'no_terminal',
|
|
277
|
+
'There is no terminal here to approve or type at, and no credentials in the environment.',
|
|
278
|
+
{ hint: 'Set NIRANZWP_USER and NIRANZWP_APP_PASSWORD, or pipe the two answers into --manual.' }
|
|
279
|
+
);
|
|
280
|
+
} else {
|
|
281
|
+
creds = flags.manual === true
|
|
282
|
+
? await loginManual(site, { open: flags.open !== false })
|
|
283
|
+
: await loginWithAppPassword(site, { open: flags.open !== false });
|
|
284
|
+
}
|
|
263
285
|
|
|
264
286
|
// A pasted credential can be mistyped, so prove it works before
|
|
265
287
|
// storing it. The loopback flow's credential came from WordPress
|
package/lib/auth.js
CHANGED
|
@@ -111,6 +111,27 @@ export async function loginWithAppPassword(siteUrl, { appName = 'NiranzWP CLI',
|
|
|
111
111
|
console.error('Approve this connection in your browser:');
|
|
112
112
|
console.error(` ${authorize}`);
|
|
113
113
|
console.error('');
|
|
114
|
+
/*
|
|
115
|
+
* Said before the wait, not after it.
|
|
116
|
+
*
|
|
117
|
+
* The callback is http://127.0.0.1, and WordPress accepts an
|
|
118
|
+
* http:// redirect only when the site's own environment type is
|
|
119
|
+
* "local" -- wp_is_authorize_application_redirect_url_valid()
|
|
120
|
+
* exempts nothing by host, not loopback, not private ranges. On a
|
|
121
|
+
* live site the browser is shown "The URL must be served over a
|
|
122
|
+
* secure connection." and this listener, which cannot see that
|
|
123
|
+
* page, waits out its five minutes in silence.
|
|
124
|
+
*
|
|
125
|
+
* Whether a given site will refuse is not knowable from here --
|
|
126
|
+
* the environment type is not in the REST root, and a public site
|
|
127
|
+
* can still be set to "local", wrongly but effectively. So this
|
|
128
|
+
* does not guess. It says what that error means and what to do
|
|
129
|
+
* about it, where it will be read.
|
|
130
|
+
*/
|
|
131
|
+
console.error('If the browser says "The URL must be served over a secure connection",');
|
|
132
|
+
console.error('this site will not hand the password back here. Stop and run:');
|
|
133
|
+
console.error(` niranzwp auth login ${siteUrl} --manual`);
|
|
134
|
+
console.error('');
|
|
114
135
|
if (open) openBrowser(authorize.toString());
|
|
115
136
|
});
|
|
116
137
|
});
|
|
@@ -156,6 +177,30 @@ export async function loginManual(siteUrl, { appName = 'NiranzWP CLI', open = tr
|
|
|
156
177
|
return { siteUrl: siteUrl.replace(/\/+$/, ''), user: user.trim(), password: password.trim(), info };
|
|
157
178
|
}
|
|
158
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Credentials from the environment, for anything with nobody sitting at it.
|
|
182
|
+
*
|
|
183
|
+
* Every other route here needs a person: a browser to approve in, or a
|
|
184
|
+
* terminal to type into. A script, a CI job or an agent has neither, and used
|
|
185
|
+
* to discover that by waiting five minutes for a callback that was never
|
|
186
|
+
* coming. Two variables connect directly:
|
|
187
|
+
*
|
|
188
|
+
* NIRANZWP_USER=editor NIRANZWP_APP_PASSWORD='abcd efgh ...' \
|
|
189
|
+
* niranzwp auth login https://example.com
|
|
190
|
+
*
|
|
191
|
+
* Deliberately not flags. A password given on the command line is written
|
|
192
|
+
* into shell history and shows up in `ps` to every other user on the machine.
|
|
193
|
+
* An environment variable does neither.
|
|
194
|
+
*
|
|
195
|
+
* @returns {{user: string, password: string} | null}
|
|
196
|
+
*/
|
|
197
|
+
export function credentialsFromEnv() {
|
|
198
|
+
const user = (process.env.NIRANZWP_USER || '').trim();
|
|
199
|
+
const password = (process.env.NIRANZWP_APP_PASSWORD || '').trim();
|
|
200
|
+
|
|
201
|
+
return user && password ? { user, password } : null;
|
|
202
|
+
}
|
|
203
|
+
|
|
159
204
|
/**
|
|
160
205
|
* Both prompts on ONE readline interface.
|
|
161
206
|
*
|