From 81f6a11d89aa105a651a952519c043e988acad35 Mon Sep 17 00:00:00 2001 From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com> Date: Mon, 10 Jan 2022 21:21:08 -0800 Subject: [PATCH] Update to QDN --- qortal-ui-core/src/apiKeyUtils.js | 76 +++++++++++++++++++ qortal-ui-core/src/components/app-info.js | 2 +- .../login-view/create-account-section.js | 7 +- .../components/login-view/login-section.js | 8 +- qortal-ui-core/src/plugins/routes.js | 18 ++++- 5 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 qortal-ui-core/src/apiKeyUtils.js diff --git a/qortal-ui-core/src/apiKeyUtils.js b/qortal-ui-core/src/apiKeyUtils.js new file mode 100644 index 00000000..9d2078f1 --- /dev/null +++ b/qortal-ui-core/src/apiKeyUtils.js @@ -0,0 +1,76 @@ +import * as api from 'qortal-ui-crypto' + +'use strict' + +export const checkApiKey = async (nodeConfig) => { + + let selectedNode = nodeConfig.knownNodes[nodeConfig.node]; + if (selectedNode.enableManagement === false) { + console.log("Skipping API key check because enableManagement is false"); + return; + } + + let apiKey = selectedNode.apiKey; + + // Attempt to generate an API key + const generateUrl = "/admin/apikey/generate"; + let generateRes = await api.request(generateUrl, { + method: "POST" + }); + + if (generateRes != null && generateRes.error == null && generateRes.length >= 8) { + console.log("Generated API key"); + apiKey = generateRes; + } + else { + console.log("Unable to generate API key"); + } + + // Now test the API key + let testResult = await testApiKey(apiKey); + if (testResult === true) { + console.log("API key test passed"); + } + else { + console.log("API key test failed"); + + let apiKeyValid = false; + + while (apiKeyValid === false) { + + let apiKeyPrompt = prompt("Please enter the API key for this node.\n\nIt can be found in a file called 'apikey.txt' in the directory where the core is installed.\n\nAlternatively, click Cancel to use the core with reduced functionality.", ""); + if (apiKeyPrompt === null) { + // Cancel was pushed - so give up + return; + } + + let testResult = await testApiKey(apiKeyPrompt); + if (testResult === true) { + console.log("API key prompt test passed"); + apiKeyValid = true; + apiKey = apiKeyPrompt; + break; + } + else { + console.log("API key prompt test failed. Re-prompting..."); + } + + } + } + + // Store API key + selectedNode.apiKey = apiKey; + nodeConfig.knownNodes[nodeConfig.node] = selectedNode; + localStorage.setItem('myQortalNodes', JSON.stringify(nodeConfig.knownNodes)); +} + +export const testApiKey = async (apiKey) => { + const testUrl = "/admin/apikey/test?apiKey=" + apiKey; + let testRes = await api.request(testUrl, { + method: "GET" + }); + if (testRes === true) { + return true; + } + return false; +} diff --git a/qortal-ui-core/src/components/app-info.js b/qortal-ui-core/src/components/app-info.js index 83981f94..a5905a0e 100644 --- a/qortal-ui-core/src/components/app-info.js +++ b/qortal-ui-core/src/components/app-info.js @@ -97,7 +97,7 @@ class AppInfo extends connect(store)(LitElement) { return html`
Block Height: ${this.blockInfo.height ? this.blockInfo.height : ''} ${this._renderStatus()} - UI Version: v${this.nodeConfig.version ? this.nodeConfig.version : ''} + UI Version: ${this.nodeConfig.version ? this.nodeConfig.version : ''} Core Version: ${this.nodeInfo.buildVersion ? this.nodeInfo.buildVersion : ''}
diff --git a/qortal-ui-core/src/components/login-view/create-account-section.js b/qortal-ui-core/src/components/login-view/create-account-section.js index 546162c7..051bccc7 100644 --- a/qortal-ui-core/src/components/login-view/create-account-section.js +++ b/qortal-ui-core/src/components/login-view/create-account-section.js @@ -10,6 +10,7 @@ import FileSaver from 'file-saver' import { doLogin, doLogout, doSelectAddress } from '../../redux/app/app-actions.js' import { doStoreWallet } from '../../redux/user/user-actions.js' +import { checkApiKey } from '../../apiKeyUtils.js' import snackbar from '../../functional-components/snackbar.js' @@ -48,7 +49,8 @@ class CreateAccountSection extends connect(store)(LitElement) { _wallet: { type: Object }, _pass: { type: String }, _name: { type: String }, - isDownloadedBackup: { type: Boolean } + isDownloadedBackup: { type: Boolean }, + nodeConfig: { type: Object } } } @@ -181,6 +183,7 @@ class CreateAccountSection extends connect(store)(LitElement) { .then(() => { store.dispatch(doLogin(this._wallet)) store.dispatch(doSelectAddress(this._wallet.addresses[0])) + checkApiKey(this.nodeConfig); this.cleanup() return ripple.fade() }) @@ -191,6 +194,7 @@ class CreateAccountSection extends connect(store)(LitElement) { } else { store.dispatch(doLogin(this._wallet)) store.dispatch(doSelectAddress(this._wallet.addresses[0])) + checkApiKey() this.cleanup() } } @@ -490,6 +494,7 @@ class CreateAccountSection extends connect(store)(LitElement) { } stateChanged(state) { + this.nodeConfig = state.app.nodeConfig // this.loggedIn = state.app.loggedIn } diff --git a/qortal-ui-core/src/components/login-view/login-section.js b/qortal-ui-core/src/components/login-view/login-section.js index b1cc3deb..d96e3785 100644 --- a/qortal-ui-core/src/components/login-view/login-section.js +++ b/qortal-ui-core/src/components/login-view/login-section.js @@ -1,6 +1,7 @@ import { LitElement, html, css } from 'lit-element' import { connect } from 'pwa-helpers' import { store } from '../../store.js' +import { checkApiKey } from '../../apiKeyUtils.js' import '@material/mwc-button' import '@material/mwc-checkbox' @@ -45,7 +46,8 @@ class LoginSection extends connect(store)(LitElement) { hasStoredWallets: { type: Boolean }, saveInBrowser: { type: Boolean }, backedUpWalletJSON: { type: Object }, - backedUpSeedLoading: { type: Boolean } + backedUpSeedLoading: { type: Boolean }, + nodeConfig: { type: Object } } } @@ -280,7 +282,7 @@ class LoginSection extends connect(store)(LitElement) {
- +
@@ -375,6 +377,7 @@ class LoginSection extends connect(store)(LitElement) { this.loggedIn = state.app.loggedIn this.wallets = state.user.storedWallets this.hasStoredWallets = this.wallets.length > 0 + this.nodeConfig = state.app.nodeConfig } keyupEnter(e, action) { @@ -535,6 +538,7 @@ class LoginSection extends connect(store)(LitElement) { })).catch(err => console.error(err)) } } + checkApiKey(this.nodeConfig) this.cleanup() return this.loadingRipple.fade() }) diff --git a/qortal-ui-core/src/plugins/routes.js b/qortal-ui-core/src/plugins/routes.js index f47f1da0..37e68f98 100644 --- a/qortal-ui-core/src/plugins/routes.js +++ b/qortal-ui-core/src/plugins/routes.js @@ -11,6 +11,7 @@ import framePasteMenu from '../functional-components/frame-paste-menu.js' const createTransaction = api.createTransaction const processTransaction = api.processTransaction const signChatTransaction = api.signChatTransaction +const signArbitraryTransaction = api.signArbitraryTransaction const tradeBotCreateRequest = api.tradeBotCreateRequest const tradeBotRespondRequest = api.tradeBotRespondRequest const signTradeBotTxn = api.signTradeBotTxn @@ -169,7 +170,7 @@ export const routes = { } return response }, - + username: async (req) => { const state = store.getState() const username = state.user.storedWallets[state.app.wallet.addresses[0].address].name @@ -206,6 +207,21 @@ export const routes = { return response }, + sign_arbitrary: async (req) => { + let response + try { + const signedArbitraryBytes = await signArbitraryTransaction(req.data.arbitraryBytesBase58, req.data.arbitraryBytesForSigningBase58, req.data.arbitraryNonce, store.getState().app.wallet._addresses[req.data.nonce].keyPair) + + const res = await processTransaction(signedArbitraryBytes) + response = res + } catch (e) { + console.error(e) + console.error(e.message) + response = false + } + return response + }, + showNotification: async (req) => { doNewMessage(req.data) },