From b00acd8512c3f9bc6863e6852befd7b8b6c77e92 Mon Sep 17 00:00:00 2001 From: John Bodley Date: Wed, 9 Sep 2020 16:30:29 -0700 Subject: [PATCH] fix: Making the database read-only --- .../src/components/TableSelector.jsx | 3 +++ .../src/datasource/DatasourceEditor.jsx | 20 +++++++++---------- superset/connectors/base/views.py | 15 ++++++++++++++ superset/connectors/druid/views.py | 17 +++++++++++++--- superset/connectors/sqla/views.py | 6 +++--- 5 files changed, 44 insertions(+), 17 deletions(-) diff --git a/superset-frontend/src/components/TableSelector.jsx b/superset-frontend/src/components/TableSelector.jsx index 7c27c437f169c..395c6bed07d70 100644 --- a/superset-frontend/src/components/TableSelector.jsx +++ b/superset-frontend/src/components/TableSelector.jsx @@ -53,6 +53,7 @@ const propTypes = { onChange: PropTypes.func, clearable: PropTypes.bool, handleError: PropTypes.func.isRequired, + isDatabaseSelectEnabled: PropTypes.bool, }; const defaultProps = { @@ -67,6 +68,7 @@ const defaultProps = { sqlLabMode: true, formMode: false, clearable: true, + isDatabaseSelectEnabled: true, }; export default class TableSelector extends React.PureComponent { @@ -313,6 +315,7 @@ export default class TableSelector extends React.PureComponent { optionRenderer={this.renderDatabaseOption} mutator={this.dbMutator} placeholder={t('Select a database')} + isDisabled={!this.props.isDatabaseSelectEnabled} autoSelect />, ); diff --git a/superset-frontend/src/datasource/DatasourceEditor.jsx b/superset-frontend/src/datasource/DatasourceEditor.jsx index fca366187a9f0..608232a664e25 100644 --- a/superset-frontend/src/datasource/DatasourceEditor.jsx +++ b/superset-frontend/src/datasource/DatasourceEditor.jsx @@ -457,15 +457,13 @@ export class DatasourceEditor extends React.PureComponent { onSchemaChange={schema => this.onDatasourcePropChange('schema', schema) } - onDbChange={database => - this.onDatasourcePropChange('database', database) - } onTableChange={table => this.onDatasourcePropChange('datasource_name', table) } sqlLabMode={false} clearable={false} handleError={this.props.addDangerToast} + isDatabaseSelectEnabled={false} /> } description={t( @@ -748,6 +746,14 @@ export class DatasourceEditor extends React.PureComponent { return ( {this.renderErrors()} +
+ + {t('Be careful.')} + {t( + 'Changing these settings will affect all charts using this dataset, including charts owned by other people.', + )} + +
{activeTabKey === 4 && (
-
- - {t('Be careful.')} - {t( - 'Changing these settings will affect all charts using this dataset, including charts owned by other people.', - )} - -
{this.renderSettingsFieldset()} diff --git a/superset/connectors/base/views.py b/superset/connectors/base/views.py index 150c05c556400..ae5013ebbf4e9 100644 --- a/superset/connectors/base/views.py +++ b/superset/connectors/base/views.py @@ -14,13 +14,28 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +from typing import Any + from flask import Markup +from flask_appbuilder.fieldwidgets import BS3TextFieldWidget from superset.connectors.base.models import BaseDatasource from superset.exceptions import SupersetException from superset.views.base import SupersetModelView +class BS3TextFieldROWidget( # pylint: disable=too-few-public-methods + BS3TextFieldWidget +): + """ + Custom read only text field widget. + """ + + def __call__(self, field: Any, **kwargs: Any) -> Markup: + kwargs["readonly"] = "true" + return super().__call__(field, **kwargs) + + class DatasourceModelView(SupersetModelView): def pre_delete(self, item: BaseDatasource) -> None: if item.slices: diff --git a/superset/connectors/druid/views.py b/superset/connectors/druid/views.py index 4c2fbf99178f0..112bcd176d710 100644 --- a/superset/connectors/druid/views.py +++ b/superset/connectors/druid/views.py @@ -25,10 +25,11 @@ from flask_appbuilder.models.sqla.interface import SQLAInterface from flask_appbuilder.security.decorators import has_access from flask_babel import lazy_gettext as _ +from wtforms import StringField from wtforms.ext.sqlalchemy.fields import QuerySelectField from superset import db, security_manager -from superset.connectors.base.views import DatasourceModelView +from superset.connectors.base.views import BS3TextFieldROWidget, DatasourceModelView from superset.connectors.connector_registry import ConnectorRegistry from superset.connectors.druid import models from superset.constants import RouteMethod @@ -98,7 +99,7 @@ class DruidColumnInlineView(CompactCRUDMixin, SupersetModelView): add_form_extra_fields = { "datasource": QuerySelectField( "Datasource", - query_factory=lambda: db.session().query(models.DruidDatasource), + query_factory=lambda: db.session.query(models.DruidDatasource), allow_blank=True, widget=Select2Widget(extra_classes="readonly"), ) @@ -179,7 +180,7 @@ class DruidMetricInlineView(CompactCRUDMixin, SupersetModelView): add_form_extra_fields = { "datasource": QuerySelectField( "Datasource", - query_factory=lambda: db.session().query(models.DruidDatasource), + query_factory=lambda: db.session.query(models.DruidDatasource), allow_blank=True, widget=Select2Widget(extra_classes="readonly"), ) @@ -333,6 +334,16 @@ class DruidDatasourceModelView(DatasourceModelView, DeleteMixin, YamlExportMixin "changed_by_": _("Changed By"), "modified": _("Modified"), } + edit_form_extra_fields = { + "cluster": QuerySelectField( + "Cluster", + query_factory=lambda: db.session.query(models.DruidCluster), + widget=Select2Widget(extra_classes="readonly"), + ), + "datasource_name": StringField( + "Datasource Name", widget=BS3TextFieldROWidget() + ), + } def pre_add(self, item: "DruidDatasourceModelView") -> None: with db.session.no_autoflush: diff --git a/superset/connectors/sqla/views.py b/superset/connectors/sqla/views.py index 23f4c1c793264..a1e28e492b5c9 100644 --- a/superset/connectors/sqla/views.py +++ b/superset/connectors/sqla/views.py @@ -160,7 +160,7 @@ class TableColumnInlineView( # pylint: disable=too-many-ancestors add_form_extra_fields = { "table": QuerySelectField( "Table", - query_factory=lambda: db.session().query(models.SqlaTable), + query_factory=lambda: db.session.query(models.SqlaTable), allow_blank=True, widget=Select2Widget(extra_classes="readonly"), ) @@ -232,7 +232,7 @@ class SqlMetricInlineView( # pylint: disable=too-many-ancestors add_form_extra_fields = { "table": QuerySelectField( "Table", - query_factory=lambda: db.session().query(models.SqlaTable), + query_factory=lambda: db.session.query(models.SqlaTable), allow_blank=True, widget=Select2Widget(extra_classes="readonly"), ) @@ -393,7 +393,7 @@ class TableModelView( # pylint: disable=too-many-ancestors edit_form_extra_fields = { "database": QuerySelectField( "Database", - query_factory=lambda: db.session().query(models.Database), + query_factory=lambda: db.session.query(models.Database), widget=Select2Widget(extra_classes="readonly"), ) }