mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-28 10:06:08 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
528dfaa583
6 changed files with 62 additions and 17 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue