mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #1176 from sharelatex/ja-manage-v1-subs
Manage v1 subscriptions from v2 GitOrigin-RevId: 1fd63b3630f781e8b4cc3dc1413966540e8d0076
This commit is contained in:
parent
e8b7ab1f8a
commit
ee800f7448
11 changed files with 151 additions and 15 deletions
|
@ -12,6 +12,7 @@ UserGetter = require "../User/UserGetter"
|
|||
FeaturesUpdater = require './FeaturesUpdater'
|
||||
planFeatures = require './planFeatures'
|
||||
GroupPlansData = require './GroupPlansData'
|
||||
V1SubscriptionManager = require "./V1SubscriptionManager"
|
||||
|
||||
module.exports = SubscriptionController =
|
||||
|
||||
|
@ -97,7 +98,8 @@ module.exports = SubscriptionController =
|
|||
managedGroupSubscriptions,
|
||||
confirmedMemberInstitutions,
|
||||
managedInstitutions,
|
||||
v1Subscriptions
|
||||
v1Subscriptions,
|
||||
v1SubscriptionStatus
|
||||
} = results
|
||||
logger.log {
|
||||
user,
|
||||
|
@ -106,7 +108,8 @@ module.exports = SubscriptionController =
|
|||
managedGroupSubscriptions,
|
||||
confirmedMemberInstitutions,
|
||||
managedInstitutions,
|
||||
v1Subscriptions
|
||||
v1Subscriptions,
|
||||
v1SubscriptionStatus
|
||||
}, "showing subscription dashboard"
|
||||
plans = SubscriptionViewModelBuilder.buildViewModel()
|
||||
data = {
|
||||
|
@ -118,7 +121,8 @@ module.exports = SubscriptionController =
|
|||
managedGroupSubscriptions,
|
||||
confirmedMemberInstitutions,
|
||||
managedInstitutions,
|
||||
v1Subscriptions
|
||||
v1Subscriptions,
|
||||
v1SubscriptionStatus
|
||||
}
|
||||
res.render "subscriptions/dashboard", data
|
||||
|
||||
|
@ -158,6 +162,15 @@ module.exports = SubscriptionController =
|
|||
return next(err)
|
||||
res.redirect "/user/subscription"
|
||||
|
||||
cancelV1Subscription: (req, res, next) ->
|
||||
user_id = AuthenticationController.getLoggedInUserId(req)
|
||||
logger.log {user_id}, "canceling v1 subscription"
|
||||
V1SubscriptionManager.cancelV1Subscription user_id, (err)->
|
||||
if err?
|
||||
logger.err err:err, user_id:user_id, "something went wrong canceling v1 subscription"
|
||||
return next(err)
|
||||
res.redirect "/user/subscription"
|
||||
|
||||
updateSubscription: (req, res, next)->
|
||||
_origin = req?.query?.origin || null
|
||||
user = AuthenticationController.getSessionUser(req)
|
||||
|
|
|
@ -40,6 +40,8 @@ module.exports =
|
|||
webRouter.post '/user/subscription/cancel', AuthenticationController.requireLogin(), SubscriptionController.cancelSubscription
|
||||
webRouter.post '/user/subscription/reactivate', AuthenticationController.requireLogin(), SubscriptionController.reactivateSubscription
|
||||
|
||||
webRouter.post '/user/subscription/v1/cancel', AuthenticationController.requireLogin(), SubscriptionController.cancelV1Subscription
|
||||
|
||||
webRouter.put '/user/subscription/extend', AuthenticationController.requireLogin(), SubscriptionController.extendTrial
|
||||
|
||||
webRouter.get "/user/subscription/upgrade-annual", AuthenticationController.requireLogin(), SubscriptionController.renderUpgradeToAnnualPlanPage
|
||||
|
|
|
@ -51,6 +51,10 @@ module.exports =
|
|||
return cb(error) if error?
|
||||
# Only return one argument to async.auto, otherwise it returns an array
|
||||
cb(null, subscriptions)
|
||||
v1SubscriptionStatus: (cb) ->
|
||||
V1SubscriptionManager.getSubscriptionStatusFromV1 user._id, (error, status, v1Id) ->
|
||||
return cb(error) if error?
|
||||
cb(null, status)
|
||||
}, (err, results) ->
|
||||
return callback(err) if err?
|
||||
{
|
||||
|
@ -60,6 +64,7 @@ module.exports =
|
|||
confirmedMemberInstitutions,
|
||||
managedInstitutions,
|
||||
v1Subscriptions,
|
||||
v1SubscriptionStatus,
|
||||
recurlySubscription,
|
||||
plan
|
||||
} = results
|
||||
|
@ -68,6 +73,7 @@ module.exports =
|
|||
confirmedMemberInstitutions ?= []
|
||||
managedInstitutions ?= []
|
||||
v1Subscriptions ?= {}
|
||||
v1SubscriptionStatus ?= {}
|
||||
|
||||
|
||||
if personalSubscription?.toObject?
|
||||
|
@ -97,7 +103,8 @@ module.exports =
|
|||
memberGroupSubscriptions,
|
||||
confirmedMemberInstitutions,
|
||||
managedInstitutions,
|
||||
v1Subscriptions
|
||||
v1Subscriptions,
|
||||
v1SubscriptionStatus
|
||||
}
|
||||
|
||||
buildViewModel : ->
|
||||
|
|
|
@ -39,6 +39,18 @@ module.exports = V1SubscriptionManager =
|
|||
url: (v1Id) -> "/api/v1/sharelatex/users/#{v1Id}/subscriptions"
|
||||
}, callback
|
||||
|
||||
getSubscriptionStatusFromV1: (userId, callback=(err, status) ->) ->
|
||||
V1SubscriptionManager._v1Request userId, {
|
||||
method: 'GET',
|
||||
url: (v1Id) -> "/api/v1/sharelatex/users/#{v1Id}/subscription_status"
|
||||
}, callback
|
||||
|
||||
cancelV1Subscription: (userId, callback=(err)->) ->
|
||||
V1SubscriptionManager._v1Request userId, {
|
||||
method: 'DELETE',
|
||||
url: (v1Id) -> "/api/v1/sharelatex/users/#{v1Id}/subscription"
|
||||
}, callback
|
||||
|
||||
v1IdForUser: (userId, callback=(err, v1Id) ->) ->
|
||||
UserGetter.getUser userId, {'overleaf.id': 1}, (err, user) ->
|
||||
return callback(err) if err?
|
||||
|
@ -76,7 +88,7 @@ module.exports = V1SubscriptionManager =
|
|||
pass: settings.apis.v1.pass
|
||||
sendImmediately: true
|
||||
json: true,
|
||||
timeout: 5 * 1000
|
||||
timeout: 15 * 1000
|
||||
}, (error, response, body) ->
|
||||
if error?
|
||||
# Specially handle no connection err, so warning can be shown
|
||||
|
|
|
@ -16,6 +16,7 @@ hashedFiles = {}
|
|||
Path = require 'path'
|
||||
Features = require "./Features"
|
||||
Modules = require "./Modules"
|
||||
moment = require 'moment'
|
||||
|
||||
jsPath =
|
||||
if Settings.useMinifiedJs
|
||||
|
@ -126,6 +127,7 @@ module.exports = (app, webRouter, privateApiRouter, publicApiRouter)->
|
|||
res.locals.fullJsPath = Url.resolve(staticFilesBase, jsPath)
|
||||
res.locals.lib = PackageVersions.lib
|
||||
|
||||
res.locals.moment = moment
|
||||
|
||||
res.locals.buildJsPath = (jsFile, opts = {})->
|
||||
path = Path.join(jsPath, jsFile)
|
||||
|
|
|
@ -35,6 +35,9 @@ block content
|
|||
-if (settings.overleaf && v1Subscriptions)
|
||||
include ./dashboard/_v1_subscriptions
|
||||
|
||||
-if (v1SubscriptionStatus)
|
||||
include ./dashboard/_v1_subscription_status
|
||||
|
||||
-if (!hasAnySubscription)
|
||||
p You're on the #{settings.appName} Free plan.
|
||||
|
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
- if (v1SubscriptionStatus['team'])
|
||||
p
|
||||
| You have a legacy group licence from Overleaf v1.
|
||||
- if (v1SubscriptionStatus['team']['will_end_at'])
|
||||
p
|
||||
| Your current group licence ends on
|
||||
|
|
||||
strong= moment(v1SubscriptionStatus['team']['will_end_at']).format('Do MMM YY')
|
||||
|
|
||||
| and will
|
||||
|
|
||||
- if (v1SubscriptionStatus['team']['will_renew'])
|
||||
| be automatically renewed.
|
||||
- else
|
||||
| not be automatically renewed.
|
||||
- if (v1SubscriptionStatus['can_cancel_team'])
|
||||
p
|
||||
form(method="POST", action="/user/subscription/v1/cancel")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
button().btn.btn-danger Stop automatic renewal
|
||||
- else
|
||||
p
|
||||
| Please
|
||||
|
|
||||
a(href="/contact") contact support
|
||||
|
|
||||
| to make changes to your plan
|
||||
hr
|
||||
|
||||
- if (v1SubscriptionStatus['product'])
|
||||
p
|
||||
| You have a legacy Overleaf v1
|
||||
|
|
||||
strong= v1SubscriptionStatus['product']['display_name']
|
||||
|
|
||||
| plan.
|
||||
p
|
||||
| Your plan ends on
|
||||
|
|
||||
strong= moment(v1SubscriptionStatus['product']['will_end_at']).format('Do MMM YY')
|
||||
|
|
||||
| and will
|
||||
|
|
||||
- if (v1SubscriptionStatus['product']['will_renew'])
|
||||
| be automatically renewed.
|
||||
- else
|
||||
| not be automatically renewed.
|
||||
- if (v1SubscriptionStatus['can_cancel'])
|
||||
p
|
||||
form(method="POST", action="/user/subscription/v1/cancel")
|
||||
input(type="hidden", name="_csrf", value=csrfToken)
|
||||
button().btn.btn-danger Stop automatic renewal
|
||||
- else
|
||||
p
|
||||
| Please
|
||||
|
|
||||
a(href="/contact") contact support
|
||||
|
|
||||
| to make changes to your plan
|
||||
hr
|
|
@ -1,11 +1,3 @@
|
|||
- if (v1Subscriptions.has_subscription)
|
||||
-hasAnySubscription = true
|
||||
p
|
||||
| You are subscribed to Overleaf through Overleaf v1
|
||||
p
|
||||
a.btn.btn-primary(href='/sign_in_to_v1?return_to=/users/edit%23status') Manage v1 Subscription
|
||||
hr
|
||||
|
||||
- if (v1Subscriptions.teams && v1Subscriptions.teams.length > 0)
|
||||
-hasAnySubscription = true
|
||||
for team in v1Subscriptions.teams
|
||||
|
|
|
@ -234,7 +234,8 @@ describe 'Subscriptions', ->
|
|||
before (done) ->
|
||||
v1Id = MockV1Api.nextV1Id()
|
||||
MockV1Api.setUser v1Id, {
|
||||
subscription: {}
|
||||
subscription: {},
|
||||
subscription_status: {}
|
||||
}
|
||||
MockV1Api.setAffiliations [{
|
||||
email: 'confirmed-affiliation-email@stanford.example.edu'
|
||||
|
@ -281,6 +282,10 @@ describe 'Subscriptions', ->
|
|||
name: 'Test team'
|
||||
}]
|
||||
}
|
||||
subscription_status: @subscription_status = {
|
||||
product: { 'mock': 'product' }
|
||||
team: null
|
||||
}
|
||||
}
|
||||
@user.setV1Id v1Id, (error) =>
|
||||
return done(error) if error?
|
||||
|
@ -295,4 +300,29 @@ describe 'Subscriptions', ->
|
|||
expect(@data.memberGroupSubscriptions).to.deep.equal []
|
||||
|
||||
it 'should return a v1Subscriptions', ->
|
||||
expect(@data.v1Subscriptions).to.deep.equal @subscription
|
||||
expect(@data.v1Subscriptions).to.deep.equal @subscription
|
||||
|
||||
it 'should return a v1SubscriptionStatus', ->
|
||||
expect(@data.v1SubscriptionStatus).to.deep.equal @subscription_status
|
||||
|
||||
describe.only 'canceling', ->
|
||||
before (done) ->
|
||||
@user = new User()
|
||||
MockV1Api.setUser v1Id = MockV1Api.nextV1Id(), @v1_user = {}
|
||||
async.series [
|
||||
(cb) => @user.login(cb)
|
||||
(cb) => @user.setV1Id(v1Id, cb)
|
||||
], (error) =>
|
||||
@user.request {
|
||||
method: 'POST',
|
||||
url: '/user/subscription/v1/cancel'
|
||||
}, (error, @response) =>
|
||||
return done(error) if error?
|
||||
done()
|
||||
|
||||
it 'should tell v1 to cancel the subscription', ->
|
||||
expect(@v1_user.canceled).to.equal true
|
||||
|
||||
it 'should redirect to the subscription dashboard', ->
|
||||
expect(@response.statusCode).to.equal 302
|
||||
expect(@response.headers.location).to.equal '/user/subscription'
|
||||
|
|
|
@ -53,6 +53,20 @@ module.exports = MockV1Api =
|
|||
else
|
||||
res.sendStatus 404
|
||||
|
||||
app.get "/api/v1/sharelatex/users/:v1_user_id/subscription_status", (req, res, next) =>
|
||||
user = @users[req.params.v1_user_id]
|
||||
if user?.subscription_status?
|
||||
res.json user.subscription_status
|
||||
else
|
||||
res.sendStatus 404
|
||||
|
||||
app.delete "/api/v1/sharelatex/users/:v1_user_id/subscription", (req, res, next) =>
|
||||
user = @users[req.params.v1_user_id]
|
||||
if user?
|
||||
user.canceled = true
|
||||
res.sendStatus 200
|
||||
else
|
||||
res.sendStatus 404
|
||||
|
||||
app.post "/api/v1/sharelatex/users/:v1_user_id/sync", (req, res, next) =>
|
||||
@syncUserFeatures(req.params.v1_user_id)
|
||||
|
|
|
@ -79,6 +79,7 @@ describe "SubscriptionController", ->
|
|||
"./RecurlyWrapper": @RecurlyWrapper = {}
|
||||
"./FeaturesUpdater": @FeaturesUpdater = {}
|
||||
"./GroupPlansData": @GroupPlansData = {}
|
||||
"./V1SubscriptionManager": @V1SubscriptionManager = {}
|
||||
|
||||
|
||||
@res = new MockResponse()
|
||||
|
|
Loading…
Reference in a new issue