| # 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 |
| from typing import Callable |
| |
| from flask import abort, request |
| from flask_appbuilder import expose |
| from flask_login import AnonymousUserMixin, LoginManager |
| from flask_wtf.csrf import same_origin |
| |
| from superset import event_logger, is_feature_enabled, security_manager |
| from superset.embedded.dao import EmbeddedDAO |
| from superset.superset_typing import FlaskResponse |
| from superset.utils import core as utils |
| from superset.views.base import BaseSupersetView, common_bootstrap_payload |
| |
| |
| class EmbeddedView(BaseSupersetView): |
| """The views for embedded resources to be rendered in an iframe""" |
| |
| route_base = "/embedded" |
| |
| @expose("/<uuid>") |
| @event_logger.log_this_with_extra_payload |
| def embedded( |
| self, |
| uuid: str, |
| add_extra_log_payload: Callable[..., None] = lambda **kwargs: None, |
| ) -> FlaskResponse: |
| """ |
| Server side rendering for the embedded dashboard page |
| :param uuid: identifier for embedded dashboard |
| :param add_extra_log_payload: added by `log_this_with_manual_updates`, set a |
| default value to appease pylint |
| """ |
| if not is_feature_enabled("EMBEDDED_SUPERSET"): |
| abort(404) |
| |
| embedded = EmbeddedDAO.find_by_id(uuid) |
| |
| if not embedded: |
| abort(404) |
| |
| # validate request referrer in allowed domains |
| is_referrer_allowed = not embedded.allowed_domains |
| for domain in embedded.allowed_domains: |
| if same_origin(request.referrer, domain): |
| is_referrer_allowed = True |
| break |
| |
| if not is_referrer_allowed: |
| abort(403) |
| |
| # Log in as an anonymous user, just for this view. |
| # This view needs to be visible to all users, |
| # and building the page fails if g.user and/or ctx.user aren't present. |
| login_manager: LoginManager = security_manager.lm |
| login_manager.reload_user(AnonymousUserMixin()) |
| |
| add_extra_log_payload( |
| embedded_dashboard_id=uuid, |
| dashboard_version="v2", |
| ) |
| |
| bootstrap_data = { |
| "common": common_bootstrap_payload(), |
| "embedded": { |
| "dashboard_id": embedded.dashboard_id, |
| }, |
| } |
| |
| return self.render_template( |
| "superset/spa.html", |
| entry="embedded", |
| bootstrap_data=json.dumps( |
| bootstrap_data, default=utils.pessimistic_json_iso_dttm_ser |
| ), |
| ) |