Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
341c5d0
Add authentication for publication
KianKwa Dec 1, 2025
16610f2
Update user provenance for CFT users
KianKwa Dec 1, 2025
e7b9e8e
Update user provenance for CFT users
KianKwa Dec 1, 2025
cc5a05f
Merge remote-tracking branch 'origin/master' into feature/VIBE-247
KianKwa Dec 3, 2025
7a224c5
Removed typo in njk file
KianKwa Dec 3, 2025
287cc96
Fixed e2e test issues
KianKwa Dec 3, 2025
d73a44d
Refactoring
KianKwa Dec 3, 2025
5ecc921
Add all e2e tests for admin users
KianKwa Dec 4, 2025
715c815
Update e2e tests
KianKwa Dec 4, 2025
cb84d3a
Fixed access denied e2e tests
KianKwa Dec 4, 2025
7e08421
Update SSO sign in for admin users
KianKwa Dec 4, 2025
e278054
Update admin e2e tests
KianKwa Dec 4, 2025
bf533a9
Update admin e2e tests
KianKwa Dec 4, 2025
1a9766b
Update admin e2e tests
KianKwa Dec 4, 2025
50842f0
Update admin e2e tests
KianKwa Dec 4, 2025
ab43094
Fixed unit tests
KianKwa Dec 4, 2025
4dfd840
Update comment
KianKwa Dec 4, 2025
4c1936f
Add clean step to publication build and update comment
KianKwa Dec 4, 2025
9981913
Updated seed data
KianKwa Dec 4, 2025
f532a40
Code review fixes
KianKwa Dec 5, 2025
90bac23
Lint fixes
KianKwa Dec 5, 2025
86d889c
Fixed failing unit tests
KianKwa Dec 5, 2025
5b74fed
Lint fixes
KianKwa Dec 5, 2025
5cd82bb
Fixed tests
KianKwa Dec 5, 2025
5659289
Merge remote-tracking branch 'origin/master' into feature/VIBE-247
KianKwa Dec 15, 2025
2dafa92
Fixed sonarqube issue
KianKwa Dec 15, 2025
fc07aa6
Merge remote-tracking branch 'origin/master' into feature/VIBE-247
KianKwa Dec 16, 2025
baefdfc
fixed merge conflicts
KianKwa Dec 16, 2025
cc8caca
Merge branch 'master' into feature/VIBE-247
junaidiqbalmoj Dec 24, 2025
769006b
refactor: consolidate publication authorisation E2E tests into compre…
ashwini-mv Dec 29, 2025
d62dcbc
feat: add WCAG 2.2 AA accessibility and keyboard navigation checks to…
ashwini-mv Dec 29, 2025
3b06874
fix: improve keyboard navigation test robustness in publication autho…
ashwini-mv Dec 29, 2025
d0a560f
fix: replace keyboard Enter with click() for reliable CI navigation
ashwini-mv Dec 29, 2025
09961ab
feat: add comprehensive WCAG 2.2 AA and keyboard navigation journey test
ashwini-mv Dec 29, 2025
01be191
fix: strengthen provenance filtering assertions to prevent silent tes…
ashwini-mv Dec 29, 2025
2353b71
fix: remove tautological assertions in unauthenticated user test
ashwini-mv Dec 29, 2025
42cec1c
refactor: remove comprehensive accessibility journey test
ashwini-mv Dec 29, 2025
708deb0
feat: add focused keyboard navigation journey test
ashwini-mv Dec 29, 2025
ac60777
feat: add WCAG 2.2 AA accessibility checks to System Admin test
ashwini-mv Dec 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/postgres/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ async function main() {
{
artefactId: "11111111-1111-1111-1111-111111111111",
locationId: "9",
listTypeId: 8, // Civil and Family Daily Cause List
listTypeId: 6, // Crown Daily List (CRIME_IDAM) - Changed from 8 to avoid conflict with E2E test data
contentDate: new Date("2025-01-15"),
sensitivity: "PUBLIC",
language: "ENGLISH",
Expand Down
165 changes: 165 additions & 0 deletions docs/tickets/VIBE-247/e2e-tests-summary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# E2E Tests for Publication Authorisation (VIBE-247)

## Overview
Created comprehensive end-to-end tests to verify role-based and provenance-based authorization for publications based on sensitivity levels.

**Test File:** `e2e-tests/tests/publication-authorisation.spec.ts`

## Test Coverage

### 1. Unauthenticated Users (PUBLIC access only)
- ✅ Should only see PUBLIC publications
- ✅ Should not see CLASSIFIED Civil and Family publications
- ✅ Should redirect to sign-in or show 403 when trying to directly access CLASSIFIED publications

### 2. CFT IDAM Authenticated Users (VERIFIED role with CFT provenance)
- ✅ Should see PUBLIC, PRIVATE, and CLASSIFIED CFT publications
- ✅ Should be able to access CLASSIFIED Civil and Family Daily Cause List
- ✅ Should see PRIVATE publications
- ✅ Should maintain access after navigation and page reload
- ✅ Should lose access to CLASSIFIED publications after logout

### 3. Provenance-based Filtering for CLASSIFIED Publications
- ✅ CFT user should see CFT CLASSIFIED publications
- ✅ Should verify CLASSIFIED publications match user provenance (no 403 errors)

### 4. Edge Cases and Error Handling
- ✅ Should handle missing sensitivity level (defaults to CLASSIFIED)
- ✅ Should show appropriate error when accessing restricted publication directly
- ✅ Should handle invalid locationId gracefully

### 5. Accessibility Compliance
- ✅ Authenticated summary page should be accessible
- ✅ All publication links should have accessible text

## Test Scenarios

### Scenario 1: Unauthenticated User Journey
```
1. Navigate to /summary-of-publications?locationId=3
2. Verify only PUBLIC publications are visible
3. Verify CLASSIFIED publications are filtered out
4. Try to directly access CLASSIFIED publication URL
5. Verify 403/404 error or redirect to sign-in
```

### Scenario 2: CFT Verified User Journey
```
1. Login with CFT IDAM credentials
2. Navigate to /summary-of-publications?locationId=3
3. Verify CFT user sees more publications than public user
4. Click on Civil and Family Daily Cause List (CLASSIFIED CFT)
5. Verify access is granted (no 403 error)
6. Navigate away and back
7. Verify access persists
8. Logout
9. Verify access is revoked
```

### Scenario 3: Provenance Matching
```
1. Login as CFT user (provenance: "CFT")
2. Navigate to summary page
3. Verify CFT CLASSIFIED publications are visible
4. Click on CFT publication
5. Verify successful access (no error)
6. Verify Crime CLASSIFIED publications are NOT visible (different provenance)
```

## Test Data Requirements

### Location ID 3
- Should have publications with different sensitivity levels:
- PUBLIC publications (visible to all)
- PRIVATE publications (visible to verified users)
- CLASSIFIED publications with CFT provenance (visible to CFT users only)

### Test Accounts
- **CFT_VALID_TEST_ACCOUNT**: CFT IDAM account with VERIFIED role and CFT provenance
- **CFT_VALID_TEST_ACCOUNT_PASSWORD**: Password for CFT test account

### Artefact IDs
- Tests use actual artefactIds from the database
- One specific test uses: `a4f06ae6-399f-4207-b676-54f35ad908ed` (from debug logs)

## Running the Tests

```bash
# Run all E2E tests
yarn test:e2e

# Run only publication authorization tests
yarn test:e2e publication-authorisation

# Run with UI mode for debugging
yarn test:e2e --ui publication-authorisation
```

## Environment Variables Required

```bash
# CFT IDAM credentials
CFT_VALID_TEST_ACCOUNT=pip-cft-valid-test-account@hmcts.net
CFT_VALID_TEST_ACCOUNT_PASSWORD=<password>

# Enable CFT IDAM
ENABLE_CFT_IDAM=true
```

## Test Results Expected

### Before Fix (Security Bug):
- ❌ CFT users would NOT see CLASSIFIED Civil and Family publications
- ❌ Provenance mismatch (`"CFT"` vs `"CFT_IDAM"`)
- ❌ Tests would fail

### After Fix:
- ✅ CFT users CAN see CLASSIFIED Civil and Family publications
- ✅ Provenance matching works correctly (`"CFT"` === `"CFT"`)
- ✅ All tests should pass

## Integration with Existing Tests

These new E2E tests complement the existing test suite:

1. **Unit Tests** (`libs/publication/src/authorisation/*.test.ts`)
- Test individual functions
- Test access logic in isolation
- 72 tests covering all scenarios

2. **E2E Tests** (this file)
- Test full user journey
- Test authentication flow integration
- Test actual publication filtering in UI
- ~20 tests covering real-world scenarios

## Accessibility Considerations

All E2E tests verify:
- Publications are accessible to screen readers
- Links have meaningful text
- No accessibility violations for authenticated users
- Error messages are clear and bilingual

## Known Limitations

1. Tests assume CFT IDAM is configured and available
2. Tests require specific test data in database (locationId=3 with mixed sensitivity publications)
3. Some tests check for flexible error handling (403/404/sign-in redirect) as implementation may vary

## Future Enhancements

Potential additions for comprehensive coverage:
- [ ] E2E tests for CRIME IDAM users (when available)
- [ ] E2E tests for Local/CTSC admin users (SSO)
- [ ] E2E tests for System Admin users
- [ ] Cross-provenance blocking tests (CFT user trying to access CRIME CLASSIFIED)
- [ ] Performance tests for filtering large publication lists

## References

- Implementation: `libs/publication/src/authorisation/service.ts`
- Middleware: `libs/publication/src/authorisation/middleware.ts`
- Unit Tests: `libs/publication/src/authorisation/*.test.ts`
- Ticket: VIBE-247
- Security Fix: Provenance mismatch (`CFT_IDAM` → `CFT`)
93 changes: 93 additions & 0 deletions docs/tickets/VIBE-247/plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# VIBE-247: Authenticate Publications Based on Sensitivity Level - Technical Plan

## Technical Approach

This ticket implements role-based and provenance-based authorisation for publications (artefacts) based on their sensitivity level. The system already has the foundational pieces: sensitivity levels on artefacts, user provenance tracking, and role-based middleware. The implementation extends the existing authorisation middleware to handle publication-specific access rules.

The approach uses a functional authorisation service that evaluates whether a user can access a publication based on: (1) their authentication status and role, (2) the publication's sensitivity level, and (3) provenance matching for classified lists. Access control is enforced through middleware that filters publications in list views and blocks unauthorized direct access. Local and CTSC admins receive special handling - they can view metadata and delete Private/Classified publications but cannot access the actual list data.

A key architectural decision is to keep authorisation logic in a separate service module that can be tested independently and reused across page controllers, API endpoints, and admin functions. The existing artefact model already contains the required fields (sensitivity, provenance), but we need to add list type provenance lookups to validate classified access.

## Implementation Details

### Key Files/Modules to Create

- `libs/publication/src/authorisation/service.ts` - Core authorisation logic
- `canAccessPublication(user, artefact, listType)` - Main authorisation function
- `canAccessPublicationData(user, artefact, listType)` - Check if user can see actual list data
- `canAccessPublicationMetadata(user, artefact)` - Check if user can see metadata only
- `filterAccessiblePublications(user, artefacts, listTypes)` - Filter list of publications

- `libs/publication/src/authorisation/middleware.ts` - Express middleware
- `requirePublicationAccess()` - Middleware to protect individual publication routes
- `requirePublicationDataAccess()` - Middleware to ensure user can view actual data (not just metadata)

- `libs/publication/src/authorisation/service.test.ts` - Comprehensive unit tests for authorisation logic

### Files to Modify

- `libs/publication/src/index.ts` - Export new authorisation functions
- `libs/public-pages/src/pages/summary-of-publications/index.ts` - Filter publications by user access
- `libs/public-pages/src/pages/publication/[id].ts` - Add authorisation check
- `libs/list-types/civil-and-family-daily-cause-list/src/pages/index.ts` - Add authorisation check (and similar for other list type pages)
- `libs/admin-pages/src/pages/remove-list-search-results/index.ts` - Show all publications to admins but indicate access restrictions
- `libs/admin-pages/src/pages/remove-list-confirmation/index.ts` - Allow admins to delete regardless of sensitivity

### Database Schema Changes

**No schema changes required.** The existing schema already has:
- `artefact.sensitivity` - Publication sensitivity level
- `artefact.provenance` - Publication source system
- `artefact.list_type_id` - Links to list type (which has provenance)
- `user.user_provenance` - User authentication source
- `user.role` - User role

The list type provenance is already available through `mockListTypes` and will be used to validate classified access.

### API Endpoints

No new API endpoints needed. Authorization will be added to existing endpoints:
- Page routes that display publications (GET handlers)
- Admin routes for publication management

## Error Handling & Edge Cases

- **Unauthenticated users accessing Private/Classified** - Redirect to login with return URL
- **Authenticated user without proper role** - Show 403 or redirect to appropriate dashboard
- **Verified user accessing Classified without matching provenance** - Show 403 error page
- **List type not found** - Treat as inaccessible (fail closed)
- **User provenance doesn't match any list type provenance** - Block access to classified lists
- **Local/CTSC admin attempting to view list data** - Show metadata only page or warning message
- **System admin** - Full access to all publications regardless of sensitivity
- **Public users** - Only see PUBLIC sensitivity publications
- **Missing sensitivity field on artefact** - Treat as CLASSIFIED (most restrictive, fail closed)
- **Malformed user session** - Redirect to login

## Acceptance Criteria Mapping

| AC | Implementation |
|---|---|
| AC1: Sensitivity level during upload | Already exists - artefact model has sensitivity field |
| AC2: Public accessible to all | `canAccessPublication` returns true for PUBLIC for all users |
| AC3: Private accessible to verified | `canAccessPublication` checks user.role is not undefined (authenticated/verified) |
| AC4: Classified accessible with provenance match | `canAccessPublication` checks userProvenance matches listType.provenance |
| AC5: Validation using user provenance | Authorization service uses UserProfile.provenance from session |
| AC6: Parent-child relationship hierarchy | Implemented through USER_ROLES constants and role checking logic |
| AC7: System admin full access | `canAccessPublication` returns true for SYSTEM_ADMIN role |
| AC8: Verified user classified check | `canAccessPublication` checks provenance match for CLASSIFIED |
| AC9: Local/CTSC admin metadata only | `canAccessPublicationData` returns false, separate metadata view implemented |
| AC10: Public users only PUBLIC | `canAccessPublication` returns false for unauthenticated on PRIVATE/CLASSIFIED |

## Open Questions

1. Should we display a message to users explaining why they cannot see certain publications, or silently filter them from lists?
- **Recommendation**: Silent filtering in list views, explicit 403 page when directly accessing

2. For Local/CTSC admins viewing metadata, what specific fields should they see? (e.g., list type, content date, display dates, but not case details)
- **Recommendation**: Show all artefact metadata (location, dates, sensitivity) but not the JSON payload

3. Should B2C verified users have automatic access to all provenances for classified lists, or should we track their specific provenance?
- **Recommendation**: Based on permissions matrix, B2C users should have access to all classified lists (provenance check only applies to differentiate between B2C, CFT_IDAM, CRIME_IDAM users)

4. How should we handle publications where the list type provenance doesn't match any known user provenance values?
- **Recommendation**: Fail closed - treat as inaccessible unless user is SYSTEM_ADMIN
Loading
Loading