From 59481245864f33fefe3c7f7422cdd450889f019d Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 18:09:06 -0800 Subject: [PATCH 1/6] Added recaptcha compatibility --- src/main/index.js | 418 ++++++++++-------- .../component/userEmailVerify/index.js | 9 +- .../component/userEmailVerify/view.jsx | 7 +- src/renderer/index.js | 28 +- src/renderer/redux/actions/app.js | 13 +- src/renderer/redux/actions/user.js | 41 +- 6 files changed, 313 insertions(+), 203 deletions(-) diff --git a/src/main/index.js b/src/main/index.js index e43a71d7f..0c8e114d6 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,52 +1,62 @@ // Module imports -const {app, BrowserWindow, ipcMain, Menu, Tray, globalShortcut} = require('electron'); -const path = require('path'); -const url = require('url'); -const jayson = require('jayson'); -const semver = require('semver'); -const https = require('https'); -const keytar = require('keytar'); +const { + app, + BrowserWindow, + ipcMain, + Menu, + Tray, + globalShortcut, +} = require("electron"); +const path = require("path"); +const url = require("url"); +const jayson = require("jayson"); +const semver = require("semver"); +const https = require("https"); +const keytar = require("keytar"); // tree-kill has better cross-platform handling of // killing a process. child-process.kill was unreliable -const kill = require('tree-kill'); -const child_process = require('child_process'); -const assert = require('assert'); +const kill = require("tree-kill"); +const child_process = require("child_process"); +const assert = require("assert"); const localVersion = app.getVersion(); -const setMenu = require('./menu/main-menu.js'); -export const contextMenu = require('./menu/context-menu'); +const setMenu = require("./menu/main-menu.js"); +export const contextMenu = require("./menu/context-menu"); // Debug configs -const isDevelopment = process.env.NODE_ENV === 'development'; +const isDevelopment = process.env.NODE_ENV === "development"; if (isDevelopment) { - try - { - const { default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS } = require('electron-devtools-installer'); - app.on('ready', () => { + try { + const { + default: installExtension, + REACT_DEVELOPER_TOOLS, + REDUX_DEVTOOLS, + } = require("electron-devtools-installer"); + app.on("ready", () => { [REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach(extension => { installExtension(extension) - .then((name) => console.log(`Added Extension: ${name}`)) - .catch((err) => console.log('An error occurred: ', err)); + .then(name => console.log(`Added Extension: ${name}`)) + .catch(err => console.log("An error occurred: ", err)); }); }); - } - catch (err) - { - console.error(err) + } catch (err) { + console.error(err); } } // Misc constants -const LATEST_RELEASE_API_URL = 'https://api.github.com/repos/lbryio/lbry-app/releases/latest'; -const DAEMON_PATH = process.env.LBRY_DAEMON || path.join(__static, 'daemon/lbrynet-daemon'); +const LATEST_RELEASE_API_URL = + "https://api.github.com/repos/lbryio/lbry-app/releases/latest"; +const DAEMON_PATH = + process.env.LBRY_DAEMON || path.join(__static, "daemon/lbrynet-daemon"); const rendererUrl = isDevelopment ? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` : `file://${__dirname}/index.html`; let client = jayson.client.http({ - host: 'localhost', + host: "localhost", port: 5279, - path: '/', - timeout: 1000 + path: "/", + timeout: 1000, }); // Keep a global reference of the window object, if you don't, the window will @@ -84,8 +94,8 @@ function processRequestedUri(uri) { // lbry://channel/#claimid. We remove the slash here as well. // On Linux and Mac, we just return the URI as given. - if (process.platform === 'win32') { - return uri.replace(/\/$/, '').replace('/#', '#'); + if (process.platform === "win32") { + return uri.replace(/\/$/, "").replace("/#", "#"); } else { return uri; } @@ -97,69 +107,87 @@ function processRequestedUri(uri) { * when no windows are open. */ function openItem(fullPath) { - const subprocOptions = { - detached: true, - stdio: 'ignore', - }; + const subprocOptions = { + detached: true, + stdio: "ignore", + }; - let child; - if (process.platform === 'darwin') { - child = child_process.spawn('open', [fullPath], subprocOptions); - } else if (process.platform === 'linux') { - child = child_process.spawn('xdg-open', [fullPath], subprocOptions); - } else if (process.platform === 'win32') { - child = child_process.spawn(fullPath, Object.assign({}, subprocOptions, {shell: true})); - } + let child; + if (process.platform === "darwin") { + child = child_process.spawn("open", [fullPath], subprocOptions); + } else if (process.platform === "linux") { + child = child_process.spawn("xdg-open", [fullPath], subprocOptions); + } else if (process.platform === "win32") { + child = child_process.spawn( + fullPath, + Object.assign({}, subprocOptions, { shell: true }) + ); + } - // Causes child process reference to be garbage collected, allowing main process to exit - child.unref(); + // Causes child process reference to be garbage collected, allowing main process to exit + child.unref(); } function getPidsForProcessName(name) { - if (process.platform === 'win32') { - const tasklistOut = child_process.execSync(`tasklist /fi "Imagename eq ${name}.exe" /nh`, {encoding: 'utf8'}); - if (tasklistOut.startsWith('INFO')) { + if (process.platform === "win32") { + const tasklistOut = child_process.execSync( + `tasklist /fi "Imagename eq ${name}.exe" /nh`, + { encoding: "utf8" } + ); + if (tasklistOut.startsWith("INFO")) { return []; } else { - return tasklistOut.match(/[^\r\n]+/g).map((line) => line.split(/\s+/)[1]); // Second column of every non-empty line + return tasklistOut.match(/[^\r\n]+/g).map(line => line.split(/\s+/)[1]); // Second column of every non-empty line } } else { - const pgrepOut = child_process.spawnSync('pgrep', ['-x', name], {encoding: 'utf8'}).stdout; + const pgrepOut = child_process.spawnSync("pgrep", ["-x", name], { + encoding: "utf8", + }).stdout; return pgrepOut.match(/\d+/g); } } -function createWindow () { +function createWindow() { // Disable renderer process's webSecurity on development to enable CORS. win = isDevelopment - ? new BrowserWindow({backgroundColor: '#155B4A', minWidth: 800, minHeight: 600, webPreferences: {webSecurity: false}}) - : new BrowserWindow({backgroundColor: '#155B4A', minWidth: 800, minHeight: 600}); + ? new BrowserWindow({ + backgroundColor: "#155B4A", + minWidth: 800, + minHeight: 600, + webPreferences: { webSecurity: false }, + }) + : new BrowserWindow({ + backgroundColor: "#155B4A", + minWidth: 800, + minHeight: 600, + }); win.webContents.session.setUserAgent(`LBRY/${localVersion}`); - win.maximize() + win.maximize(); if (isDevelopment) { win.webContents.openDevTools(); } - win.loadURL(rendererUrl) - if (openUri) { // We stored and received a URI that an external app requested before we had a window object - win.webContents.on('did-finish-load', () => { - win.webContents.send('open-uri-requested', openUri); + win.loadURL(rendererUrl); + if (openUri) { + // We stored and received a URI that an external app requested before we had a window object + win.webContents.on("did-finish-load", () => { + win.webContents.send("open-uri-requested", openUri, true); }); } win.removeAllListeners(); - win.on('close', function(event) { + win.on("close", function(event) { if (minimize) { event.preventDefault(); win.hide(); } - }) + }); - win.on('closed', () => { - win = null - }) + win.on("closed", () => { + win = null; + }); win.on("hide", () => { // Checks what to show in the tray icon menu @@ -176,7 +204,7 @@ function createWindow () { if (minimize) updateTray(); // Unregisters Alt+F4 shortcut - globalShortcut.unregister('Alt+F4'); + globalShortcut.unregister("Alt+F4"); }); win.on("focus", () => { @@ -184,23 +212,22 @@ function createWindow () { if (minimize) updateTray(); // Registers shortcut for closing(quitting) the app - globalShortcut.register('Alt+F4', () => safeQuit()); + globalShortcut.register("Alt+F4", () => safeQuit()); - win.webContents.send('window-is-focused', null); + win.webContents.send("window-is-focused", null); }); // Menu bar win.setAutoHideMenuBar(true); win.setMenuBarVisibility(isDevelopment); setMenu(); +} -}; - -function createTray () { +function createTray() { // Minimize to tray logic follows: // Set the tray icon let iconPath; - if (process.platform === 'darwin') { + if (process.platform === "darwin") { // Using @2x for mac retina screens so the icon isn't blurry // file name needs to include "Template" at the end for dark menu bar iconPath = path.join(__static, "/img/fav/macTemplate@2x.png"); @@ -211,9 +238,9 @@ function createTray () { tray = new Tray(iconPath); tray.setToolTip("LBRY App"); tray.setTitle("LBRY"); - tray.on('double-click', () => { - win.show() - }) + tray.on("double-click", () => { + win.show(); + }); } // This needs to be done as for linux the context menu doesn't update automatically(docs) @@ -226,27 +253,26 @@ function updateTray() { } } -function getMenuTemplate () { +function getMenuTemplate() { return [ getToggleItem(), { label: "Quit", click: () => safeQuit(), }, - ] + ]; - function getToggleItem () { + function getToggleItem() { if (win.isVisible() && win.isFocused()) { return { - label: 'Hide LBRY App', - click: () => win.hide() - - } + label: "Hide LBRY App", + click: () => win.hide(), + }; } else { return { - label: 'Show LBRY App', - click: () => win.show() - } + label: "Show LBRY App", + click: () => win.show(), + }; } } } @@ -256,20 +282,19 @@ function handleOpenUriRequested(uri) { // Window not created yet, so store up requested URI for when it is openUri = processRequestedUri(uri); } else { - if (win.isMinimized()) { - win.restore() + win.restore(); } else if (!win.isVisible()) { - win.show() + win.show(); } win.focus(); - win.webContents.send('open-uri-requested', processRequestedUri(uri)); + win.webContents.send("open-uri-requested", processRequestedUri(uri)); } } function handleDaemonSubprocessExited() { - console.log('The daemon has exited.'); + console.log("The daemon has exited."); daemonSubprocess = null; if (!daemonStopRequested) { // We didn't request to stop the daemon, so display a @@ -277,27 +302,31 @@ function handleDaemonSubprocessExited() { // // TODO: maybe it would be better to restart the daemon? if (win) { - console.log('Did not request daemon stop, so quitting in 5 seconds.'); + console.log("Did not request daemon stop, so quitting in 5 seconds."); win.loadURL(`file://${__static}/warning.html`); setTimeout(quitNow, 5000); } else { - console.log('Did not request daemon stop, so quitting.'); + console.log("Did not request daemon stop, so quitting."); quitNow(); } } } function launchDaemon() { - assert(!daemonSubprocess, 'Tried to launch daemon twice'); + assert(!daemonSubprocess, "Tried to launch daemon twice"); - console.log('Launching daemon:', DAEMON_PATH) - daemonSubprocess = child_process.spawn(DAEMON_PATH) + console.log("Launching daemon:", DAEMON_PATH); + daemonSubprocess = child_process.spawn(DAEMON_PATH); // Need to handle the data event instead of attaching to // process.stdout because the latter doesn't work. I believe on // windows it buffers stdout and we don't get any meaningful output - daemonSubprocess.stdout.on('data', (buf) => {console.log(String(buf).trim());}); - daemonSubprocess.stderr.on('data', (buf) => {console.log(String(buf).trim());}); - daemonSubprocess.on('exit', handleDaemonSubprocessExited); + daemonSubprocess.stdout.on("data", buf => { + console.log(String(buf).trim()); + }); + daemonSubprocess.stderr.on("data", buf => { + console.log(String(buf).trim()); + }); + daemonSubprocess.on("exit", handleDaemonSubprocessExited); } /* @@ -318,7 +347,7 @@ function quitNow() { safeQuit(); } -const isSecondaryInstance = app.makeSingleInstance((argv) => { +const isSecondaryInstance = app.makeSingleInstance(argv => { if (argv.length >= 2) { handleOpenUriRequested(argv[1]); // This will handle restoring and focusing the window } else if (win) { @@ -331,25 +360,23 @@ const isSecondaryInstance = app.makeSingleInstance((argv) => { } }); -if (isSecondaryInstance) { // We're not in the original process, so quit +if (isSecondaryInstance) { + // We're not in the original process, so quit quitNow(); } function launchDaemonIfNotRunning() { // Check if the daemon is already running. If we get // an error its because its not running - console.log('Checking for lbrynet daemon'); - client.request( - 'status', [], - function (err, res) { - if (err) { - console.log('lbrynet daemon needs to be launched') - launchDaemon(); - } else { - console.log('lbrynet daemon is already running') - } + console.log("Checking for lbrynet daemon"); + client.request("status", [], function(err, res) { + if (err) { + console.log("lbrynet daemon needs to be launched"); + launchDaemon(); + } else { + console.log("lbrynet daemon is already running"); } - ); + }); } /* @@ -358,21 +385,31 @@ function launchDaemonIfNotRunning() { * tries to force kill them. */ function forceKillAllDaemonsAndQuit() { - console.log('Attempting to force kill any running lbrynet-daemon instances...'); + console.log( + "Attempting to force kill any running lbrynet-daemon instances..." + ); - const daemonPids = getPidsForProcessName('lbrynet-daemon'); + const daemonPids = getPidsForProcessName("lbrynet-daemon"); if (!daemonPids) { - console.log('No lbrynet-daemon found running.'); + console.log("No lbrynet-daemon found running."); quitNow(); } else { - console.log(`Found ${daemonPids.length} running daemon instances. Attempting to force kill...`); + console.log( + `Found ${ + daemonPids.length + } running daemon instances. Attempting to force kill...` + ); for (const pid of daemonPids) { let daemonKillAttemptsComplete = 0; - kill(pid, 'SIGKILL', (err) => { + kill(pid, "SIGKILL", err => { daemonKillAttemptsComplete++; if (err) { - console.log(`Failed to force kill daemon task with pid ${pid}. Error message: ${err.message}`); + console.log( + `Failed to force kill daemon task with pid ${pid}. Error message: ${ + err.message + }` + ); } else { console.log(`Force killed daemon task with pid ${pid}.`); } @@ -384,15 +421,15 @@ function forceKillAllDaemonsAndQuit() { } } -app.setAsDefaultProtocolClient('lbry'); +app.setAsDefaultProtocolClient("lbry"); -app.on('ready', function() { +app.on("ready", function() { launchDaemonIfNotRunning(); if (process.platform === "linux") { - checkLinuxTraySupport( err => { + checkLinuxTraySupport(err => { if (!err) createTray(); else minimize = false; - }) + }); } else { createTray(); } @@ -400,36 +437,35 @@ app.on('ready', function() { }); // Quit when all windows are closed. -app.on('window-all-closed', () => { +app.on("window-all-closed", () => { // On macOS it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== 'darwin') { - app.quit() + if (process.platform !== "darwin") { + app.quit(); } -}) +}); - -app.on('before-quit', (event) => { +app.on("before-quit", event => { if (!readyToQuit) { // We need to shutdown the daemon before we're ready to actually quit. This // event will be triggered re-entrantly once preparation is done. event.preventDefault(); shutdownDaemonAndQuit(); } else { - console.log('Quitting.') + console.log("Quitting."); } }); -app.on('activate', () => { +app.on("activate", () => { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (win === null) { - createWindow() + createWindow(); } }); -if (process.platform === 'darwin') { - app.on('open-url', (event, uri) => { +if (process.platform === "darwin") { + app.on("open-url", (event, uri) => { handleOpenUriRequested(uri); }); } else if (process.argv.length >= 2) { @@ -440,14 +476,18 @@ if (process.platform === 'darwin') { // then calls quitNow() to quit for real. function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { function doShutdown() { - console.log('Shutting down daemon'); + console.log("Shutting down daemon"); daemonStopRequested = true; - client.request('daemon_stop', [], (err, res) => { + client.request("daemon_stop", [], (err, res) => { if (err) { - console.log(`received error when stopping lbrynet-daemon. Error message: ${err.message}\n`); - console.log('You will need to manually kill the daemon.'); + console.log( + `received error when stopping lbrynet-daemon. Error message: ${ + err.message + }\n` + ); + console.log("You will need to manually kill the daemon."); } else { - console.log('Successfully stopped daemon via RPC call.') + console.log("Successfully stopped daemon via RPC call."); quitNow(); } }); @@ -456,7 +496,7 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { if (daemonSubprocess) { doShutdown(); } else if (!evenIfNotStartedByApp) { - console.log('Not killing lbrynet-daemon because app did not start it'); + console.log("Not killing lbrynet-daemon because app did not start it"); quitNow(); } else { doShutdown(); @@ -467,24 +507,27 @@ function shutdownDaemonAndQuit(evenIfNotStartedByApp = false) { } // Taken from webtorrent-desktop -function checkLinuxTraySupport (cb) { +function checkLinuxTraySupport(cb) { // Check that we're on Ubuntu (or another debian system) and that we have // libappindicator1. - child_process.exec('dpkg --get-selections libappindicator1', function (err, stdout) { - if (err) return cb(err) + child_process.exec("dpkg --get-selections libappindicator1", function( + err, + stdout + ) { + if (err) return cb(err); // Unfortunately there's no cleaner way, as far as I can tell, to check // whether a debian package is installed: - if (stdout.endsWith('\tinstall\n')) { - cb(null) + if (stdout.endsWith("\tinstall\n")) { + cb(null); } else { - cb(new Error('debian package not installed')) + cb(new Error("debian package not installed")); } - }) + }); } -ipcMain.on('upgrade', (event, installerPath) => { - app.on('quit', () => { - console.log('Launching upgrade installer at', installerPath); +ipcMain.on("upgrade", (event, installerPath) => { + app.on("quit", () => { + console.log("Launching upgrade installer at", installerPath); // This gets triggered called after *all* other quit-related events, so // we'll only get here if we're fully prepared and quitting for real. openItem(installerPath); @@ -497,58 +540,77 @@ ipcMain.on('upgrade', (event, installerPath) => { shutdownDaemonAndQuit(true); // wait for daemon to shut down before upgrading // what to do if no shutdown in a long time? - console.log('Update downloaded to', installerPath); - console.log('The app will close, and you will be prompted to install the latest version of LBRY.'); - console.log('After the install is complete, please reopen the app.'); + console.log("Update downloaded to", installerPath); + console.log( + "The app will close, and you will be prompted to install the latest version of LBRY." + ); + console.log("After the install is complete, please reopen the app."); }); -ipcMain.on('version-info-requested', () => { +ipcMain.on("version-info-requested", () => { function formatRc(ver) { // Adds dash if needed to make RC suffix semver friendly - return ver.replace(/([^-])rc/, '$1-rc'); + return ver.replace(/([^-])rc/, "$1-rc"); } - let result = ''; + let result = ""; const opts = { headers: { - 'User-Agent': `LBRY/${localVersion}`, - } + "User-Agent": `LBRY/${localVersion}`, + }, }; - const req = https.get(Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)), (res) => { - res.on('data', (data) => { - result += data; - }); - res.on('end', () => { - const tagName = JSON.parse(result).tag_name; - const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/); - if (!remoteVersion) { - if (win) { - win.webContents.send('version-info-received', null); + const req = https.get( + Object.assign(opts, url.parse(LATEST_RELEASE_API_URL)), + res => { + res.on("data", data => { + result += data; + }); + res.on("end", () => { + const tagName = JSON.parse(result).tag_name; + const [_, remoteVersion] = tagName.match(/^v([\d.]+(?:-?rc\d+)?)$/); + if (!remoteVersion) { + if (win) { + win.webContents.send("version-info-received", null); + } + } else { + const upgradeAvailable = semver.gt( + formatRc(remoteVersion), + formatRc(localVersion) + ); + if (win) { + win.webContents.send("version-info-received", { + remoteVersion, + localVersion, + upgradeAvailable, + }); + } } - } else { - const upgradeAvailable = semver.gt(formatRc(remoteVersion), formatRc(localVersion)); - if (win) { - win.webContents.send('version-info-received', {remoteVersion, localVersion, upgradeAvailable}); - } - } - }) - }); + }); + } + ); - req.on('error', (err) => { - console.log('Failed to get current version from GitHub. Error:', err); + req.on("error", err => { + console.log("Failed to get current version from GitHub. Error:", err); if (win) { - win.webContents.send('version-info-received', null); + win.webContents.send("version-info-received", null); } }); }); -ipcMain.on('get-auth-token', (event) => { +ipcMain.on("get-auth-token", event => { keytar.getPassword("LBRY", "auth_token").then(token => { - event.sender.send('auth-token-response', token ? token.toString().trim() : null) + event.sender.send( + "auth-token-response", + token ? token.toString().trim() : null + ); }); }); -ipcMain.on('set-auth-token', (event, token) => { - keytar.setPassword("LBRY", "auth_token", token ? token.toString().trim() : null); +ipcMain.on("set-auth-token", (event, token) => { + keytar.setPassword( + "LBRY", + "auth_token", + token ? token.toString().trim() : null + ); }); diff --git a/src/renderer/component/userEmailVerify/index.js b/src/renderer/component/userEmailVerify/index.js index e0fa0902b..872471e23 100644 --- a/src/renderer/component/userEmailVerify/index.js +++ b/src/renderer/component/userEmailVerify/index.js @@ -1,6 +1,9 @@ import React from "react"; import { connect } from "react-redux"; -import { doUserEmailVerify } from "redux/actions/user"; +import { + doUserEmailVerify, + doUserEmailVerifyFailure, +} from "redux/actions/user"; import { selectEmailVerifyIsPending, selectEmailToVerify, @@ -20,7 +23,9 @@ const select = state => ({ }); const perform = dispatch => ({ - verifyUserEmail: code => dispatch(doUserEmailVerify(code)), + verifyUserEmail: (code, recaptcha) => + dispatch(doUserEmailVerify(code, recaptcha)), + verifyUserEmailFailure: error => dispatch(doUserEmailVerifyFailure(error)), }); export default connect(select, perform)(UserEmailVerify); diff --git a/src/renderer/component/userEmailVerify/view.jsx b/src/renderer/component/userEmailVerify/view.jsx index 2e330acbe..146045904 100644 --- a/src/renderer/component/userEmailVerify/view.jsx +++ b/src/renderer/component/userEmailVerify/view.jsx @@ -20,7 +20,12 @@ class UserEmailVerify extends React.PureComponent { handleSubmit() { const { code } = this.state; - this.props.verifyUserEmail(code); + try { + let verification = JSON.parse(atob(code)); + this.props.verifyUserEmail(verification.token, verification.recaptcha); + } catch (error) { + this.props.verifyUserEmailFailure("Invalid Verification Token"); + } } render() { diff --git a/src/renderer/index.js b/src/renderer/index.js index e3ed7836b..a79cc9a81 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -5,8 +5,13 @@ import SnackBar from "component/snackBar"; import { Provider } from "react-redux"; import store from "store.js"; import SplashScreen from "component/splash"; -import { doDaemonReady } from "redux/actions/app"; +import { + doDaemonReady, + doShowSnackBar, + doConditionalAuthNavigate, +} from "redux/actions/app"; import { doNavigate } from "redux/actions/navigation"; +import { doUserEmailVerify } from "redux/actions/user"; import { doDownloadLanguages } from "redux/actions/settings"; import * as types from "constants/action_types"; import amplitude from "amplitude-js"; @@ -37,9 +42,26 @@ window.addEventListener("contextmenu", event => { event.preventDefault(); }); -ipcRenderer.on("open-uri-requested", (event, uri) => { +ipcRenderer.on("open-uri-requested", (event, uri, newSession) => { if (uri && uri.startsWith("lbry://")) { - app.store.dispatch(doNavigate("/show", { uri })); + if (uri.startsWith("lbry://?verify=")) { + let verification = {}; + try { + verification = JSON.parse(atob(uri.substring(15))); + } catch (error) {} + if (verification.token && verification.recaptcha) { + app.store.dispatch(doConditionalAuthNavigate(newSession)); + app.store.dispatch( + doUserEmailVerify(verification.token, verification.recaptcha) + ); + } else { + app.store.dispatch( + doShowSnackBar({ message: "Invalid Verification URI" }) + ); + } + } else { + app.store.dispatch(doNavigate("/show", { uri })); + } } }); diff --git a/src/renderer/redux/actions/app.js b/src/renderer/redux/actions/app.js index bf82fb269..7bcb43473 100644 --- a/src/renderer/redux/actions/app.js +++ b/src/renderer/redux/actions/app.js @@ -7,6 +7,7 @@ import { selectUpgradeFilename, selectIsUpgradeSkipped, selectRemoteVersion, + selectCurrentModal, } from "redux/selectors/app"; import { doFetchDaemonSettings } from "redux/actions/settings"; import { doBalanceSubscribe } from "redux/actions/wallet"; @@ -14,8 +15,7 @@ import { doAuthenticate } from "redux/actions/user"; import { doFetchFileInfosAndPublishedClaims } from "redux/actions/file_info"; import * as modals from "constants/modal_types"; import { doFetchRewardedContent } from "redux/actions/content"; -import { selectCurrentModal } from "redux/selectors/app"; - +import { doAuthNavigate } from "redux/actions/navigation"; const { remote, ipcRenderer, shell } = require("electron"); const path = require("path"); const { download } = remote.require("electron-dl"); @@ -266,3 +266,12 @@ export function doChangeVolume(volume) { }); }; } + +export function doConditionalAuthNavigate(newSession) { + return function(dispatch, getState) { + const state = getState(); + if (newSession || selectCurrentModal(state) !== "email_collection") { + dispatch(doAuthNavigate()); + } + }; +} diff --git a/src/renderer/redux/actions/user.js b/src/renderer/redux/actions/user.js index 7111369e8..3796db0d1 100644 --- a/src/renderer/redux/actions/user.js +++ b/src/renderer/redux/actions/user.js @@ -68,14 +68,14 @@ export function doUserEmailNew(email) { data: { email }, }); dispatch(doUserFetch()); - } + }; const failure = error => { dispatch({ type: types.USER_EMAIL_NEW_FAILURE, data: { error }, }); - } + }; lbryio .call( @@ -86,12 +86,14 @@ export function doUserEmailNew(email) { ) .catch(error => { if (error.response && error.response.status == 409) { - return lbryio.call( - "user_email", - "resend_token", - { email: email, only_if_expired: true }, - "post" - ).then(success, failure); + return lbryio + .call( + "user_email", + "resend_token", + { email: email, only_if_expired: true }, + "post" + ) + .then(success, failure); } throw error; }) @@ -99,21 +101,25 @@ export function doUserEmailNew(email) { }; } -export function doUserEmailVerify(verificationToken) { +export function doUserEmailVerify(verificationToken, recaptcha) { return function(dispatch, getState) { const email = selectEmailToVerify(getState()); - verificationToken = verificationToken.toString().trim(); dispatch({ type: types.USER_EMAIL_VERIFY_STARTED, code: verificationToken, + recaptcha: recaptcha, }); lbryio .call( "user_email", "confirm", - { verification_token: verificationToken, email: email }, + { + verification_token: verificationToken, + email: email, + recaptcha: recaptcha, + }, "post" ) .then(userEmail => { @@ -128,12 +134,13 @@ export function doUserEmailVerify(verificationToken) { throw new Error("Your email is still not verified."); //shouldn't happen } }) - .catch(error => { - dispatch({ - type: types.USER_EMAIL_VERIFY_FAILURE, - data: { error }, - }); - }); + .catch(error => dispatch(doUserEmailVerifyFailure(error))); + }; +} +export function doUserEmailVerifyFailure(error) { + return { + type: types.USER_EMAIL_VERIFY_FAILURE, + data: { error }, }; } From 3d95251865fa9c529ab0a8e7f99a4fdae2d17ebc Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 19:15:52 -0800 Subject: [PATCH 2/6] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a57edac4..06aab92fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,14 +9,17 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added * Added copy address button to the Wallet Address component on Send / Receive (#875) + * Link to creators’ channels on homepage (#869) + * Pause playing video when file is opened (#880) + * Reenabled rewards with new verification process (#897) * ### Changed - * + * Contributor documentation * ### Fixed - * + * Linux app categorization (#877) * ### Deprecated From 101650f37214930188f4addc6971edcd11689771 Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 19:16:15 -0800 Subject: [PATCH 3/6] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06aab92fb..c3a9152ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * ### Changed - * Contributor documentation + * Contributor documentation (#879) * ### Fixed From 1cf8826ac0eec22ab6051c6d554cf526531b415e Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 19:18:42 -0800 Subject: [PATCH 4/6] =?UTF-8?q?Bump=20version:=200.19.1=20=E2=86=92=200.19?= =?UTF-8?q?.2rc1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 91764cc37..49dd1aad8 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.1 +current_version = 0.19.2rc1 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/package.json b/package.json index ff83432b9..42b8b3324 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.1", + "version": "0.19.2rc1", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From b3e47a8f8615e664c1fa7682a9c79a398d8cbc9d Mon Sep 17 00:00:00 2001 From: Liam Cardenas Date: Fri, 22 Dec 2017 22:25:05 -0800 Subject: [PATCH 5/6] =?UTF-8?q?Bump=20version:=200.19.2rc1=20=E2=86=92=200?= =?UTF-8?q?.19.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- CHANGELOG.md | 27 +++++++++++++++++++++------ package.json | 2 +- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 49dd1aad8..dd3d60359 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.19.2rc1 +current_version = 0.19.2 commit = True tag = True parse = (?P\d+)\.(?P\d+)\.(?P\d+)((?P[a-z]+)(?P\d+))? diff --git a/CHANGELOG.md b/CHANGELOG.md index c3a9152ab..7e2feea50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,18 +8,15 @@ Web UI version numbers should always match the corresponding version of LBRY App ## [Unreleased] ### Added - * Added copy address button to the Wallet Address component on Send / Receive (#875) - * Link to creators’ channels on homepage (#869) - * Pause playing video when file is opened (#880) - * Reenabled rewards with new verification process (#897) + * * ### Changed - * Contributor documentation (#879) + * * ### Fixed - * Linux app categorization (#877) + * * ### Deprecated @@ -30,6 +27,24 @@ Web UI version numbers should always match the corresponding version of LBRY App * * +## [0.19.2] - 2017-12-22 + +### Added + * Added copy address button to the Wallet Address component on Send / Receive (#875) + * Link to creators’ channels on homepage (#869) + * Pause playing video when file is opened (#880) + * Reenabled rewards with new verification process (#897) + + +### Changed + * Contributor documentation (#879) + + +### Fixed + * Linux app categorization (#877) + + + ## [0.19.1] - 2017-12-13 ### Added diff --git a/package.json b/package.json index 42b8b3324..f15fb3714 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "LBRY", - "version": "0.19.2rc1", + "version": "0.19.2", "description": "A browser for the LBRY network, a digital marketplace controlled by its users.", "homepage": "https://lbry.io/", "bugs": { From d038a6544bda899a63dec336ccff2743aa757912 Mon Sep 17 00:00:00 2001 From: Thomas Zarebczan Date: Sat, 23 Dec 2017 01:29:49 -0500 Subject: [PATCH 6/6] update message about rewards --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e2feea50..e0da8b5c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,7 +33,7 @@ Web UI version numbers should always match the corresponding version of LBRY App * Added copy address button to the Wallet Address component on Send / Receive (#875) * Link to creators’ channels on homepage (#869) * Pause playing video when file is opened (#880) - * Reenabled rewards with new verification process (#897) + * Add captcha to verification process (#897) ### Changed