From 43a34bf4c8e5060fcbc0a7d3b168c0cccc35ccdc Mon Sep 17 00:00:00 2001 From: zef Date: Tue, 23 Aug 2022 17:11:22 -0700 Subject: [PATCH 1/7] chore: migrate available_domains to api/v1 --- superset/available_domains/__init__.py | 16 ++++++ superset/available_domains/api.py | 51 +++++++++++++++++++ superset/initialization/__init__.py | 2 + superset/views/core.py | 5 ++ .../available_domains/__init__.py | 0 .../available_domains/api_tests.py | 31 +++++++++++ 6 files changed, 105 insertions(+) create mode 100644 superset/available_domains/__init__.py create mode 100644 superset/available_domains/api.py create mode 100644 tests/integration_tests/available_domains/__init__.py create mode 100644 tests/integration_tests/available_domains/api_tests.py diff --git a/superset/available_domains/__init__.py b/superset/available_domains/__init__.py new file mode 100644 index 0000000000000..13a83393a9124 --- /dev/null +++ b/superset/available_domains/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/superset/available_domains/api.py b/superset/available_domains/api.py new file mode 100644 index 0000000000000..94ee2fc1572ad --- /dev/null +++ b/superset/available_domains/api.py @@ -0,0 +1,51 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +import logging + +from flask import Response +from flask_appbuilder.api import BaseApi, expose, protect, safe + +from superset import conf +from superset.constants import MODEL_API_RW_METHOD_PERMISSION_MAP, RouteMethod +from superset.extensions import event_logger + +logger = logging.getLogger(__name__) + + +class AvailableDomainsRestApi(BaseApi): + method_permission_name = MODEL_API_RW_METHOD_PERMISSION_MAP + include_route_methods = {RouteMethod.GET} + allow_browser_login = True + class_permission_name = "AvailableDomain" + resource_name = "available_domains" + openapi_spec_tag = "Available Domains" + openapi_spec_component_schemas = () + + @expose("/", methods=["GET"]) + @protect() + @safe + @event_logger.log_this_with_context( + action=lambda self, *args, **kwargs: f"{self.__class__.__name__}.get", + log_to_statsd=True, + ) + def get(self) -> Response: + """ + Returns the list of available Superset Webserver domains (if any) + defined in config. This enables charts embedded in other apps to + leverage domain sharding if appropriately configured. + """ + return self.response(200, result=conf.get("SUPERSET_WEBSERVER_DOMAINS")) diff --git a/superset/initialization/__init__.py b/superset/initialization/__init__.py index 2fe5591dac65b..a4dcfc9291c3b 100644 --- a/superset/initialization/__init__.py +++ b/superset/initialization/__init__.py @@ -116,6 +116,7 @@ def init_views(self) -> None: from superset.annotation_layers.annotations.api import AnnotationRestApi from superset.annotation_layers.api import AnnotationLayerRestApi from superset.async_events.api import AsyncEventsRestApi + from superset.available_domains.api import AvailableDomainsRestApi from superset.cachekeys.api import CacheRestApi from superset.charts.api import ChartRestApi from superset.charts.data.api import ChartDataRestApi @@ -193,6 +194,7 @@ def init_views(self) -> None: appbuilder.add_api(AnnotationLayerRestApi) appbuilder.add_api(AsyncEventsRestApi) appbuilder.add_api(AdvancedDataTypeRestApi) + appbuilder.add_api(AvailableDomainsRestApi) appbuilder.add_api(CacheRestApi) appbuilder.add_api(ChartRestApi) appbuilder.add_api(ChartDataRestApi) diff --git a/superset/views/core.py b/superset/views/core.py index 4f392337902b8..93818f311a769 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -1570,6 +1570,11 @@ def available_domains(self) -> FlaskResponse: # pylint: disable=no-self-use defined in config. This enables charts embedded in other apps to leverage domain sharding if appropriately configured. """ + logger.warning( + "%s.available_domains " + "This API endpoint is deprecated and will be removed in version 3.0.0", + self.__class__.__name__, + ) return Response( json.dumps(conf.get("SUPERSET_WEBSERVER_DOMAINS")), mimetype="text/json" ) diff --git a/tests/integration_tests/available_domains/__init__.py b/tests/integration_tests/available_domains/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/integration_tests/available_domains/api_tests.py b/tests/integration_tests/available_domains/api_tests.py new file mode 100644 index 0000000000000..cfabab788970d --- /dev/null +++ b/tests/integration_tests/available_domains/api_tests.py @@ -0,0 +1,31 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +import json + +import pytest + +from tests.integration_tests.test_app import app + + +@pytest.mark.usefixtures("login_as_admin") +def test_get_available_domains(test_client): + app.config["SUPERSET_WEBSERVER_DOMAINS"] = ["a", "b"] + resp = test_client.get(f"api/v1/available_domains/") + assert resp.status_code == 200 + data = json.loads(resp.data.decode("utf-8")) + result = data.get("result") + assert result == ["a", "b"] From 46e339e2fc2b73307506a333f145e89ba5a908e3 Mon Sep 17 00:00:00 2001 From: zef Date: Wed, 24 Aug 2022 12:16:53 -0700 Subject: [PATCH 2/7] fixed tests --- superset/available_domains/api.py | 2 +- tests/integration_tests/available_domains/api_tests.py | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/superset/available_domains/api.py b/superset/available_domains/api.py index 94ee2fc1572ad..bf5c7fff0560c 100644 --- a/superset/available_domains/api.py +++ b/superset/available_domains/api.py @@ -30,7 +30,7 @@ class AvailableDomainsRestApi(BaseApi): method_permission_name = MODEL_API_RW_METHOD_PERMISSION_MAP include_route_methods = {RouteMethod.GET} allow_browser_login = True - class_permission_name = "AvailableDomain" + class_permission_name = "AvailableDomains" resource_name = "available_domains" openapi_spec_tag = "Available Domains" openapi_spec_component_schemas = () diff --git a/tests/integration_tests/available_domains/api_tests.py b/tests/integration_tests/available_domains/api_tests.py index cfabab788970d..ee16aae76dcf5 100644 --- a/tests/integration_tests/available_domains/api_tests.py +++ b/tests/integration_tests/available_domains/api_tests.py @@ -16,15 +16,12 @@ # under the License. import json -import pytest - from tests.integration_tests.test_app import app -@pytest.mark.usefixtures("login_as_admin") -def test_get_available_domains(test_client): +def test_get_available_domains(test_client, login_as_admin): app.config["SUPERSET_WEBSERVER_DOMAINS"] = ["a", "b"] - resp = test_client.get(f"api/v1/available_domains/") + resp = test_client.get("api/v1/available_domains/") assert resp.status_code == 200 data = json.loads(resp.data.decode("utf-8")) result = data.get("result") From f51d53037f4035578f890152b5162f131a1b6648 Mon Sep 17 00:00:00 2001 From: zef Date: Thu, 25 Aug 2022 09:48:15 -0700 Subject: [PATCH 3/7] fixed openapi spec --- superset/available_domains/api.py | 32 +++++++++++++++++-- superset/available_domains/schemas.py | 21 ++++++++++++ .../available_domains/__init__.py | 16 ++++++++++ .../available_domains/api_tests.py | 4 ++- 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 superset/available_domains/schemas.py diff --git a/superset/available_domains/api.py b/superset/available_domains/api.py index bf5c7fff0560c..ad15e028dfc02 100644 --- a/superset/available_domains/api.py +++ b/superset/available_domains/api.py @@ -20,6 +20,7 @@ from flask_appbuilder.api import BaseApi, expose, protect, safe from superset import conf +from superset.available_domains.schemas import AvailableDomainsSchema from superset.constants import MODEL_API_RW_METHOD_PERMISSION_MAP, RouteMethod from superset.extensions import event_logger @@ -27,13 +28,15 @@ class AvailableDomainsRestApi(BaseApi): + available_domains_schema = AvailableDomainsSchema() + method_permission_name = MODEL_API_RW_METHOD_PERMISSION_MAP include_route_methods = {RouteMethod.GET} allow_browser_login = True class_permission_name = "AvailableDomains" resource_name = "available_domains" openapi_spec_tag = "Available Domains" - openapi_spec_component_schemas = () + openapi_spec_component_schemas = (AvailableDomainsSchema,) @expose("/", methods=["GET"]) @protect() @@ -47,5 +50,30 @@ def get(self) -> Response: Returns the list of available Superset Webserver domains (if any) defined in config. This enables charts embedded in other apps to leverage domain sharding if appropriately configured. + --- + get: + description: >- + Get all available domains + responses: + 200: + description: a list of available domains + content: + application/json: + schema: + type: object + properties: + result: + $ref: '#/components/schemas/AvailableDomainsSchema' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 404: + $ref: '#/components/responses/404' """ - return self.response(200, result=conf.get("SUPERSET_WEBSERVER_DOMAINS")) + result = self.available_domains_schema.dump( + {"domains": conf.get("SUPERSET_WEBSERVER_DOMAINS")} + ) + return self.response(200, result=result) diff --git a/superset/available_domains/schemas.py b/superset/available_domains/schemas.py new file mode 100644 index 0000000000000..e9aa1b0a0c936 --- /dev/null +++ b/superset/available_domains/schemas.py @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# License ); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +from marshmallow import fields, Schema + + +class AvailableDomainsSchema(Schema): + domains = fields.List(fields.String()) diff --git a/tests/integration_tests/available_domains/__init__.py b/tests/integration_tests/available_domains/__init__.py index e69de29bb2d1d..13a83393a9124 100644 --- a/tests/integration_tests/available_domains/__init__.py +++ b/tests/integration_tests/available_domains/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/tests/integration_tests/available_domains/api_tests.py b/tests/integration_tests/available_domains/api_tests.py index ee16aae76dcf5..8838207d29094 100644 --- a/tests/integration_tests/available_domains/api_tests.py +++ b/tests/integration_tests/available_domains/api_tests.py @@ -20,9 +20,11 @@ def test_get_available_domains(test_client, login_as_admin): + cached = app.config["SUPERSET_WEBSERVER_DOMAINS"] app.config["SUPERSET_WEBSERVER_DOMAINS"] = ["a", "b"] resp = test_client.get("api/v1/available_domains/") assert resp.status_code == 200 data = json.loads(resp.data.decode("utf-8")) result = data.get("result") - assert result == ["a", "b"] + assert result == {"domains": ["a", "b"]} + app.config["SUPERSET_WEBSERVER_DOMAINS"] = cached From e45dfb137821323677547284ce7028834138352f Mon Sep 17 00:00:00 2001 From: zef Date: Mon, 29 Aug 2022 10:48:35 -0700 Subject: [PATCH 4/7] fixing tests --- tests/integration_tests/security_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration_tests/security_tests.py b/tests/integration_tests/security_tests.py index 409f060625a78..79bce34b83d6b 100644 --- a/tests/integration_tests/security_tests.py +++ b/tests/integration_tests/security_tests.py @@ -83,6 +83,7 @@ ["can_write", "CssTemplate"], ["can_read", "ReportSchedule"], ["can_write", "ReportSchedule"], + ["can_read", "AvailableDomains"], ["can_read", "Chart"], ["can_write", "Chart"], ["can_read", "Annotation"], From 80e065b0e31fcb58dc876811727f102e646efcd7 Mon Sep 17 00:00:00 2001 From: zef Date: Mon, 29 Aug 2022 12:54:09 -0700 Subject: [PATCH 5/7] dummy From f53120950423ec893adaa743d95e9d8b100b9f89 Mon Sep 17 00:00:00 2001 From: zef Date: Tue, 30 Aug 2022 08:58:15 -0700 Subject: [PATCH 6/7] removing 400/404 from openapi spec --- superset/available_domains/api.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/superset/available_domains/api.py b/superset/available_domains/api.py index ad15e028dfc02..533f240afba4b 100644 --- a/superset/available_domains/api.py +++ b/superset/available_domains/api.py @@ -64,14 +64,10 @@ def get(self) -> Response: properties: result: $ref: '#/components/schemas/AvailableDomainsSchema' - 400: - $ref: '#/components/responses/400' 401: $ref: '#/components/responses/401' 403: $ref: '#/components/responses/403' - 404: - $ref: '#/components/responses/404' """ result = self.available_domains_schema.dump( {"domains": conf.get("SUPERSET_WEBSERVER_DOMAINS")} From b821bc1188da8555c7a022f9c41618a2ebe2f7b5 Mon Sep 17 00:00:00 2001 From: zef Date: Tue, 30 Aug 2022 10:25:56 -0700 Subject: [PATCH 7/7] dummy