Skip to content

Commit

Permalink
24293 - verify auth access to entity (#66)
Browse files Browse the repository at this point in the history
* 24293 - feature: add verification and redirect on page access for forbidden entities.

* 24293 - tests: refactor tests; add tests; add interface types for commands.

* 24293 - tests:updating tests that are failing.

* 24293 - chore: eslint

* pr fixes.

* fix: remove dev/testing check to hardcoded redirect.

* tryin' to fix test not working in PR.
  • Loading branch information
hfekete authored Nov 19, 2024
1 parent 7ca7820 commit 463f8c0
Show file tree
Hide file tree
Showing 18 changed files with 320 additions and 69 deletions.
41 changes: 24 additions & 17 deletions cypress/e2e/components/filings/addStaffFiling.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ context('Add Staff Filing', () => {
})
cy.visitBusinessDashFor('businessInfo/ben/active.json', undefined, false, false, undefined, allFilings, true)
// cy.wait(5000)
cy.get('[data-cy="add-staff-filing"]').should('exist').click()
cy.get('[data-cy="add-staff-filing"]').should('exist')
cy.get('[data-cy="add-staff-filing"]').click()
cy.get('[data-cy="admin-freeze"]').should('exist').should('not.be.disabled')
cy.get('[data-cy="dissolution"]').should('exist').should('not.be.disabled')
cy.get('[data-cy="registrar-notation"]').should('exist').should('not.be.disabled')
Expand All @@ -42,7 +43,8 @@ context('Add Staff Filing', () => {
})
cy.visitBusinessDashFor('businessInfo/sp/active.json', undefined, false, false, undefined, allFilings, true)
// cy.wait(5000)
cy.get('[data-cy="add-staff-filing"]').should('exist').click()
cy.get('[data-cy="add-staff-filing"]').should('exist')
cy.get('[data-cy="add-staff-filing"]').click()
cy.get('[data-cy="admin-freeze"]').should('exist').should('not.be.disabled')
cy.get('[data-cy="dissolution"]').should('exist').should('not.be.disabled')
cy.get('[data-cy="registrar-notation"]').should('exist').should('not.be.disabled')
Expand All @@ -65,7 +67,8 @@ context('Add Staff Filing', () => {
})
cy.visitBusinessDashFor('businessInfo/bc/historical.json', undefined, false, false, undefined, allFilings, true)
// cy.wait(5000)
cy.get('[data-cy="add-staff-filing"]').should('exist').click()
cy.get('[data-cy="add-staff-filing"]').should('exist')
cy.get('[data-cy="add-staff-filing"]').click()
cy.get('[data-cy="admin-freeze"]').should('not.exist')
cy.get('[data-cy="dissolution"]').should('not.exist')
cy.get('[data-cy="registrar-notation"]').should('exist').should('not.be.disabled')
Expand Down Expand Up @@ -142,27 +145,31 @@ context('Add Staff Filing', () => {
response).as('businessComments')
})
cy.visitBusinessDashFor('businessInfo/ben/active.json', undefined, false, false, undefined, allFilings, true)
cy.get('[data-cy="add-staff-filing"]').should('exist').click()
cy.get('[data-cy="add-staff-filing"]').should('exist')
cy.get('[data-cy="add-staff-filing"]').click()

// Add Registrar Notation
cy.get('[data-cy="registrar-notation"]').click()
.get('[data-cy="modal-body"]')

cy.get('[data-cy="modal-body"]')
.should('contain', 'Enter a Registrar\'s Notation that will appear on the ledger for this entity')
.get('[data-cy="notation"]').should('exist')
.get('[data-cy="court-order-number"]').should('exist')
.get('[data-cy="plan-of-arrangement"]').should('exist')
.get('[data-cy="submit-add-staff-filing-modal"]').click()
.get('[data-cy="modal-body"]').should('contain', 'Enter a Registrar\'s Notation')
.get('[data-cy="cancel-add-staff-filing-modal"]').click()

cy.get('[data-cy="notation"]').should('exist')
cy.get('[data-cy="court-order-number"]').should('exist')
cy.get('[data-cy="plan-of-arrangement"]').should('exist')
cy.get('[data-cy="submit-add-staff-filing-modal"]').click()
cy.get('[data-cy="modal-body"]').should('contain', 'Enter a Registrar\'s Notation')
cy.get('[data-cy="cancel-add-staff-filing-modal"]').click()

// Add Court Order
cy.get('[data-cy="add-staff-filing"]').click()
.get('[data-cy="court-order"]').click()
.get('[data-cy="modal-body"]')

cy.get('[data-cy="court-order"]').click()
cy.get('[data-cy="modal-body"]')
.should('contain', 'Enter a Court Order that will appear on the ledger for this entity')
.get('[data-cy="notation"]').should('exist')
.get('[data-cy="court-order-upload"]').should('exist')
.get('[data-cy="court-order-number"]').should('exist')
.get('[data-cy="plan-of-arrangement"]').should('exist')
cy.get('[data-cy="notation"]').should('exist')
cy.get('[data-cy="court-order-upload"]').should('exist')
cy.get('[data-cy="court-order-number"]').should('exist')
cy.get('[data-cy="plan-of-arrangement"]').should('exist')
})
})
2 changes: 1 addition & 1 deletion cypress/e2e/components/todos/continuation-in.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ context('TODOs -> Continuation-In todo items', () => {
// subtitle
cy.get('[data-cy^="todoItem-label-"]')
.should('exist')
.contains('DRAFT')
.should('contain', 'DRAFT')

// View More button should not exist as this example has no Name Request
cy.get('[data-cy^="todoItem-showMore-"]').should('not.exist')
Expand Down
21 changes: 12 additions & 9 deletions cypress/e2e/components/tombstone/menu-options.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ context('Business tombstone - action buttons in the dropdown menu', () => {

cy.get('[data-cy="button.moreActions"]')
.click()
cy.get('[data-cy="button.moreActions"]')
.find('[data-cy="button.digitalCredentials"]')
.should('have.text', 'Digital Business Cards')
.as('digitalBusinessCardsButton')

cy.fixture('businessInfo/sp/withDigitalCredential.json').then((businessInfo) => {
cy.get('@digitalBusinessCardsButton')
.click()
cy.get('@digitalBusinessCardsButton')
.wait('@getDigitalCredentials')
.its('request.url').should('include', `/${businessInfo.business.identifier}/digital-credentials/`)
})
Expand All @@ -24,6 +26,7 @@ context('Business tombstone - action buttons in the dropdown menu', () => {

cy.get('[data-cy="button.moreActions"]')
.click()
cy.get('[data-cy="button.moreActions"]')
.find('[data-cy="button.digitalCredentials"]')
.should('not.exist')
})
Expand All @@ -32,10 +35,7 @@ context('Business tombstone - action buttons in the dropdown menu', () => {
Cypress.on('uncaught:exception', (error: Error) => {
// returning false here prevents Cypress from failing the test for the postMessage error that happens sometimes
console.error('Caught error', error)
if (error.stack?.includes('PrimaryOriginCommunicator.toSource')) {
return false
}
return true
return !error.stack?.includes('PrimaryOriginCommunicator.toSource')
})
// Intercept the request for Continuation Out, Request AGM Extension, Request AGM Location Change, and Amalgamate
cy.intercept('GET', '**/**/consent-continuation-out?**filingId=0**').as('goToContinuationOut')
Expand Down Expand Up @@ -90,18 +90,21 @@ context('Business tombstone - action buttons in the dropdown menu', () => {
.find('[data-cy="bcros-dialog-title"]')
.should('have.text', 'Voluntary Dissolution')

cy.get('[data-cy="dissolution-button"]').click().wait('@fileDissolution') // Cypress doesn't like to wait for CORS urls .wait('@goToDissolution')
cy.get('[data-cy="dissolution-button"]').click()
cy.wait(['@fileDissolution']) // Cypress doesn't like to wait for CORS urls .wait('@goToDissolution')

// open the dissolution confirm dialog for 'Dissolution' for a SP company
cy.visitBusinessDashFor('businessInfo/sp/active.json')
.get('[data-cy="button.moreActions"]')
.click()
cy.get('[data-cy="button.moreActions"]').click()

cy.get('[data-cy="button.moreActions"]')
.find('[data-cy="button.dissolveBusiness"]')
.click()
.get('[data-cy="bcros-dialog-confirmDissolution"]')
cy.get('[data-cy="bcros-dialog-confirmDissolution"]')
.find('[data-cy="bcros-dialog-title"]')
.should('have.text', 'Dissolution')

cy.get('[data-cy="dissolution-button"]').click().wait('@fileDissolution')// Cypress doesn't like to wait for CORS urls .wait('@goToDissolution')
cy.get('[data-cy="dissolution-button"]').click()
cy.wait(['@fileDissolution'])// Cypress doesn't like to wait for CORS urls .wait('@goToDissolution')
})
})
13 changes: 9 additions & 4 deletions cypress/e2e/error-flows/entry-auth-error.cy.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
context('Business Dash Auth Error Handling', () => {
beforeEach(() => {
cy.visitBusinessDashAuthError()
})

it('should display error modal', () => {
cy.visitBusinessDashAuthError()
cy.get('[data-cy="bcros-dialog"]').should('exist')
cy.get('[data-cy="bcros-dialog"]').find('h1').should('have.text', 'Business Dashboard Unavailable')
cy.get('[data-cy="bcros-dialog"]').find('[data-cy="bcros-dialog-text"]').find('p')
Expand All @@ -13,4 +10,12 @@ context('Business Dash Auth Error Handling', () => {
cy.get('[data-cy="bcros-dialog"]').find('[data-cy="contact-value"]').should('exist')
cy.get('[data-cy="bcros-dialog"]').find('[data-cy="bcros-dialog-btn"]').should('exist')
})

it('should redirect to error page and show modal', () => {
cy.visitBusinessDashAuthError('BC0871429', 'BEN', 'EntityAuthError')
cy.url().should('contain', 'errors/entity')
cy.get('[data-cy="bcros-dialog-text"]').should('exist')
cy.get('[data-cy="bcros-dialog-text"]').should('contain',
'Your account is currently unable to access this Business. This may be because of the following:')
})
})
10 changes: 5 additions & 5 deletions cypress/e2e/initial-page-load.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ context('Business Dashboard -> Basic page rendering tests', () => {
cy.interceptParties(legalType, isHistorical).as('getParties')
cy.interceptAffiliationRequests(false, false).as('getAffiliationRequests')
cy.interceptTasks('tasksEmpty.json').as('getTasks')
cy.interceptAuthorizations(businessIdentifier)

cy.visit(`/${businessIdentifier}`).then(() => {
cy.get('[data-cy="loading-icon"]').should('be.visible').then(() => {
cy.wait(['@getBusinessInfo'])
cy.get('[data-cy="loading-icon"]').should('not.be.visible')
})
cy.visit(`/${businessIdentifier}`)
cy.get('[data-cy="loading-icon"]').should('be.visible').then(() => {
cy.wait(['@getBusinessInfo'])
cy.get('[data-cy="loading-icon"]').should('not.be.visible')
})
})
})
64 changes: 48 additions & 16 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BusinessI } from '../../src/interfaces/business-i'
import { BusinessStateE } from '../../src/enums/business-state-e'
import { BoostrapFiling } from '../fixtures/filings/draft/incorporation-applicaton'

Cypress.Commands.add('interceptBusinessInfo', (identifier, legalType, isHistorical) => {
Cypress.Commands.add('interceptBusinessInfo', (identifier, legalType, isHistorical = false) => {
cy.fixture(`business${legalType}`).then((business) => {
business.identifier = identifier
if (isHistorical) {
Expand Down Expand Up @@ -128,6 +128,14 @@ Cypress.Commands.add('interceptFilingHistory', (businessIdentifier, filings) =>
)
})

Cypress.Commands.add('interceptAuthorizations', (businessIdentifier: string) => {
cy.intercept(
'GET',
`**/api/v1/entities/${businessIdentifier}/authorizations`,
{ body: { roles: ['view'] } }
)
})

Cypress.Commands.add('visitBusinessDash',
(
identifier = 'BC0871427',
Expand All @@ -139,6 +147,7 @@ Cypress.Commands.add('visitBusinessDash',
) => {
cy.wait(500) // https://github.com/cypress-io/cypress/issues/27648
sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true')
cy.interceptAuthorizations(identifier).as('authorizations')
cy.intercept('GET', '**/api/v1/users/**/settings', { fixture: 'settings.json' }).as('getSettings')
cy.intercept(
'REPORT',
Expand All @@ -156,6 +165,7 @@ Cypress.Commands.add('visitBusinessDash',

cy.visit(`/${identifier}`)
cy.wait([
'@authorizations',
'@getSettings',
'@getProducts',
'@getBusinessContact',
Expand Down Expand Up @@ -206,6 +216,7 @@ Cypress.Commands.add('visitBusinessDashFor',
}

// load interceptors
cy.interceptAuthorizations(business.identifier).as('authorizations')
cy.interceptBusinessInfoFor(business).as('getBusinessInfo')
cy.interceptBusinessContact(business.identifier, 'BEN').as('getBusinessContact')
cy.interceptAddresses(business.legalType).as('getAddresses')
Expand All @@ -218,6 +229,7 @@ Cypress.Commands.add('visitBusinessDashFor',
// go !
cy.visit(`/${business.identifier}`)
cy.wait([
'@authorizations',
'@getSettings',
'@getProducts',
'@getBusinessContact',
Expand Down Expand Up @@ -265,28 +277,48 @@ Cypress.Commands.add('visitTempBusinessDash', (draftFiling = undefined, asStaff
`**/api/v2/businesses/${tempBusiness.identifier}/filings`,
bootstrapFiling
)
cy.interceptAuthorizations(tempBusiness.identifier).as('authorizations')

// go !
cy.visit(`/${tempBusiness.identifier}`)
cy.wait([
'@authorizations',
'@getSettings',
'@getProducts'
])
cy.injectAxe()
})

Cypress.Commands.add('visitBusinessDashAuthError', (identifier = 'BC0871427', legalType = 'BEN') => {
cy.wait(500) // https://github.com/cypress-io/cypress/issues/27648
sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true')
cy.intercept('GET', '**/api/v1/users/**/settings', { statusCode: 500, body: {} }).as('getSettingsError')
cy.intercept(
'REPORT',
'https://app.launchdarkly.com/sdk/evalx/**/context',
{ fixture: 'ldarklyContext.json' }
).as('getLdarklyContext')
cy.interceptBusinessContact(identifier, legalType).as('getBusinessContact')
cy.interceptBusinessInfo(identifier, legalType).as('getBusinessInfo')
cy.visit(`/${identifier}`)
cy.wait(['@getSettingsError'])
cy.injectAxe()
})
Cypress.Commands.add('visitBusinessDashAuthError',
(identifier = 'BC0871427', legalType = 'BEN', errorType = 'SettingsError') => {
cy.wait(500) // https://github.com/cypress-io/cypress/issues/27648
sessionStorage.setItem('FAKE_CYPRESS_LOGIN', 'true')
const waitFor = []

if (errorType === 'SettingsError') {
cy.intercept('GET', '**/api/v1/users/**/settings', { statusCode: 500, body: {} }).as('getSettingsError')
waitFor.push('@getSettingsError')
} else {
cy.intercept('GET', '**/api/v1/users/**/settings', { fixture: 'settings.json' }).as('getSettings')
waitFor.push('@getSettings')
}

if (errorType === 'EntityAuthError') {
cy.intercept('GET', `**/api/v1/entities/${identifier}/authorizations`, {}).as('authorizationsError')
waitFor.push('@authorizationsError')
} else {
cy.interceptAuthorizations(identifier).as('authorizations')
waitFor.push('@authorizations')
}

cy.intercept(
'REPORT',
'https://app.launchdarkly.com/sdk/evalx/**/context',
{ fixture: 'ldarklyContext.json' }
).as('getLdarklyContext')
cy.interceptBusinessContact(identifier, legalType).as('getBusinessContact')
cy.interceptBusinessInfo(identifier, legalType).as('getBusinessInfo')
cy.visit(`/${identifier}`)
cy.wait(waitFor)
cy.injectAxe()
})
53 changes: 53 additions & 0 deletions cypress/support/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// cypress/support/index.ts
import { ApiResponseFilingI } from '../../src/interfaces/filing-i'
import { BusinessI } from '../../src/interfaces/business-i'

declare global {
namespace Cypress {
interface Chainable {
interceptBusinessInfo (identifier: string, legalType: string, isHistorical?: boolean): Chainable<null>,

interceptBusinessInfoFor (business: BusinessI): Chainable<null>,

interceptBusinessContact (identifier: string, legalType: string): Chainable<null>,

interceptAffiliationRequests (
hasAffiliationInvitations: boolean, hasAffiliationInvitationError: boolean): Chainable<null>,

interceptAddresses (legalType: string): Chainable<null>,

interceptParties (legalType: string, hasCustodian: boolean): Chainable<null>,

interceptPayApiResponse (code: string): Chainable<null>,

interceptTasks (fixture: string): Chainable<null>,

interceptFilingHistory (businessIdentifier: string, filings: ApiResponseFilingI[]): Chainable<null>,

interceptAuthorizations (businessIdentifier: string): Chainable<null>,

visitBusinessDash (
identifier?: string,
legalType?: string,
isHistorical?: boolean,
hasAffiliationInvitations?: boolean,
hasAffiliationInvitationError?: boolean,
taskFixture?: string
): Chainable,

visitBusinessDashFor (
path: string,
identifier?: string,
hasAffiliationInvitations?: boolean,
hasAffiliationInvitationError?: boolean,
taskFixture?: string,
filings?: ApiResponseFilingI[],
asStaff?: boolean
): Chainable,

visitTempBusinessDash (draftFiling?: unknown, asStaff?: boolean): Chainable

visitBusinessDashAuthError (identifier?: string, legalType?: string, errorType?: string): Chainable
}
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
"build:local": "nuxt build",
"dev": "nuxt dev --port=3000",
"generate": "nuxt generate",
"lint": "eslint --cache --ext '.ts,.vue' . --max-warnings 0",
"lint:fix": "eslint --cache --ext '.ts,.vue' . --max-warnings 0 --fix",
"lint": "eslint --cache --ext '.ts,.vue' src --max-warnings 0",
"lint:fix": "eslint --cache --ext '.ts,.vue' src --max-warnings 0 --fix",
"preview": "nuxt preview",
"postinstall": "nuxt prepare",
"test:unit": "vitest",
Expand Down
3 changes: 2 additions & 1 deletion src/app.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { StatusCodes } from 'http-status-codes'
import { ErrorCodeE } from '~/enums/error-code-e'
// // errors
const errorDisplay = ref(false)
Expand Down Expand Up @@ -47,7 +48,7 @@ const handleError = (error: ErrorI) => {
// Sentry.captureException(error)
}
errorContactInfo.value = true
errorDisplay.value = true
errorDisplay.value = error.type !== ErrorCodeE.AUTH_ENTITY_ACCESS_ERROR
break
case ErrorCategoryE.ACCOUNT_SETTINGS:
errorInfo.value = getDefaultError()
Expand Down
Loading

0 comments on commit 463f8c0

Please sign in to comment.