Skip to content

Commit

Permalink
Merge pull request #2485 from alphagov/PP-7583-move-3ds-route
Browse files Browse the repository at this point in the history
PP-7583 Move 3ds routes to use account URL structure
  • Loading branch information
stephencdaly authored Jan 14, 2021
2 parents ce949f2 + 221c412 commit 055b084
Show file tree
Hide file tree
Showing 11 changed files with 63 additions and 51 deletions.
4 changes: 2 additions & 2 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "package-lock.json",
"lines": null
},
"generated_at": "2021-01-12T17:03:50Z",
"generated_at": "2021-01-13T17:09:45Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down Expand Up @@ -72,7 +72,7 @@
"hashed_secret": "ece65afda87c1c6120602c9a3b66890308d7e53c",
"is_secret": false,
"is_verified": false,
"line_number": 52,
"line_number": 58,
"type": "Secret Keyword"
}
],
Expand Down
4 changes: 2 additions & 2 deletions app/controllers/payment-types/post-index.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module.exports = async (req, res) => {
if (typeof acceptedDebitCards === 'undefined' && typeof acceptedCreditCards === 'undefined') {
req.flash('genericError', 'You must choose at least one card')
return res.redirect(
formatAccountPathsFor(paths.paymentTypes.index, req.account && req.account.external_id)
formatAccountPathsFor(paths.account.paymentTypes.index, req.account && req.account.external_id)
)
}

Expand All @@ -31,7 +31,7 @@ module.exports = async (req, res) => {
await connector.postAcceptedCardsForAccount(accountId, payload, correlationId)
req.flash('generic', 'Accepted card types have been updated')
return res.redirect(
formatAccountPathsFor(paths.paymentTypes.index, req.account && req.account.external_id)
formatAccountPathsFor(paths.account.paymentTypes.index, req.account && req.account.external_id)
)
} catch (error) {
return renderErrorView(req, res, 'Unable to update payment types. Please try again or contact support team.', error.errorCode)
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/toggle-3ds/3ds.post.controller.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict'

const paths = require('../../paths')
const formatAccountPathsFor = require('../../utils/format-account-paths-for')
const { renderErrorView } = require('../../utils/response')
const { ConnectorClient } = require('../../services/clients/connector.client')
const { correlationHeader } = require('../../utils/correlation-header')
Expand All @@ -23,7 +24,7 @@ module.exports = async (req, res) => {

await connector.update3dsEnabled(params)
req.flash('generic', '3D secure settings have been updated')
return res.redirect(paths.toggle3ds.index)
return res.redirect(formatAccountPathsFor(paths.account.toggle3ds.index, req.account && req.account.external_id))
} catch (error) {
return renderErrorView(req, res, false, error.errorCode)
}
Expand Down
12 changes: 6 additions & 6 deletions app/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ module.exports = {
keys,
account: {
root: `/account/:${keys.GATEWAY_ACCOUNT_EXTERNAL_ID}`,
paymentTypes: {
index: '/payment-types'
},
toggle3ds: {
index: '/3ds'
},
toggleBillingAddress: {
index: '/billing-address'
}
Expand Down Expand Up @@ -72,9 +78,6 @@ module.exports = {
revoke: '/api-keys/revoke',
update: '/api-keys/update'
},
paymentTypes: {
index: '/payment-types'
},
digitalWallet: {
applePay: '/digital-wallet/apple-pay',
googlePay: '/digital-wallet/google-pay'
Expand Down Expand Up @@ -129,9 +132,6 @@ module.exports = {
logUserIn: '/create-service/proceed-to-login',
serviceNaming: '/service/set-name'
},
toggle3ds: {
index: '/3ds'
},
toggleMotoMaskCardNumberAndSecurityCode: {
cardNumber: '/moto-hide-card-number',
securityCode: '/moto-hide-security-code'
Expand Down
62 changes: 33 additions & 29 deletions app/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,15 @@ const stripeSetupDashboardRedirectController = require('./controllers/stripe-set
const {
healthcheck, registerUser, user, dashboard, selfCreateService, transactions, credentials,
apiKeys, serviceSwitcher, teamMembers, staticPaths, inviteValidation, editServiceName, merchantDetails,
notificationCredentials: nc, paymentTypes: pt, emailNotifications: en, toggle3ds: t3ds, toggleMotoMaskCardNumberAndSecurityCode, prototyping, paymentLinks,
notificationCredentials, emailNotifications: emailNotifications, toggleMotoMaskCardNumberAndSecurityCode, prototyping, paymentLinks,
requestToGoLive, policyPages, stripeSetup, stripe, digitalWallet,
settings, yourPsp, allServiceTransactions, payouts
} = paths
const { toggleBillingAddress: billingAddress } = paths.account
const {
paymentTypes,
toggle3ds,
toggleBillingAddress
} = paths.account

// Exports
module.exports.generateRoute = generateRoute
Expand Down Expand Up @@ -170,20 +174,20 @@ module.exports.bind = function (app) {
...lodash.values(transactions),
...lodash.values(allServiceTransactions),
...lodash.values(credentials),
...lodash.values(nc),
...lodash.values(notificationCredentials),
...lodash.values(apiKeys),
...lodash.values(pt),
...lodash.values(en),
...lodash.values(paymentTypes),
...lodash.values(emailNotifications),
...lodash.values(editServiceName),
...lodash.values(serviceSwitcher),
...lodash.values(teamMembers),
...lodash.values(t3ds),
...lodash.values(toggle3ds),
...lodash.values(merchantDetails),
...lodash.values(prototyping.demoPayment),
...lodash.values(prototyping.demoService),
...lodash.values(paymentLinks),
...lodash.values(user.profile),
...lodash.values(billingAddress),
...lodash.values(toggleBillingAddress),
...lodash.values(requestToGoLive),
...lodash.values(policyPages),
...lodash.values(stripeSetup),
Expand Down Expand Up @@ -225,9 +229,9 @@ module.exports.bind = function (app) {
app.get(credentials.edit, permission('gateway-credentials:update'), getAccount, paymentMethodIsCard, credentialsController.editCredentials)
app.post(credentials.index, permission('gateway-credentials:update'), getAccount, paymentMethodIsCard, credentialsController.update)

app.get(nc.index, permission('gateway-credentials:read'), getAccount, paymentMethodIsCard, credentialsController.index)
app.get(nc.edit, permission('gateway-credentials:update'), getAccount, paymentMethodIsCard, credentialsController.editNotificationCredentials)
app.post(nc.update, permission('gateway-credentials:update'), getAccount, paymentMethodIsCard, credentialsController.updateNotificationCredentials)
app.get(notificationCredentials.index, permission('gateway-credentials:read'), getAccount, paymentMethodIsCard, credentialsController.index)
app.get(notificationCredentials.edit, permission('gateway-credentials:update'), getAccount, paymentMethodIsCard, credentialsController.editNotificationCredentials)
app.post(notificationCredentials.update, permission('gateway-credentials:update'), getAccount, paymentMethodIsCard, credentialsController.updateNotificationCredentials)

// MERCHANT DETAILS
app.get(merchantDetails.index, permission('merchant-details:read'), merchantDetailsController.getIndex)
Expand All @@ -242,8 +246,8 @@ module.exports.bind = function (app) {
app.post(apiKeys.revoke, permission('tokens:delete'), getAccount, apiKeysController.postRevoke)
app.post(apiKeys.update, permission('tokens:update'), getAccount, apiKeysController.postUpdate)

account.get(pt.index, permission('payment-types:read'), paymentTypesController.getIndex)
account.post(pt.index, permission('payment-types:update'), paymentTypesController.postIndex)
account.get(paymentTypes.index, permission('payment-types:read'), paymentTypesController.getIndex)
account.post(paymentTypes.index, permission('payment-types:update'), paymentTypesController.postIndex)

// DIGITAL WALLET
app.get(digitalWallet.applePay, permission('payment-types:update'), getAccount, paymentMethodIsCard, digitalWalletController.getApplePay)
Expand All @@ -252,19 +256,19 @@ module.exports.bind = function (app) {
app.post(digitalWallet.googlePay, permission('payment-types:update'), getAccount, paymentMethodIsCard, digitalWalletController.postGooglePay)

// EMAIL
app.get(en.index, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.index)
app.get(en.indexRefundTabEnabled, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.indexRefundTabEnabled)
app.get(en.edit, permission('email-notification-paragraph:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.edit)
app.post(en.confirm, permission('email-notification-paragraph:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirm)
app.post(en.update, permission('email-notification-paragraph:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.update)
app.get(en.collection, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.collectionEmailIndex)
app.post(en.collection, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.collectionEmailUpdate)
app.get(en.confirmation, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirmationEmailIndex)
app.post(en.confirmation, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirmationEmailUpdate)
app.post(en.off, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirmationEmailOff)
app.post(en.on, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirmationEmailOn)
app.get(en.refund, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.refundEmailIndex)
app.post(en.refund, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.refundEmailUpdate)
app.get(emailNotifications.index, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.index)
app.get(emailNotifications.indexRefundTabEnabled, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.indexRefundTabEnabled)
app.get(emailNotifications.edit, permission('email-notification-paragraph:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.edit)
app.post(emailNotifications.confirm, permission('email-notification-paragraph:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirm)
app.post(emailNotifications.update, permission('email-notification-paragraph:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.update)
app.get(emailNotifications.collection, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.collectionEmailIndex)
app.post(emailNotifications.collection, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.collectionEmailUpdate)
app.get(emailNotifications.confirmation, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirmationEmailIndex)
app.post(emailNotifications.confirmation, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirmationEmailUpdate)
app.post(emailNotifications.off, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirmationEmailOff)
app.post(emailNotifications.on, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.confirmationEmailOn)
app.get(emailNotifications.refund, permission('email-notification-template:read'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.refundEmailIndex)
app.post(emailNotifications.refund, permission('email-notification-toggle:update'), getAccount, getEmailNotification, paymentMethodIsCard, emailNotificationsController.refundEmailUpdate)

// SERVICE SWITCHER
app.get(serviceSwitcher.index, myServicesController.getIndex)
Expand All @@ -289,17 +293,17 @@ module.exports.bind = function (app) {
app.post(teamMembers.invite, permission('users-service:create'), inviteUserController.invite)

// 3D SECURE TOGGLE
app.get(t3ds.index, permission('toggle-3ds:read'), getAccount, paymentMethodIsCard, toggle3dsController.get)
app.post(t3ds.index, permission('toggle-3ds:update'), getAccount, paymentMethodIsCard, toggle3dsController.post)
account.get(toggle3ds.index, permission('toggle-3ds:read'), paymentMethodIsCard, toggle3dsController.get)
account.post(toggle3ds.index, permission('toggle-3ds:update'), paymentMethodIsCard, toggle3dsController.post)

// MOTO MASK CARD NUMBER & SECURITY CODE TOGGLE
app.get(toggleMotoMaskCardNumberAndSecurityCode.cardNumber, permission('moto-mask-input:read'), getAccount, paymentMethodIsCard, toggleMotoMaskCardNumber.get)
app.post(toggleMotoMaskCardNumberAndSecurityCode.cardNumber, permission('moto-mask-input:update'), getAccount, paymentMethodIsCard, toggleMotoMaskCardNumber.post)
app.get(toggleMotoMaskCardNumberAndSecurityCode.securityCode, permission('moto-mask-input:read'), getAccount, paymentMethodIsCard, toggleMotoMaskSecurityCode.get)
app.post(toggleMotoMaskCardNumberAndSecurityCode.securityCode, permission('moto-mask-input:update'), getAccount, paymentMethodIsCard, toggleMotoMaskSecurityCode.post)

account.get(billingAddress.index, permission('toggle-billing-address:read'), toggleBillingAddressController.getIndex)
account.post(billingAddress.index, permission('toggle-billing-address:update'), toggleBillingAddressController.postIndex)
account.get(toggleBillingAddress.index, permission('toggle-billing-address:read'), toggleBillingAddressController.getIndex)
account.post(toggleBillingAddress.index, permission('toggle-billing-address:update'), toggleBillingAddressController.postIndex)

// Prototyping
app.get(prototyping.demoService.index, permission('transactions:read'), resolveService, getAccount, restrictToSandbox, testWithYourUsersController.index)
Expand Down
12 changes: 8 additions & 4 deletions app/utils/nav-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const formatPSPname = require('./format-PSP-name')
const mainSettingsPaths = [
paths.settings,
paths.digitalWallet,
paths.toggle3ds,
paths.account.toggle3ds,
paths.account.toggleBillingAddress,
paths.emailNotifications,
paths.toggleMotoMaskCardNumberAndSecurityCode
Expand Down Expand Up @@ -54,7 +54,7 @@ const serviceNavigationItems = (currentPath, permissions, type) => {
...mainSettingsPaths,
...yourPspPaths,
paths.apiKeys,
paths.paymentTypes
paths.account.paymentTypes
]) : false,
permissions: _.some([
permissions.tokens_read,
Expand Down Expand Up @@ -94,13 +94,17 @@ const adminNavigationItems = (currentPath, permissions, type, paymentProvider, a
{
id: 'navigation-menu-payment-types',
name: 'Card types',
url: formatAccountPathsFor(paths.paymentTypes.index, account.external_id),
current: pathLookup(currentPath, paths.paymentTypes.index),
url: formatAccountPathsFor(paths.account.paymentTypes.index, account.external_id),
current: pathLookup(currentPath, paths.account.paymentTypes.index),
permissions: permissions.payment_types_read && type === 'card'
}
]
}

// const pathMatches(url, paths) {

// }

module.exports = {
serviceNavigationItems: serviceNavigationItems,
adminNavigationItems: adminNavigationItems
Expand Down
2 changes: 1 addition & 1 deletion app/views/settings/index.njk
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
classes: 'govuk-!-width-one-quarter',
items: [
{
href: routes.toggle3ds.index,
href: formatAccountPathsFor(routes.account.toggle3ds.index, currentGatewayAccount.external_id),
classes: 'govuk-link--no-visited-state',
text: 'Change' if permissions.toggle_3ds_update else 'View',
visuallyHiddenText: '3D Secure settings'
Expand Down
2 changes: 1 addition & 1 deletion app/views/toggle-3ds/index.njk
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
})
}}
</form>
<p class="govuk-body">or <a href="/" class="govuk-link govuk-link--no-visited-state">cancel</a></p>
<p class="govuk-body">or <a href="{{routes.settings.index}}" class="govuk-link govuk-link--no-visited-state">cancel</a></p>
{% else %}
<h1 class="govuk-heading-l govuk-!-margin-top-6">3D Secure</h1>
<p class="govuk-body" id="threeds-not-supported">3D Secure is not currently supported for this payment service provider (PSP).</p>
Expand Down
7 changes: 5 additions & 2 deletions test/cypress/integration/settings/3ds.cy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const stripeAccountSetupStubs = require('../../stubs/stripe-account-setup-stub')
describe('3DS settings page', () => {
const userExternalId = 'cd0fa54cf3b7408a80ae2f1b93e7c16e'
const gatewayAccountId = 42
const gatewayAccountExternalId = 'a-valid-external-id'
const serviceName = 'Purchase a positron projection permit'

function setup3dsStubs (opts = {}) {
Expand All @@ -31,10 +32,11 @@ describe('3DS settings page', () => {
user = userStubs.getUserSuccess({ userExternalId, gatewayAccountId, serviceName })
}
const gatewayAccount = gatewayAccountStubs.getGatewayAccountSuccess({ gatewayAccountId, paymentProvider: opts.gateway, requires3ds: opts.requires3ds })
const gatewayAccountByExternalId = gatewayAccountStubs.getGatewayAccountByExternalIdSuccess({ gatewayAccountId, gatewayAccountExternalId, paymentProvider: opts.gateway, requires3ds: opts.requires3ds })

const card = gatewayAccountStubs.getAcceptedCardTypesSuccess({ gatewayAccountId, updated: false, maestro: opts.maestro })

stubs.push(user, gatewayAccount, card)
stubs.push(user, gatewayAccount, gatewayAccountByExternalId, card)

cy.task('setupStubs', stubs)
}
Expand All @@ -52,7 +54,7 @@ describe('3DS settings page', () => {
cy.setEncryptedCookies(userExternalId, gatewayAccountId)
cy.visit('/settings')
cy.get('.govuk-summary-list__key').first().should('not.contain', '3D Secure')
cy.visit('/3ds')
cy.visit(`/account/${gatewayAccountExternalId}/3ds`)
cy.title().should('eq', `3D Secure - ${serviceName} - GOV.UK Pay`)
cy.get('#threeds-not-supported').should('be.visible')
cy.get('#threeds-not-supported').should('contain', '3D Secure is not currently supported for this payment service provider (PSP).')
Expand Down Expand Up @@ -182,6 +184,7 @@ describe('3DS settings page', () => {
cy.task('setupStubs', [
userStubs.getUserSuccess({ userExternalId, gatewayAccountId, serviceName }),
gatewayAccountStubs.getGatewayAccountSuccess({ gatewayAccountId, type: 'live', paymentProvider: 'stripe', requires3ds: true }),
gatewayAccountStubs.getGatewayAccountByExternalIdSuccess({ gatewayAccountId, gatewayAccountExternalId, type: 'live', paymentProvider: 'stripe', requires3ds: true }),
gatewayAccountStubs.getAcceptedCardTypesSuccess({ gatewayAccountId, updated: false }),
stripeAccountSetupStubs.getGatewayAccountStripeSetupSuccess({ gatewayAccountId, vatNumber: true, bankAccount: true, companyNumber: true, responsiblePerson: true })
])
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/stubs/user-stubs.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ function getUserSuccessRespondDifferentlySecondTime (userExternalId, firstRespon
function buildServiceRoleOpts (opts) {
const serviceRole = {
service: {
gateway_account_ids: [opts.gatewayAccountId]
gateway_account_ids: [String(opts.gatewayAccountId)]
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/integration/payment-types/payment-types.it.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let app

function whenGetPaymentTypes (baseApp) {
return request(baseApp)
.get(formatAccountPathsFor(paths.paymentTypes.index, gatewayAccountExternalId))
.get(formatAccountPathsFor(paths.account.paymentTypes.index, gatewayAccountExternalId))
}

function whenPaymentTypesUpdated (baseApp, payload) {
Expand All @@ -34,7 +34,7 @@ function whenPaymentTypesUpdated (baseApp, payload) {
csrfToken: csrf().create('123')
}
return request(baseApp)
.post(formatAccountPathsFor(paths.paymentTypes.index, gatewayAccountExternalId))
.post(formatAccountPathsFor(paths.account.paymentTypes.index, gatewayAccountExternalId))
.send(payload)
}

Expand Down

0 comments on commit 055b084

Please sign in to comment.