Skip to content
This repository has been archived by the owner on Oct 4, 2024. It is now read-only.

Commit

Permalink
Fix login prompt when web server redirect doesn’t work (#299)
Browse files Browse the repository at this point in the history
* Fix login prompt when web server redirect doesn’t work

* Lint fixes
  • Loading branch information
vgrichina authored Apr 1, 2020
1 parent 8ea0aae commit fe1d3f1
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 32 deletions.
73 changes: 44 additions & 29 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,61 +57,76 @@ exports.login = async function(options) {
newUrl.searchParams.set('public_key', keyPair.getPublicKey());

console.log(chalk`\n{bold.yellow Please authorize NEAR Shell} on at least one of your accounts.`);
console.log(chalk`\n{dim If your browser doesn't automatically open, please visit this URL\n${newUrl.toString()}}`);

// attempt to capture accountId automatically via browser callback
let tempUrl;
let accountId;

// find a callback URL on the local machine
try {
tempUrl = await capture.callback();
} catch (error) {
// console.error("Failed to find suitable port.", error.message)
// TODO: Is it? Try triggering error
// silent error is better here
}

// if we found a suitable URL, attempt to use it
if(tempUrl){
if (tempUrl) {
// open a browser to capture NEAR Wallet callback (and quietly direct the user if open fails)
try {
newUrl.searchParams.set('success_url', `http://${tempUrl.hostname}:${tempUrl.port}`);
await open(newUrl.toString());
} catch (error) {
console.error(`Failed to open the URL [ ${newUrl.toString()} ]`, error);
}
}

console.log(chalk`\n{dim If your browser doesn't automatically open, please visit this URL\n${newUrl.toString()}}`);

const getAccountFromWebpage = async () => {
// capture account_id as provided by NEAR Wallet
try {
[accountId] = await capture.payload(['account_id'], tempUrl);
} catch (error) {
console.error('Failed to capture payload.', error.message);
}
}
const [accountId] = await capture.payload(['account_id'], tempUrl);
return accountId;
};

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});

const getAccountFromConsole = async () => {
return await new Promise((resolve) => {
rl.question(
chalk`Please authorize at least one account at the URL above.\n\n` +
chalk`Which account did you authorize for use with NEAR Shell?\n` +
chalk`{bold Enter it here (if not redirected automatically):}\n`, async (accountId) => {
resolve(accountId);
});
});
};

// verify the accountId if we captured it or ...
if(accountId) {
try {
await verify(accountId, keyPair, options);
} catch(error) {
console.error('Failed to verify accountId.', error.message);
}
// prompt user to enter it at the terminal if we didn't
let accountId;
if (!tempUrl) {
accountId = await getAccountFromConsole();
} else {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
accountId = await new Promise((resolve, reject) => {
let resolved = false;
const resolveOnce = (result) => { if (!resolved) resolve(result); resolved = true; };
getAccountFromWebpage()
.then(resolveOnce); // NOTE: error ignored on purpose
getAccountFromConsole()
.then(resolveOnce)
.catch(reject);
});
}
rl.close();
capture.cancel();

rl.question(chalk`Please authorize at least one account at the URL above.\n\nWhich account did you authorize for use with NEAR Shell? {bold Enter it here:} `, async (accountId) => {
try {
await verify(accountId, keyPair, options);
} catch (error) {
console.error(error);
} finally {
rl.close();
}
});
// verify the accountId if we captured it or ...
try {
await verify(accountId, keyPair, options);
} catch (error) {
console.error('Failed to verify accountId.', error.message);
}
}
};
Expand Down
12 changes: 9 additions & 3 deletions utils/capture-login-success.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const http = require('http');
const url = require('url');
const stoppable = require('stoppable'); // graceful, effective server shutdown
var tcpPortUsed = require('tcp-port-used'); // avoid port collisions
const tcpPortUsed = require('tcp-port-used'); // avoid port collisions

let server;

/**
extract arbitrary collection of fields from temporary HTTP server
Expand All @@ -14,7 +16,7 @@ var tcpPortUsed = require('tcp-port-used'); // avoid port collisions
const payload = (fields, { port, hostname }) => new Promise((resolve, reject) => {

const message = renderWebPage('You are logged in. Please close this window.');
const server = stoppable(http.createServer(handler)).listen(port, hostname);
server = stoppable(http.createServer(handler)).listen(port, hostname);

/**
request handler for single-use node server
Expand Down Expand Up @@ -69,7 +71,11 @@ const callback = async (port = 3000, hostname = '127.0.0.1', range = 10) => {
return { port, hostname };
};

module.exports = { payload, callback };
const cancel = () => {
if (server) server.stop();
};

module.exports = { payload, callback, cancel };


/**
Expand Down

0 comments on commit fe1d3f1

Please sign in to comment.