Skip to content

Commit

Permalink
feat(Embed Dashboard by slug or id - [Part 2/2]): Allow embedding by …
Browse files Browse the repository at this point in the history
…slug (#42)

* update apis to allow embedding by id or slug

* token by type, add pin config

* prefer internal config

* and dfeault to false

* space lint

* lint

---------

Co-authored-by: naral <[email protected]>
  • Loading branch information
2 people authored and kgopal492 committed Jan 27, 2025
1 parent c90442d commit e96f17d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
6 changes: 6 additions & 0 deletions superset/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ class D3TimeFormat(TypedDict, total=False):
# and FEATURE_FLAGS = { 'BAR': True, 'BAZ': True } in superset_config.py
# will result in combined feature flags of { 'FOO': True, 'BAR': True, 'BAZ': True }
DEFAULT_FEATURE_FLAGS: dict[str, bool] = {
# [pinterest-specific]: Allows embedding by dashboard id or slug
"PINTEREST_EMBEDDED_SUPERSET_BY_ID_OR_SLUG": False,
# When using a recent version of Druid that supports JOINs turn this on
"DRUID_JOINS": False,
"DYNAMIC_PLUGINS": False,
Expand Down Expand Up @@ -1826,8 +1828,12 @@ class ExtraRelatedQueryFilters(TypedDict, total=False):

EXTRA_RELATED_QUERY_FILTERS: ExtraRelatedQueryFilters = {}

# [pinterest-specific]
PINTEREST_MENU_ITEMS: list[PinterestMenuItems] | None = None
PINTEREST_HELP_LINK: str | None = None
# List of allowed domains for PINTEREST_EMBEDDED_SUPERSET_BY_ID_OR_SLUG feature.
# If empty, all domains are allowed, leave empty for dev.
PINTEREST_EMBEDDED_SUPERSET_BY_ID_OR_SLUG_ALLOWED_DOMAINS: list[str] = []


# Extra dynamic query filters make it possible to limit which objects are shown
Expand Down
23 changes: 22 additions & 1 deletion superset/embedded/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
from flask_login import AnonymousUserMixin, login_user
from flask_wtf.csrf import same_origin

from superset import event_logger, is_feature_enabled
from superset import conf, event_logger, is_feature_enabled
from superset.daos.dashboard import EmbeddedDashboardDAO
from superset.models.dashboard import Dashboard
from superset.models.embedded_dashboard import EmbeddedDashboard
from superset.superset_typing import FlaskResponse
from superset.utils import json
from superset.views.base import BaseSupersetView, common_bootstrap_payload
Expand All @@ -43,6 +45,7 @@ def embedded(
"""
Server side rendering for the embedded dashboard page
:param uuid: identifier for embedded dashboard
[pinterest-specific]: can use dashboard id or slug as uuid
:param add_extra_log_payload: added by `log_this_with_manual_updates`, set a
default value to appease pylint
"""
Expand All @@ -51,6 +54,22 @@ def embedded(

embedded = EmbeddedDashboardDAO.find_by_id(uuid)

# [pinterest-specific] Allow embedding by dashboard id or slug
if not embedded and is_feature_enabled(
"PINTEREST_EMBEDDED_SUPERSET_BY_ID_OR_SLUG"
):
dashboard = Dashboard.get(uuid)

if dashboard:
embedded = EmbeddedDashboard()
embedded.allow_domain_list = ",".join(
conf.get(
"PINTEREST_EMBEDDED_SUPERSET_BY_ID_OR_SLUG_ALLOWED_DOMAINS"
)
)
embedded.dashboard_id = dashboard.id
uuid = None

if not embedded:
abort(404)

Expand All @@ -74,6 +93,8 @@ def embedded(
add_extra_log_payload(
embedded_dashboard_id=uuid,
dashboard_version="v2",
# [pinterest-specific] Only add extra log payload if uuid is None.
**({"embedded_by_id_or_slug": True} if uuid is None else {}),
)

bootstrap_data = {
Expand Down
32 changes: 32 additions & 0 deletions superset/security/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@
from flask_wtf.csrf import generate_csrf
from marshmallow import EXCLUDE, fields, post_load, Schema, ValidationError

from superset import is_feature_enabled
from superset.commands.dashboard.embedded.exceptions import (
EmbeddedDashboardNotFoundError,
)
from superset.commands.dashboard.exceptions import (
DashboardAccessDeniedError,
DashboardNotFoundError,
)
from superset.daos.dashboard import DashboardDAO
from superset.exceptions import SupersetGenericErrorException
from superset.extensions import event_logger
from superset.security.guest_token import GuestTokenResourceType
Expand Down Expand Up @@ -64,6 +70,32 @@ def convert_enum_to_value( # pylint: disable=unused-argument
data["type"] = data["type"].value
return data

# [pinterest-specific]
@post_load
def convert_slug_to_id( # pylint: disable=unused-argument
self,
data: dict[str, Any],
**kwargs: Any,
) -> dict[str, Any]:
"""
Allows creating guest token via dashboard slug which in return allows
embedding dashboard by its slug.
"""
is_dashboard = data["type"] == GuestTokenResourceType.DASHBOARD.value
is_embedding_by_slug_enabled = is_feature_enabled(
"PINTEREST_EMBEDDED_SUPERSET_BY_ID_OR_SLUG"
)

if is_dashboard and is_embedding_by_slug_enabled:
id_or_slug = data["id"]
try:
dashboard = DashboardDAO.get_by_id_or_slug(id_or_slug)
data["id"] = dashboard.id
except (DashboardNotFoundError, DashboardAccessDeniedError):
pass

return data


class RlsRuleSchema(PermissiveSchema):
dataset = fields.Integer()
Expand Down

0 comments on commit e96f17d

Please sign in to comment.