dpgaspar commented on code in PR #23227:
URL: https://github.com/apache/superset/pull/23227#discussion_r1126140144


##########
tests/integration_tests/databases/api_tests.py:
##########
@@ -3619,3 +3619,45 @@ def test_validate_sql_endpoint_failure(self, 
get_validator_by_name):
             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="admin")

Review Comment:
   nit: we could have used `gamma` user, since it has no predefined access to 
any database.
   
   So we should have a test with `gamma` user testing data permissions.
   And a simple test with `admin` (or not) to a non existing database.



##########
superset/databases/api.py:
##########
@@ -1455,3 +1458,61 @@ def delete_ssh_tunnel(self, pk: int) -> Response:
                 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()
+
+        try:
+            schemas_allowed = database.get_schema_access_for_file_upload()
+            if security_manager.can_access_database(database):

Review Comment:
   I found it a bit confusing at first, why do we need to check 
`can_access_database` again, but the initial filter applied to 
`DatabaseDAO.find_by_id` will show the databases that the user has access 
directly and by child dependency, datasets and schemas.
   
   On the other hand `get_schemas_accessible_by_user` will check 
`security_manager.can_access_database(database)` and return `schemas_allowed` 
has is, so the following check is not needed



##########
superset/databases/api.py:
##########
@@ -1455,3 +1458,61 @@ def delete_ssh_tunnel(self, pk: int) -> Response:
                 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()
+
+        try:
+            schemas_allowed = database.get_schema_access_for_file_upload()
+            if security_manager.can_access_database(database):
+                return self.response(200, schemas=schemas_allowed)
+            # 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

Review Comment:
   if we call it using:
   
   ```
   security_manager.get_schemas_accessible_by_user(
                   database, schemas_allowed, True
   )
   ```
   we can remove the previous is 
`security_manager.can_access_database(database)`
   



##########
superset/databases/api.py:
##########
@@ -1455,3 +1458,61 @@ def delete_ssh_tunnel(self, pk: int) -> Response:
                 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()
+
+        try:
+            schemas_allowed = database.get_schema_access_for_file_upload()
+            if security_manager.can_access_database(database):
+                return self.response(200, schemas=schemas_allowed)
+            # 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, False
+            )
+            return self.response(200, schemas=schemas_allowed_processed)
+        except Exception as ex:  # pylint: disable=broad-except

Review Comment:
   We can remove the broad exception catch, since Superset has a catch all 
exceptions on the API, so the broad exception will return HTTP 500 using our 
defaults



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@superset.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@superset.apache.org
For additional commands, e-mail: notifications-h...@superset.apache.org

Reply via email to