buster/packages/access-controls/tests/unit/chats.test.ts

310 lines
8.3 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import { canUserAccessChat } from '../../src/chats';
// Mock the database module
vi.mock('@buster/database', () => ({
getDb: vi.fn(),
and: vi.fn((...args) => ({ _and: args })),
eq: vi.fn((a, b) => ({ _eq: [a, b] })),
isNull: vi.fn((a) => ({ _isNull: a })),
assetPermissions: {
assetId: 'assetId',
assetType: 'assetType',
identityId: 'identityId',
identityType: 'identityType',
deletedAt: 'deletedAt',
},
collectionsToAssets: {
collectionId: 'collectionId',
assetId: 'assetId',
assetType: 'assetType',
deletedAt: 'deletedAt',
},
chats: {
id: 'id',
createdBy: 'createdBy',
organizationId: 'organizationId',
deletedAt: 'deletedAt',
},
usersToOrganizations: {
userId: 'userId',
organizationId: 'organizationId',
role: 'role',
deletedAt: 'deletedAt',
},
}));
describe('canUserAccessChat', () => {
let getDb: any;
let mockDb: any;
beforeEach(async () => {
vi.clearAllMocks();
// Get the mocked module
const dbModule = await import('@buster/database');
getDb = vi.mocked(dbModule.getDb);
// Create a fresh mock database object for each test
const mockSelect = vi.fn();
const mockSelectDistinct = vi.fn();
const mockFrom = vi.fn();
const mockWhere = vi.fn();
const mockInnerJoin = vi.fn();
const mockLimit = vi.fn();
// Setup the chain
mockLimit.mockResolvedValue([]);
mockWhere.mockReturnValue({ limit: mockLimit });
mockInnerJoin.mockReturnValue({ where: mockWhere });
mockFrom.mockReturnValue({
where: mockWhere,
innerJoin: mockInnerJoin
});
mockSelect.mockReturnValue({ from: mockFrom });
mockSelectDistinct.mockReturnValue({ from: mockFrom });
mockDb = {
select: mockSelect,
selectDistinct: mockSelectDistinct,
_mockLimit: mockLimit,
_mockWhere: mockWhere,
_mockFrom: mockFrom,
_mockInnerJoin: mockInnerJoin,
};
getDb.mockReturnValue(mockDb);
});
it('should return false if chat does not exist', async () => {
// All queries return empty arrays
mockDb._mockLimit.mockResolvedValue([]);
const result = await canUserAccessChat({
userId: '123e4567-e89b-12d3-a456-426614174000',
chatId: '223e4567-e89b-12d3-a456-426614174000',
});
expect(result).toBe(false);
expect(getDb).toHaveBeenCalled();
});
it('should return true if user has direct permission', async () => {
let callCount = 0;
mockDb._mockLimit.mockImplementation(() => {
callCount++;
if (callCount === 1) {
// Direct permission check - has permission
return Promise.resolve([{ id: 'chat-id' }]);
} else if (callCount === 3) {
// Chat info
return Promise.resolve([{
createdBy: 'other-user',
organizationId: 'org-id',
}]);
}
return Promise.resolve([]);
});
mockDb._mockWhere.mockImplementation((...args) => {
// For user organizations query (doesn't use limit)
if (mockDb._mockWhere.mock.calls.length === 4) {
return Promise.resolve([]);
}
return { limit: mockDb._mockLimit };
});
const result = await canUserAccessChat({
userId: '123e4567-e89b-12d3-a456-426614174000',
chatId: '223e4567-e89b-12d3-a456-426614174000',
});
expect(result).toBe(true);
});
it('should return true if user has collection permission', async () => {
let callCount = 0;
mockDb._mockLimit.mockImplementation(() => {
callCount++;
if (callCount === 2) {
// Collection permission check - has permission
return Promise.resolve([{ collectionId: 'collection-id' }]);
} else if (callCount === 3) {
// Chat info
return Promise.resolve([{
createdBy: 'other-user',
organizationId: 'org-id',
}]);
}
return Promise.resolve([]);
});
mockDb._mockWhere.mockImplementation(() => {
// For user organizations query (doesn't use limit)
if (mockDb._mockWhere.mock.calls.length === 4) {
return Promise.resolve([]);
}
return { limit: mockDb._mockLimit };
});
const result = await canUserAccessChat({
userId: '123e4567-e89b-12d3-a456-426614174000',
chatId: '223e4567-e89b-12d3-a456-426614174000',
});
expect(result).toBe(true);
});
it('should return true if user is the creator', async () => {
const userId = '123e4567-e89b-12d3-a456-426614174000';
let callCount = 0;
mockDb._mockLimit.mockImplementation(() => {
callCount++;
if (callCount === 3) {
// Chat info - user is creator
return Promise.resolve([{
createdBy: userId,
organizationId: 'org-id',
}]);
}
return Promise.resolve([]);
});
mockDb._mockWhere.mockImplementation(() => {
// For user organizations query (doesn't use limit)
if (mockDb._mockWhere.mock.calls.length === 4) {
return Promise.resolve([]);
}
return { limit: mockDb._mockLimit };
});
const result = await canUserAccessChat({
userId,
chatId: '223e4567-e89b-12d3-a456-426614174000',
});
expect(result).toBe(true);
});
it('should return true if user is workspace_admin', async () => {
const orgId = 'org-123';
let callCount = 0;
mockDb._mockLimit.mockImplementation(() => {
callCount++;
if (callCount === 3) {
// Chat info
return Promise.resolve([{
createdBy: 'other-user',
organizationId: orgId,
}]);
}
return Promise.resolve([]);
});
mockDb._mockWhere.mockImplementation(() => {
// For user organizations query (doesn't use limit)
if (mockDb._mockWhere.mock.calls.length === 4) {
return Promise.resolve([{
organizationId: orgId,
role: 'workspace_admin',
}]);
}
return { limit: mockDb._mockLimit };
});
const result = await canUserAccessChat({
userId: '123e4567-e89b-12d3-a456-426614174000',
chatId: '223e4567-e89b-12d3-a456-426614174000',
});
expect(result).toBe(true);
});
it('should return true if user is data_admin', async () => {
const orgId = 'org-123';
let callCount = 0;
mockDb._mockLimit.mockImplementation(() => {
callCount++;
if (callCount === 3) {
// Chat info
return Promise.resolve([{
createdBy: 'other-user',
organizationId: orgId,
}]);
}
return Promise.resolve([]);
});
mockDb._mockWhere.mockImplementation(() => {
// For user organizations query (doesn't use limit)
if (mockDb._mockWhere.mock.calls.length === 4) {
return Promise.resolve([{
organizationId: orgId,
role: 'data_admin',
}]);
}
return { limit: mockDb._mockLimit };
});
const result = await canUserAccessChat({
userId: '123e4567-e89b-12d3-a456-426614174000',
chatId: '223e4567-e89b-12d3-a456-426614174000',
});
expect(result).toBe(true);
});
it('should return false if user has no access', async () => {
const orgId = 'org-123';
let callCount = 0;
mockDb._mockLimit.mockImplementation(() => {
callCount++;
if (callCount === 3) {
// Chat info exists
return Promise.resolve([{
createdBy: 'other-user',
organizationId: orgId,
}]);
}
return Promise.resolve([]);
});
mockDb._mockWhere.mockImplementation(() => {
// For user organizations query (doesn't use limit)
if (mockDb._mockWhere.mock.calls.length === 4) {
return Promise.resolve([{
organizationId: orgId,
role: 'viewer', // Not an admin role
}]);
}
return { limit: mockDb._mockLimit };
});
const result = await canUserAccessChat({
userId: '123e4567-e89b-12d3-a456-426614174000',
chatId: '223e4567-e89b-12d3-a456-426614174000',
});
expect(result).toBe(false);
});
it('should validate input UUIDs', async () => {
await expect(
canUserAccessChat({
userId: 'invalid-uuid',
chatId: '223e4567-e89b-12d3-a456-426614174000',
})
).rejects.toThrow();
await expect(
canUserAccessChat({
userId: '123e4567-e89b-12d3-a456-426614174000',
chatId: 'invalid-uuid',
})
).rejects.toThrow();
});
});