/** * Field-Level Access Control Unit Tests * * Tests for field-level access control patterns. * Covers: SMTP password protection, sensitive field hiding, tenant membership * * IMPORTANT: These tests import the actual field access functions from @/lib/access * to ensure regressions in live collections are detected. */ import { describe, it, expect, vi } from 'vitest' import type { FieldAccess, PayloadRequest } from 'payload' import { createSuperAdmin, createTenantUser, createMockPayloadRequest, TEST_USERS, } from '../../helpers/access-control-test-utils' // ============================================================================ // Import REAL field access functions from centralized library // ============================================================================ import { neverReadable, superAdminOnlyField, authenticatedOnlyField, tenantMemberField, } from '@/lib/access' // ============================================================================ // Field Access Function Types // ============================================================================ interface MockFieldAccessArgs { req: ReturnType doc?: Record data?: Record siblingData?: Record } // ============================================================================ // Execute Field Access Helper // ============================================================================ async function executeFieldAccess( accessFn: FieldAccess, args: MockFieldAccessArgs, ): Promise { const result = await accessFn({ req: args.req as unknown as PayloadRequest, doc: args.doc, data: args.data, siblingData: args.siblingData, }) return result } // ============================================================================ // SMTP Password Field Tests (neverReadable) // ============================================================================ describe('SMTP Password Field Access (neverReadable)', () => { describe('Read Access', () => { it('blocks read for super admin', async () => { const request = createMockPayloadRequest(TEST_USERS.superAdmin) const result = await executeFieldAccess(neverReadable, { req: request }) expect(result).toBe(false) }) it('blocks read for regular user', async () => { const request = createMockPayloadRequest(TEST_USERS.porwollUser) const result = await executeFieldAccess(neverReadable, { req: request }) expect(result).toBe(false) }) it('blocks read for anonymous user', async () => { const request = createMockPayloadRequest(null) const result = await executeFieldAccess(neverReadable, { req: request }) expect(result).toBe(false) }) it('ensures password never appears in API response', async () => { // This tests the intent: no one should ever read the SMTP password via API const users = [ TEST_USERS.superAdmin, TEST_USERS.porwollUser, TEST_USERS.multiTenantUser, null, ] for (const user of users) { const request = createMockPayloadRequest(user) const result = await executeFieldAccess(neverReadable, { req: request }) expect(result).toBe(false) } }) }) }) // ============================================================================ // Super Admin Only Field Tests // ============================================================================ describe('Super Admin Only Field Access (superAdminOnlyField)', () => { it('grants access to super admin', async () => { const request = createMockPayloadRequest(TEST_USERS.superAdmin) const result = await executeFieldAccess(superAdminOnlyField, { req: request }) expect(result).toBe(true) }) it('denies access to regular tenant user', async () => { const request = createMockPayloadRequest(TEST_USERS.porwollUser) const result = await executeFieldAccess(superAdminOnlyField, { req: request }) expect(result).toBe(false) }) it('denies access to multi-tenant user without super admin', async () => { const request = createMockPayloadRequest(TEST_USERS.multiTenantUser) const result = await executeFieldAccess(superAdminOnlyField, { req: request }) expect(result).toBe(false) }) it('denies access to anonymous user', async () => { const request = createMockPayloadRequest(null) const result = await executeFieldAccess(superAdminOnlyField, { req: request }) expect(result).toBe(false) }) }) // ============================================================================ // Authenticated Field Tests // ============================================================================ describe('Authenticated Field Access (authenticatedOnlyField)', () => { it('grants access to any authenticated user', async () => { const users = [ TEST_USERS.superAdmin, TEST_USERS.porwollUser, TEST_USERS.c2sUser, TEST_USERS.multiTenantUser, ] for (const user of users) { const request = createMockPayloadRequest(user) const result = await executeFieldAccess(authenticatedOnlyField, { req: request }) expect(result).toBe(true) } }) it('denies access to anonymous user', async () => { const request = createMockPayloadRequest(null) const result = await executeFieldAccess(authenticatedOnlyField, { req: request }) expect(result).toBe(false) }) }) // ============================================================================ // Tenant Member Field Tests // ============================================================================ describe('Tenant Member Field Access (tenantMemberField)', () => { describe('Authentication Checks', () => { it('denies anonymous users', async () => { const request = createMockPayloadRequest(null) const result = await executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 1 }, }) expect(result).toBe(false) }) it('grants super admin access to any tenant document', async () => { const request = createMockPayloadRequest(TEST_USERS.superAdmin) const result = await executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 999 }, // Arbitrary tenant }) expect(result).toBe(true) }) }) describe('Tenant Membership', () => { it('grants user access to own tenant document', async () => { const request = createMockPayloadRequest(TEST_USERS.porwollUser) // tenant 1 const result = await executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 1 }, }) expect(result).toBe(true) }) it('denies user access to other tenant document', async () => { const request = createMockPayloadRequest(TEST_USERS.porwollUser) // tenant 1 only const result = await executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 4 }, // c2s tenant }) expect(result).toBe(false) }) it('handles tenant as object format in document', async () => { const request = createMockPayloadRequest(TEST_USERS.porwollUser) const result = await executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: { id: 1 } }, }) expect(result).toBe(true) }) it('multi-tenant user has access to all assigned tenants', async () => { const request = createMockPayloadRequest(TEST_USERS.multiTenantUser) // tenants 1, 4, 5 const results = await Promise.all([ executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 1 } }), executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 4 } }), executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 5 } }), executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 999 } }), ]) expect(results).toEqual([true, true, true, false]) }) }) describe('Edge Cases', () => { it('returns false when doc has no tenant', async () => { const request = createMockPayloadRequest(TEST_USERS.porwollUser) const result = await executeFieldAccess(tenantMemberField, { req: request, doc: {}, }) expect(result).toBe(false) }) it('returns false when doc is undefined', async () => { const request = createMockPayloadRequest(TEST_USERS.porwollUser) const result = await executeFieldAccess(tenantMemberField, { req: request, doc: undefined, }) expect(result).toBe(false) }) }) }) // ============================================================================ // Security: Sensitive Data Protection Tests // ============================================================================ describe('Sensitive Data Protection', () => { // List of sensitive field patterns that should never be readable via API const sensitiveFieldPatterns = [ { name: 'SMTP Password (neverReadable)', access: neverReadable }, ] describe.each(sensitiveFieldPatterns)('$name field', ({ access }) => { it('is never readable by super admin', async () => { const request = createMockPayloadRequest(TEST_USERS.superAdmin) const result = await executeFieldAccess(access, { req: request }) expect(result).toBe(false) }) it('is never readable by regular user', async () => { const request = createMockPayloadRequest(TEST_USERS.porwollUser) const result = await executeFieldAccess(access, { req: request }) expect(result).toBe(false) }) it('is never readable by anonymous user', async () => { const request = createMockPayloadRequest(null) const result = await executeFieldAccess(access, { req: request }) expect(result).toBe(false) }) }) describe('Defense in Depth', () => { it('sensitive field access is stateless (no bypass via repeated requests)', async () => { const request = createMockPayloadRequest(TEST_USERS.superAdmin) // Multiple attempts should all fail for (let i = 0; i < 5; i++) { const result = await executeFieldAccess(neverReadable, { req: request }) expect(result).toBe(false) } }) it('sensitive field access ignores document context', async () => { const request = createMockPayloadRequest(TEST_USERS.superAdmin) const result = await executeFieldAccess(neverReadable, { req: request, doc: { isSuperAdmin: true, owner: 1, password: 'secret' }, }) expect(result).toBe(false) }) }) }) // ============================================================================ // Field Access with Document Context (tenantMemberField) // ============================================================================ describe('Field Access with Document Context', () => { it('grants access to document within user tenant', async () => { const user = createTenantUser([1], { id: 5 }) const request = createMockPayloadRequest(user) const result = await executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 1 }, }) expect(result).toBe(true) }) it('denies access to document outside user tenant', async () => { const user = createTenantUser([1], { id: 5 }) const request = createMockPayloadRequest(user) const result = await executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 4 }, // Different tenant }) expect(result).toBe(false) }) it('grants access to super admin regardless of tenant', async () => { const request = createMockPayloadRequest(TEST_USERS.superAdmin) const result = await executeFieldAccess(tenantMemberField, { req: request, doc: { tenant: 999 }, // Any tenant }) expect(result).toBe(true) }) }) // ============================================================================ // Comprehensive Field Access Matrix // ============================================================================ describe('Field Access Matrix', () => { const allUsers = [ { name: 'Super Admin', user: TEST_USERS.superAdmin }, { name: 'Porwoll User', user: TEST_USERS.porwollUser }, { name: 'Multi-Tenant User', user: TEST_USERS.multiTenantUser }, { name: 'Anonymous', user: null }, ] describe('neverReadable', () => { it.each(allUsers)('$name cannot read field', async ({ user }) => { const request = createMockPayloadRequest(user) const result = await executeFieldAccess(neverReadable, { req: request }) expect(result).toBe(false) }) }) describe('superAdminOnlyField', () => { it.each(allUsers)('$name access is correctly evaluated', async ({ user }) => { const request = createMockPayloadRequest(user) const result = await executeFieldAccess(superAdminOnlyField, { req: request }) if (user?.isSuperAdmin) { expect(result).toBe(true) } else { expect(result).toBe(false) } }) }) describe('authenticatedOnlyField', () => { it.each(allUsers)('$name access is correctly evaluated', async ({ user }) => { const request = createMockPayloadRequest(user) const result = await executeFieldAccess(authenticatedOnlyField, { req: request }) if (user !== null) { expect(result).toBe(true) } else { expect(result).toBe(false) } }) }) })