Skip to content

Commit

Permalink
Adds capctha to the grant flow
Browse files Browse the repository at this point in the history
Resolves brave#14188

Auditors:

Test Plan:
  • Loading branch information
NejcZdovc committed May 25, 2018
1 parent 4033816 commit 1d5794e
Show file tree
Hide file tree
Showing 18 changed files with 550 additions and 30 deletions.
75 changes: 66 additions & 9 deletions app/browser/api/ledger.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,10 @@ const promoCodeFirstRunStorage = require('../../promoCodeFirstRunStorage')
const appUrlUtil = require('../../../js/lib/appUrlUtil')
const urlutil = require('../../../js/lib/urlutil')
const windowState = require('../../common/state/windowState')
const {makeImmutable, makeJS, isList} = require('../../common/state/immutableUtil')
const {makeImmutable, makeJS, isList, isImmutable} = require('../../common/state/immutableUtil')
const siteHacks = require('../../siteHacks')
const UrlUtil = require('../../../js/lib/urlutil')
const promotionStatuses = require('../../common/constants/promotionStatuses')

// Caching
let locationDefault = 'NOOP'
Expand Down Expand Up @@ -1305,7 +1306,6 @@ const enable = (state, paymentsEnabled) => {

if (paymentsEnabled === getSetting(settings.PAYMENTS_ENABLED)) {
// on start

if (togglePromotionTimeoutId) {
clearTimeout(togglePromotionTimeoutId)
}
Expand All @@ -1314,7 +1314,7 @@ const enable = (state, paymentsEnabled) => {
checkPromotions()
}, random.randomInt({min: 10 * ledgerUtil.milliseconds.second, max: 15 * ledgerUtil.milliseconds.second}))
} else if (paymentsEnabled) {
// on toggle
// toggle on
if (togglePromotionTimeoutId) {
clearTimeout(togglePromotionTimeoutId)
}
Expand All @@ -1326,6 +1326,9 @@ const enable = (state, paymentsEnabled) => {

state = ledgerState.setActivePromotion(state, paymentsEnabled)
getPromotion(state)
} else {
// toggle off
state = ledgerState.setPromotionProp(state, 'promotionStatus', null)
}

if (synopsis) {
Expand Down Expand Up @@ -1520,6 +1523,7 @@ const roundTripFromWindow = (params, callback) => {
* @param {object} params.payload - payload that we want to send to the server
* @param {object} params.headers - HTTP headers
* @param {string} params.path - relative path to requested url
* @param {boolean} params.binaryP - are we receiving raw payload back
* @param {object} options
* @param {boolean} options.verboseP - tells us if we want to log the process or not
* @param {object} options.headers - headers that are used in the request.request
Expand All @@ -1534,7 +1538,7 @@ const roundtrip = (params, options, callback) => {
let parts = typeof params.server === 'string' ? urlParse(params.server)
: typeof params.server !== 'undefined' ? params.server
: typeof options.server === 'string' ? urlParse(options.server) : options.server
const binaryP = options.binaryP
const binaryP = options.binaryP || params.binaryP
const rawP = binaryP || options.rawP || options.scrapeP

if (!params.method) params.method = 'GET'
Expand Down Expand Up @@ -2928,7 +2932,7 @@ const getPromotion = (state) => {
})
}

const claimPromotion = (state) => {
const getCaptcha = (state) => {
if (!client) {
return
}
Expand All @@ -2938,7 +2942,45 @@ const claimPromotion = (state) => {
return
}

client.setPromotion(promotion.get('promotionId'), (err, _, status) => {
client.getPromotionCaptcha(promotion.get('promotionId'), (err, body) => {
if (err) {
console.error(`Problem getting promotion captcha ${err.toString()}`)
appActions.onCaptchaResponse(null)
}

appActions.onCaptchaResponse(body)
})
}

const onCaptchaResponse = (state, body) => {
if (body == null) {
state = ledgerState.setPromotionProp(state, 'promotionStatus', promotionStatuses.CAPTCHA_ERROR)
return state
}

const image = `data:image/jpeg;base64,${Buffer.from(body).toString('base64')}`

state = ledgerState.setPromotionProp(state, 'captcha', image)
const currentStatus = ledgerState.getPromotionProp(state, 'promotionStatus')

if (currentStatus !== promotionStatuses.CAPTCHA_ERROR) {
state = ledgerState.setPromotionProp(state, 'promotionStatus', promotionStatuses.CAPTCHA_CHECK)
}

return state
}

const claimPromotion = (state, x, y) => {
if (!client) {
return
}

const promotion = ledgerState.getPromotion(state)
if (promotion.isEmpty()) {
return
}

client.setPromotion(promotion.get('promotionId'), {x, y}, (err, _, status) => {
let param = null
if (err) {
console.error(`Problem claiming promotion ${err.toString()}`)
Expand All @@ -2950,17 +2992,30 @@ const claimPromotion = (state) => {
}

const onPromotionResponse = (state, status) => {
if (status) {
if (status && isImmutable(status)) {
if (status.get('statusCode') === 422) {
// promotion already claimed
state = ledgerState.setPromotionProp(state, 'promotionStatus', 'expiredError')
state = ledgerState.setPromotionProp(state, 'promotionStatus', promotionStatuses.PROMO_EXPIRED)
} else if (status.get('statusCode') === 403) {
// captcha verification failed
state = ledgerState.setPromotionProp(state, 'promotionStatus', promotionStatuses.CAPTCHA_ERROR)
module.exports.getCaptcha(state)
} else {
// general error
state = ledgerState.setPromotionProp(state, 'promotionStatus', 'generalError')
state = ledgerState.setPromotionProp(state, 'promotionStatus', promotionStatuses.GENERAL_ERROR)
}
return state
}

const currentStatus = ledgerState.getPromotionProp(state, 'promotionStatus')

if (
currentStatus === promotionStatuses.CAPTCHA_ERROR ||
currentStatus === promotionStatuses.CAPTCHA_CHECK
) {
state = ledgerState.setPromotionProp(state, 'promotionStatus', null)
}

ledgerNotifications.removePromotionNotification(state)
state = ledgerState.setPromotionProp(state, 'claimedTimestamp', new Date().getTime())

Expand Down Expand Up @@ -3123,6 +3178,8 @@ const getMethods = () => {
processMediaData,
addNewLocation,
addSiteVisit,
getCaptcha,
onCaptchaResponse,
shouldTrackTab
}

Expand Down
17 changes: 16 additions & 1 deletion app/browser/reducers/ledgerReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,24 @@ const ledgerReducer = (state, action, immutableAction) => {
state = ledgerNotifications.onPromotionReceived(state)
break
}
case appConstants.APP_ON_PROMOTION_CLICK:
{
ledgerApi.getCaptcha(state)
break
}
case appConstants.APP_ON_CAPTCHA_RESPONSE:
{
state = ledgerApi.onCaptchaResponse(state, action.get('body'))
break
}
case appConstants.APP_ON_CAPTCHA_CLOSE:
{
state = ledgerState.setPromotionProp(state, 'promotionStatus', null)
break
}
case appConstants.APP_ON_PROMOTION_CLAIM:
{
ledgerApi.claimPromotion(state)
ledgerApi.claimPromotion(state, action.get('x'), action.get('y'))
break
}
case appConstants.APP_ON_PROMOTION_REMIND:
Expand Down
12 changes: 12 additions & 0 deletions app/common/constants/promotionStatuses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

const statuses = {
GENERAL_ERROR: 'generalError',
PROMO_EXPIRED: 'expiredError',
CAPTCHA_CHECK: 'captchaCheck',
CAPTCHA_ERROR: 'captchaError'
}

module.exports = statuses
5 changes: 5 additions & 0 deletions app/common/state/ledgerState.js
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ const ledgerState = {
let promotion = ledgerState.getActivePromotion(state)
const claim = state.getIn(['ledger', 'promotion', 'claimedTimestamp']) || null
const status = state.getIn(['ledger', 'promotion', 'promotionStatus']) || null
const captcha = state.getIn(['ledger', 'promotion', 'captcha']) || null

if (claim) {
promotion = promotion.set('claimedTimestamp', claim)
Expand All @@ -550,6 +551,10 @@ const ledgerState = {
promotion = promotion.set('promotionStatus', status)
}

if (captcha) {
promotion = promotion.set('captcha', captcha)
}

return promotion
},

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions app/extensions/brave/locales/en-US/preferences.properties
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ printKeys=Print key
privacy=Privacy
privateData=Private Data
privateDataMessage=Clear the following data types when I close Brave
promotionCaptchaTitle=Almost there!
promotionCaptchaErrorTitle=Hmmm…not quite.
promotionCaptchaErrorText=Please try again.
promotionCaptchaText=First, prove you are human:
promotionCaptchaMessage=Drag and drop the BAT logo onto the target
promotionGeneralErrorMessage=The Brave Payments server is not responding. Please try again later to claim your token grant.
promotionGeneralErrorText=Note: This error could also be caused by a network connection problem.
promotionGeneralErrorTitle=Uh oh.
Expand Down
Loading

0 comments on commit 1d5794e

Please sign in to comment.