5

I am combining connect-roles with dust template ejs template have something like this syntax

<% if (userCan('impersonate')) { %>
  <button id="impersonate">Impersonate</button>
<% } %>  

and that in jade

if userCan('impersonate')
  button#impersonate Impersonate

How to do this in dust?

            {@eq key=userCan('edit data') value="true" }
                <td><a href='/assets/edit/{.ID_ASSET}'>Edit</a></td>
                <td><a href='/assets/delete/{.ID_ASSET}'>Delete</a></td>
            {:else}

            {/eq}

This code get me an error

Wed, 06 Jan 2016 16:57:47 GMT uncaughtException Expected end tag for assets but it was not found. At line : 42, column : 13

Edit: I have this in {@contextDump key="full"/}

   "tail": {},
  "isObject": true,
  "head": {
    "enrouten": {
      "routes": {},
      "path": "function path(name, data) {var route;route = this.routes[name];if (typeof route === 'string') {return path2regexp.compile(route)(data);}return undefined;}"
    },
    "userIs": "function (action) {var act = ert(req, action);return roles.test(req, act)}",
    "userCan": "function (action) {var act = ert(req, action);return roles.test(req, act)}",
    "isAuthenticated": "function () { [native code] }",
    "_csrf": "FSaqN0PWxOF4slTUfnGHXJ0NkPOTJFl0u57eM=",
    "title": "Справочник спецификаций",
    "assets": [
      {
        "ID_ASSET": 1,
        "SYMBOL_KODE": "12.TR.18",
        "DOK_NAME": "ТХ9042",
        "DESCRIPTION": "Контроллер программируемый ТХ9042",
        "DATE_RELISE": "2001-10-04T21:00:00.000Z",
        "POS_KODE": "pos kode 1                                                                                                                                                                                                                                                     ",

And this is my controller

    router.get('/',  function (req, res) {
   var context = {
   req: req, // from Express callback
   userCan: function(chunk, context, bodies, params) {
     var permission = context.resolve(params.permission);
     return context.get('req').userCan(permission);
   }
 }
    models.SPR_ASSET.findAll({
      include: [ models.SPR_TYPE_UM, models.SPR_TYPE_ASSETS,  models.SPR_ASSETS_DS ]
    }).then(function(assets) {
      res.render('assets', {
        title: 'Справочник спецификаций',
        assets: assets
        context: context
      });
    });

var context here didn't work

Anatoly Ruchka
  • 543
  • 4
  • 17

1 Answers1

4

Dust doesn't know what functions are. It only knows about "references", which are keys in your context.

If a key in your context is a function, Dust will invoke the function and use the result in its rendering. Such functions are called context helpers, and you can read about them in the documentation. Alternatively, you can register functions directly with Dust that are accessible anywhere-- these are referred to as global helpers.

If userCan is some sort of global that connect-roles makes available, you might make use of it in a global helper like this:

dust.helpers.userCan = function(chunk, context, bodies, params) {
  var permission = context.resolve(params.permission);
  return userCan(permission);
}

And in your template:

{@userCan permission="edit data"}
  <td><a href='/assets/edit/{.ID_ASSET}'>Edit</a></td>
  <td><a href='/assets/delete/{.ID_ASSET}'>Delete</a></td>
{:else}
  Please log in.
{/userCan}

Edit: It looks like userCan is request-scoped, so you can use it by adding the request variable to your context. Something like:

var context = {
  req: req, // from Express callback
  userCan: function(chunk, context, bodies, params) {
    var permission = context.resolve(params.permission);
    return context.get('req').userCan(permission);
  }
}

{#userCan permission="edit data"}
  <td><a href='/assets/edit/{.ID_ASSET}'>Edit</a></td>
  <td><a href='/assets/delete/{.ID_ASSET}'>Delete</a></td>
{:else}
  Please log in.
{/userCan}

To be clear, there is no method to invoke a function directly in your template in Dust-- it does not support arbitrary JS execution. To invoke a function with parameters, you must provide a helper that invokes the function so that it can transform the params into the format that your function expects.

Interrobang
  • 16,984
  • 3
  • 55
  • 63
  • I have userCan func in my req object in controller but i didn't see it in any parameter in dust helper, simply i can't call req.userCan("something") from dust template – Anatoly Ruchka Jan 13 '16 at 13:06
  • If `userCan` is request-scoped, you'll need to write a context helper instead and pass the request object into your context. – Interrobang Jan 13 '16 at 20:51
  • this var context should be in router? and pass it to view? then(function(assets) { res.render('assets', { title: 'Title', context: context }); }); It didn't work that way. And i can't get req in view – Anatoly Ruchka Jan 14 '16 at 07:42
  • i updated my question with {@contextDump key="full"/} – Anatoly Ruchka Jan 14 '16 at 07:52
  • Don't pass `context: context`-- `context` just refers to the object you use to render with. Just add `req` into that object. You should consider reading the Dust and Express documentation. – Interrobang Jan 14 '16 at 18:55
  • well its seems to be confusing for me, after edit you wrote #userCan, with # sign, and i already have "userCan": "function (action)" in my contextDump, why i need pass req via context? and i don't know how – Anatoly Ruchka Jan 15 '16 at 08:12
  • You can't invoke functions (or execute Javascript) inside a Dust template. You can only ask Dust to render keys in its context. When Dust finds a key that is a function, it will execute the function and operate on the result, but if you want to pass params to the function it needs to be in Dust's special format, called a "helper". The documentation linked above explains how helpers work and how to write them. – Interrobang Jan 26 '16 at 18:48