Search code examples
flaskjinja2apache-superset

How can I attach a value at login time for Jinja and reuse it later on in Apache Superset's SQLLab?


We need some parameters handed over using a JWT token that are evaluated at a custom SecurityManager within Apache Superset. I read some information about g being able to handle information like this (in newer versions also across requests).

Ninja states it can read Flask's information from 'g' out of the box (docu Ninja Standard Context). This is a sample code snippet:

    @expose('/login/', methods=['GET', 'POST'])
    def login(self):
            g.my_value = 'bar'
            ...

Still I do have issues when trying to use the information within SQLLab using e.g.

--{% set x = 'foo' %}
SELECT 
{{x}}, 
{{g.my_value}}
FROM table_xyz

Will result in

g not defined

x is evaluated correctly to 'foo' if the g field is removed. Any hint if this is possible?


Solution

  • Hi @Supernova , I Found the Solution for Your Problem some patched are required for That.

    superset_config.py file configuration.

    (1) Enable the Template Processing using FEATURE_FLAGS

    FEATURE_FLAGS = {
             "ENABLE_TEMPLATE_PROCESSING": True,
     }
    

    (2) Add the Temporary Value in JINJA_CONTEXT_ADDONS

    JINJA_CONTEXT_ADDONS = {
     'field1': value1,
     'field2': value2,
     'field3': value3
    }
    

    Above JINJA_CONTEXT_ADDONS is override the current JINJA_CONTEXT_ADDONS that exists in Superset. Now I update the JINJA_CONTEXT_ADDONS from /login API. check below Code base.

    (3) I write one keycloak_security_manager.py and override the login API of Flask App for Superset

    @expose('/login/', methods=['GET', 'POST'])
    def login(self, flag=True):
        sm = self.appbuilder.sm
        oidc = sm.oid
        superset_roles = [str(item) for item in sm.get_all_roles()]
        default_role = "Gamma"
    
        @self.appbuilder.sm.oid.require_login
        def handle_login():
    
            user_email = oidc.user_getfield('email')
            user = sm.auth_user_oid(user_email)
    
            info = oidc.user_getinfo(['preferred_username', 'given_name', 'email', 'groups', "branchId","orgId", "orgRole"])
    
            # Update the Jinja Context for Dynamic Use of Our Custom Variable - Custom Attribute Define as camelCase
            f = current_app.config.get("JINJA_CONTEXT_ADDONS", {})
            f.update({
                "branchId":info.get('branchId'),
                "orgId":info.get('orgId'),
                "orgRole":info.get('orgRole')
            })
    
            if user is None:
                roles = [role for role in superset_roles if role in info.get('groups', [])]
                roles += [default_role, ] if not roles else []
                user = sm.add_user(info.get('preferred_username'), info.get('given_name', ''), "", info.get('email'), [sm.find_role(role) for role in roles])
            else:
                user = sm.find_user(email=user_email)
                roles = [role for role in superset_roles if role in info.get('groups', [])]
                user.roles = [sm.find_role(role) for role in roles]
                sm.update_user(user=user)
    
            login_user(user, remember=False)
            return redirect(self.appbuilder.get_url_for_index)
    
        return handle_login()
    

    I Successfully Get the Updated value in SQL Lab in Superset. using below syntax.

    '{{field1}}' ,  '{{field2}}' ,  '{{field3}}'