Search code examples
angularjsnode.jsacldust.jsdust-helpers

Dust.js Template Custom Helper in Bootstrap Inconsistent Behaviour


I have a Dust.js helper where I apply some acl logic as follows:

'use strict';

import dust from 'dustjs-linkedin';
import acl from '../config/acl';

dust.helpers.accessControl = function(chunk, context, bodies, params) {
    let userId = params.userId;
    let resource = params.resource;
    let permission = params.permission;

    acl.acl.isAllowed(userId, resource, permission, function(err, res){

        if(res){
            chunk.render(bodies.block, context);
            return chunk;
        }
        else {
            return chunk;
        }
    });
};

In the template:

{@accessControl userId=user._id resource="/admin" permission="get"}
                    <li class="nav-item">
                        <a class="nav-link" ng-class="{'active' : getPath()[0] == 'admin'}" href="/admin">Admin</a>
                    </li>
                {/accessControl}

The helpers gets called correctly with correct params, and node_acl authorizes the user correctly (res in the callback is true). At many places within my templates, it displays the intended behaviour, except for the Bootstrap 3 navbar, where it usually renders nothing, and sometimes below the ul in the navbar:

Below the navbar

Any thoughts? Note that I am using Angular to put active class in the links, it is not an SPA and deep linking is disabled, but it should have nothing to do since the templates are being rendered at the server-side. Thanks!


Solution

  • node_acl's requests are asynchronous. I needed to change my helper to:

    dust.helpers.accessControl = function(chunk, context, bodies, params) {
        let userId = params.userId;
        let resource = params.resource;
        let permission = params.permission;
    
        return chunk.map(function(chunk) {
            acl.acl.isAllowed(userId, _reverse(resource), permission, function(err, res){
                if(res && bodies['block']) {
                    return chunk.render(bodies['block'], context).end();
                }
                else {
                    return chunk;
                }
            });
        });
    };
    

    to overcome out-of-order chunks.