Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-11-29 10:52:59 -08:00
commit 528dfaa583
6 changed files with 62 additions and 17 deletions

View file

@ -83,6 +83,7 @@
.language-dropdown .language-dropdown
width: auto width: auto
padding: 0px 10px
display: inline-block display: inline-block
#site-nav-smooth-edge #site-nav-smooth-edge

View file

@ -70,10 +70,11 @@ block modal-body-wait-content
block modal-footer block modal-footer
.modal-footer .modal-footer
div.network-login // GitHub login too buggy to survive
btn.btn.btn-sm.github-login-button#github-login-button //div.network-login
img(src="/images/pages/modal/auth/github_icon.png") // btn.btn.btn-sm.github-login-button#github-login-button
| GitHub // img(src="/images/pages/modal/auth/github_icon.png")
// | GitHub
div.network-login div.network-login
.fb-login-button(data-show-faces="false", data-width="200", data-max-rows="1", data-scope="email") .fb-login-button(data-show-faces="false", data-width="200", data-max-rows="1", data-scope="email")
// Google+ login causing script errors on IE10 // Google+ login causing script errors on IE10

View file

@ -25,6 +25,7 @@
if state === 'unknown_error' if state === 'unknown_error'
#error-alert.alert.alert-danger.alert-dismissible #error-alert.alert.alert-danger.alert-dismissible
span(data-i18n="loading_error.unknown")
button.close(type="button" data-dismiss="alert") button.close(type="button" data-dismiss="alert")
span(aria-hidden="true") × span(aria-hidden="true") ×
p(data-i18n="loading_error.unknown")
p= stateMessage

View file

@ -35,6 +35,7 @@ module.exports = class BuyGemsModal extends ModalView
c = super() c = super()
c.products = @products c.products = @products
c.state = @state c.state = @state
c.stateMessage = @stateMessage
return c return c
onIPadProducts: (e) -> onIPadProducts: (e) ->
@ -89,6 +90,7 @@ module.exports = class BuyGemsModal extends ModalView
_.delay f, 2000 _.delay f, 2000
else else
@state = 'unknown_error' @state = 'unknown_error'
@stateMessage = "#{jqxhr.status}: #{jqxhr.responseText}"
@render() @render()
) )

View file

@ -71,7 +71,7 @@ def which(cmd, mode=os.F_OK | os.X_OK, path=None):
current_directory = os.path.dirname(os.path.realpath(sys.argv[0])) current_directory = os.path.dirname(os.path.realpath(sys.argv[0]))
allowedMongoVersions = ["v2.6.0","v2.6.4"] allowedMongoVersions = ["v2.6.0","v2.6.1","v2.6.4","v2.6.5"]
if which("mongod") and any(i in subprocess.check_output("mongod --version",shell=True) for i in allowedMongoVersions): if which("mongod") and any(i in subprocess.check_output("mongod --version",shell=True) for i in allowedMongoVersions):
mongo_executable = "mongod" mongo_executable = "mongod"
else: else:

View file

@ -37,6 +37,17 @@ PaymentHandler = class PaymentHandler extends Handler
postEditableProperties: ['purchased'] postEditableProperties: ['purchased']
jsonSchema: require '../../app/schemas/models/payment.schema' jsonSchema: require '../../app/schemas/models/payment.schema'
get: (req, res) ->
return res.send([]) unless req.user
q = Payment.find({recipient:req.user._id})
q.exec((err, payments) ->
return @sendDatabaseError(res, err) if err
res.send(payments)
)
logPaymentError: (req, msg) ->
console.warn "Payment Error: #{req.user.get('slug')} (#{req.user._id}): '#{msg}'"
makeNewInstance: (req) -> makeNewInstance: (req) ->
payment = super(req) payment = super(req)
payment.set 'purchaser', req.user._id payment.set 'purchaser', req.user._id
@ -53,16 +64,20 @@ PaymentHandler = class PaymentHandler extends Handler
productID = req.body.productID productID = req.body.productID
if not (appleReceipt or (stripeTimestamp and productID)) if not (appleReceipt or (stripeTimestamp and productID))
@logPaymentError(req, "Missing data. Apple? #{!!appleReceipt}. Stripe timestamp? #{!!stripeTimestamp}. Product id? #{!!productID}.")
return @sendBadInputError(res, 'Need either apple.rawReceipt or stripe.timestamp and productID') return @sendBadInputError(res, 'Need either apple.rawReceipt or stripe.timestamp and productID')
if stripeTimestamp and not productID if stripeTimestamp and not productID
@logPaymentError(req, 'Missing stripe productID')
return @sendBadInputError(res, 'Need productID if paying with Stripe.') return @sendBadInputError(res, 'Need productID if paying with Stripe.')
if stripeTimestamp and (not stripeToken) and (not user.get('stripeCustomerID')) if stripeTimestamp and (not stripeToken) and (not user.get('stripeCustomerID'))
@logPaymentError(req, 'Missing stripe token')
return @sendBadInputError(res, 'Need stripe.token if new customer.') return @sendBadInputError(res, 'Need stripe.token if new customer.')
if appleReceipt if appleReceipt
if not appleTransactionID if not appleTransactionID
@logPaymentError(req, 'Missing apple transaction id')
return @sendBadInputError(res, 'Apple purchase? Need to specify which transaction.') return @sendBadInputError(res, 'Apple purchase? Need to specify which transaction.')
@handleApplePaymentPost(req, res, appleReceipt, appleTransactionID, appleLocalPrice) @handleApplePaymentPost(req, res, appleReceipt, appleTransactionID, appleLocalPrice)
@ -80,11 +95,14 @@ PaymentHandler = class PaymentHandler extends Handler
verifyReq = request.post({url: config.apple.verifyURL, json: formFields}, (err, verifyRes, body) => verifyReq = request.post({url: config.apple.verifyURL, json: formFields}, (err, verifyRes, body) =>
if err or not body?.receipt?.in_app or (not body?.bundle_id is 'com.codecombat.CodeCombat') if err or not body?.receipt?.in_app or (not body?.bundle_id is 'com.codecombat.CodeCombat')
console.warn 'apple receipt error?', err, body console.warn 'apple receipt error?', err, body
@logPaymentError(req, 'Unable to verify apple receipt')
@sendBadInputError(res, 'Unable to verify Apple receipt.') @sendBadInputError(res, 'Unable to verify Apple receipt.')
return return
transaction = _.find body.receipt.in_app, { transaction_id: transactionID } transaction = _.find body.receipt.in_app, { transaction_id: transactionID }
return @sendBadInputError(res, 'Invalid transactionID.') unless transaction unless transaction
@logPaymentError(req, 'Missing transaction given id.')
return @sendBadInputError(res, 'Invalid transactionID.')
#- Check existence #- Check existence
transactionID = transaction.transaction_id transactionID = transaction.transaction_id
@ -93,10 +111,13 @@ PaymentHandler = class PaymentHandler extends Handler
if payment if payment
unless payment.get('recipient').equals(req.user._id) unless payment.get('recipient').equals(req.user._id)
@logPaymentError(req, 'Cross user apple payment.')
return @sendForbiddenError(res) return @sendForbiddenError(res)
@recalculateGemsFor(req.user, (err) => @recalculateGemsFor(req.user, (err) =>
return @sendDatabaseError(res, err) if err if err
@logPaymentError(req, 'Apple recalc db error.'+err)
return @sendDatabaseError(res, err)
@sendSuccess(res, @formatEntity(req, payment)) @sendSuccess(res, @formatEntity(req, payment))
) )
return return
@ -114,11 +135,18 @@ PaymentHandler = class PaymentHandler extends Handler
} }
validation = @validateDocumentInput(payment.toObject()) validation = @validateDocumentInput(payment.toObject())
return @sendBadInputError(res, validation.errors) if validation.valid is false if validation.valid is false
@logPaymentError(req, 'Invalid apple payment object.')
return @sendBadInputError(res, validation.errors)
payment.save((err) => payment.save((err) =>
return @sendDatabaseError(res, err) if err if err
@logPaymentError(req, 'Apple payment save error.'+err)
return @sendDatabaseError(res, err)
@incrementGemsFor(req.user, product.gems, (err) => @incrementGemsFor(req.user, product.gems, (err) =>
return @sendDatabaseError(res, err) if err if err
@logPaymentError(req, 'Apple incr db error.'+err)
return @sendDatabaseError(res, err)
@sendPaymentHipChatMessage user: req.user, payment: payment @sendPaymentHipChatMessage user: req.user, payment: payment
@sendCreated(res, @formatEntity(req, payment)) @sendCreated(res, @formatEntity(req, payment))
) )
@ -139,11 +167,14 @@ PaymentHandler = class PaymentHandler extends Handler
}).then(((customer) => }).then(((customer) =>
req.user.set('stripeCustomerID', customer.id) req.user.set('stripeCustomerID', customer.id)
req.user.save((err) => req.user.save((err) =>
return @sendDatabaseError(res, err) if err if err
@logPaymentError(req, 'Stripe customer id save db error. '+err)
return @sendDatabaseError(res, err)
@beginStripePayment(req, res, timestamp, productID) @beginStripePayment(req, res, timestamp, productID)
) )
), ),
(err) => (err) =>
@logPaymentError(req, 'Stripe customer creation error. '+err)
return @sendDatabaseError(res, err) return @sendDatabaseError(res, err)
) )
@ -171,7 +202,9 @@ PaymentHandler = class PaymentHandler extends Handler
], ],
((err, results) => ((err, results) =>
return @sendDatabaseError(res, err) if err if err
@logPaymentError(req, 'Stripe async load db error. '+err)
return @sendDatabaseError(res, err)
[payment, charge] = results [payment, charge] = results
if not (payment or charge) if not (payment or charge)
@ -185,7 +218,9 @@ PaymentHandler = class PaymentHandler extends Handler
else else
# Charged Stripe and recorded it. Recalculate gems to make sure credited the purchase. # Charged Stripe and recorded it. Recalculate gems to make sure credited the purchase.
@recalculateGemsFor(req.user, (err) => @recalculateGemsFor(req.user, (err) =>
return @sendDatabaseError(res, err) if err if err
@logPaymentError(req, 'Stripe recalc db error. '+err)
return @sendDatabaseError(res, err)
@sendPaymentHipChatMessage user: req.user, payment: payment @sendPaymentHipChatMessage user: req.user, payment: payment
@sendSuccess(res, @formatEntity(req, payment)) @sendSuccess(res, @formatEntity(req, payment))
) )
@ -214,6 +249,7 @@ PaymentHandler = class PaymentHandler extends Handler
if err.type in ['StripeCardError', 'StripeInvalidRequestError'] if err.type in ['StripeCardError', 'StripeInvalidRequestError']
@sendError(res, 402, err.message) @sendError(res, 402, err.message)
else else
@logPaymentError(req, 'Stripe charge error. '+err)
@sendDatabaseError(res, 'Error charging card, please retry.')) @sendDatabaseError(res, 'Error charging card, please retry.'))
) )
@ -232,13 +268,17 @@ PaymentHandler = class PaymentHandler extends Handler
} }
validation = @validateDocumentInput(payment.toObject()) validation = @validateDocumentInput(payment.toObject())
return @sendBadInputError(res, validation.errors) if validation.valid is false if validation.valid is false
@logPaymentError(req, 'Invalid stripe payment object.')
return @sendBadInputError(res, validation.errors)
payment.save((err) => payment.save((err) =>
# Credit gems # Credit gems
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
@incrementGemsFor(req.user, product.gems, (err) => @incrementGemsFor(req.user, product.gems, (err) =>
return @sendDatabaseError(res, err) if err if err
@logPaymentError(req, 'Stripe incr db error. '+err)
return @sendDatabaseError(res, err)
@sendCreated(res, @formatEntity(req, payment)) @sendCreated(res, @formatEntity(req, payment))
) )
) )