fix: Making the database read-only (#10823)

Co-authored-by: John Bodley <john.bodley@airbnb.com>
This commit is contained in:
John Bodley 2020-09-10 16:23:24 -07:00 committed by GitHub
parent d80f406239
commit a3e2e65121
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 44 additions and 17 deletions

View File

@ -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
/>,
);

View File

@ -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 (
<DatasourceContainer>
{this.renderErrors()}
<div className="m-t-10">
<Alert bsStyle="warning">
<strong>{t('Be careful.')} </strong>
{t(
'Changing these settings will affect all charts using this dataset, including charts owned by other people.',
)}
</Alert>
</div>
<Tabs
id="table-tabs"
onSelect={this.handleTabSelect}
@ -830,14 +836,6 @@ export class DatasourceEditor extends React.PureComponent {
<Tab eventKey={4} title={t('Settings')}>
{activeTabKey === 4 && (
<div>
<div className="m-t-10">
<Alert bsStyle="warning">
<strong>{t('Be careful.')} </strong>
{t(
'Changing these settings will affect all charts using this dataset, including charts owned by other people.',
)}
</Alert>
</div>
<Col md={6}>
<FormContainer>{this.renderSettingsFieldset()}</FormContainer>
</Col>

View File

@ -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:

View File

@ -25,10 +25,11 @@ from flask_appbuilder.fieldwidgets import Select2Widget
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:

View File

@ -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"),
)
}