Skip to content
Snippets Groups Projects
Commit b16e0272 authored by Tom Robinson's avatar Tom Robinson
Browse files

In SQL editor don't show dbs the user doesn't have native write permissions for

parent 329af5c5
No related branches found
No related tags found
No related merge requests found
......@@ -50,6 +50,7 @@ export default class NativeQueryEditor extends Component {
static propTypes = {
card: PropTypes.object.isRequired,
databases: PropTypes.array.isRequired,
nativeDatabases: PropTypes.array.isRequired,
query: PropTypes.object.isRequired,
setQueryFn: PropTypes.func.isRequired,
setDatabaseFn: PropTypes.func.isRequired,
......@@ -200,13 +201,13 @@ export default class NativeQueryEditor extends Component {
// we only render a db selector if there are actually multiple to choose from
let dataSelectors = [];
if (this.state.showEditor && this.props.databases && (this.props.databases.length > 1 || modeInfo.requiresTable)) {
if (this.props.databases.length > 1) {
if (this.state.showEditor && this.props.nativeDatabases && (this.props.nativeDatabases.length > 1 || modeInfo.requiresTable)) {
if (this.props.nativeDatabases.length > 1) {
dataSelectors.push(
<div key="db_selector" className="GuiBuilder-section GuiBuilder-data flex align-center">
<span className="GuiBuilder-section-label Query-label">Database</span>
<DataSelector
databases={this.props.databases}
databases={this.props.nativeDatabases}
query={this.props.query}
setDatabaseFn={this.setDatabaseID}
/>
......@@ -214,7 +215,7 @@ export default class NativeQueryEditor extends Component {
)
}
if (modeInfo.requiresTable) {
let databases = this.props.databases,
let databases = this.props.nativeDatabases,
dbId = this.props.query.database,
database = databases ? _.findWhere(databases, { id: dbId }) : null,
tables = database ? database.tables : [],
......
......@@ -169,10 +169,12 @@ export default class QueryHeader extends Component {
}
getHeaderButtons() {
const { isNew, isDirty, isEditing, tableMetadata } = this.props;
var buttonSections = [];
// NEW card
if (this.props.isNew && this.props.isDirty) {
if (isNew && isDirty) {
buttonSections.push([
<ModalWithTrigger
key="save"
......@@ -194,8 +196,8 @@ export default class QueryHeader extends Component {
}
// persistence buttons on saved cards
if (!this.props.isNew) {
if (!this.props.isEditing) {
if (!isNew) {
if (!isEditing) {
if (this.state.recentlySaved) {
// existing card + not editing + recently saved = save confirmation
buttonSections.push([
......@@ -273,7 +275,7 @@ export default class QueryHeader extends Component {
}
// add to dashboard
if (!this.props.isNew && !this.props.isEditing) {
if (!isNew && !isEditing) {
// simply adding an existing saved card to a dashboard, so show the modal to do so
buttonSections.push([
<Tooltip key="addtodash" tooltip="Add to dashboard">
......@@ -282,7 +284,7 @@ export default class QueryHeader extends Component {
</span>
</Tooltip>
]);
} else if (this.props.isNew && this.props.isDirty) {
} else if (isNew && isDirty) {
// this is a new card, so we need the user to save first then they can add to dash
buttonSections.push([
<Tooltip key="addtodashsave" tooltip="Add to dashboard">
......@@ -306,7 +308,7 @@ export default class QueryHeader extends Component {
}
// history icon on saved cards
if (!this.props.isNew) {
if (!isNew) {
buttonSections.push([
<Tooltip key="history" tooltip="Revision history">
<ModalWithTrigger
......@@ -332,10 +334,13 @@ export default class QueryHeader extends Component {
<QueryModeButton
key="queryModeToggle"
mode={this.props.card.dataset_query.type}
allowNativeToQuery={this.props.isNew && !this.props.isDirty}
allowNativeToQuery={isNew && !isDirty}
allowQueryToNative={isNew && (!isDirty ||
(tableMetadata && tableMetadata.db && tableMetadata.db.native_permissions === "write")
)}
nativeForm={this.props.result && this.props.result.data && this.props.result.data.native_form}
onSetMode={this.props.setQueryModeFn}
tableMetadata={this.props.tableMetadata}
tableMetadata={tableMetadata}
/>
]);
......
......@@ -21,16 +21,17 @@ export default class QueryModeButton extends Component {
static propTypes = {
mode: PropTypes.string.isRequired,
allowNativeToQuery: PropTypes.bool,
allowQueryToNative: PropTypes.bool,
nativeForm: PropTypes.object,
onSetMode: PropTypes.func.isRequired
};
static defaultProps = {
allowNativeToQuery: false
allowNativeToQuery: false,
}
render() {
const { allowNativeToQuery, mode, nativeForm, onSetMode, tableMetadata } = this.props;
const { allowQueryToNative, allowNativeToQuery, mode, nativeForm, onSetMode, tableMetadata } = this.props;
// determine the type to switch to based on the type
var targetType = (mode === "query") ? "native" : "query";
......@@ -41,7 +42,7 @@ export default class QueryModeButton extends Component {
// maybe switch up the icon based on mode?
let onClick = null;
let tooltip = "Not Supported";
if (mode === "query") {
if (mode === "query" && allowQueryToNative) {
onClick = nativeForm ? () => this.setState({isOpen: true}) : () => onSetMode("native");
tooltip = nativeForm ? `View the ${nativeQueryName}` : `Switch to ${nativeQueryName}`;
} else if (mode === "native" && allowNativeToQuery) {
......
......@@ -18,7 +18,7 @@ import { isPK, isFK } from "metabase/lib/types";
import Utils from "metabase/lib/utils";
import { applyParameters } from "metabase/meta/Card";
import { getParameters } from "./selectors";
import { getParameters, getNativeDatabases } from "./selectors";
const Metabase = new AngularResourceProxy("Metabase", ["db_list_with_tables", "db_fields", "dataset", "table_query_metadata"]);
const CardAPI = new AngularResourceProxy("Card", ["query"]);
......@@ -593,7 +593,17 @@ export const setQueryMode = createThunkAction(SET_QUERY_MODE, (type) => {
// we are translating an empty query
} else {
let newCard = startNewCard(type, card.dataset_query.database);
let databaseId = card.dataset_query.database;
// only carry over the database id if the user can write native queries
if (type === "native") {
let nativeDatabases = getNativeDatabases(getState());
if (!_.findWhere(nativeDatabases, { id: databaseId })) {
databaseId = nativeDatabases.length > 0 ? nativeDatabases[0].id : null
}
}
let newCard = startNewCard(type, databaseId);
dispatch(loadMetadataForCard(newCard));
......
......@@ -37,6 +37,7 @@ import {
getDatabaseFields,
getSampleDatasetId,
getFullDatasetQuery,
getNativeDatabases,
} from "../selectors";
import * as actions from "../actions";
......@@ -78,6 +79,7 @@ const mapStateToProps = (state, props) => {
query: state.qb.card && state.qb.card.dataset_query, // TODO: EOL, redundant
parameterValues: parameterValues(state),
databases: databases(state),
nativeDatabases: getNativeDatabases(state),
tables: tables(state),
tableMetadata: tableMetadata(state),
tableForeignKeys: tableForeignKeys(state),
......
......@@ -32,9 +32,9 @@ export const getDatabaseId = createSelector(
);
export const databases = state => state.qb.databases;
export const tableMetadata = state => state.qb.tableMetadata;
export const tableForeignKeys = state => state.qb.tableForeignKeys;
export const tableForeignKeyReferences = state => state.qb.tableForeignKeyReferences;
export const tables = createSelector(
[getDatabaseId, databases],
(databaseId, databases) => {
......@@ -49,6 +49,21 @@ export const tables = createSelector(
}
);
export const getNativeDatabases = createSelector(
databases,
(databases) =>
databases && databases.filter(db => db.native_permissions === "write")
)
export const tableMetadata = createSelector(
state => state.qb.tableMetadata,
databases,
(tableMetadata, databases) => tableMetadata && {
...tableMetadata,
db: _.findWhere(databases, { id: tableMetadata.db_id })
}
)
export const getSampleDatasetId = createSelector(
[databases],
(databases) => {
......
......@@ -39,7 +39,7 @@
(for [db dbs]
(let [user-has-perms? (fn [f] (perms/set-has-full-permissions? @*current-user-permissions-set* (f (u/get-id db))))]
(assoc db :native_permissions (cond
(user-has-perms? perms/native-readwrite-path) :readwrite
(user-has-perms? perms/native-readwrite-path) :write
(user-has-perms? perms/native-read-path) :read
:else :none)))))
......
......@@ -163,7 +163,7 @@
:id $
:updated_at $
:name "test-data"
:native_permissions "readwrite"
:native_permissions "write"
:is_sample false
:is_full_sync true
:description nil
......@@ -176,7 +176,7 @@
:id $
:updated_at $
:name $
:native_permissions "readwrite"
:native_permissions "write"
:is_sample false
:is_full_sync true
:description nil
......@@ -197,7 +197,7 @@
:id $
:updated_at $
:name $
:native_permissions "readwrite"
:native_permissions "write"
:is_sample false
:is_full_sync true
:description nil
......@@ -214,7 +214,7 @@
:id $
:updated_at $
:name "test-data"
:native_permissions "readwrite"
:native_permissions "write"
:is_sample false
:is_full_sync true
:description nil
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment