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
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:
@@ -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)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user