chore: Migrate /superset/schemas_access_for_file_upload to v1 (#23227)
Co-authored-by: Diego Medina <diegomedina24@gmail.com>
This commit is contained in:
parent
1874f9a3b6
commit
9920ab3fd9
|
|
@ -1834,10 +1834,10 @@
|
|||
"type": "string"
|
||||
},
|
||||
"last_saved_by": {
|
||||
"$ref": "#/components/schemas/ChartDataRestApi.get_list.User3"
|
||||
"$ref": "#/components/schemas/ChartDataRestApi.get_list.User1"
|
||||
},
|
||||
"owners": {
|
||||
"$ref": "#/components/schemas/ChartDataRestApi.get_list.User1"
|
||||
"$ref": "#/components/schemas/ChartDataRestApi.get_list.User3"
|
||||
},
|
||||
"params": {
|
||||
"nullable": true,
|
||||
|
|
@ -1925,16 +1925,11 @@
|
|||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name",
|
||||
"username"
|
||||
"last_name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
|
|
@ -1972,11 +1967,16 @@
|
|||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name"
|
||||
"last_name",
|
||||
"username"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
|
|
@ -2627,10 +2627,10 @@
|
|||
"type": "string"
|
||||
},
|
||||
"last_saved_by": {
|
||||
"$ref": "#/components/schemas/ChartRestApi.get_list.User3"
|
||||
"$ref": "#/components/schemas/ChartRestApi.get_list.User1"
|
||||
},
|
||||
"owners": {
|
||||
"$ref": "#/components/schemas/ChartRestApi.get_list.User1"
|
||||
"$ref": "#/components/schemas/ChartRestApi.get_list.User3"
|
||||
},
|
||||
"params": {
|
||||
"nullable": true,
|
||||
|
|
@ -2718,16 +2718,11 @@
|
|||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name",
|
||||
"username"
|
||||
"last_name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
|
|
@ -2765,11 +2760,16 @@
|
|||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name"
|
||||
"last_name",
|
||||
"username"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
|
|
@ -3420,7 +3420,7 @@
|
|||
"readOnly": true
|
||||
},
|
||||
"created_by": {
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.User2"
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.User1"
|
||||
},
|
||||
"created_on_delta_humanized": {
|
||||
"readOnly": true
|
||||
|
|
@ -3446,7 +3446,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"owners": {
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.User1"
|
||||
"$ref": "#/components/schemas/DashboardRestApi.get_list.User2"
|
||||
},
|
||||
"position_json": {
|
||||
"nullable": true,
|
||||
|
|
@ -3519,6 +3519,27 @@
|
|||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.get_list.User1": {
|
||||
"properties": {
|
||||
"first_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.get_list.User2": {
|
||||
"properties": {
|
||||
"email": {
|
||||
"maxLength": 64,
|
||||
|
|
@ -3549,27 +3570,6 @@
|
|||
],
|
||||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.get_list.User2": {
|
||||
"properties": {
|
||||
"first_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"DashboardRestApi.post": {
|
||||
"properties": {
|
||||
"certification_details": {
|
||||
|
|
@ -4293,6 +4293,18 @@
|
|||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DatabaseSchemaAccessForFileUploadResponse": {
|
||||
"properties": {
|
||||
"schemas": {
|
||||
"description": "The list of schemas allowed for the database to upload information",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"DatabaseTablesResponse": {
|
||||
"properties": {
|
||||
"extra": {
|
||||
|
|
@ -4917,7 +4929,7 @@
|
|||
"$ref": "#/components/schemas/DatasetRestApi.get.TableColumn"
|
||||
},
|
||||
"created_by": {
|
||||
"$ref": "#/components/schemas/DatasetRestApi.get.User2"
|
||||
"$ref": "#/components/schemas/DatasetRestApi.get.User1"
|
||||
},
|
||||
"created_on": {
|
||||
"format": "date-time",
|
||||
|
|
@ -4981,7 +4993,7 @@
|
|||
"type": "integer"
|
||||
},
|
||||
"owners": {
|
||||
"$ref": "#/components/schemas/DatasetRestApi.get.User1"
|
||||
"$ref": "#/components/schemas/DatasetRestApi.get.User2"
|
||||
},
|
||||
"schema": {
|
||||
"maxLength": 255,
|
||||
|
|
@ -5190,6 +5202,23 @@
|
|||
"type": "object"
|
||||
},
|
||||
"DatasetRestApi.get.User1": {
|
||||
"properties": {
|
||||
"first_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"DatasetRestApi.get.User2": {
|
||||
"properties": {
|
||||
"first_name": {
|
||||
"maxLength": 64,
|
||||
|
|
@ -5215,23 +5244,6 @@
|
|||
],
|
||||
"type": "object"
|
||||
},
|
||||
"DatasetRestApi.get.User2": {
|
||||
"properties": {
|
||||
"first_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"first_name",
|
||||
"last_name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"DatasetRestApi.get_list": {
|
||||
"properties": {
|
||||
"changed_by": {
|
||||
|
|
@ -6971,7 +6983,7 @@
|
|||
"type": "integer"
|
||||
},
|
||||
"created_by": {
|
||||
"$ref": "#/components/schemas/ReportScheduleRestApi.get_list.User2"
|
||||
"$ref": "#/components/schemas/ReportScheduleRestApi.get_list.User1"
|
||||
},
|
||||
"created_on": {
|
||||
"format": "date-time",
|
||||
|
|
@ -7021,7 +7033,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"owners": {
|
||||
"$ref": "#/components/schemas/ReportScheduleRestApi.get_list.User1"
|
||||
"$ref": "#/components/schemas/ReportScheduleRestApi.get_list.User2"
|
||||
},
|
||||
"recipients": {
|
||||
"$ref": "#/components/schemas/ReportScheduleRestApi.get_list.ReportRecipients"
|
||||
|
|
@ -7082,10 +7094,6 @@
|
|||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
|
|
@ -7103,6 +7111,10 @@
|
|||
"maxLength": 64,
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"format": "int32",
|
||||
"type": "integer"
|
||||
},
|
||||
"last_name": {
|
||||
"maxLength": 64,
|
||||
"type": "string"
|
||||
|
|
@ -15301,6 +15313,50 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/database/{pk}/schemas_access_for_file_upload/": {
|
||||
"get": {
|
||||
"parameters": [
|
||||
{
|
||||
"in": "path",
|
||||
"name": "pk",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/DatabaseSchemaAccessForFileUploadResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "The list of the database schemas where to upload information"
|
||||
},
|
||||
"401": {
|
||||
"$ref": "#/components/responses/401"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/404"
|
||||
},
|
||||
"500": {
|
||||
"$ref": "#/components/responses/500"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"jwt": []
|
||||
}
|
||||
],
|
||||
"summary": "The list of the database schemas where to upload information",
|
||||
"tags": [
|
||||
"Database"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/database/{pk}/select_star/{table_name}/": {
|
||||
"get": {
|
||||
"description": "Get database select star for table",
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ MODEL_API_RW_METHOD_PERMISSION_MAP = {
|
|||
"delete_ssh_tunnel": "write",
|
||||
"get_updated_since": "read",
|
||||
"stop_query": "read",
|
||||
"schemas_access_for_file_upload": "read",
|
||||
"get_objects": "read",
|
||||
"get_all_objects": "read",
|
||||
"add_objects": "write",
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ from superset.databases.schemas import (
|
|||
DatabasePostSchema,
|
||||
DatabasePutSchema,
|
||||
DatabaseRelatedObjectsResponse,
|
||||
DatabaseSchemaAccessForFileUploadResponse,
|
||||
DatabaseTablesResponse,
|
||||
DatabaseTestConnectionSchema,
|
||||
DatabaseValidateParametersSchema,
|
||||
|
|
@ -120,6 +121,7 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
|
|||
"validate_parameters",
|
||||
"validate_sql",
|
||||
"delete_ssh_tunnel",
|
||||
"schemas_access_for_file_upload",
|
||||
}
|
||||
resource_name = "database"
|
||||
class_permission_name = "Database"
|
||||
|
|
@ -222,6 +224,7 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
|
|||
openapi_spec_tag = "Database"
|
||||
openapi_spec_component_schemas = (
|
||||
DatabaseFunctionNamesResponse,
|
||||
DatabaseSchemaAccessForFileUploadResponse,
|
||||
DatabaseRelatedObjectsResponse,
|
||||
DatabaseTablesResponse,
|
||||
DatabaseTestConnectionSchema,
|
||||
|
|
@ -814,7 +817,7 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
|
|||
)
|
||||
except NoSuchTableError:
|
||||
self.incr_stats("error", self.select_star.__name__)
|
||||
return self.response(404, message="Table not found in the database")
|
||||
return self.response(404, message="Table not found on the database")
|
||||
self.incr_stats("success", self.select_star.__name__)
|
||||
return self.response(200, result=result)
|
||||
|
||||
|
|
@ -1453,3 +1456,52 @@ class DatabaseRestApi(BaseSupersetModelRestApi):
|
|||
exc_info=True,
|
||||
)
|
||||
return self.response_400(message=str(ex))
|
||||
|
||||
@expose("/<int:pk>/schemas_access_for_file_upload/")
|
||||
@protect()
|
||||
@safe
|
||||
@statsd_metrics
|
||||
@event_logger.log_this_with_context(
|
||||
action=lambda self, *args, **kwargs: f"{self.__class__.__name__}"
|
||||
f".schemas_access_for_file_upload",
|
||||
log_to_statsd=False,
|
||||
)
|
||||
def schemas_access_for_file_upload(self, pk: int) -> Response:
|
||||
"""The list of the database schemas where to upload information
|
||||
---
|
||||
get:
|
||||
summary:
|
||||
The list of the database schemas where to upload information
|
||||
parameters:
|
||||
- in: path
|
||||
name: pk
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
200:
|
||||
description: The list of the database schemas where to upload information
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/DatabaseSchemaAccessForFileUploadResponse"
|
||||
401:
|
||||
$ref: '#/components/responses/401'
|
||||
404:
|
||||
$ref: '#/components/responses/404'
|
||||
500:
|
||||
$ref: '#/components/responses/500'
|
||||
"""
|
||||
database = DatabaseDAO.find_by_id(pk)
|
||||
if not database:
|
||||
return self.response_404()
|
||||
|
||||
schemas_allowed = database.get_schema_access_for_file_upload()
|
||||
# the list schemas_allowed should not be empty here
|
||||
# and the list schemas_allowed_processed returned from security_manager
|
||||
# should not be empty either,
|
||||
# otherwise the database should have been filtered out
|
||||
# in CsvToDatabaseForm
|
||||
schemas_allowed_processed = security_manager.get_schemas_accessible_by_user(
|
||||
database, schemas_allowed, True
|
||||
)
|
||||
return self.response(200, schemas=schemas_allowed_processed)
|
||||
|
|
|
|||
|
|
@ -808,3 +808,10 @@ def encrypted_field_properties(self, field: Any, **_) -> Dict[str, Any]: # type
|
|||
if self.openapi_version.major > 2:
|
||||
ret["x-encrypted-extra"] = True
|
||||
return ret
|
||||
|
||||
|
||||
class DatabaseSchemaAccessForFileUploadResponse(Schema):
|
||||
schemas = fields.List(
|
||||
fields.String(),
|
||||
description="The list of schemas allowed for the database to upload information",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -32,12 +32,11 @@ under the License.
|
|||
function update_schemas_allowed_for_csv_upload(db_id) {
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
url: "/superset/schemas_access_for_file_upload",
|
||||
data: {db_id: db_id},
|
||||
url: `/api/v1/database/${db_id}/schemas_access_for_file_upload/`,
|
||||
dataType: 'json',
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function (data) {
|
||||
change_schema_field_in_formview(data)
|
||||
change_schema_field_in_formview(data ? data.schemas : [])
|
||||
}).fail(function (error) {
|
||||
var errorMsg = error.responseJSON.error;
|
||||
alert("ERROR: " + errorMsg);
|
||||
|
|
|
|||
|
|
@ -2747,6 +2747,7 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
|
|||
@has_access_api
|
||||
@event_logger.log_this
|
||||
@expose("/schemas_access_for_file_upload")
|
||||
@deprecated()
|
||||
def schemas_access_for_file_upload(self) -> FlaskResponse:
|
||||
"""
|
||||
This method exposes an API endpoint to
|
||||
|
|
|
|||
|
|
@ -3619,3 +3619,44 @@ class TestDatabaseApi(SupersetTestCase):
|
|||
return
|
||||
self.assertEqual(rv.status_code, 422)
|
||||
self.assertIn("Kaboom!", response["errors"][0]["message"])
|
||||
|
||||
@mock.patch(
|
||||
"superset.security.SupersetSecurityManager.get_schemas_accessible_by_user"
|
||||
)
|
||||
@mock.patch("superset.security.SupersetSecurityManager.can_access_database")
|
||||
@mock.patch("superset.security.SupersetSecurityManager.can_access_all_datasources")
|
||||
def test_schemas_access_for_csv_upload_not_found_endpoint(
|
||||
self,
|
||||
mock_can_access_all_datasources,
|
||||
mock_can_access_database,
|
||||
mock_schemas_accessible,
|
||||
):
|
||||
self.login(username="gamma")
|
||||
self.create_fake_db()
|
||||
mock_can_access_database.return_value = False
|
||||
mock_schemas_accessible.return_value = ["this_schema_is_allowed_too"]
|
||||
rv = self.client.get(f"/api/v1/database/120ff/schemas_access_for_file_upload")
|
||||
self.assertEqual(rv.status_code, 404)
|
||||
self.delete_fake_db()
|
||||
|
||||
@mock.patch(
|
||||
"superset.security.SupersetSecurityManager.get_schemas_accessible_by_user"
|
||||
)
|
||||
@mock.patch("superset.security.SupersetSecurityManager.can_access_database")
|
||||
@mock.patch("superset.security.SupersetSecurityManager.can_access_all_datasources")
|
||||
def test_schemas_access_for_csv_upload_endpoint(
|
||||
self,
|
||||
mock_can_access_all_datasources,
|
||||
mock_can_access_database,
|
||||
mock_schemas_accessible,
|
||||
):
|
||||
self.login(username="admin")
|
||||
dbobj = self.create_fake_db()
|
||||
mock_can_access_all_datasources.return_value = False
|
||||
mock_can_access_database.return_value = False
|
||||
mock_schemas_accessible.return_value = ["this_schema_is_allowed_too"]
|
||||
data = self.get_json_resp(
|
||||
url=f"/api/v1/database/{dbobj.id}/schemas_access_for_file_upload"
|
||||
)
|
||||
assert data == {"schemas": ["this_schema_is_allowed_too"]}
|
||||
self.delete_fake_db()
|
||||
|
|
|
|||
Loading…
Reference in New Issue