mirror of https://github.com/buster-so/buster.git
Merge pull request #1272 from buster-so/nate/upgrade-access-controls-biome2
upgrade access controls to use biome 2
This commit is contained in:
commit
2dfb3d6e5a
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
"$schema": "https://biomejs.dev/schemas/2.2.5/schema.json",
|
||||||
"extends": ["../../biome.json"],
|
"extends": ["../../biome2.json"],
|
||||||
"files": {
|
"files": {
|
||||||
"include": ["src/**/*"]
|
"includes": ["src/**/*"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
"@buster/env-utils": "workspace:*",
|
"@buster/env-utils": "workspace:*",
|
||||||
"@buster/typescript-config": "workspace:*",
|
"@buster/typescript-config": "workspace:*",
|
||||||
"@buster/vitest-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",
|
"node-sql-parser": "^5.3.12",
|
||||||
"yaml": "^2.8.1",
|
"yaml": "^2.8.1",
|
||||||
"zod": "catalog:",
|
"zod": "catalog:",
|
||||||
|
|
|
@ -464,11 +464,8 @@ export async function hasAllDatasetsAccess(userId: string, datasetIds: string[])
|
||||||
// --- Step 3: Check specific permissions for each dataset ---
|
// --- Step 3: Check specific permissions for each dataset ---
|
||||||
for (const datasetId of input.datasetIds) {
|
for (const datasetId of input.datasetIds) {
|
||||||
const datasetOrgId = datasetInfos.find(
|
const datasetOrgId = datasetInfos.find(
|
||||||
(info: {
|
(info: { id: string; organizationId: string; deletedAt: string | null }) =>
|
||||||
id: string;
|
info.id === datasetId
|
||||||
organizationId: string;
|
|
||||||
deletedAt: string | null;
|
|
||||||
}) => info.id === datasetId
|
|
||||||
)?.organizationId;
|
)?.organizationId;
|
||||||
|
|
||||||
if (!datasetOrgId) {
|
if (!datasetOrgId) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { beforeEach, describe, expect, it } from 'vitest';
|
import { beforeEach, describe, expect, it } from 'vitest';
|
||||||
import {
|
import {
|
||||||
clearAllCaches,
|
clearAllCaches,
|
||||||
getCacheStats,
|
|
||||||
getCachedCascadingPermission,
|
getCachedCascadingPermission,
|
||||||
getCachedPermission,
|
getCachedPermission,
|
||||||
|
getCacheStats,
|
||||||
invalidateAsset,
|
invalidateAsset,
|
||||||
invalidateOnPermissionChange,
|
invalidateOnPermissionChange,
|
||||||
invalidateUser,
|
invalidateUser,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
import type { User } from '@buster/database/queries';
|
||||||
import {
|
import {
|
||||||
checkChatsContainingAsset,
|
checkChatsContainingAsset,
|
||||||
checkCollectionsContainingAsset,
|
checkCollectionsContainingAsset,
|
||||||
checkDashboardsContainingMetric,
|
checkDashboardsContainingMetric,
|
||||||
checkReportsContainingMetric,
|
checkReportsContainingMetric,
|
||||||
} from '@buster/database/queries';
|
} from '@buster/database/queries';
|
||||||
import type { User } from '@buster/database/queries';
|
|
||||||
import type { AssetType } from '@buster/database/schema-types';
|
import type { AssetType } from '@buster/database/schema-types';
|
||||||
import type { AssetPermissionRole, WorkspaceSharing } from '../types/asset-permissions';
|
import type { AssetPermissionRole, WorkspaceSharing } from '../types/asset-permissions';
|
||||||
import { AccessControlError } from '../types/errors';
|
import { AccessControlError } from '../types/errors';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
import { checkPermission, computeEffectivePermission } from './checks';
|
|
||||||
import type { AssetPermissionResult } from './checks';
|
import type { AssetPermissionResult } from './checks';
|
||||||
|
import { checkPermission, computeEffectivePermission } from './checks';
|
||||||
|
|
||||||
// Mock database queries
|
// Mock database queries
|
||||||
vi.mock('@buster/database/queries', () => ({
|
vi.mock('@buster/database/queries', () => ({
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
import type { User } from '@buster/database/queries';
|
||||||
import {
|
import {
|
||||||
type CheckAssetPermissionParams,
|
type CheckAssetPermissionParams,
|
||||||
checkAssetPermission as checkDbAssetPermission,
|
checkAssetPermission as checkDbAssetPermission,
|
||||||
getUserOrganizationsByUserId,
|
getUserOrganizationsByUserId,
|
||||||
} from '@buster/database/queries';
|
} from '@buster/database/queries';
|
||||||
import type { User } from '@buster/database/queries';
|
|
||||||
import type { AssetType } from '@buster/database/schema-types';
|
import type { AssetType } from '@buster/database/schema-types';
|
||||||
import type { AssetPermissionRole, OrganizationMembership, WorkspaceSharing } from '../types';
|
import type { AssetPermissionRole, OrganizationMembership, WorkspaceSharing } from '../types';
|
||||||
import { getHighestPermission, isPermissionSufficient } from '../types/asset-permissions';
|
import { getHighestPermission, isPermissionSufficient } from '../types/asset-permissions';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Asset permissions module exports
|
// Asset permissions module exports
|
||||||
|
|
||||||
export * from './permissions';
|
|
||||||
export * from './checks';
|
|
||||||
export * from './cascading-permissions';
|
|
||||||
export * from './cache';
|
export * from './cache';
|
||||||
|
export * from './cascading-permissions';
|
||||||
|
export * from './checks';
|
||||||
|
export * from './permissions';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { checkPermission } from './checks';
|
|
||||||
import type { AssetPermissionCheck } from './checks';
|
import type { AssetPermissionCheck } from './checks';
|
||||||
|
import { checkPermission } from './checks';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached version of hasAssetPermission
|
* Cached version of hasAssetPermission
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import {
|
import {
|
||||||
type ListAssetPermissionsParams,
|
|
||||||
type RemoveAssetPermissionParams,
|
|
||||||
bulkCreateAssetPermissions,
|
bulkCreateAssetPermissions,
|
||||||
createAssetPermission,
|
createAssetPermission,
|
||||||
findUserByEmail,
|
findUserByEmail,
|
||||||
|
type ListAssetPermissionsParams,
|
||||||
listAssetPermissions,
|
listAssetPermissions,
|
||||||
|
type RemoveAssetPermissionParams,
|
||||||
removeAssetPermission,
|
removeAssetPermission,
|
||||||
} from '@buster/database/queries';
|
} from '@buster/database/queries';
|
||||||
import type { AssetType } from '@buster/database/schema-types';
|
import type { AssetType } from '@buster/database/schema-types';
|
||||||
|
|
|
@ -2,9 +2,9 @@ import { beforeEach, describe, expect, it } from 'vitest';
|
||||||
import type { PermissionedDataset } from '../types/dataset-permissions';
|
import type { PermissionedDataset } from '../types/dataset-permissions';
|
||||||
import {
|
import {
|
||||||
clearAllCaches,
|
clearAllCaches,
|
||||||
getCacheStats,
|
|
||||||
getCachedDatasetAccess,
|
getCachedDatasetAccess,
|
||||||
getCachedPermissionedDatasets,
|
getCachedPermissionedDatasets,
|
||||||
|
getCacheStats,
|
||||||
invalidateDataset,
|
invalidateDataset,
|
||||||
invalidateOnPermissionChange,
|
invalidateOnPermissionChange,
|
||||||
invalidateUser,
|
invalidateUser,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Dataset permissions module exports
|
// Dataset permissions module exports
|
||||||
|
|
||||||
export * from './permissions';
|
|
||||||
export * from './cache';
|
export * from './cache';
|
||||||
|
export * from './permissions';
|
||||||
|
|
|
@ -1,89 +1,80 @@
|
||||||
// Export all types
|
// 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 legacy access control functions
|
||||||
export {
|
export {
|
||||||
checkPermission as legacyCheckPermission,
|
checkPermission as legacyCheckPermission,
|
||||||
hasRole,
|
|
||||||
validateAccess,
|
|
||||||
getPermissionedDatasets as legacyGetPermissionedDatasets,
|
getPermissionedDatasets as legacyGetPermissionedDatasets,
|
||||||
hasDatasetAccess as legacyHasDatasetAccess,
|
|
||||||
hasAllDatasetsAccess as legacyHasAllDatasetsAccess,
|
hasAllDatasetsAccess as legacyHasAllDatasetsAccess,
|
||||||
|
hasDatasetAccess as legacyHasDatasetAccess,
|
||||||
|
hasRole,
|
||||||
type PermissionedDataset as LegacyPermissionedDataset,
|
type PermissionedDataset as LegacyPermissionedDataset,
|
||||||
|
validateAccess,
|
||||||
} from './access-controls';
|
} 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 { canUserAccessChat } from './chats';
|
||||||
|
|
||||||
// Export cached version and cache management functions
|
// Export cached version and cache management functions
|
||||||
export {
|
export {
|
||||||
canUserAccessChatCached,
|
canUserAccessChatCached,
|
||||||
getCacheStats,
|
|
||||||
resetCacheStats,
|
|
||||||
clearCache,
|
clearCache,
|
||||||
|
getCacheStats,
|
||||||
invalidateAccess,
|
invalidateAccess,
|
||||||
invalidateUserAccess,
|
|
||||||
invalidateChatAccess,
|
invalidateChatAccess,
|
||||||
|
invalidateUserAccess,
|
||||||
|
resetCacheStats,
|
||||||
} from './chats-cached';
|
} from './chats-cached';
|
||||||
|
// Export dataset permissions
|
||||||
// Export utility functions
|
export * from './datasets';
|
||||||
export { formatPermissionName, buildAccessQuery } from './utils';
|
// 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 user organization functions
|
||||||
export {
|
export {
|
||||||
checkUserInOrganization,
|
|
||||||
getUserOrganizations,
|
|
||||||
checkEmailDomainForOrganization,
|
checkEmailDomainForOrganization,
|
||||||
getOrganizationWithDefaults,
|
checkUserInOrganization,
|
||||||
createUserInOrganization,
|
createUserInOrganization,
|
||||||
type UserOrganizationInfo,
|
getOrganizationWithDefaults,
|
||||||
|
getUserOrganizations,
|
||||||
type OrganizationWithDefaults,
|
type OrganizationWithDefaults,
|
||||||
|
type UserOrganizationInfo,
|
||||||
} from './user-organizations';
|
} from './user-organizations';
|
||||||
|
// Export user utilities
|
||||||
|
export * from './users';
|
||||||
|
// Export utility functions
|
||||||
|
export { buildAccessQuery, formatPermissionName } from './utils';
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
|
export * from './execute-with-permission-check';
|
||||||
export * from './parser-helpers';
|
export * from './parser-helpers';
|
||||||
export * from './validator';
|
export * from './validator';
|
||||||
export * from './execute-with-permission-check';
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import pkg from 'node-sql-parser';
|
import pkg from 'node-sql-parser';
|
||||||
|
|
||||||
const { Parser } = pkg;
|
const { Parser } = pkg;
|
||||||
|
|
||||||
import type { BaseFrom, ColumnRefItem, Join, Select } from 'node-sql-parser';
|
import type { BaseFrom, ColumnRefItem, Join, Select } from 'node-sql-parser';
|
||||||
import * as yaml from 'yaml';
|
import * as yaml from 'yaml';
|
||||||
|
|
||||||
|
export type { QueryTypeCheckResult } from '@buster/data-source';
|
||||||
// Import checkQueryIsReadOnly from data-source package
|
// Import checkQueryIsReadOnly from data-source package
|
||||||
export { checkQueryIsReadOnly } from '@buster/data-source';
|
export { checkQueryIsReadOnly } from '@buster/data-source';
|
||||||
export type { QueryTypeCheckResult } from '@buster/data-source';
|
|
||||||
|
|
||||||
export interface ParsedTable {
|
export interface ParsedTable {
|
||||||
database?: string;
|
database?: string;
|
||||||
|
@ -155,7 +158,7 @@ export function extractPhysicalTables(sql: string, dataSourceSyntax?: string): P
|
||||||
*/
|
*/
|
||||||
export function parseTableReference(tableRef: string): ParsedTable {
|
export function parseTableReference(tableRef: string): ParsedTable {
|
||||||
// Remove any quotes and trim
|
// 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"
|
// Handle node-sql-parser format: "type::database::table" or "type::table"
|
||||||
if (cleanRef.includes('::')) {
|
if (cleanRef.includes('::')) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { getPermissionedDatasets } from '../datasets/permissions';
|
import { getPermissionedDatasets } from '../datasets/permissions';
|
||||||
import {
|
import {
|
||||||
type ParsedDataset,
|
|
||||||
type ParsedTable,
|
|
||||||
checkQueryIsReadOnly,
|
checkQueryIsReadOnly,
|
||||||
extractColumnReferences,
|
extractColumnReferences,
|
||||||
extractDatasetsFromYml,
|
extractDatasetsFromYml,
|
||||||
extractPhysicalTables,
|
extractPhysicalTables,
|
||||||
extractTablesFromYml,
|
extractTablesFromYml,
|
||||||
|
type ParsedDataset,
|
||||||
|
type ParsedTable,
|
||||||
tablesMatch,
|
tablesMatch,
|
||||||
validateWildcardUsage,
|
validateWildcardUsage,
|
||||||
} from './parser-helpers';
|
} from './parser-helpers';
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { z } from 'zod';
|
||||||
|
|
||||||
// Re-export all internal types
|
// Re-export all internal types
|
||||||
export * from './types/asset-permissions';
|
export * from './types/asset-permissions';
|
||||||
export * from './types/dataset-permissions';
|
|
||||||
export * from './types/cascading-permissions';
|
export * from './types/cascading-permissions';
|
||||||
|
export * from './types/dataset-permissions';
|
||||||
export * from './types/errors';
|
export * from './types/errors';
|
||||||
|
|
||||||
// Custom error class for access control operations (legacy - use AccessControlError instead)
|
// Custom error class for access control operations (legacy - use AccessControlError instead)
|
||||||
|
|
|
@ -1016,6 +1016,9 @@ importers:
|
||||||
|
|
||||||
packages/access-controls:
|
packages/access-controls:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@biomejs/biome':
|
||||||
|
specifier: 2.2.5
|
||||||
|
version: 2.2.5
|
||||||
'@buster/data-source':
|
'@buster/data-source':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../data-source
|
version: link:../data-source
|
||||||
|
@ -1035,8 +1038,8 @@ importers:
|
||||||
specifier: 'catalog:'
|
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)
|
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:
|
lru-cache:
|
||||||
specifier: ^11.1.0
|
specifier: ^11.2.2
|
||||||
version: 11.1.0
|
version: 11.2.2
|
||||||
node-sql-parser:
|
node-sql-parser:
|
||||||
specifier: ^5.3.12
|
specifier: ^5.3.12
|
||||||
version: 5.3.12
|
version: 5.3.12
|
||||||
|
@ -9419,10 +9422,6 @@ packages:
|
||||||
lru-cache@10.4.3:
|
lru-cache@10.4.3:
|
||||||
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
|
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.2:
|
lru-cache@11.2.2:
|
||||||
resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==}
|
resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==}
|
||||||
engines: {node: 20 || >=22}
|
engines: {node: 20 || >=22}
|
||||||
|
@ -22666,8 +22665,6 @@ snapshots:
|
||||||
|
|
||||||
lru-cache@10.4.3: {}
|
lru-cache@10.4.3: {}
|
||||||
|
|
||||||
lru-cache@11.1.0: {}
|
|
||||||
|
|
||||||
lru-cache@11.2.2: {}
|
lru-cache@11.2.2: {}
|
||||||
|
|
||||||
lru-cache@5.1.1:
|
lru-cache@5.1.1:
|
||||||
|
|
Loading…
Reference in New Issue