mirror of https://github.com/apache/superset.git
fix: impose dataset ownership check on old API (#12491)
* fix: impose dataset ownership check on old API * update UPDATING.md * partially protect the old MVC also * prevent metric and column add and update
This commit is contained in:
parent
7ac6e61b96
commit
a078296330
|
@ -23,6 +23,7 @@ This file documents any backwards-incompatible changes in Superset and
|
||||||
assists people when migrating to a new version.
|
assists people when migrating to a new version.
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
- [11509](https://github.com/apache/superset/pull/12491): Dataset metadata updates check user ownership, only owners or an Admin are allowed.
|
||||||
- Security simplification (SIP-19), the following permission domains were simplified:
|
- Security simplification (SIP-19), the following permission domains were simplified:
|
||||||
- [12072](https://github.com/apache/superset/pull/12072): `Query` with `can_read`, `can_write`
|
- [12072](https://github.com/apache/superset/pull/12072): `Query` with `can_read`, `can_write`
|
||||||
- [12036](https://github.com/apache/superset/pull/12036): `Database` with `can_read`, `can_write`.
|
- [12036](https://github.com/apache/superset/pull/12036): `Database` with `can_read`, `can_write`.
|
||||||
|
|
|
@ -69,7 +69,7 @@ class DeleteFailedError(CommandException):
|
||||||
|
|
||||||
|
|
||||||
class ForbiddenError(CommandException):
|
class ForbiddenError(CommandException):
|
||||||
status = 500
|
status = 403
|
||||||
message = "Action is forbidden"
|
message = "Action is forbidden"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ from superset.constants import MODEL_VIEW_RW_METHOD_PERMISSION_MAP, RouteMethod
|
||||||
from superset.typing import FlaskResponse
|
from superset.typing import FlaskResponse
|
||||||
from superset.utils import core as utils
|
from superset.utils import core as utils
|
||||||
from superset.views.base import (
|
from superset.views.base import (
|
||||||
|
check_ownership,
|
||||||
create_table_permissions,
|
create_table_permissions,
|
||||||
DatasourceFilter,
|
DatasourceFilter,
|
||||||
DeleteMixin,
|
DeleteMixin,
|
||||||
|
@ -171,6 +172,15 @@ class TableColumnInlineView( # pylint: disable=too-many-ancestors
|
||||||
|
|
||||||
edit_form_extra_fields = add_form_extra_fields
|
edit_form_extra_fields = add_form_extra_fields
|
||||||
|
|
||||||
|
def pre_add(self, item: "models.SqlMetric") -> None:
|
||||||
|
check_ownership(item.table)
|
||||||
|
|
||||||
|
def pre_update(self, item: "models.SqlMetric") -> None:
|
||||||
|
check_ownership(item.table)
|
||||||
|
|
||||||
|
def pre_delete(self, item: "models.SqlMetric") -> None:
|
||||||
|
check_ownership(item.table)
|
||||||
|
|
||||||
|
|
||||||
class SqlMetricInlineView( # pylint: disable=too-many-ancestors
|
class SqlMetricInlineView( # pylint: disable=too-many-ancestors
|
||||||
CompactCRUDMixin, SupersetModelView
|
CompactCRUDMixin, SupersetModelView
|
||||||
|
@ -245,6 +255,15 @@ class SqlMetricInlineView( # pylint: disable=too-many-ancestors
|
||||||
|
|
||||||
edit_form_extra_fields = add_form_extra_fields
|
edit_form_extra_fields = add_form_extra_fields
|
||||||
|
|
||||||
|
def pre_add(self, item: "models.SqlMetric") -> None:
|
||||||
|
check_ownership(item.table)
|
||||||
|
|
||||||
|
def pre_update(self, item: "models.SqlMetric") -> None:
|
||||||
|
check_ownership(item.table)
|
||||||
|
|
||||||
|
def pre_delete(self, item: "models.SqlMetric") -> None:
|
||||||
|
check_ownership(item.table)
|
||||||
|
|
||||||
|
|
||||||
class RowLevelSecurityListWidget(
|
class RowLevelSecurityListWidget(
|
||||||
SupersetListWidget
|
SupersetListWidget
|
||||||
|
@ -459,6 +478,9 @@ class TableModelView( # pylint: disable=too-many-ancestors
|
||||||
def pre_add(self, item: "TableModelView") -> None:
|
def pre_add(self, item: "TableModelView") -> None:
|
||||||
validate_sqlatable(item)
|
validate_sqlatable(item)
|
||||||
|
|
||||||
|
def pre_update(self, item: "TableModelView") -> None:
|
||||||
|
check_ownership(item)
|
||||||
|
|
||||||
def post_add( # pylint: disable=arguments-differ
|
def post_add( # pylint: disable=arguments-differ
|
||||||
self,
|
self,
|
||||||
item: "TableModelView",
|
item: "TableModelView",
|
||||||
|
|
|
@ -24,8 +24,10 @@ from sqlalchemy.orm.exc import NoResultFound
|
||||||
|
|
||||||
from superset import db
|
from superset import db
|
||||||
from superset.connectors.connector_registry import ConnectorRegistry
|
from superset.connectors.connector_registry import ConnectorRegistry
|
||||||
from superset.exceptions import SupersetException
|
from superset.datasets.commands.exceptions import DatasetForbiddenError
|
||||||
|
from superset.exceptions import SupersetException, SupersetSecurityException
|
||||||
from superset.typing import FlaskResponse
|
from superset.typing import FlaskResponse
|
||||||
|
from superset.views.base import check_ownership
|
||||||
|
|
||||||
from .base import api, BaseSupersetView, handle_api_exception, json_error_response
|
from .base import api, BaseSupersetView, handle_api_exception, json_error_response
|
||||||
|
|
||||||
|
@ -52,6 +54,14 @@ class Datasource(BaseSupersetView):
|
||||||
orm_datasource.database_id = database_id
|
orm_datasource.database_id = database_id
|
||||||
|
|
||||||
if "owners" in datasource_dict and orm_datasource.owner_class is not None:
|
if "owners" in datasource_dict and orm_datasource.owner_class is not None:
|
||||||
|
# Check ownership
|
||||||
|
try:
|
||||||
|
check_ownership(orm_datasource)
|
||||||
|
except SupersetSecurityException:
|
||||||
|
return json_error_response(
|
||||||
|
f"{DatasetForbiddenError.message}", DatasetForbiddenError.status
|
||||||
|
)
|
||||||
|
|
||||||
datasource_dict["owners"] = (
|
datasource_dict["owners"] = (
|
||||||
db.session.query(orm_datasource.owner_class)
|
db.session.query(orm_datasource.owner_class)
|
||||||
.filter(orm_datasource.owner_class.id.in_(datasource_dict["owners"]))
|
.filter(orm_datasource.owner_class.id.in_(datasource_dict["owners"]))
|
||||||
|
|
Loading…
Reference in New Issue