This is an automated email from the ASF dual-hosted git repository.

johnbodley pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 903217f  Fix SQL Lab schema permission checks (#9756)
903217f is described below

commit 903217f64d38b2083bb62a8a2b81686a607ba479
Author: Bogdan <[email protected]>
AuthorDate: Fri May 8 14:59:49 2020 -0700

    Fix SQL Lab schema permission checks (#9756)
    
    Co-authored-by: bogdan kyryliuk <[email protected]>
---
 superset/security/manager.py |  3 +-
 tests/base_tests.py          | 23 +++++++++++++-
 tests/sqllab_tests.py        | 76 ++++++++++++++++++++++++++++++++------------
 3 files changed, 78 insertions(+), 24 deletions(-)

diff --git a/superset/security/manager.py b/superset/security/manager.py
index fac9068..c48c231 100644
--- a/superset/security/manager.py
+++ b/superset/security/manager.py
@@ -333,7 +333,7 @@ class SupersetSecurityManager(SecurityManager):
         if self.database_access(database) or self.all_datasource_access():
             return True
 
-        schema_perm = self.get_schema_perm(database, schema)
+        schema_perm = self.get_schema_perm(database, schema=table.schema or 
schema)
         if schema_perm and self.can_access("schema_access", schema_perm):
             return True
 
@@ -356,7 +356,6 @@ class SupersetSecurityManager(SecurityManager):
         :param schema: The SQL database schema
         :returns: The rejected tables
         """
-
         query = sql_parse.ParsedQuery(sql)
 
         return {
diff --git a/tests/base_tests.py b/tests/base_tests.py
index ebe1d9a..88c5f7b 100644
--- a/tests/base_tests.py
+++ b/tests/base_tests.py
@@ -18,7 +18,7 @@
 """Unit tests for Superset"""
 import imp
 import json
-from typing import Dict, Union
+from typing import Dict, Union, List
 from unittest.mock import Mock, patch
 
 import pandas as pd
@@ -59,6 +59,24 @@ class SupersetTestCase(TestCase):
         return app
 
     @staticmethod
+    def create_user_with_roles(username: str, roles: List[str]):
+        user_to_create = security_manager.find_user(username)
+        if not user_to_create:
+            security_manager.add_user(
+                username,
+                username,
+                username,
+                f"{username}@superset.com",
+                security_manager.find_role("Gamma"),  # it needs a role
+                password="general",
+            )
+            db.session.commit()
+            user_to_create = security_manager.find_user(username)
+            assert user_to_create
+        user_to_create.roles = [security_manager.find_role(r) for r in roles]
+        db.session.commit()
+
+    @staticmethod
     def create_user(
         username: str,
         password: str,
@@ -240,6 +258,7 @@ class SupersetTestCase(TestCase):
         sql_editor_id=None,
         select_as_cta=False,
         tmp_table_name=None,
+        schema=None,
     ):
         if user_name:
             self.logout()
@@ -256,6 +275,8 @@ class SupersetTestCase(TestCase):
             json_payload["tmp_table_name"] = tmp_table_name
         if select_as_cta:
             json_payload["select_as_cta"] = select_as_cta
+        if schema:
+            json_payload["schema"] = schema
 
         resp = self.get_json_resp(
             "/superset/sql_json/", raise_on_error=False, json_=json_payload
diff --git a/tests/sqllab_tests.py b/tests/sqllab_tests.py
index bbc63d2..6f08f0d 100644
--- a/tests/sqllab_tests.py
+++ b/tests/sqllab_tests.py
@@ -24,9 +24,8 @@ from unittest import mock
 import prison
 
 import tests.test_app
-from superset import config, db, security_manager
+from superset import db, security_manager
 from superset.connectors.sqla.models import SqlaTable
-from superset.dataframe import df_to_records
 from superset.db_engine_specs import BaseEngineSpec
 from superset.models.sql_lab import Query
 from superset.result_set import SupersetResultSet
@@ -122,30 +121,65 @@ class SqlLabTests(SupersetTestCase):
         examples_db_permission_view = 
security_manager.add_permission_view_menu(
             "database_access", examples_db.perm
         )
-
-        astronaut = security_manager.add_role("Astronaut")
+        astronaut = security_manager.add_role("ExampleDBAccess")
         security_manager.add_permission_role(astronaut, 
examples_db_permission_view)
-        # Astronaut role is Gamma + sqllab + db permissions
-        for perm in security_manager.find_role("Gamma").permissions:
-            security_manager.add_permission_role(astronaut, perm)
-        for perm in security_manager.find_role("sql_lab").permissions:
-            security_manager.add_permission_role(astronaut, perm)
-
-        gagarin = security_manager.find_user("gagarin")
-        if not gagarin:
-            security_manager.add_user(
-                "gagarin",
-                "Iurii",
-                "Gagarin",
-                "[email protected]",
-                astronaut,
-                password="general",
-            )
-        data = self.run_sql(QUERY_1, "3", user_name="gagarin")
+        # Gamma user, with sqllab and db permission
+        self.create_user_with_roles("Gagarin", ["ExampleDBAccess", "Gamma", 
"sql_lab"])
+
+        data = self.run_sql(QUERY_1, "1", user_name="Gagarin")
         db.session.query(Query).delete()
         db.session.commit()
         self.assertLess(0, len(data["data"]))
 
+    def test_sql_json_schema_access(self):
+        examples_db = get_example_database()
+        db_backend = examples_db.backend
+        if db_backend == "sqlite":
+            # sqlite doesn't support database creation
+            return
+
+        sqllab_test_db_schema_permission_view = 
security_manager.add_permission_view_menu(
+            "schema_access", f"[{examples_db.name}].[sqllab_test_db]"
+        )
+        schema_perm_role = security_manager.add_role("SchemaPermission")
+        security_manager.add_permission_role(
+            schema_perm_role, sqllab_test_db_schema_permission_view
+        )
+        self.create_user_with_roles(
+            "SchemaUser", ["SchemaPermission", "Gamma", "sql_lab"]
+        )
+
+        db.session.execute(
+            "CREATE TABLE IF NOT EXISTS sqllab_test_db.test_table AS SELECT 1 
as c1, 2 as c2"
+        )
+
+        data = self.run_sql(
+            "SELECT * FROM sqllab_test_db.test_table", "3", 
user_name="SchemaUser"
+        )
+        self.assertEqual(1, len(data["data"]))
+
+        data = self.run_sql(
+            "SELECT * FROM sqllab_test_db.test_table",
+            "4",
+            user_name="SchemaUser",
+            schema="sqllab_test_db",
+        )
+        self.assertEqual(1, len(data["data"]))
+
+        # postgres needs a schema as a part of the table name.
+        if db_backend == "mysql":
+            data = self.run_sql(
+                "SELECT * FROM test_table",
+                "5",
+                user_name="SchemaUser",
+                schema="sqllab_test_db",
+            )
+            self.assertEqual(1, len(data["data"]))
+
+        db.session.query(Query).delete()
+        db.session.execute("DROP TABLE IF EXISTS sqllab_test_db.test_table")
+        db.session.commit()
+
     def test_queries_endpoint(self):
         self.run_some_queries()
 

Reply via email to