Explorar o código

Merge pull request #4672 from overleaf/sk-validate-currency-param

Subscription: validate currency in query param
GitOrigin-RevId: 0c9f841ba56b5ce85bbd2adeb3fb2d45d0ad753a
June Kelly %!s(int64=5) %!d(string=hai) anos
pai
achega
8aeb782791

+ 7 - 3
services/web/app/src/Features/Subscription/SubscriptionController.js

@@ -63,9 +63,13 @@ async function paymentPage(req, res) {
     if (!valid) {
       res.redirect('/user/subscription?hasSubscription=true')
     } else {
-      let currency = req.query.currency
-        ? req.query.currency.toUpperCase()
-        : undefined
+      let currency = null
+      if (req.query.currency) {
+        const queryCurrency = req.query.currency.toUpperCase()
+        if (GeoIpLookup.isValidCurrencyParam(queryCurrency)) {
+          currency = queryCurrency
+        }
+      }
       const {
         currencyCode: recommendedCurrency,
         countryCode,

+ 10 - 0
services/web/app/src/infrastructure/GeoIpLookup.js

@@ -17,6 +17,8 @@ const currencyMappings = {
   SE: 'SEK',
 }
 
+const validCurrencyParams = Object.values(currencyMappings).concat(['EUR'])
+
 // Countries which would likely prefer Euro's
 const EuroCountries = [
   'AT',
@@ -48,6 +50,13 @@ const EuroCountries = [
 
 _.each(EuroCountries, country => (currencyMappings[country] = 'EUR'))
 
+function isValidCurrencyParam(currency) {
+  if (!currency) {
+    return false
+  }
+  return validCurrencyParams.includes(currency)
+}
+
 function getDetails(ip, callback) {
   if (!ip) {
     return callback(new Error('no ip passed'))
@@ -89,6 +98,7 @@ function getCurrencyCode(ip, callback) {
 module.exports = {
   getDetails,
   getCurrencyCode,
+  isValidCurrencyParam,
   promises: {
     getDetails: promisify(getDetails),
     getCurrencyCode: promisifyMultiResult(getCurrencyCode, [

+ 11 - 0
services/web/test/unit/src/Subscription/SubscriptionControllerTests.js

@@ -108,6 +108,7 @@ describe('SubscriptionController', function () {
       gaExperiments: {},
     }
     this.GeoIpLookup = {
+      isValidCurrencyParam: sinon.stub().returns(true),
       getCurrencyCode: sinon.stub(),
       promises: {
         getCurrencyCode: sinon.stub(),
@@ -263,6 +264,16 @@ describe('SubscriptionController', function () {
         }
         this.SubscriptionController.paymentPage(this.req, this.res)
       })
+
+      it('should use the geo ip currency if not valid', function (done) {
+        this.req.query.currency = 'WAT'
+        this.GeoIpLookup.isValidCurrencyParam.returns(false)
+        this.res.render = (page, opts) => {
+          opts.currency.should.equal(this.stubbedCurrencyCode)
+          done()
+        }
+        this.SubscriptionController.paymentPage(this.req, this.res)
+      })
     })
 
     describe('with a recurly subscription already', function () {

+ 12 - 0
services/web/test/unit/src/infrastructure/GeoIpLookupTest.js

@@ -41,6 +41,18 @@ describe('GeoIpLookup', function () {
     }
   })
 
+  describe('isValidCurrencyParam', function () {
+    it('should reject invalid currency codes', function () {
+      expect(this.GeoIpLookup.isValidCurrencyParam('GBP')).to.equal(true)
+      expect(this.GeoIpLookup.isValidCurrencyParam('USD')).to.equal(true)
+      expect(this.GeoIpLookup.isValidCurrencyParam('AUD')).to.equal(true)
+      expect(this.GeoIpLookup.isValidCurrencyParam('EUR')).to.equal(true)
+      expect(this.GeoIpLookup.isValidCurrencyParam('WAT')).to.equal(false)
+      expect(this.GeoIpLookup.isValidCurrencyParam('NON')).to.equal(false)
+      expect(this.GeoIpLookup.isValidCurrencyParam('LOL')).to.equal(false)
+    })
+  })
+
   describe('getDetails', function () {
     beforeEach(function () {
       this.request.get.callsArgWith(1, null, null, this.stubbedResponse)