diff --git a/app/assets/images/common/button-background-brown-active-border.png b/app/assets/images/common/button-background-brown-active-border.png new file mode 100644 index 000000000..8a666e47b Binary files /dev/null and b/app/assets/images/common/button-background-brown-active-border.png differ diff --git a/app/assets/images/common/button-background-brown-active.png b/app/assets/images/common/button-background-brown-active.png new file mode 100644 index 000000000..eeff76f4f Binary files /dev/null and b/app/assets/images/common/button-background-brown-active.png differ diff --git a/app/assets/images/common/button-background-brown-disabled-border.png b/app/assets/images/common/button-background-brown-disabled-border.png new file mode 100644 index 000000000..62f12be18 Binary files /dev/null and b/app/assets/images/common/button-background-brown-disabled-border.png differ diff --git a/app/assets/images/common/button-background-brown-disabled.png b/app/assets/images/common/button-background-brown-disabled.png new file mode 100644 index 000000000..a0e743222 Binary files /dev/null and b/app/assets/images/common/button-background-brown-disabled.png differ diff --git a/app/assets/images/common/button-background-brown-pressed-border.png b/app/assets/images/common/button-background-brown-pressed-border.png new file mode 100644 index 000000000..ca2134e18 Binary files /dev/null and b/app/assets/images/common/button-background-brown-pressed-border.png differ diff --git a/app/assets/images/common/button-background-brown-pressed.png b/app/assets/images/common/button-background-brown-pressed.png new file mode 100644 index 000000000..21e6bd380 Binary files /dev/null and b/app/assets/images/common/button-background-brown-pressed.png differ diff --git a/app/assets/images/common/button-background-fb-active-border.png b/app/assets/images/common/button-background-fb-active-border.png new file mode 100644 index 000000000..140858b50 Binary files /dev/null and b/app/assets/images/common/button-background-fb-active-border.png differ diff --git a/app/assets/images/common/button-background-fb-active.png b/app/assets/images/common/button-background-fb-active.png new file mode 100644 index 000000000..7e054911c Binary files /dev/null and b/app/assets/images/common/button-background-fb-active.png differ diff --git a/app/assets/images/common/button-background-fb-disabled-border.png b/app/assets/images/common/button-background-fb-disabled-border.png new file mode 100644 index 000000000..b3a0fedcf Binary files /dev/null and b/app/assets/images/common/button-background-fb-disabled-border.png differ diff --git a/app/assets/images/common/button-background-fb-disabled.png b/app/assets/images/common/button-background-fb-disabled.png new file mode 100644 index 000000000..adb402464 Binary files /dev/null and b/app/assets/images/common/button-background-fb-disabled.png differ diff --git a/app/assets/images/common/button-background-fb-pressed-border.png b/app/assets/images/common/button-background-fb-pressed-border.png new file mode 100644 index 000000000..2cb8f9059 Binary files /dev/null and b/app/assets/images/common/button-background-fb-pressed-border.png differ diff --git a/app/assets/images/common/button-background-fb-pressed.png b/app/assets/images/common/button-background-fb-pressed.png new file mode 100644 index 000000000..cc7ab716a Binary files /dev/null and b/app/assets/images/common/button-background-fb-pressed.png differ diff --git a/app/assets/images/common/button-background-gplus-active-border.png b/app/assets/images/common/button-background-gplus-active-border.png new file mode 100644 index 000000000..30ed218dd Binary files /dev/null and b/app/assets/images/common/button-background-gplus-active-border.png differ diff --git a/app/assets/images/common/button-background-gplus-active.png b/app/assets/images/common/button-background-gplus-active.png new file mode 100644 index 000000000..b198ed621 Binary files /dev/null and b/app/assets/images/common/button-background-gplus-active.png differ diff --git a/app/assets/images/common/button-background-gplus-disabled-border.png b/app/assets/images/common/button-background-gplus-disabled-border.png new file mode 100644 index 000000000..eabd86d3f Binary files /dev/null and b/app/assets/images/common/button-background-gplus-disabled-border.png differ diff --git a/app/assets/images/common/button-background-gplus-disabled.png b/app/assets/images/common/button-background-gplus-disabled.png new file mode 100644 index 000000000..494f85869 Binary files /dev/null and b/app/assets/images/common/button-background-gplus-disabled.png differ diff --git a/app/assets/images/common/button-background-gplus-pressed-border.png b/app/assets/images/common/button-background-gplus-pressed-border.png new file mode 100644 index 000000000..eadb03397 Binary files /dev/null and b/app/assets/images/common/button-background-gplus-pressed-border.png differ diff --git a/app/assets/images/common/button-background-gplus-pressed.png b/app/assets/images/common/button-background-gplus-pressed.png new file mode 100644 index 000000000..2438ad3ee Binary files /dev/null and b/app/assets/images/common/button-background-gplus-pressed.png differ diff --git a/app/assets/images/level/loading_left_wing_1366.jpg b/app/assets/images/level/loading_left_wing_1366.jpg new file mode 100644 index 000000000..29fe67e9c Binary files /dev/null and b/app/assets/images/level/loading_left_wing_1366.jpg differ diff --git a/app/assets/images/level/loading_left_wing_1920.jpg b/app/assets/images/level/loading_left_wing_1920.jpg new file mode 100644 index 000000000..73aab0978 Binary files /dev/null and b/app/assets/images/level/loading_left_wing_1920.jpg differ diff --git a/app/assets/images/level/loading_right_wing_1366.jpg b/app/assets/images/level/loading_right_wing_1366.jpg new file mode 100644 index 000000000..963feba9b Binary files /dev/null and b/app/assets/images/level/loading_right_wing_1366.jpg differ diff --git a/app/assets/images/level/loading_right_wing_1920.jpg b/app/assets/images/level/loading_right_wing_1920.jpg new file mode 100644 index 000000000..2fe4465ce Binary files /dev/null and b/app/assets/images/level/loading_right_wing_1920.jpg differ diff --git a/app/assets/images/pages/play/level/modal/reward_plate.png b/app/assets/images/pages/play/level/modal/reward_plate.png index 3ee2bba20..0a0a7b6e7 100644 Binary files a/app/assets/images/pages/play/level/modal/reward_plate.png and b/app/assets/images/pages/play/level/modal/reward_plate.png differ diff --git a/app/assets/images/pages/play/level/modal/reward_plate_wide.png b/app/assets/images/pages/play/level/modal/reward_plate_wide.png index 466c0af7f..d99ae8fac 100644 Binary files a/app/assets/images/pages/play/level/modal/reward_plate_wide.png and b/app/assets/images/pages/play/level/modal/reward_plate_wide.png differ diff --git a/app/assets/images/pages/play/map_dungeon_1366.jpg b/app/assets/images/pages/play/map_dungeon_1366.jpg new file mode 100644 index 000000000..b4bd41c6a Binary files /dev/null and b/app/assets/images/pages/play/map_dungeon_1366.jpg differ diff --git a/app/assets/images/pages/play/map_dungeon_1920.jpg b/app/assets/images/pages/play/map_dungeon_1920.jpg new file mode 100644 index 000000000..857ace0d0 Binary files /dev/null and b/app/assets/images/pages/play/map_dungeon_1920.jpg differ diff --git a/app/assets/images/pages/play/map_forest_1366.jpg b/app/assets/images/pages/play/map_forest_1366.jpg new file mode 100644 index 000000000..362124291 Binary files /dev/null and b/app/assets/images/pages/play/map_forest_1366.jpg differ diff --git a/app/assets/images/pages/play/map_forest_1920.jpg b/app/assets/images/pages/play/map_forest_1920.jpg new file mode 100644 index 000000000..3631cabd7 Binary files /dev/null and b/app/assets/images/pages/play/map_forest_1920.jpg differ diff --git a/app/models/User.coffee b/app/models/User.coffee index 716f71443..90a7264fa 100644 --- a/app/models/User.coffee +++ b/app/models/User.coffee @@ -112,6 +112,13 @@ module.exports = class User extends CocoModel application.tracker.identify gemPromptGroup: @gemPromptGroup unless me.isAdmin() @gemPromptGroup + isPremium: -> + return false unless stripe = @get('stripe') + return true if stripe.subscriptionID + return true if stripe.free is true + return true if _.isString(stripe.free) and new Date() < new Date(stripe.free) + return false + tiersByLevel = [-1, 0, 0.05, 0.14, 0.18, 0.32, 0.41, 0.5, 0.64, 0.82, 0.91, 1.04, 1.22, 1.35, 1.48, 1.65, 1.78, 1.96, 2.1, 2.24, 2.38, 2.55, 2.69, 2.86, 3.03, 3.16, 3.29, 3.42, 3.58, 3.74, 3.89, 4.04, 4.19, 4.32, 4.47, 4.64, 4.79, 4.96, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10.5, 11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15 ] diff --git a/app/views/account/PaymentsView.coffee b/app/views/account/PaymentsView.coffee index 992cbd8fa..2654afa2d 100644 --- a/app/views/account/PaymentsView.coffee +++ b/app/views/account/PaymentsView.coffee @@ -24,7 +24,7 @@ module.exports = class PaymentsView extends RootView c = super() c.payments = @payments c.subscribed = me.get('stripe')?.planID - c.active = me.get('stripe')?.subscriptionID + c.active = me.isPremium() c onClickStartSubscription: (e) -> diff --git a/app/views/play/WorldMapView.coffee b/app/views/play/WorldMapView.coffee index 9e0552859..4548b14b1 100644 --- a/app/views/play/WorldMapView.coffee +++ b/app/views/play/WorldMapView.coffee @@ -81,7 +81,7 @@ module.exports = class WorldMapView extends RootView $('body').append($('')) trackedHourOfCode = true - @requiresSubscription = @terrain isnt 'dungeon' and not me.get('stripe')?.subscriptionID + @requiresSubscription = @terrain isnt 'dungeon' and not me.isPremium() destroy: -> @setupManager?.destroy() diff --git a/server/levels/level_handler.coffee b/server/levels/level_handler.coffee index 2f68a1280..ace23c255 100644 --- a/server/levels/level_handler.coffee +++ b/server/levels/level_handler.coffee @@ -72,7 +72,7 @@ LevelHandler = class LevelHandler extends Handler Session.findOne(sessionQuery).exec (err, doc) => return @sendDatabaseError(res, err) if err return @sendSuccess(res, doc) if doc? - return @sendPaymentRequiredError(res, err) if (not req.user.get('stripe')?.subscriptionID) and level.get('requiresSubscription') + return @sendPaymentRequiredError(res, err) if (not req.user.isPremium()) and level.get('requiresSubscription') @createAndSaveNewSession sessionQuery, req, res createAndSaveNewSession: (sessionQuery, req, res) => diff --git a/server/payments/payment_handler.coffee b/server/payments/payment_handler.coffee index cc077994b..4f9707494 100644 --- a/server/payments/payment_handler.coffee +++ b/server/payments/payment_handler.coffee @@ -8,7 +8,6 @@ sendwithus = require '../sendwithus' hipchat = require '../hipchat' config = require '../../server_config' request = require 'request' -stripe = require('stripe')(config.stripe.secretKey) async = require 'async' products = { diff --git a/server/payments/subscription_handler.coffee b/server/payments/subscription_handler.coffee index fdf428873..2ab45ed48 100644 --- a/server/payments/subscription_handler.coffee +++ b/server/payments/subscription_handler.coffee @@ -2,8 +2,6 @@ # the stripe property in the user with what's being stored in Stripe. Handler = require '../commons/Handler' -config = require '../../server_config' -stripe = require('stripe')(config.stripe.secretKey) discountHandler = require './discount_handler' subscriptions = { @@ -13,17 +11,17 @@ subscriptions = { } class SubscriptionHandler extends Handler - logSubscriptionError: (req, msg) -> - console.warn "Subscription Error: #{req.user.get('slug')} (#{req.user._id}): '#{msg}'" + logSubscriptionError: (user, msg) -> + console.warn "Subscription Error: #{user.get('slug')} (#{user._id}): '#{msg}'" subscribeUser: (req, user, done) -> - if (not req.user) or req.user.isAnonymous() + if (not req.user) or req.user.isAnonymous() or user.isAnonymous() return done({res: 'You must be signed in to subscribe.', code: 403}) token = req.body.stripe.token customerID = user.get('stripe')?.customerID if not (token or customerID) - @logSubscriptionError(req, 'Missing stripe token or customer ID.') + @logSubscriptionError(user, 'Missing stripe token or customer ID.') return done({res: 'Missing stripe token or customer ID.', code: 422}) if token @@ -31,15 +29,15 @@ class SubscriptionHandler extends Handler stripe.customers.update customerID, { card: token }, (err, customer) => if err or not customer # should not happen outside of test and production polluting each other - @logSubscriptionError(req, 'Cannot find customer: ', +customer.id + '\n\n' + err) + @logSubscriptionError(user, 'Cannot find customer: ', +customer.id + '\n\n' + err) return done({res: 'Cannot find customer.', code: 404}) @checkForExistingSubscription(req, user, customer, done) else newCustomer = { card: token - email: req.user.get('email') - metadata: { id: req.user._id + '', slug: req.user.get('slug') } + email: user.get('email') + metadata: { id: user._id + '', slug: user.get('slug') } } stripe.customers.create newCustomer, (err, customer) => @@ -47,22 +45,22 @@ class SubscriptionHandler extends Handler if err.type in ['StripeCardError', 'StripeInvalidRequestError'] return done({res: 'Card error', code: 402}) else - @logSubscriptionError(req, 'Stripe customer creation error. '+err) + @logSubscriptionError(user, 'Stripe customer creation error. '+err) return done({res: 'Database error.', code: 500}) - stripeInfo = _.cloneDeep(req.user.get('stripe') ? {}) + stripeInfo = _.cloneDeep(user.get('stripe') ? {}) stripeInfo.customerID = customer.id - req.user.set('stripe', stripeInfo) - req.user.save (err) => + user.set('stripe', stripeInfo) + user.save (err) => if err - @logSubscriptionError(req, 'Stripe customer id save db error. '+err) + @logSubscriptionError(user, 'Stripe customer id save db error. '+err) return done({res: 'Database error.', code: 500}) @checkForExistingSubscription(req, user, customer, done) else stripe.customers.retrieve(customerID, (err, customer) => if err - @logSubscriptionError(req, 'Stripe customer creation error. '+err) + @logSubscriptionError(user, 'Stripe customer creation error. '+err) return done({res: 'Database error.', code: 500}) @checkForExistingSubscription(req, user, customer, done) ) @@ -79,14 +77,14 @@ class SubscriptionHandler extends Handler # subscription a trial period that ends when the cancelled subscription would have ended. stripe.customers.cancelSubscription subscription.customer, subscription.id, (err) => if err - @logSubscriptionError(req, 'Stripe cancel subscription error. '+err) + @logSubscriptionError(user, 'Stripe cancel subscription error. '+err) return done({res: 'Database error.', code: 500}) options = { plan: 'basic', trial_end: subscription.current_period_end } options.coupon = couponID if couponID - stripe.customers.update req.user.get('stripe').customerID, options, (err, customer) => + stripe.customers.update user.get('stripe').customerID, options, (err, customer) => if err - @logSubscriptionError(req, 'Stripe customer plan setting error. '+err) + @logSubscriptionError(user, 'Stripe customer plan setting error. '+err) return done({res: 'Database error.', code: 500}) @updateUser(req, user, customer, false, done) @@ -98,9 +96,9 @@ class SubscriptionHandler extends Handler else options = { plan: 'basic' } options.coupon = couponID if couponID - stripe.customers.update req.user.get('stripe').customerID, options, (err, customer) => + stripe.customers.update user.get('stripe').customerID, options, (err, customer) => if err - @logSubscriptionError(req, 'Stripe customer plan setting error. '+err) + @logSubscriptionError(user, 'Stripe customer plan setting error. '+err) return done({res: 'Database error.', code: 500}) @updateUser(req, user, customer, true, done) @@ -123,25 +121,25 @@ class SubscriptionHandler extends Handler user.save (err) => if err - @logSubscriptionError(req, 'Stripe user plan saving error. '+err) + @logSubscriptionError(user, 'Stripe user plan saving error. '+err) return done({res: 'Database error.', code: 500}) - req.user?.saveActiveUser 'subscribe' + user?.saveActiveUser 'subscribe' return done() unsubscribeUser: (req, user, done) -> stripeInfo = _.cloneDeep(user.get('stripe')) stripe.customers.cancelSubscription stripeInfo.customerID, stripeInfo.subscriptionID, { at_period_end: true }, (err) => if err - @logSubscriptionError(req, 'Stripe cancel subscription error. '+err) + @logSubscriptionError(user, 'Stripe cancel subscription error. '+err) return done({res: 'Database error.', code: 500}) delete stripeInfo.planID user.set('stripe', stripeInfo) req.body.stripe = stripeInfo user.save (err) => if err - @logSubscriptionError(req, 'User save unsubscribe error. '+err) + @logSubscriptionError(user, 'User save unsubscribe error. '+err) return done({res: 'Database error.', code: 500}) - req.user?.saveActiveUser 'unsubscribe' + user?.saveActiveUser 'unsubscribe' return done() module.exports = new SubscriptionHandler() diff --git a/server/users/User.coffee b/server/users/User.coffee index cd9d50381..6f1ff5fbe 100644 --- a/server/users/User.coffee +++ b/server/users/User.coffee @@ -179,6 +179,13 @@ UserSchema.methods.register = (done) -> delighted.addDelightedUser @ @saveActiveUser 'register' +UserSchema.methods.isPremium = -> + return false unless stripe = @get('stripe') + return true if stripe.subscriptionID + return true if stripe.free is true + return true if _.isString(stripe.free) and new Date() < new Date(stripe.free) + return false + UserSchema.statics.saveActiveUser = (id, event, done=null) -> id = mongoose.Types.ObjectId id if _.isString id @findById id, (err, user) -> diff --git a/server/users/user_handler.coffee b/server/users/user_handler.coffee index 5e1d07de6..0e534a21a 100644 --- a/server/users/user_handler.coffee +++ b/server/users/user_handler.coffee @@ -230,9 +230,19 @@ UserHandler = class UserHandler extends Handler return @trackActivity(req, res, args[0], args[2], args[3]) if args[1] is 'track' and args[2] return @getRemark(req, res, args[0]) if args[1] is 'remark' return @searchForUser(req, res) if args[1] is 'admin_search' + return @getStripeInfo(req, res, args[0]) if args[1] is 'stripe' return @sendNotFoundError(res) super(arguments...) + getStripeInfo: (req, res, handle) -> + @getDocumentForIdOrSlug handle, (err, user) => + return @sendNotFoundError(res) if not user + return @sendForbiddenError(res) unless req.user and (req.user.isAdmin() or req.user.get('_id').equals(user.get('_id'))) + return @sendNotFoundError(res) #if not customerID = user.get('stripe')?.customerID + stripe.customers.retrieve customerID, (err, customer) => + return @sendDatabaseError(res, err) if err + @sendSuccess(res, JSON.stringify(customer, null, '\t')) + agreeToCLA: (req, res) -> return @sendForbiddenError(res) unless req.user doc = diff --git a/server_setup.coffee b/server_setup.coffee index ae76032c2..97b734a09 100644 --- a/server_setup.coffee +++ b/server_setup.coffee @@ -16,6 +16,8 @@ UserHandler = require './server/users/user_handler' hipchat = require './server/hipchat' global.tv4 = require 'tv4' # required for TreemaUtils to work global.jsondiffpatch = require 'jsondiffpatch' +global.stripe = require('stripe')(config.stripe.secretKey) + productionLogging = (tokens, req, res) -> status = res.statusCode