import { describe, expect, it } from 'vitest' import { assertReadAllowed, EsGuardError } from '../../../src/es/guard.js' describe('assertReadAllowed', () => { it('allows GET and HEAD anywhere', () => { expect(() => assertReadAllowed('GET', '/idx/_doc/1')).not.toThrow() expect(() => assertReadAllowed('HEAD', '/idx')).not.toThrow() }) it('allows POST to read endpoints', () => { for (const p of [ '/idx/_search', '/_msearch', '/idx/_count', '/_field_caps', '/_cat/indices', '/idx/_mapping', '/_search/scroll', '/idx/_pit' ]) { expect(() => assertReadAllowed('POST', p), p).not.toThrow() } }) it('blocks POST to write endpoints', () => { for (const p of [ '/idx/_doc', '/idx/_bulk', '/idx/_update/1', '/idx/_delete_by_query', '/_sql' ]) { expect(() => assertReadAllowed('POST', p), p).toThrow(EsGuardError) } }) it('blocks PUT and generic DELETE', () => { expect(() => assertReadAllowed('PUT', '/idx')).toThrow(EsGuardError) expect(() => assertReadAllowed('DELETE', '/idx/_doc/1')).toThrow(EsGuardError) }) it('allows DELETE only for pit and scroll cleanup', () => { expect(() => assertReadAllowed('DELETE', '/_pit')).not.toThrow() expect(() => assertReadAllowed('DELETE', '/_search/scroll')).not.toThrow() }) it('ignores query strings when matching', () => { expect(() => assertReadAllowed('POST', '/idx/_search?scroll=1m')).not.toThrow() }) it('ignores a trailing slash', () => { expect(() => assertReadAllowed('POST', '/idx/_search/')).not.toThrow() }) it('treats a missing leading slash like the slashed path', () => { expect(() => assertReadAllowed('POST', '_search')).not.toThrow() expect(() => assertReadAllowed('POST', 'idx/_search')).not.toThrow() expect(() => assertReadAllowed('POST', 'idx/_doc')).toThrow(EsGuardError) }) it('rejects an unknown method', () => { expect(() => assertReadAllowed('PATCH', '/idx/_search')).toThrow(EsGuardError) }) })