fix(explore): Display missing dataset for denied access (#34129)

This commit is contained in:
JUST.in DO IT
2025-07-16 13:36:03 -07:00
committed by GitHub
parent 94d47113ea
commit 96cb6030c8
10 changed files with 263 additions and 78 deletions

View File

@@ -479,3 +479,30 @@ test('should show missing dataset state', () => {
),
).toBeVisible();
});
test('should show forbidden dataset state', () => {
// @ts-ignore
delete window.location;
// @ts-ignore
window.location = { search: '?slice_id=152' };
const error = {
error_type: 'TABLE_SECURITY_ACCESS_ERROR',
statusText: 'FORBIDDEN',
message: 'You do not have access to the following tables: blocked_table',
extra: {
datasource: 152,
datasource_name: 'forbidden dataset',
},
};
const props = createProps({
datasource: {
...fallbackExploreInitialData.dataset,
extra: {
error,
},
},
});
render(<DatasourceControl {...props} />, { useRedux: true, useRouter: true });
expect(screen.getByText(error.message)).toBeInTheDocument();
expect(screen.getByText(error.statusText)).toBeVisible();
});

View File

@@ -50,6 +50,7 @@ import {
userHasPermission,
isUserAdmin,
} from 'src/dashboard/util/permissionUtils';
import { ErrorMessageWithStackTrace } from 'src/components/ErrorMessage/ErrorMessageWithStackTrace';
import ViewQueryModalFooter from 'src/explore/components/controls/ViewQueryModalFooter';
import ViewQuery from 'src/explore/components/controls/ViewQuery';
import { SaveDatasetModal } from 'src/SqlLab/components/SaveDatasetModal';
@@ -281,7 +282,17 @@ class DatasourceControl extends PureComponent {
showSaveDatasetModal,
} = this.state;
const { datasource, onChange, theme } = this.props;
const isMissingDatasource = !datasource?.id;
let extra;
if (datasource?.extra) {
if (typeof datasource.extra === 'string') {
try {
extra = JSON.parse(datasource.extra);
} catch {} // eslint-disable-line no-empty
} else {
extra = datasource.extra; // eslint-disable-line prefer-destructuring
}
}
const isMissingDatasource = !datasource?.id || Boolean(extra?.error);
let isMissingParams = false;
if (isMissingDatasource) {
const datasourceId = getUrlParam(URL_PARAMS.datasourceId);
@@ -386,20 +397,10 @@ class DatasourceControl extends PureComponent {
const { health_check_message: healthCheckMessage } = datasource;
let extra;
if (datasource?.extra) {
if (typeof datasource.extra === 'string') {
try {
extra = JSON.parse(datasource.extra);
} catch {} // eslint-disable-line no-empty
} else {
extra = datasource.extra; // eslint-disable-line prefer-destructuring
}
}
const titleText = isMissingDatasource
? t('Missing dataset')
: getDatasourceTitle(datasource);
const titleText =
isMissingDatasource && !datasource.name
? t('Missing dataset')
: getDatasourceTitle(datasource);
const tooltip = titleText;
@@ -452,31 +453,44 @@ class DatasourceControl extends PureComponent {
)}
{isMissingDatasource && !isMissingParams && (
<div className="error-alert">
<ErrorAlert
type="warning"
errorType={t('Missing dataset')}
descriptionPre={false}
descriptionDetailsCollapsed={false}
descriptionDetails={
<>
<p>
{t(
'The dataset linked to this chart may have been deleted.',
)}
</p>
<p>
<Button
buttonStyle="warning"
onClick={() =>
this.handleMenuItemClick({ key: CHANGE_DATASET })
}
>
{t('Swap dataset')}
</Button>
</p>
</>
}
/>
{extra?.error ? (
<div className="error-alert">
<ErrorMessageWithStackTrace
title={extra.error.statusText || extra.error.message}
subtitle={
extra.error.statusText ? extra.error.message : undefined
}
error={extra.error}
source="explore"
/>
</div>
) : (
<ErrorAlert
type="warning"
errorType={t('Missing dataset')}
descriptionPre={false}
descriptionDetailsCollapsed={false}
descriptionDetails={
<>
<p>
{t(
'The dataset linked to this chart may have been deleted.',
)}
</p>
<p>
<Button
buttonStyle="warning"
onClick={() =>
this.handleMenuItemClick({ key: CHANGE_DATASET })
}
>
{t('Swap dataset')}
</Button>
</p>
</>
}
/>
)}
</div>
)}
{showEditDatasourceModal && (