database_api_tests.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. # Licensed to the Apache Software Foundation (ASF) under one
  2. # or more contributor license agreements. See the NOTICE file
  3. # distributed with this work for additional information
  4. # regarding copyright ownership. The ASF licenses this file
  5. # to you under the Apache License, Version 2.0 (the
  6. # "License"); you may not use this file except in compliance
  7. # with the License. You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing,
  12. # software distributed under the License is distributed on an
  13. # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. # KIND, either express or implied. See the License for the
  15. # specific language governing permissions and limitations
  16. # under the License.
  17. # isort:skip_file
  18. """Unit tests for Superset"""
  19. import json
  20. import prison
  21. from sqlalchemy.sql import func
  22. from superset import db, security_manager
  23. from superset.connectors.sqla.models import SqlaTable
  24. from superset.models.core import Database
  25. from superset.utils.core import get_example_database
  26. from .base_tests import SupersetTestCase
  27. class DatabaseApiTests(SupersetTestCase):
  28. def test_get_items(self):
  29. """
  30. Database API: Test get items
  31. """
  32. self.login(username="admin")
  33. uri = "api/v1/database/"
  34. rv = self.client.get(uri)
  35. self.assertEqual(rv.status_code, 200)
  36. response = json.loads(rv.data.decode("utf-8"))
  37. expected_columns = [
  38. "allow_csv_upload",
  39. "allow_ctas",
  40. "allow_dml",
  41. "allow_multi_schema_metadata_fetch",
  42. "allow_run_async",
  43. "allows_cost_estimate",
  44. "allows_subquery",
  45. "backend",
  46. "database_name",
  47. "expose_in_sqllab",
  48. "force_ctas_schema",
  49. "function_names",
  50. "id",
  51. ]
  52. self.assertEqual(response["count"], 2)
  53. self.assertEqual(list(response["result"][0].keys()), expected_columns)
  54. def test_get_items_filter(self):
  55. fake_db = (
  56. db.session.query(Database).filter_by(database_name="fake_db_100").one()
  57. )
  58. old_expose_in_sqllab = fake_db.expose_in_sqllab
  59. fake_db.expose_in_sqllab = False
  60. db.session.commit()
  61. self.login(username="admin")
  62. arguments = {
  63. "keys": ["none"],
  64. "filters": [{"col": "expose_in_sqllab", "opr": "eq", "value": True}],
  65. "order_columns": "database_name",
  66. "order_direction": "asc",
  67. "page": 0,
  68. "page_size": -1,
  69. }
  70. uri = f"api/v1/database/?q={prison.dumps(arguments)}"
  71. rv = self.client.get(uri)
  72. response = json.loads(rv.data.decode("utf-8"))
  73. self.assertEqual(rv.status_code, 200)
  74. self.assertEqual(response["count"], 1)
  75. fake_db = (
  76. db.session.query(Database).filter_by(database_name="fake_db_100").one()
  77. )
  78. fake_db.expose_in_sqllab = old_expose_in_sqllab
  79. db.session.commit()
  80. def test_get_items_not_allowed(self):
  81. """
  82. Database API: Test get items not allowed
  83. """
  84. self.login(username="gamma")
  85. uri = f"api/v1/database/"
  86. rv = self.client.get(uri)
  87. self.assertEqual(rv.status_code, 200)
  88. response = json.loads(rv.data.decode("utf-8"))
  89. self.assertEqual(response["count"], 0)
  90. def test_get_table_metadata(self):
  91. """
  92. Database API: Test get table metadata info
  93. """
  94. example_db = get_example_database()
  95. self.login(username="admin")
  96. uri = f"api/v1/database/{example_db.id}/table/birth_names/null/"
  97. rv = self.client.get(uri)
  98. self.assertEqual(rv.status_code, 200)
  99. response = json.loads(rv.data.decode("utf-8"))
  100. self.assertEqual(response["name"], "birth_names")
  101. self.assertTrue(len(response["columns"]) > 5)
  102. self.assertTrue(response.get("selectStar").startswith("SELECT"))
  103. def test_get_invalid_database_table_metadata(self):
  104. """
  105. Database API: Test get invalid database from table metadata
  106. """
  107. database_id = 1000
  108. self.login(username="admin")
  109. uri = f"api/v1/database/{database_id}/table/some_table/some_schema/"
  110. rv = self.client.get(uri)
  111. self.assertEqual(rv.status_code, 404)
  112. uri = f"api/v1/database/some_database/table/some_table/some_schema/"
  113. rv = self.client.get(uri)
  114. self.assertEqual(rv.status_code, 404)
  115. def test_get_invalid_table_table_metadata(self):
  116. """
  117. Database API: Test get invalid table from table metadata
  118. """
  119. example_db = get_example_database()
  120. uri = f"api/v1/database/{example_db.id}/wrong_table/null/"
  121. self.login(username="admin")
  122. rv = self.client.get(uri)
  123. self.assertEqual(rv.status_code, 404)
  124. def test_get_table_metadata_no_db_permission(self):
  125. """
  126. Database API: Test get table metadata from not permitted db
  127. """
  128. self.login(username="gamma")
  129. example_db = get_example_database()
  130. uri = f"api/v1/database/{example_db.id}/birth_names/null/"
  131. rv = self.client.get(uri)
  132. self.assertEqual(rv.status_code, 404)
  133. def test_get_select_star(self):
  134. """
  135. Database API: Test get select star
  136. """
  137. self.login(username="admin")
  138. example_db = get_example_database()
  139. uri = f"api/v1/database/{example_db.id}/select_star/birth_names/"
  140. rv = self.client.get(uri)
  141. self.assertEqual(rv.status_code, 200)
  142. response = json.loads(rv.data.decode("utf-8"))
  143. self.assertIn("gender", response["result"])
  144. def test_get_select_star_not_allowed(self):
  145. """
  146. Database API: Test get select star not allowed
  147. """
  148. self.login(username="gamma")
  149. example_db = get_example_database()
  150. uri = f"api/v1/database/{example_db.id}/select_star/birth_names/"
  151. rv = self.client.get(uri)
  152. self.assertEqual(rv.status_code, 404)
  153. def test_get_select_star_datasource_access(self):
  154. """
  155. Database API: Test get select star with datasource access
  156. """
  157. session = db.session
  158. table = SqlaTable(
  159. schema="main", table_name="ab_permission", database=get_example_database()
  160. )
  161. session.add(table)
  162. session.commit()
  163. tmp_table_perm = security_manager.find_permission_view_menu(
  164. "datasource_access", table.get_perm()
  165. )
  166. gamma_role = security_manager.find_role("Gamma")
  167. security_manager.add_permission_role(gamma_role, tmp_table_perm)
  168. self.login(username="gamma")
  169. example_db = get_example_database()
  170. uri = f"api/v1/database/{example_db.id}/select_star/ab_permission/"
  171. rv = self.client.get(uri)
  172. self.assertEqual(rv.status_code, 200)
  173. # rollback changes
  174. security_manager.del_permission_role(gamma_role, tmp_table_perm)
  175. db.session.delete(table)
  176. db.session.commit()
  177. def test_get_select_star_not_found_database(self):
  178. """
  179. Database API: Test get select star not found database
  180. """
  181. self.login(username="admin")
  182. max_id = db.session.query(func.max(Database.id)).scalar()
  183. uri = f"api/v1/database/{max_id + 1}/select_star/birth_names/"
  184. rv = self.client.get(uri)
  185. self.assertEqual(rv.status_code, 404)
  186. def test_get_select_star_not_found_table(self):
  187. """
  188. Database API: Test get select star not found database
  189. """
  190. self.login(username="admin")
  191. example_db = get_example_database()
  192. # sqllite will not raise a NoSuchTableError
  193. if example_db.backend == "sqlite":
  194. return
  195. uri = f"api/v1/database/{example_db.id}/select_star/table_does_not_exist/"
  196. rv = self.client.get(uri)
  197. self.assertEqual(rv.status_code, 404)