import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { handleActuateAPI } from '../../api/index.js';
import { createSession } from '../../auth/session.js';
import { setActuateConfig } from '../../config/runtime.js';
import { initDB } from '../../db.js';
import { createGraphQLHandler } from '../../graphql/index.js';
/**
 * Regression for roadmap #392 / audit finding: collection CRUD read paths
 * must enforce each collection's `access.read` rule (not just API-key scope).
 */
const SECRET = 'a'.repeat(48);
const PAGE_DOC = {
    id: 'doc-1',
    collection: 'pages',
    title: 'Hello',
    slug: 'hello',
    status: 'DRAFT',
    data: { title: 'Hello' },
    deletedAt: null,
    createdAt: new Date(),
    updatedAt: new Date(),
};
function createMockDB() {
    return {
        session: {
            findUnique: async () => ({ revokedAt: null }),
        },
        user: {},
        apiKey: {
            findMany: async () => [],
            findUnique: async () => null,
        },
        document: {
            findFirst: async ({ where }) => {
                if (where.id === PAGE_DOC.id && where.collection === 'pages')
                    return PAGE_DOC;
                return null;
            },
            findMany: async ({ where }) => {
                if (where.collection === 'pages')
                    return [PAGE_DOC];
                return [];
            },
            count: async ({ where }) => {
                if (where.collection === 'pages')
                    return 1;
                return 0;
            },
        },
        media: {},
    };
}
async function sessionCookie(role, userId = 'user-1') {
    const token = await createSession({ userId, role, sessionId: `sess-${userId}` }, { secret: SECRET });
    return `actuate_session=${token}`;
}
const RESTRICTED_CONFIG = {
    collections: {
        pages: {
            labels: { singular: 'Page', plural: 'Pages' },
            fields: { title: { type: 'text' } },
            access: {
                read: ({ user }) => user?.role === 'ADMIN',
                create: () => true,
                update: () => true,
                delete: () => true,
            },
        },
    },
};
describe('collection access.read on REST read paths', () => {
    beforeEach(() => {
        delete globalThis.__actuateConfig;
        process.env.CMS_SECRET = SECRET;
        initDB(createMockDB());
    });
    afterEach(() => {
        delete process.env.CMS_SECRET;
    });
    it('GET /collections/:slug returns 403 when access.read denies the user', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB(),
            config: RESTRICTED_CONFIG,
        });
        const res = await handler(new Request('https://x.com/api/cms/collections/pages', {
            headers: { cookie: await sessionCookie('VIEWER') },
        }));
        expect(res.status).toBe(403);
    });
    it('GET /collections/:slug/:id returns 403 when access.read denies the user', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB(),
            config: RESTRICTED_CONFIG,
        });
        const res = await handler(new Request('https://x.com/api/cms/collections/pages/doc-1', {
            headers: { cookie: await sessionCookie('VIEWER') },
        }));
        expect(res.status).toBe(403);
    });
    it('GET /collections/:slug returns 200 when access.read allows the user', async () => {
        const handler = handleActuateAPI({
            prismaClient: createMockDB(),
            config: RESTRICTED_CONFIG,
        });
        const res = await handler(new Request('https://x.com/api/cms/collections/pages', {
            headers: { cookie: await sessionCookie('ADMIN') },
        }));
        expect(res.status).toBe(200);
        const body = (await res.json());
        expect(body.data.docs).toHaveLength(1);
    });
});
describe('collection access.read on GraphQL read paths', () => {
    beforeEach(() => {
        delete globalThis.__actuateConfig;
        process.env.CMS_SECRET = SECRET;
        initDB(createMockDB());
    });
    afterEach(() => {
        delete process.env.CMS_SECRET;
    });
    it('GraphQL list query rejects when access.read denies the user', async () => {
        setActuateConfig(RESTRICTED_CONFIG);
        const yoga = createGraphQLHandler({ config: RESTRICTED_CONFIG, secret: SECRET });
        const token = await createSession({ userId: 'viewer-1', role: 'VIEWER', sessionId: 'sess-viewer' }, { secret: SECRET });
        const res = await yoga.fetch('https://x.com/api/cms/graphql', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                cookie: `actuate_session=${token}`,
            },
            body: JSON.stringify({ query: '{ pages { docs { id } total } }' }),
        });
        expect(res.status).toBe(200);
        const body = (await res.json());
        expect(body.errors?.length).toBeGreaterThan(0);
        expect(body.data?.pages).toBeUndefined();
    });
});
//# sourceMappingURL=collection-read-access.test.js.map