diff --git a/package.json b/package.json index ff83432b9..33645fcb8 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "lbry" ], "dependencies": { + "@segment/load-script": "^1.0.1", "amplitude-js": "^4.0.0", "classnames": "^2.2.5", "electron-dl": "^1.6.0", @@ -46,6 +47,7 @@ "react-markdown": "^2.5.0", "react-modal": "^3.1.7", "react-paginate": "^5.0.0", + "react-recaptcha": "^2.3.5", "react-redux": "^5.0.3", "react-simplemde-editor": "^3.6.11", "redux": "^3.6.0", diff --git a/src/renderer/component/userEmailVerify/index.js b/src/renderer/component/userEmailVerify/index.js index e0fa0902b..2566f44b0 100644 --- a/src/renderer/component/userEmailVerify/index.js +++ b/src/renderer/component/userEmailVerify/index.js @@ -20,7 +20,8 @@ const select = state => ({ }); const perform = dispatch => ({ - verifyUserEmail: code => dispatch(doUserEmailVerify(code)), + verifyUserEmail: (code, recaptcha) => + dispatch(doUserEmailVerify(code, recaptcha)), }); export default connect(select, perform)(UserEmailVerify); diff --git a/src/renderer/component/userEmailVerify/view.jsx b/src/renderer/component/userEmailVerify/view.jsx index 2e330acbe..aba6a453a 100644 --- a/src/renderer/component/userEmailVerify/view.jsx +++ b/src/renderer/component/userEmailVerify/view.jsx @@ -2,6 +2,12 @@ import React from "react"; import Link from "component/link"; import { CreditAmount } from "component/common"; import { Form, FormRow, Submit } from "component/form.js"; +import Recaptcha from "react-recaptcha"; + +const sitekey = + process.env.NODE_ENV === "development" + ? "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" + : "6LcWvj0UAAAAAGBAEp6-UDoe0_iSAn8IZW0GDcf0"; class UserEmailVerify extends React.PureComponent { constructor(props) { @@ -9,6 +15,7 @@ class UserEmailVerify extends React.PureComponent { this.state = { code: "", + recaptcha: "", }; } @@ -19,8 +26,14 @@ class UserEmailVerify extends React.PureComponent { } handleSubmit() { - const { code } = this.state; - this.props.verifyUserEmail(code); + const { code, recaptcha } = this.state; + this.props.verifyUserEmail(code, recaptcha); + } + + verifyCallback(response) { + this.setState({ + recaptcha: String(response), + }); } render() { @@ -44,6 +57,10 @@ class UserEmailVerify extends React.PureComponent { }} errorMessage={errorMessage} /> + {/* render help separately so it always shows */}

@@ -54,7 +71,10 @@ class UserEmailVerify extends React.PureComponent {

- + {cancelButton}
diff --git a/src/renderer/index.js b/src/renderer/index.js index e3ed7836b..9d85c0831 100644 --- a/src/renderer/index.js +++ b/src/renderer/index.js @@ -17,6 +17,9 @@ const env = process.env.NODE_ENV || "production"; const { remote, ipcRenderer, shell } = require("electron"); const contextMenu = remote.require("./main.js").contextMenu; const app = require("./app"); +const load = require("@segment/load-script"); + +load("//www.google.com/recaptcha/api.js?render=explicit"); // Workaround for https://github.com/electron-userland/electron-webpack/issues/52 if (process.env.NODE_ENV !== "development") { diff --git a/src/renderer/redux/actions/user.js b/src/renderer/redux/actions/user.js index 7111369e8..9b1afdd55 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,10 +101,11 @@ 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(); + recaptcha = recaptcha.toString(); dispatch({ type: types.USER_EMAIL_VERIFY_STARTED, @@ -113,7 +116,11 @@ export function doUserEmailVerify(verificationToken) { .call( "user_email", "confirm", - { verification_token: verificationToken, email: email }, + { + verification_token: verificationToken, + email: email, + recaptcha: recaptcha, + }, "post" ) .then(userEmail => { diff --git a/yarn.lock b/yarn.lock index 65aa0ebaf..e3ef9f10a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34,6 +34,14 @@ version "0.0.6" resolved "https://registry.yarnpkg.com/7zip/-/7zip-0.0.6.tgz#9cafb171af82329490353b4816f03347aa150a30" +"@segment/load-script@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@segment/load-script/-/load-script-1.0.1.tgz#adb7a2def2c99ac248cc8e2c154fb4bb03094399" + dependencies: + component-type "^1.2.0" + next-tick "^0.2.2" + script-onload "^1.0.2" + "@segment/top-domain@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@segment/top-domain/-/top-domain-3.0.0.tgz#02e5a5a4fd42a9f6cf886b05e82f104012a3c3a7" @@ -1892,6 +1900,10 @@ component-cookie@^1.1.2: dependencies: debug "*" +component-type@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-type/-/component-type-1.2.1.tgz#8a47901700238e4fc32269771230226f24b415a9" + component-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/component-url/-/component-url-0.2.1.tgz#4e4f4799c43ead9fd3ce91b5a305d220208fee47" @@ -5249,6 +5261,10 @@ next-event@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/next-event/-/next-event-1.0.0.tgz#e7778acde2e55802e0ad1879c39cf6f75eda61d8" +next-tick@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-0.2.2.tgz#75da4a927ee5887e39065880065b7336413b310d" + no-case@^2.2.0: version "2.3.2" resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" @@ -6619,6 +6635,10 @@ react-paginate@^5.0.0: prop-types "^15.6.0" react-addons-create-fragment "^15.0.0" +react-recaptcha@^2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/react-recaptcha/-/react-recaptcha-2.3.5.tgz#a5db337125bb00fb13c2fa2e4ebfbe8b0cd06bb7" + react-redux@^5.0.3: version "5.0.6" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.6.tgz#23ed3a4f986359d68b5212eaaa681e60d6574946" @@ -7194,6 +7214,10 @@ schema-utils@^0.3.0: dependencies: ajv "^5.0.0" +script-onload@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/script-onload/-/script-onload-1.0.2.tgz#6bdca122875487192ccaf4e6884fcfdd0c7fde32" + scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"