ericf / express-handlebars

A Handlebars view engine for Express which doesn't suck.
BSD 3-Clause "New" or "Revised" License
2.32k stars 382 forks source link

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

Open craj1031tx opened 4 years ago

craj1031tx commented 4 years ago

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.)

QLaille commented 4 years ago

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.

meitzner-hannes commented 4 years ago

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.

craj1031tx commented 4 years ago

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

meitzner-hannes commented 4 years ago

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 commented 4 years ago

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?

matigumma commented 4 years ago

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
    });
});
meitzner-hannes commented 4 years ago

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))