You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@superset.apache.org by GitBox <gi...@apache.org> on 2018/08/08 00:39:17 UTC

[GitHub] mistercrunch closed pull request #5550: Template dashboard

mistercrunch closed pull request #5550: Template dashboard
URL: https://github.com/apache/incubator-superset/pull/5550
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/superset/config.py b/superset/config.py
index ca9fcbdb6a..a5e4f2988c 100644
--- a/superset/config.py
+++ b/superset/config.py
@@ -412,6 +412,9 @@ class CeleryConfig(object):
 # an XSS security vulnerability
 ENABLE_JAVASCRIPT_CONTROLS = False
 
+# The id of a template dashboard that should be copied to every new user
+DASHBOARD_TEMPLATE_ID = None
+
 # A callable that allows altering the database conneciton URL and params
 # on the fly, at runtime. This allows for things like impersonation or
 # arbitrary logic. For instance you can wire different users to
diff --git a/superset/migrations/versions/0c5070e96b57_add_user_attributes_table.py b/superset/migrations/versions/0c5070e96b57_add_user_attributes_table.py
new file mode 100644
index 0000000000..69eba1b62f
--- /dev/null
+++ b/superset/migrations/versions/0c5070e96b57_add_user_attributes_table.py
@@ -0,0 +1,35 @@
+"""add user attributes table
+
+Revision ID: 0c5070e96b57
+Revises: 7fcdcde0761c
+Create Date: 2018-08-06 14:38:18.965248
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '0c5070e96b57'
+down_revision = '7fcdcde0761c'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+    op.create_table('user_attribute',
+    sa.Column('created_on', sa.DateTime(), nullable=True),
+    sa.Column('changed_on', sa.DateTime(), nullable=True),
+    sa.Column('id', sa.Integer(), nullable=False),
+    sa.Column('user_id', sa.Integer(), nullable=True),
+    sa.Column('welcome_dashboard_id', sa.Integer(), nullable=True),
+    sa.Column('created_by_fk', sa.Integer(), nullable=True),
+    sa.Column('changed_by_fk', sa.Integer(), nullable=True),
+    sa.ForeignKeyConstraint(['changed_by_fk'], ['ab_user.id'], ),
+    sa.ForeignKeyConstraint(['created_by_fk'], ['ab_user.id'], ),
+    sa.ForeignKeyConstraint(['user_id'], ['ab_user.id'], ),
+    sa.ForeignKeyConstraint(['welcome_dashboard_id'], ['dashboards.id'], ),
+    sa.PrimaryKeyConstraint('id')
+    )
+
+
+def downgrade():
+    op.drop_table('user_attribute')
diff --git a/superset/models/__init__.py b/superset/models/__init__.py
index 18df0e6088..2084aee0c9 100644
--- a/superset/models/__init__.py
+++ b/superset/models/__init__.py
@@ -1,3 +1,4 @@
 # -*- coding: utf-8 -*-
 from . import core  # noqa
 from . import sql_lab  # noqa
+from . import user_attributes  # noqa
diff --git a/superset/models/core.py b/superset/models/core.py
index a02be607b9..d4f5fa158f 100644
--- a/superset/models/core.py
+++ b/superset/models/core.py
@@ -17,6 +17,7 @@
 from flask import escape, g, Markup, request
 from flask_appbuilder import Model
 from flask_appbuilder.models.decorators import renders
+from flask_appbuilder.security.sqla.models import User
 from future.standard_library import install_aliases
 import numpy
 import pandas as pd
@@ -28,7 +29,7 @@
 )
 from sqlalchemy.engine import url
 from sqlalchemy.engine.url import make_url
-from sqlalchemy.orm import relationship, subqueryload
+from sqlalchemy.orm import relationship, sessionmaker, subqueryload
 from sqlalchemy.orm.session import make_transient
 from sqlalchemy.pool import NullPool
 from sqlalchemy.schema import UniqueConstraint
@@ -39,6 +40,7 @@
 from superset.connectors.connector_registry import ConnectorRegistry
 from superset.legacy import update_time_range
 from superset.models.helpers import AuditMixinNullable, ImportMixin, set_perm
+from superset.models.user_attributes import UserAttribute
 from superset.viz import viz_types
 install_aliases()
 from urllib import parse  # noqa
@@ -59,6 +61,41 @@ def set_related_perm(mapper, connection, target):  # noqa
             target.perm = ds.perm
 
 
+def copy_dashboard(mapper, connection, target):
+    dashboard_id = config.get('DASHBOARD_TEMPLATE_ID')
+    if dashboard_id is None:
+        return
+
+    Session = sessionmaker(autoflush=False)
+    session = Session(bind=connection)
+    new_user = session.query(User).filter_by(id=target.id).first()
+
+    # copy template dashboard to user
+    template = session.query(Dashboard).filter_by(id=int(dashboard_id)).first()
+    dashboard = Dashboard(
+        dashboard_title=template.dashboard_title,
+        position_json=template.position_json,
+        description=template.description,
+        css=template.css,
+        json_metadata=template.json_metadata,
+        slices=template.slices,
+        owners=[new_user],
+    )
+    session.add(dashboard)
+    session.commit()
+
+    # set dashboard as the welcome dashboard
+    extra_attributes = UserAttribute(
+        user_id=target.id,
+        welcome_dashboard_id=dashboard.id,
+    )
+    session.add(extra_attributes)
+    session.commit()
+
+
+sqla.event.listen(User, 'after_insert', copy_dashboard)
+
+
 class Url(Model, AuditMixinNullable):
     """Used for the short url feature"""
 
diff --git a/superset/models/user_attributes.py b/superset/models/user_attributes.py
new file mode 100644
index 0000000000..faf41274dc
--- /dev/null
+++ b/superset/models/user_attributes.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
+from flask_appbuilder import Model
+from sqlalchemy import Column, ForeignKey, Integer
+from sqlalchemy.orm import relationship
+
+from superset import security_manager
+from superset.models.helpers import AuditMixinNullable
+
+
+class UserAttribute(Model, AuditMixinNullable):
+
+    """
+    Custom attributes attached to the user.
+
+    Extending the user attribute is tricky due to its dependency on the
+    authentication typew an circular dependencies in Superset. Instead, we use
+    a custom model for adding attributes.
+
+    """
+
+    __tablename__ = 'user_attribute'
+    id = Column(Integer, primary_key=True)  # pylint: disable=invalid-name
+    user_id = Column(Integer, ForeignKey('ab_user.id'))
+    user = relationship(
+        security_manager.user_model,
+        backref='extra_attributes',
+        foreign_keys=[user_id],
+    )
+
+    welcome_dashboard_id = Column(Integer, ForeignKey('dashboards.id'))
+    welcome_dashboard = relationship('Dashboard')
diff --git a/superset/views/core.py b/superset/views/core.py
index 14c5469195..e4a4dfa639 100755
--- a/superset/views/core.py
+++ b/superset/views/core.py
@@ -45,6 +45,7 @@
 from superset.legacy import cast_form_data, update_time_range
 import superset.models.core as models
 from superset.models.sql_lab import Query
+from superset.models.user_attributes import UserAttribute
 from superset.sql_parse import SupersetQuery
 from superset.utils import (
     merge_extra_filters, merge_request_params, QueryStatus,
@@ -2694,6 +2695,15 @@ def welcome(self):
         if not g.user or not g.user.get_id():
             return redirect(appbuilder.get_url_for_login)
 
+        welcome_dashboard_id = (
+            db.session
+            .query(UserAttribute.welcome_dashboard_id)
+            .filter_by(user_id=g.user.get_id())
+            .scalar()
+        )
+        if welcome_dashboard_id:
+            return self.dashboard(str(welcome_dashboard_id))
+
         payload = {
             'user': bootstrap_user_data(),
             'common': self.common_bootsrap_payload(),


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org