security: harden production configuration and routes
Run Tests on Branches / Detect Changes (push) Successful in 12s
Run Tests on Branches / Frontend Tests (push) Successful in 2m12s
Run Tests on Branches / Frontend Mobile Tests (push) Has been skipped
Run Tests on Branches / Parapharmacy API Tests (push) Successful in 2m2s
Run Tests on Branches / PIP Platform Tests (push) Has been skipped
Run Tests on Branches / Backend Tests (push) Successful in 2m8s

This commit is contained in:
Antoni Nuñez Romeu
2026-07-22 17:24:54 +02:00
parent f60af5f6b2
commit 849763896d
21 changed files with 638 additions and 68 deletions
@@ -0,0 +1,59 @@
import { jest } from '@jest/globals'
process.env.NODE_ENV = 'test'
process.env.INGEST_API_KEY = 'ingest-test-key'
process.env.ADMIN_API_KEY = 'admin-test-key'
jest.unstable_mockModule('../src/models/Product.js', () => ({
default: {
search: jest.fn(async () => ({ results: [], total: 0, page: 1, pages: 0 })),
distinct: jest.fn(async () => []),
find: jest.fn(() => ({ sort: () => ({ skip: () => ({ limit: () => ({ lean: async () => [] }) }) }) })),
countDocuments: jest.fn(async () => 0),
},
}))
jest.unstable_mockModule('../src/scraper.js', () => ({
scrapeAll: jest.fn(async () => ({ total: 0 })),
}))
const { default: supertest } = await import('supertest')
const { default: app } = await import('../src/server.js')
describe('parapharmacy security', () => {
test('keeps public product search available without credentials', async () => {
const res = await supertest(app).get('/api/products/search?q=cream')
expect(res.status).toBe(200)
})
test.each(['/api/products', '/api/products/bulk', '/api/scrape'])(
'rejects unauthenticated mutation route %s',
async (path) => {
const res = await supertest(app).post(path).send({})
expect(res.status).toBe(401)
},
)
test('accepts a valid ingest key for product creation', async () => {
const res = await supertest(app)
.post('/api/products')
.set('Authorization', 'Bearer ingest-test-key')
.send({})
expect(res.status).toBe(400)
})
test('requires a separate admin key for product deletion', async () => {
const res = await supertest(app)
.delete('/api/products/507f1f77bcf86cd799439011')
.set('Authorization', 'Bearer ingest-test-key')
expect(res.status).toBe(403)
})
test('does not expose Swagger in production', async () => {
const original = process.env.NODE_ENV
process.env.NODE_ENV = 'production'
const res = await supertest(app).get('/api/docs')
process.env.NODE_ENV = original
expect(res.status).toBe(404)
})
})