express-handlebars icon indicating copy to clipboard operation
express-handlebars copied to clipboard

Handlebars 4.6.0+ breaks some functionality within Express-Handlebars; any way to run runtime options?

Open craj1031tx opened this issue 5 years ago • 7 comments

There are new access restrictions on Objects within Handlebars since 4.6 which was released in early January 2020. The only way to ignore these new restrictions is to include runtime options to ignore them, which express-handlebars doesn't support. Is there any plan to update so that exphbs allows for runtime options?

https://github.com/wycats/handlebars.js/pull/1633 https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access

Baring that, does anyone know of a method to force exphbs to use a specific version of Handlebars (namely 4.5.3, which is the most recent revision before these new restrictions went into effect.)

craj1031tx avatar Feb 04 '20 19:02 craj1031tx

Second this, adding runtime options throws. I've been trying to use npm shrimkwrap but I can't fully understand how to force handlebars' version after.

QLaille avatar Feb 05 '20 18:02 QLaille

This is an issue, for all that are or will using (express-)handlebars in the newest versions.

As for my self I upgraded my kubuntu to 19.10 and with mongodb 3.6 I have had to update my npm resources because of mongoose. So with the updated express-handlebars and everything I now have the trouble of my software, based on express-handlebars, is not working anymore.

meitzner-hannes avatar Feb 06 '20 16:02 meitzner-hannes

This fix referenced here is a temporary workaround. This fix was created as a fix to express-handlebars by the creators of handlebars.

https://www.npmjs.com/package/@handlebars/allow-prototype-access#usage--express-handlebars-and-mongoose-

https://github.com/wycats/handlebars.js/issues/1648

craj1031tx avatar Feb 06 '20 19:02 craj1031tx

interesting approach

its a good way to revert the breaking changes, that way its update-save.

But I would really like to see an implementation of runtime options into express-handlebars so we can have the security buff the changes of handlebars brings.

meitzner-hannes avatar Feb 06 '20 20:02 meitzner-hannes

ok, here is an other approach:

we can use the _renderTemplate hook quiet easily.

var expressHbs = require('express-handlebars');

var hbs = expressHbs.create({
    defaultLayout: 'main',
    layoutsDir: path.join(__dirname, 'views/layouts'),
    extname: 'hbs',
    partialsDir: [
      path.join(__dirname, 'public/templates'),
      path.join(__dirname, 'views/partials')
    ]
});

hbs._renderTemplate = function (template, context, options) {

    options.allowProtoMethodsByDefault = true;
    options.allowProtoPropertiesByDefault = true;

    return template(context, options);
};

worked for me or did I missed something?

meitzner-hannes avatar Feb 06 '20 21:02 meitzner-hannes

ok, here is an other approach:

we can use the _renderTemplate hook quiet easily.

var expressHbs = require('express-handlebars');

var hbs = expressHbs.create({
    defaultLayout: 'main',
    layoutsDir: path.join(__dirname, 'views/layouts'),
    extname: 'hbs',
    partialsDir: [
      path.join(__dirname, 'public/templates'),
      path.join(__dirname, 'views/partials')
    ]
});

hbs._renderTemplate = function (template, context, options) {

    options.allowProtoMethodsByDefault = true;
    options.allowProtoPropertiesByDefault = true;

    return template(context, options);
};

worked for me or did I missed something?

how to implement this on express?? just i missunderstand this

i have this code:

const express = require("express");
const path = require("path");
const hbs = require("express-handlebars");
const app = express();
app.engine('.hbs',hbs({
    defaultLayout: 'main',
    layoutsDir: path.join(app.get('views'), 'layouts'),
    partialsDir: path.join(app.get('views'), 'partials'),
    extname: '.hbs'
}));
app.set('view engine', '.hbs')
`
``
and my route:
const router = require("express").Router();

const anObject = { 
foo: 'bar', 
bar: 'foo'
}
router.get('/', (req, res) => {
    res.render('index', {
        anObject,
        helpers: ifeqHelper
    });
});

matigumma avatar Feb 17 '20 23:02 matigumma

how to implement this on express?? just i missunderstand this

i have this code:

const express = require("express");
const path = require("path");
const hbs = require("express-handlebars");
const app = express();
app.engine('.hbs',hbs({
    defaultLayout: 'main',
    layoutsDir: path.join(app.get('views'), 'layouts'),
    partialsDir: path.join(app.get('views'), 'partials'),
    extname: '.hbs'
}));
app.set('view engine', '.hbs')
`
``
and my route:
const router = require("express").Router();

const anObject = { 
foo: 'bar', 
bar: 'foo'
}
router.get('/', (req, res) => {
    res.render('index', {
        anObject,
        helpers: ifeqHelper
    });
});

Try the following:

const express = require("express");
const path = require("path");
const expressHandlebars = require("express-handlebars");
const app = express();

var hbs = expressHandlebars.create({
   defaultLayout: 'main',
   layoutsDir: path.join(app.get('views'), 'layouts'),
   partialsDir: path.join(app.get('views'), 'partials'),
   extname: '.hbs'
});

hbs._renderTemplate = function (template, context, options) {

   options.allowProtoMethodsByDefault = true;
   options.allowProtoPropertiesByDefault = true;

   return template(context, options);
};

app.engine('.hbs',hbs);
app.set('view engine', '.hbs')

Should be something like that, have not tested it but you should get the gist of it.

Would also be possible to do everything within the ""app.engine('.hbs', hbs({"" block but I would have to test it.

Also, are you sure that

app.engine('.hbs'

is correct? if there are further Problems try: app.engine('hbs' (without the . (dot))

meitzner-hannes avatar Feb 18 '20 17:02 meitzner-hannes