Skip to content

Commit

Permalink
Added access check + Druid in endpoint (#1224)
Browse files Browse the repository at this point in the history
* Explore control panel - Chart control, TimeFilter, GroupBy, Filters (#1205)

* create structure for new forked explore view (#1099)

* create structure for new forked explore view

* update component name

* add bootstrap data pattern

* remove console.log

* Associate version to entry files (#1060)

* Associate version to entry files

* Modified path joins for configs

* Made changes based on comments

* Created store and reducers (#1108)

* Created store and reducers

* Added spec

* Modifications based on comments

* Explore control panel components: Chart control, Time filter, SQL,
GroupBy and Filters

* Modifications based on comments

* Added access check + Druid in endpoint

* pull grains to constants

* Switch explore.html to old version
  • Loading branch information
vera-liu committed Oct 4, 2016
1 parent a92190c commit 8ab5e50
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const CHANGE_FILTER_OP = 'CHANGE_FILTER_OP';
export const CHANGE_FILTER_VALUE = 'CHANGE_FILTER_VALUE';
export const RESET_FORM_DATA = 'RESET_FORM_DATA';
export const CLEAR_ALL_OPTS = 'CLEAR_ALL_OPTS';
export const SET_DATASOURCE_CLASS = 'SET_DATASOURCE_CLASS';

export function setTimeColumnOpts(timeColumnOpts) {
return { type: SET_TIME_COLUMN_OPTS, timeColumnOpts };
Expand Down Expand Up @@ -59,6 +60,10 @@ export function clearAllOpts() {
return { type: CLEAR_ALL_OPTS };
}

export function setDatasourceClass(datasourceClass) {
return { type: SET_DATASOURCE_CLASS, datasourceClass };
}

export function setFormOpts(datasourceId, datasourceType) {
return function (dispatch) {
const timeColumnOpts = [];
Expand All @@ -73,7 +78,7 @@ export function setFormOpts(datasourceId, datasourceType) {

$.get(url, (data, status) => {
if (status === 'success') {
data.dttm_cols.forEach((d) => {
data.time_columns.forEach((d) => {
if (d) timeColumnOpts.push({ value: d, label: d });
});
data.groupby_cols.forEach((d) => {
Expand All @@ -89,6 +94,7 @@ export function setFormOpts(datasourceId, datasourceType) {
if (d) timeGrainOpts.push({ value: d, label: d });
});
// Repopulate options for controls
dispatch(setDatasourceClass(data.datasource_class));
dispatch(setTimeColumnOpts(timeColumnOpts));
dispatch(setTimeGrainOpts(timeGrainOpts));
dispatch(setGroupByColumnOpts(groupByColumnOpts));
Expand Down
12 changes: 9 additions & 3 deletions caravel/assets/javascripts/explorev2/components/TimeFilter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { sinceOptions, untilOptions } from '../constants';

const propTypes = {
actions: React.PropTypes.object,
datasourceClass: React.PropTypes.string,
timeColumnOpts: React.PropTypes.array,
timeColumn: React.PropTypes.string,
timeGrainOpts: React.PropTypes.array,
Expand Down Expand Up @@ -42,16 +43,20 @@ class TimeFilter extends React.Component {
this.props.actions.setUntil(val);
}
render() {
const timeColumnPlaceHolder =
(this.props.datasourceClass === 'SqlaTable') ? 'Time Column' : 'Time Granularity';
const timeGrainPlaceHolder =
(this.props.datasourceClass === 'SqlaTable') ? 'Time Grain' : 'Origin';
return (
<div className="panel space-1">
<div className="panel-header">Time Filter</div>
<div className="panel-body">
<div className="row">
<h5 className="section-heading">Time Column & Grain</h5>
<h5 className="section-heading">Time Column & Grains</h5>
<Select
className="col-sm-6"
name="select-time-column"
placeholder="Select a time column"
placeholder={`Select a ${timeColumnPlaceHolder}`}
options={this.props.timeColumnOpts}
value={this.props.timeColumn}
autosize={false}
Expand All @@ -60,7 +65,7 @@ class TimeFilter extends React.Component {
<Select
className="col-sm-6"
name="select-time-grain"
placeholder="Select a time grain"
placeholder={`Select a ${timeGrainPlaceHolder}`}
options={this.props.timeGrainOpts}
value={this.props.timeGrain}
autosize={false}
Expand Down Expand Up @@ -99,6 +104,7 @@ TimeFilter.defaultProps = defaultProps;

function mapStateToProps(state) {
return {
datasourceClass: state.datasourceClass,
timeColumnOpts: state.timeColumnOpts,
timeColumn: state.timeColumn,
timeGrainOpts: state.timeGrainOpts,
Expand Down
3 changes: 2 additions & 1 deletion caravel/assets/javascripts/explorev2/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ const bootstrappedState = Object.assign(initialState, {
datasources: bootstrapData.datasources,
datasourceId: parseInt(bootstrapData.datasource_id, 10),
datasourceType: bootstrapData.datasource_type,
datasourceClass: bootstrapData.datasource_class,
sliceName: bootstrapData.viz.form_data.slice_name,
sliceId: bootstrapData.viz.form_data.slice_id,
vizType: bootstrapData.viz.form_data.viz_type,
timeColumn: bootstrapData.viz.form_data.granularity_sqla,
timeGrain: bootstrapData.viz.form_data.time_grain_sqla,
metrics: [bootstrapData.viz.form_data.metric].map((m) => ({ value: m, label: m })),
metrics: [bootstrapData.viz.form_data.metrics].map((m) => ({ value: m, label: m })),
since: bootstrapData.viz.form_data.since,
until: bootstrapData.viz.form_data.until,
havingClause: bootstrapData.viz.form_data.having,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ export const exploreReducer = function (state, action) {
[actions.CLEAR_ALL_OPTS]() {
return Object.assign({}, state, defaultOpts);
},
[actions.SET_DATASOURCE_CLASS]() {
return Object.assign({}, state, { datasourceClass: action.datasourceClass });
},
};
if (action.type in actionHandlers) {
return actionHandlers[action.type]();
Expand Down
1 change: 1 addition & 0 deletions caravel/assets/javascripts/explorev2/stores/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const initialState = {
datasources: null,
datasourceId: null,
datasourceType: null,
datasourceClass: null,
vizType: null,
timeColumnOpts: [],
timeColumn: null,
Expand Down
44 changes: 32 additions & 12 deletions caravel/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@
log_this = models.Log.log_this
can_access = utils.can_access
QueryStatus = models.QueryStatus
DRUID_TIME_GRAINS = [
'all', '5 seconds', '30 seconds', '1 minute',
'5 minutes', '1 hour', '6 hour', '1 day', '7 days'
]


class BaseCaravelView(BaseView):
Expand Down Expand Up @@ -1297,6 +1301,7 @@ def exploreV2(self, datasource_type, datasource_id, slice_id=None):
"datasources": [(d.id, d.full_name) for d in datasources],
"datasource_id": datasource_id,
"datasource_type": datasource_type,
"datasource_class": datasource_class.__name__,
"user_id": g.user.get_id() if g.user else None,
"viz": json.loads(viz_obj.get_json())
}
Expand Down Expand Up @@ -1942,8 +1947,6 @@ def csv(self, client_id):
@expose("/fetch_datasource_metadata")
@log_this
def fetch_datasource_metadata(self):
# TODO: check permissions
# TODO: check if datasource exits
session = db.session
datasource_type = request.args.get('datasource_type')
datasource_class = SourceRegistry.sources[datasource_type]
Expand All @@ -1952,17 +1955,34 @@ def fetch_datasource_metadata(self):
.filter_by(id=request.args.get('datasource_id'))
.first()
)
# SUPPORT DRUID
# TODO: move this logic to the model (maybe)
datasource_grains = datasource.database.grains()
grain_names = [str(grain.name) for grain in datasource_grains]

# Check if datasource exists
if not datasource:
return json_error_response(DATASOURCE_MISSING_ERR)
# Check permission for datasource
if not self.datasource_access(datasource):
return json_error_response(DATASOURCE_ACCESS_ERR)

time_columns = []
grains_choices = []
datasource_class_name = datasource_class.__name__
if datasource_class_name == 'SqlaTable':
time_columns = datasource.dttm_cols
grains = datasource.database.grains()
grains_choices = [grain.name for grain in grains]
elif datasource_class_name == 'DruidDatasource':
time_columns = DRUID_TIME_GRAINS
grains_choices = ['now']

form_data = {
"dttm_cols": datasource.dttm_cols,
"time_grains": grain_names,
"groupby_cols": datasource.groupby_column_names,
"metrics": datasource.metrics_combo,
"filter_cols": datasource.filterable_column_names,
}
"datasource_class": datasource_class_name,
"time_columns": time_columns,
"time_grains": grains_choices,
"groupby_cols": datasource.groupby_column_names,
"metrics": datasource.metrics_combo,
"filter_cols": datasource.filterable_column_names,
}

return Response(
json.dumps(form_data), mimetype="application/json")

Expand Down

0 comments on commit 8ab5e50

Please sign in to comment.