Skip to content

Commit

Permalink
MIA-85: RBAC for keyworkers homepage
Browse files Browse the repository at this point in the history
  • Loading branch information
JackReeveMoJ committed Jan 17, 2025
1 parent a2dc65e commit f07fb7b
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 27 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,6 @@ integration_tests/screenshots/
*/*.iml
**/Chart.lock
**/.DS_Store

# wiremock
wiremock.jar
15 changes: 15 additions & 0 deletions integration_tests/mockApis/keyworkerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ const stubKeyworkerApiHealth = () =>
},
})

const stubKeyworkerApiStatusIsKeyworker = (isKeyworker: boolean) =>
stubFor({
request: {
method: 'GET',
urlPattern: '/keyworker-api/prisons/LEI/key-workers/USER1/status',
},
response: {
status: 200,
headers: { 'Content-Type': 'application/json;charset=UTF-8' },
jsonBody: { isKeyworker },
},
})

export default {
stubKeyworkerApiHealth,
stubKeyworkerApiStatusIsKeyworker: () => stubKeyworkerApiStatusIsKeyworker(true),
stubKeyworkerApiStatusIsNotKeyworker: () => stubKeyworkerApiStatusIsKeyworker(false),
}
6 changes: 6 additions & 0 deletions server/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ export default function createApp(services: Services): express.Application {
})
app.use(breadcrumbs())
app.use(dpsComponents.retrieveCaseLoadData({ logger }))

app.get('/not-authorised', (_, res) => {
res.status(403)
res.render('not-authorised', { showBreadcrumbs: true })
})

app.use(populateUserPermissions())
app.use(routes(services))

Expand Down
8 changes: 6 additions & 2 deletions server/middleware/permissionsMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ export default function populateUserPermissions(): RequestHandler {
res.locals.user.permissions.push('view')
}

next()
if (!res.locals.user.permissions.length) {
return res.redirect('/not-authorised')
}

return next()
} catch (e) {
logger.error(e, `Failed to retrieve keyworker status: ${res.locals.user?.username}`)
next()
return next(e)
}
}
}
2 changes: 2 additions & 0 deletions server/routes/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export class HomePageController {
res.locals.breadcrumbs.popLastItem()

return res.render('view', {
hasViewPermission: res.locals.user.permissions.includes('view'),
hasAllocatePermission: res.locals.user.permissions.includes('allocate'),
showBreadcrumbs: true,
})
}
Expand Down
74 changes: 64 additions & 10 deletions server/routes/test.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,72 @@ context('test / homepage', () => {
cy.task('reset')
})

describe('Role based access', () => {
it('should redirect to not-authorised page if user has no permission', () => {
cy.task('stubSignIn', {
roles: [],
})
cy.task('stubKeyworkerApiStatusIsNotKeyworker')
navigateToTestPage()
cy.url().should('include', 'not-authorised')
cy.findByText('You do not have permission to access this page').should('be.visible')
cy.findByText('Contact the helpdesk').should('be.visible')
})

it('should show correct services when user has only a view permission', () => {
cy.task('stubSignIn', {
roles: [],
})
cy.task('stubKeyworkerApiStatusIsKeyworker')
navigateToTestPage()

cy.findByRole('heading', { name: /^Key workers$/i }).should('be.visible')

cy.findByRole('link', { name: /View all without a key worker$/i }).should('be.visible')

cy.findByRole('link', { name: /View by residential location$/i }).should('be.visible')

cy.findByRole('link', { name: /Search for a prisoner$/i }).should('be.visible')

cy.findByRole('link', { name: /View key workers in your establishment$/i }).should('be.visible')

cy.findByText('You can view a key worker’s availability and check their individual statistics.')

cy.findByRole('link', { name: /Key worker statistics$/i }).should('be.visible')

cy.findAllByRole('link', { name: /Manage your establishments key worker settings$/i }).should('not.exist')
})

it('should show correct services when user has allocate permission', () => {
cy.task('stubSignIn', {
roles: ['OMIC_ADMIN'],
})
cy.task('stubKeyworkerApiStatusIsNotKeyworker')
navigateToTestPage()

cy.findByRole('heading', { name: /^Key workers$/i }).should('be.visible')

cy.findByRole('link', { name: /View all without a key worker$/i }).should('be.visible')

cy.findByRole('link', { name: /View by residential location$/i }).should('be.visible')

cy.findByRole('link', { name: /Search for a prisoner$/i }).should('be.visible')

cy.findByRole('link', { name: /View key workers in your establishment$/i }).should('be.visible')

cy.findByText(
'You can manage a key worker’s availability, reassign their prisoners and check their individual statistics.',
)

cy.findByRole('link', { name: /Key worker statistics$/i }).should('be.visible')

cy.findAllByRole('link', { name: /Manage your establishments key worker settings$/i }).should('be.visible')
})
})

it('shows all tiles when user has all required roles', () => {
cy.task('stubSignIn', {
roles: [],
roles: ['OMIC_ADMIN', 'KEYWORKER_MONITOR'],
})
navigateToTestPage()

Expand Down Expand Up @@ -42,15 +105,6 @@ context('test / homepage', () => {
.and('to.equal', 'https://legacy.key-workers.url/manage-key-worker-settings')
})

it.skip('shows unauthorised message if user does not have any of the required roles', () => {
cy.task('stubSignIn', {
roles: [],
})
navigateToTestPage()
cy.findByText('You are not authorised to use this application.').should('be.visible')
cy.findByRole('heading', { name: /^Key workers$/i }).should('not.exist')
})

const navigateToTestPage = () => {
cy.signIn({ failOnStatusCode: false })
cy.visit('/', { failOnStatusCode: false })
Expand Down
37 changes: 22 additions & 15 deletions server/routes/view.njk
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,20 @@
</div>
</div>

<div class="govuk-grid-column-one-third card-group__item">
<div class="card card--clickable">
<h2 class="govuk-heading-m card__heading">
<a class="govuk-link govuk-link--no-visited-state card__link" href="{{ legacyKeyWorkersUiUrl }}/key-worker-search">View key workers in your establishment</a>
</h2>
<p class="govuk-body card__description">You can manage a key worker’s availability, reassign their prisoners and check their individual statistics.</p>
{% if hasViewPermission or hasAllocatePermission %}
<div class="govuk-grid-column-one-third card-group__item">
<div class="card card--clickable">
<h2 class="govuk-heading-m card__heading">
<a class="govuk-link govuk-link--no-visited-state card__link" href="{{ legacyKeyWorkersUiUrl }}/key-worker-search">View key workers in your establishment</a>
</h2>
{% if hasAllocatePermission %}
<p class="govuk-body card__description">You can manage a key worker’s availability, reassign their prisoners and check their individual statistics.</p>
{% else %}
<p class="govuk-body card__description">You can view a key worker’s availability and check their individual statistics.</p>
{% endif %}
</div>
</div>
</div>
{% endif %}

<div class="govuk-grid-column-one-third card-group__item">
<div class="card card--clickable">
Expand All @@ -57,15 +63,16 @@
<p class="govuk-body card__description">View the statistics for your establishment’s key workers.</p>
</div>
</div>

<div class="govuk-grid-column-one-third card-group__item">
<div class="card card--clickable">
<h2 class="govuk-heading-m card__heading">
<a class="govuk-link govuk-link--no-visited-state card__link" href="{{ legacyKeyWorkersUiUrl }}/manage-key-worker-settings">Manage your establishment’s key worker settings</a>
</h2>
<p class="govuk-body card__description">Allow auto-allocation, edit key worker capacity and session frequency.</p>
{% if hasAllocatePermission %}
<div class="govuk-grid-column-one-third card-group__item">
<div class="card card--clickable">
<h2 class="govuk-heading-m card__heading">
<a class="govuk-link govuk-link--no-visited-state card__link" href="{{ legacyKeyWorkersUiUrl }}/manage-key-worker-settings">Manage your establishment’s key worker settings</a>
</h2>
<p class="govuk-body card__description">Allow auto-allocation, edit key worker capacity and session frequency.</p>
</div>
</div>
</div>
{% endif %}

</div>
</div>
Expand Down
File renamed without changes.

0 comments on commit f07fb7b

Please sign in to comment.