Tutorial - How to integrate superset in your own application

Keywords: Python Docker Apache SQL Database

Superset is an incubator project of apache, positioned as a modern, quasi-commercial BI system

superset

Apache Superset (incubating) is a modern, enterprise-ready business intelligence web application

Superset is an incubation project of apache, positioned as a modern, quasi-commercial BI system.

Superset (Caravel) is an open source data analysis and visualization platform of Airbnb (known as Caravel, Panoramix). The main features of this tool are self-help analysis, custom dashboard, visualization of analysis results (export), user/role rights control, and integration of an SQL editor. It can be used to edit and query SQL.

Through superset, beautiful statistical charts can be made.

preview

Supset installation

We use docker directly here

git clone https://github.com/apache/incubator-superset/
cd incubator-superset/contrib/docker
# prefix with SUPERSET_LOAD_EXAMPLES=yes to load examples:
docker-compose run --rm superset ./docker-init.sh
# you can run this command everytime you need to start superset now:
docker-compose up

When the build is complete, visit http://localhost:8088.

If you want to integrate your own applications, you need to solve authentication first.

Supset authentication analysis

Supset is developed based on flask-appbuilder, security is based on flask_appbuilder.security, and its code is scanned.

Find the entrance: superset/_init_.py:

custom_sm = app.config.get('CUSTOM_SECURITY_MANAGER') or SupersetSecurityManager
if not issubclass(custom_sm, SupersetSecurityManager):
    raise Exception(
        """Your CUSTOM_SECURITY_MANAGER must now extend SupersetSecurityManager,
         not FAB's security manager.
         See [4565] in UPDATING.md""")

appbuilder = AppBuilder(
    app,
    db.session,
    base_template='superset/base.html',
    indexview=MyIndexView,
    security_manager_class=custom_sm,
    update_perms=get_update_perms_flag(),
)

security_manager = appbuilder.sm

Superset Security Manager is used by default, inherited from Security Manager:

class SupersetSecurityManager(SecurityManager):

    def get_schema_perm(self, database, schema):
        if schema:
            return '[{}].[{}]'.format(database, schema)

    def can_access(self, permission_name, view_name):
        """Protecting from has_access failing from missing perms/view"""
        user = g.user
        if user.is_anonymous:
            return self.is_item_public(permission_name, view_name)
        return self._has_view_access(user, permission_name, view_name)
        
        ...

Looking at the Security Manager and its parent class, we find that login is controlled by auth_view, which defaults to AUTH_DB, or AuthDBView.

""" Override if you want your own Authentication LDAP view """
      authdbview = AuthDBView
      
        if self.auth_type == AUTH_DB:
            self.user_view = self.userdbmodelview
            self.auth_view = self.authdbview()
    
 @property
    def get_url_for_login(self):
        return url_for('%s.%s' % (self.sm.auth_view.endpoint, 'login'))

Look again at authdbview:

class AuthDBView(AuthView):
    login_template = 'appbuilder/general/security/login_db.html'

    @expose('/login/', methods=['GET', 'POST'])
    def login(self):
        if g.user is not None and g.user.is_authenticated:
            return redirect(self.appbuilder.get_url_for_index)
        form = LoginForm_db()
        if form.validate_on_submit():
            user = self.appbuilder.sm.auth_user_db(form.username.data, form.password.data)
            if not user:
                flash(as_unicode(self.invalid_login_message), 'warning')
                return redirect(self.appbuilder.get_url_for_login)
            login_user(user, remember=False)
            return redirect(self.appbuilder.get_url_for_index)
        return self.render_template(self.login_template,
                               title=self.title,
                               form=form,
                               appbuilder=self.appbuilder)

Provide the'/ login/'interface to the outside world, read the user name and password in HTTP POST, then call auth_user_db authentication to verify that the authentication information is generated by calling login_user.

Therefore, we can customize AuthDBView and authenticate it from our own application.

Verify superset with jwt

Custom AuthDBView, inherited from AuthDBView, can be imported into jwt token through cookie or url parameters when login, and then authenticated, automatically login.

import jwt
import json
class CustomAuthDBView(AuthDBView):
    login_template = 'appbuilder/general/security/login_db.html'

    @expose('/login/', methods=['GET', 'POST'])
    def login(self):
        token = request.args.get('token')
        if not token:
            token = request.cookies.get('access_token')
        if token is not None:
            jwt_payload = jwt.decode(token,'secret',algorithms=['RS256'])
            user_name = jwt_payload.get("user_name")
            user = self.appbuilder.sm.find_user(username=user_name)
            if not user:
               role_admin = self.appbuilder.sm.find_role('Admin')
               user = self.appbuilder.sm.add_user(user_name, user_name, 'aimind', user_name + "@aimind.com", role_admin, password = "aimind" + user_name)
            if user:
                login_user(user, remember=False)
                redirect_url = request.args.get('redirect')
                if not redirect_url:
                    redirect_url = self.appbuilder.get_url_for_index
                return redirect(redirect_url)
            else:
                return super(CustomAuthDBView,self).login()
        else:
            flash('Unable to auto login', 'warning')
            return super(CustomAuthDBView,self).login()

If the user does not exist, the user is automatically added through self.appbuilder.sm.add_user.

Then the Custom AuthDBView is introduced.

class CustomSecurityManager(SupersetSecurityManager):
    authdbview = CustomAuthDBView

Finally, the Custom Security Manager is introduced and added in superset_config.py:

from aimind_security import CustomSecurityManager
CUSTOM_SECURITY_MANAGER = CustomSecurityManager

Integrating Supset in Applications

Integration is simple, access,'SUPER_SET_URL/login/?token=jwt_token', can be seamlessly integrated through iframe.

Author: Jadepeng
Origin: jqpeng's technical notebook-- http://www.cnblogs.com/xiaoqi
Your support is the biggest encouragement to bloggers. Thank you for your careful reading.
Copyright of this article belongs to the author. Reproduction is welcomed, but without the author's consent, the statement must be retained, and the link of the original text should be given clearly on the page of the article, otherwise the right to pursue legal liability will be reserved.

Posted by stopblackholes on Tue, 17 Sep 2019 05:57:13 -0700