diff --git a/tests/integration/helpers/API-service/dto/upload-typhoon-track.dto.ts b/tests/integration/helpers/API-service/dto/upload-typhoon-track.dto.ts index cfde082bd..d440b5811 100644 --- a/tests/integration/helpers/API-service/dto/upload-typhoon-track.dto.ts +++ b/tests/integration/helpers/API-service/dto/upload-typhoon-track.dto.ts @@ -8,7 +8,8 @@ export interface UploadTyphoonTrackDto { readonly date: Date; } -export enum TyphoonCategory { // https://www.pagasa.dost.gov.ph/information/about-tropical-cyclone +export enum TyphoonCategory { + // https://www.pagasa.dost.gov.ph/information/about-tropical-cyclone TropicalDepression = 'TD', // a tropical cyclone with maximum sustained winds of up to 62 kilometers per hour (kph) or less than 34 nautical miles per hour (knots) TropicalStorm = 'TS', // a tropical cyclone with maximum wind speed of 62 to 88 kph or 34 - 47 knots // eslint-disable-next-line perfectionist/sort-enums diff --git a/tests/integration/helpers/utility.helper.ts b/tests/integration/helpers/utility.helper.ts index 026d6af1b..05a1da72a 100644 --- a/tests/integration/helpers/utility.helper.ts +++ b/tests/integration/helpers/utility.helper.ts @@ -8,6 +8,7 @@ import { MalariaScenario, TyphoonScenario, } from './API-service/enum/mock-scenario.enum'; +import { UserRole } from './API-service/enum/user-role.enum'; export function api(token?: string) { const request = agent(process.env.API_SERVICE_URL); @@ -31,6 +32,39 @@ export async function getToken() { return token; } +export async function getNonAdminToken() { + // First get admin token to create a non-admin user + const adminToken = await getToken(); + + const nonAdminUser = { + email: 'operator@redcross.nl', + firstName: 'Test', + lastName: 'Operator', + userRole: UserRole.Operator, + countryCodesISO3: ['UGA'], + disasterTypes: ['floods'], + password: 'password', + }; + + // Try to create the user (will fail if it already exists, which is fine) + try { + await api(adminToken).post('/user').send(nonAdminUser); + } catch (error) { + // User already exists, continue + } + + // Login with the non-admin user + const { + body: { + user: { token }, + }, + } = await api() + .post(`/user/login`) + .send({ email: nonAdminUser.email, password: nonAdminUser.password }); + + return token; +} + export async function reset() { const token = await getToken(); diff --git a/tests/integration/tests/all.test.ts b/tests/integration/tests/all.test.ts index 5d307d508..9a3f40b23 100644 --- a/tests/integration/tests/all.test.ts +++ b/tests/integration/tests/all.test.ts @@ -5,6 +5,7 @@ import { adminAreaDeleteTests } from './admin-areas/admin-areas-delete.test'; import adminAreaAggregatesTests from './admin-areas/aggregates.test'; import eventAdminAreaTests from './admin-areas/event-admin-areas.test'; import communityNotificationTests from './community-notification/community-notification.test'; +import countryAdminAccessTests from './country/country-admin-access.test'; import createCountryTests from './country/create-country.test'; import emailTests from './email/emails.test'; import getEventsTests from './events/get-events.test'; @@ -22,6 +23,7 @@ describe('integration tests', () => { communityNotificationTests(); createCountryTests(); + countryAdminAccessTests(); emailTests(); diff --git a/tests/integration/tests/country/country-admin-access.test.ts b/tests/integration/tests/country/country-admin-access.test.ts new file mode 100644 index 000000000..7a7b6c033 --- /dev/null +++ b/tests/integration/tests/country/country-admin-access.test.ts @@ -0,0 +1,107 @@ +import { countryData } from '../../fixtures/country.const'; +import { notificationInfoData } from '../../fixtures/notification-info.const'; +import { getNonAdminToken, getToken } from '../../helpers/utility.helper'; +import { + addOrUpdateCountries, + addOrUpdateNotificationInfo, +} from './country.api'; + +export default function countryAdminAccessTests() { + describe('country admin access control', () => { + let adminToken: string; + let nonAdminToken: string; + + beforeAll(async () => { + adminToken = await getToken(); + nonAdminToken = await getNonAdminToken(); + }); + + describe('POST /country - admin access required', () => { + it('should allow admin users to create/update countries', async () => { + // Arrange + const testCountryData = structuredClone(countryData); + + // Act + const result = await addOrUpdateCountries( + { countries: testCountryData }, + adminToken, + ); + + // Assert + expect(result.status).toBe(201); + }); + + it('should deny non-admin users access to create/update countries', async () => { + // Arrange + const testCountryData = structuredClone(countryData); + + // Act + const result = await addOrUpdateCountries( + { countries: testCountryData }, + nonAdminToken, + ); + + // Assert + expect(result.status).toBe(403); + }); + + it('should deny unauthenticated users access to create/update countries', async () => { + // Arrange + const testCountryData = structuredClone(countryData); + + // Act + const result = await addOrUpdateCountries( + { countries: testCountryData }, + '', // empty token + ); + + // Assert + expect(result.status).toBe(401); + }); + }); + + describe('POST /country/notification-info - admin access required', () => { + it('should allow admin users to create/update notification info', async () => { + // Arrange + const testNotificationData = structuredClone(notificationInfoData); + + // Act + const result = await addOrUpdateNotificationInfo( + testNotificationData, + adminToken, + ); + + // Assert + expect(result.status).toBe(201); + }); + + it('should deny non-admin users access to create/update notification info', async () => { + // Arrange + const testNotificationData = structuredClone(notificationInfoData); + + // Act + const result = await addOrUpdateNotificationInfo( + testNotificationData, + nonAdminToken, + ); + + // Assert + expect(result.status).toBe(403); + }); + + it('should deny unauthenticated users access to create/update notification info', async () => { + // Arrange + const testNotificationData = structuredClone(notificationInfoData); + + // Act + const result = await addOrUpdateNotificationInfo( + testNotificationData, + '', // empty token + ); + + // Assert + expect(result.status).toBe(401); + }); + }); + }); +}