diff --git a/.DS_Store b/.DS_Store index 606a28c2c..802c59b69 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/packages/access-controls/biome.json b/packages/access-controls/biome.json index b242fa54d..fd4e132e2 100644 --- a/packages/access-controls/biome.json +++ b/packages/access-controls/biome.json @@ -1,7 +1,7 @@ { - "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", - "extends": ["../../biome.json"], + "$schema": "https://biomejs.dev/schemas/2.2.5/schema.json", + "extends": ["../../biome2.json"], "files": { - "include": ["src/**/*"] + "includes": ["src/**/*"] } } diff --git a/packages/access-controls/package.json b/packages/access-controls/package.json index 232bc84f4..586c1cb62 100644 --- a/packages/access-controls/package.json +++ b/packages/access-controls/package.json @@ -32,7 +32,8 @@ "@buster/env-utils": "workspace:*", "@buster/typescript-config": "workspace:*", "@buster/vitest-config": "workspace:*", - "lru-cache": "^11.1.0", + "@biomejs/biome": "2.2.5", + "lru-cache": "^11.2.2", "node-sql-parser": "^5.3.12", "yaml": "^2.8.1", "zod": "catalog:", diff --git a/packages/access-controls/src/access-controls.ts b/packages/access-controls/src/access-controls.ts index 554a2e365..6372dfa87 100644 --- a/packages/access-controls/src/access-controls.ts +++ b/packages/access-controls/src/access-controls.ts @@ -464,11 +464,8 @@ export async function hasAllDatasetsAccess(userId: string, datasetIds: string[]) // --- Step 3: Check specific permissions for each dataset --- for (const datasetId of input.datasetIds) { const datasetOrgId = datasetInfos.find( - (info: { - id: string; - organizationId: string; - deletedAt: string | null; - }) => info.id === datasetId + (info: { id: string; organizationId: string; deletedAt: string | null }) => + info.id === datasetId )?.organizationId; if (!datasetOrgId) { diff --git a/packages/access-controls/src/assets/cache.test.ts b/packages/access-controls/src/assets/cache.test.ts index c7872b343..ae7dd212f 100644 --- a/packages/access-controls/src/assets/cache.test.ts +++ b/packages/access-controls/src/assets/cache.test.ts @@ -1,9 +1,9 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { clearAllCaches, - getCacheStats, getCachedCascadingPermission, getCachedPermission, + getCacheStats, invalidateAsset, invalidateOnPermissionChange, invalidateUser, diff --git a/packages/access-controls/src/assets/cascading-permissions.ts b/packages/access-controls/src/assets/cascading-permissions.ts index f9554ba1f..90b851398 100644 --- a/packages/access-controls/src/assets/cascading-permissions.ts +++ b/packages/access-controls/src/assets/cascading-permissions.ts @@ -1,10 +1,10 @@ +import type { User } from '@buster/database/queries'; import { checkChatsContainingAsset, checkCollectionsContainingAsset, checkDashboardsContainingMetric, checkReportsContainingMetric, } from '@buster/database/queries'; -import type { User } from '@buster/database/queries'; import type { AssetType } from '@buster/database/schema-types'; import type { AssetPermissionRole, WorkspaceSharing } from '../types/asset-permissions'; import { AccessControlError } from '../types/errors'; diff --git a/packages/access-controls/src/assets/checks.test.ts b/packages/access-controls/src/assets/checks.test.ts index 1baad34bd..2e56ed958 100644 --- a/packages/access-controls/src/assets/checks.test.ts +++ b/packages/access-controls/src/assets/checks.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { checkPermission, computeEffectivePermission } from './checks'; import type { AssetPermissionResult } from './checks'; +import { checkPermission, computeEffectivePermission } from './checks'; // Mock database queries vi.mock('@buster/database/queries', () => ({ diff --git a/packages/access-controls/src/assets/checks.ts b/packages/access-controls/src/assets/checks.ts index 20d91e818..b0a629a6b 100644 --- a/packages/access-controls/src/assets/checks.ts +++ b/packages/access-controls/src/assets/checks.ts @@ -1,9 +1,9 @@ +import type { User } from '@buster/database/queries'; import { type CheckAssetPermissionParams, checkAssetPermission as checkDbAssetPermission, getUserOrganizationsByUserId, } from '@buster/database/queries'; -import type { User } from '@buster/database/queries'; import type { AssetType } from '@buster/database/schema-types'; import type { AssetPermissionRole, OrganizationMembership, WorkspaceSharing } from '../types'; import { getHighestPermission, isPermissionSufficient } from '../types/asset-permissions'; diff --git a/packages/access-controls/src/assets/index.ts b/packages/access-controls/src/assets/index.ts index 5b0cfddae..a0dbb3d5c 100644 --- a/packages/access-controls/src/assets/index.ts +++ b/packages/access-controls/src/assets/index.ts @@ -1,6 +1,6 @@ // Asset permissions module exports -export * from './permissions'; -export * from './checks'; -export * from './cascading-permissions'; export * from './cache'; +export * from './cascading-permissions'; +export * from './checks'; +export * from './permissions'; diff --git a/packages/access-controls/src/assets/permissions-cached.ts b/packages/access-controls/src/assets/permissions-cached.ts index 0c697773c..beaf07320 100644 --- a/packages/access-controls/src/assets/permissions-cached.ts +++ b/packages/access-controls/src/assets/permissions-cached.ts @@ -1,5 +1,5 @@ -import { checkPermission } from './checks'; import type { AssetPermissionCheck } from './checks'; +import { checkPermission } from './checks'; /** * Cached version of hasAssetPermission diff --git a/packages/access-controls/src/assets/permissions.ts b/packages/access-controls/src/assets/permissions.ts index ff8389d75..60976f2c9 100644 --- a/packages/access-controls/src/assets/permissions.ts +++ b/packages/access-controls/src/assets/permissions.ts @@ -1,10 +1,10 @@ import { - type ListAssetPermissionsParams, - type RemoveAssetPermissionParams, bulkCreateAssetPermissions, createAssetPermission, findUserByEmail, + type ListAssetPermissionsParams, listAssetPermissions, + type RemoveAssetPermissionParams, removeAssetPermission, } from '@buster/database/queries'; import type { AssetType } from '@buster/database/schema-types'; diff --git a/packages/access-controls/src/datasets/cache.test.ts b/packages/access-controls/src/datasets/cache.test.ts index 44d677ed2..deca2d101 100644 --- a/packages/access-controls/src/datasets/cache.test.ts +++ b/packages/access-controls/src/datasets/cache.test.ts @@ -2,9 +2,9 @@ import { beforeEach, describe, expect, it } from 'vitest'; import type { PermissionedDataset } from '../types/dataset-permissions'; import { clearAllCaches, - getCacheStats, getCachedDatasetAccess, getCachedPermissionedDatasets, + getCacheStats, invalidateDataset, invalidateOnPermissionChange, invalidateUser, diff --git a/packages/access-controls/src/datasets/index.ts b/packages/access-controls/src/datasets/index.ts index 8a4f28838..d4d0db63f 100644 --- a/packages/access-controls/src/datasets/index.ts +++ b/packages/access-controls/src/datasets/index.ts @@ -1,4 +1,4 @@ // Dataset permissions module exports -export * from './permissions'; export * from './cache'; +export * from './permissions'; diff --git a/packages/access-controls/src/index.ts b/packages/access-controls/src/index.ts index 00a92eb89..6694a1932 100644 --- a/packages/access-controls/src/index.ts +++ b/packages/access-controls/src/index.ts @@ -1,89 +1,80 @@ // Export all types -export * from './types'; - -// Export asset permissions (excluding cache functions to avoid conflicts) -export { - // From permissions.ts - hasAssetPermission, - createPermission, - createPermissionByEmail, - removePermission, - removePermissionByEmail, - listPermissions, - // From checks.ts - checkPermission, - computeEffectivePermission, - type AssetPermissionCheck, - type AssetPermissionResult, - // From cascading-permissions.ts - checkCascadingPermissions, - checkMetricDashboardAccess, - checkMetricChatAccess, - checkMetricCollectionAccess, - checkMetricReportAccess, - checkDashboardChatAccess, - checkDashboardCollectionAccess, -} from './assets'; - -// Export dataset permissions -export * from './datasets'; - -// Export user utilities -export * from './users'; - -// Export SQL permissions -export * from './sql-permissions'; - -// Export cache functions separately -export { - clearAllCaches, - invalidateUser, - invalidateOnPermissionChange, - getCacheStats as getAssetCacheStats, -} from './assets/cache'; - -// Export legacy access control functionality (for backward compatibility) -export { - AccessControlsError, - type Permission, - type Role, - type AccessControlOptions, -} from './types'; // Export legacy access control functions export { checkPermission as legacyCheckPermission, - hasRole, - validateAccess, getPermissionedDatasets as legacyGetPermissionedDatasets, - hasDatasetAccess as legacyHasDatasetAccess, hasAllDatasetsAccess as legacyHasAllDatasetsAccess, + hasDatasetAccess as legacyHasDatasetAccess, + hasRole, type PermissionedDataset as LegacyPermissionedDataset, + validateAccess, } from './access-controls'; +// Export asset permissions (excluding cache functions to avoid conflicts) +export { + type AssetPermissionCheck, + type AssetPermissionResult, + // From cascading-permissions.ts + checkCascadingPermissions, + checkDashboardChatAccess, + checkDashboardCollectionAccess, + checkMetricChatAccess, + checkMetricCollectionAccess, + checkMetricDashboardAccess, + checkMetricReportAccess, + // From checks.ts + checkPermission, + computeEffectivePermission, + createPermission, + createPermissionByEmail, + // From permissions.ts + hasAssetPermission, + listPermissions, + removePermission, + removePermissionByEmail, +} from './assets'; +// Export cache functions separately +export { + clearAllCaches, + getCacheStats as getAssetCacheStats, + invalidateOnPermissionChange, + invalidateUser, +} from './assets/cache'; export { canUserAccessChat } from './chats'; - // Export cached version and cache management functions export { canUserAccessChatCached, - getCacheStats, - resetCacheStats, clearCache, + getCacheStats, invalidateAccess, - invalidateUserAccess, invalidateChatAccess, + invalidateUserAccess, + resetCacheStats, } from './chats-cached'; - -// Export utility functions -export { formatPermissionName, buildAccessQuery } from './utils'; - +// Export dataset permissions +export * from './datasets'; +// Export SQL permissions +export * from './sql-permissions'; +export * from './types'; +// Export legacy access control functionality (for backward compatibility) +export { + type AccessControlOptions, + AccessControlsError, + type Permission, + type Role, +} from './types'; // Export user organization functions export { - checkUserInOrganization, - getUserOrganizations, checkEmailDomainForOrganization, - getOrganizationWithDefaults, + checkUserInOrganization, createUserInOrganization, - type UserOrganizationInfo, + getOrganizationWithDefaults, + getUserOrganizations, type OrganizationWithDefaults, + type UserOrganizationInfo, } from './user-organizations'; +// Export user utilities +export * from './users'; +// Export utility functions +export { buildAccessQuery, formatPermissionName } from './utils'; diff --git a/packages/access-controls/src/sql-permissions/index.ts b/packages/access-controls/src/sql-permissions/index.ts index ff92b2e46..3583ce7e7 100644 --- a/packages/access-controls/src/sql-permissions/index.ts +++ b/packages/access-controls/src/sql-permissions/index.ts @@ -1,3 +1,3 @@ +export * from './execute-with-permission-check'; export * from './parser-helpers'; export * from './validator'; -export * from './execute-with-permission-check'; diff --git a/packages/access-controls/src/sql-permissions/parser-helpers.ts b/packages/access-controls/src/sql-permissions/parser-helpers.ts index 6168fd01a..bc88dc75e 100644 --- a/packages/access-controls/src/sql-permissions/parser-helpers.ts +++ b/packages/access-controls/src/sql-permissions/parser-helpers.ts @@ -1,10 +1,13 @@ import pkg from 'node-sql-parser'; + const { Parser } = pkg; + import type { BaseFrom, ColumnRefItem, Join, Select } from 'node-sql-parser'; import * as yaml from 'yaml'; + +export type { QueryTypeCheckResult } from '@buster/data-source'; // Import checkQueryIsReadOnly from data-source package export { checkQueryIsReadOnly } from '@buster/data-source'; -export type { QueryTypeCheckResult } from '@buster/data-source'; export interface ParsedTable { database?: string; @@ -155,7 +158,7 @@ export function extractPhysicalTables(sql: string, dataSourceSyntax?: string): P */ export function parseTableReference(tableRef: string): ParsedTable { // Remove any quotes and trim - let cleanRef = tableRef.replace(/["'`\[\]]/g, '').trim(); + let cleanRef = tableRef.replace(/["'`[\]]/g, '').trim(); // Handle node-sql-parser format: "type::database::table" or "type::table" if (cleanRef.includes('::')) { diff --git a/packages/access-controls/src/sql-permissions/validator.ts b/packages/access-controls/src/sql-permissions/validator.ts index 187f05315..d4441df2a 100644 --- a/packages/access-controls/src/sql-permissions/validator.ts +++ b/packages/access-controls/src/sql-permissions/validator.ts @@ -1,12 +1,12 @@ import { getPermissionedDatasets } from '../datasets/permissions'; import { - type ParsedDataset, - type ParsedTable, checkQueryIsReadOnly, extractColumnReferences, extractDatasetsFromYml, extractPhysicalTables, extractTablesFromYml, + type ParsedDataset, + type ParsedTable, tablesMatch, validateWildcardUsage, } from './parser-helpers'; diff --git a/packages/access-controls/src/types.ts b/packages/access-controls/src/types.ts index 1c0613f60..57ee22222 100644 --- a/packages/access-controls/src/types.ts +++ b/packages/access-controls/src/types.ts @@ -2,8 +2,8 @@ import { z } from 'zod'; // Re-export all internal types export * from './types/asset-permissions'; -export * from './types/dataset-permissions'; export * from './types/cascading-permissions'; +export * from './types/dataset-permissions'; export * from './types/errors'; // Custom error class for access control operations (legacy - use AccessControlError instead) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 738589a76..4cdc511a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1016,6 +1016,9 @@ importers: packages/access-controls: dependencies: + '@biomejs/biome': + specifier: 2.2.5 + version: 2.2.5 '@buster/data-source': specifier: workspace:* version: link:../data-source @@ -1035,8 +1038,8 @@ importers: specifier: 'catalog:' version: 0.44.5(@opentelemetry/api@1.9.0)(@types/pg@8.15.4)(bun-types@1.2.23(@types/react@19.1.13))(mysql2@3.14.1)(pg@8.16.3)(postgres@3.4.7) lru-cache: - specifier: ^11.1.0 - version: 11.1.0 + specifier: ^11.2.2 + version: 11.2.2 node-sql-parser: specifier: ^5.3.12 version: 5.3.12 @@ -9568,14 +9571,14 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@11.1.0: - resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} - engines: {node: 20 || >=22} - lru-cache@11.2.1: resolution: {integrity: sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==} engines: {node: 20 || >=22} + lru-cache@11.2.2: + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -13215,7 +13218,7 @@ snapshots: '@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - lru-cache: 11.2.1 + lru-cache: 11.2.2 '@asamuzakjp/dom-selector@6.5.4': dependencies: @@ -22925,10 +22928,10 @@ snapshots: lru-cache@10.4.3: {} - lru-cache@11.1.0: {} - lru-cache@11.2.1: {} + lru-cache@11.2.2: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -24378,7 +24381,7 @@ snapshots: path-scurry@2.0.0: dependencies: - lru-cache: 11.2.1 + lru-cache: 11.2.2 minipass: 7.1.2 path-to-regexp@0.1.12: {}