Search code examples
javascriptnode.jshandlebars.jskeystonejs

I have a website, that uses handlebars, but when I try to rich one of the pages I get an error


I've created a KeystoneJS-based website, that uses handlebars. I've created some models and templates for them. But when I try to reach one of my website pages I get the following error:

Handlebars: Access has been denied to resolve the property "title" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "coverImage" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "duration" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "distance" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "price" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "content" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details
Handlebars: Access has been denied to resolve the property "images" because it is not an "own property" of its parent.
You can add a runtime option to disable the check or this warning:
See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details

Here's a code of the page I'm trying to reach:

<!DOCTYPE html>

<html lang="en">
<head>
    <title>{{#if data.trip}}{{data.trip.title}}{{/if}}</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="/styles/custom/trip.css">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
    <script src="https://code.jquery.com/jquery-3.4.1.js"></script>
    <script>
        function showDiv () {
            let order = document.getElementById("order");
            if (order.style.display === 'flex') {
                order.style.display = 'none';
            } else {
                order.style.display = 'flex';
            }
        }
    </script>
</head>
<body>
    {{#if data.trip}}
        <div class="container" style="background: url('{{ cloudinaryUrl data.trip.coverImage }}') center no-repeat; background-size: cover; ">
            <div class="tour">
                <div class="content">
                    <h1 class="title">{{data.trip.title}}</h1>
                    <div class="info">
                        <p class="item">Duration: <br>{{data.trip.duration}}</p>
                        <p class="item">Distance: <br>{{data.trip.distance}}</p>
                        <p class="item">Price: <br>{{data.trip.price}}€</p>    
                    </div>
                    {{#if data.trip.content.additional}}
                        <div class="additional">
                            <p>{{{data.trip.content.additional}}}</p>
                        </div>
                    {{/if}}
                </div>
            </div>
        </div>
        <div class="extended">
            <p class="text">{{# if data.trip.content.extended }} {{{data.trip.content.extended}}} {{/if}}</p>
        </div>
        <div class="photos">
            {{#each data.trip.images }}
                <img src="{{cloudinaryUrl}}" class="list-photo" alt="{{../data.trip.title}} Photo">
            {{/each}}
        </div>
        <div class="order-container">
            <button class="order" onclick="showDiv()">Order</button>
            <div id="order" class="order-form">
                <h1 class="form-title">Order</h1>
                <form class="form-container" id="order-trip-form" name="simple-contact-form" accept-charset="utf-8" action="https://formspree.io/info@seebelarus.by" method="post">
                    <div class="input-1">
                        <input class="input input-name" type="text" name="name" placeholder="Name" required="required">
                        <input class="input input-email" type="email" name="email" placeholder="Email" required="required">
                        <input class="input input-phone" type="telephone" name="telephone" placeholder="Phone (Optional)" required="">
                        <input class="input input-number" type="number" name="plus" placeholder="Number of people" required="required">
                    </div>
                    <div class="input-2">
                        <input class="input input-place" type="text" name="street" placeholder="Place to meet" required="required">
                        <input class="input input-date" type="date" name="date" placeholder="Date" required="required">
                        <textarea class="comments" name="message" placeholder="Any comments" required=""></textarea>
                    </div>
                    <div class="submit-buttons">
                        <input type="hidden" name="_subject" id="email-subject" value="Contact Form Submission">
                        <input type="submit" value="Submit" class="input-button" id="button-submit">
                    </div>
                </form>
            </div>
        </div>
    {{/if}}
</body>
</html>

This is my route file:


let keystone = require('keystone');

exports = module.exports = function (req, res) {

    let view = new keystone.View(req, res);
    let locals = res.locals;

    // Set locals
    locals.section = 'tours';
    locals.filters = {
        trip: req.params.trip,
    };
    locals.data = {
        trip: [],
    };

    view.on('init', function (next) {


        keystone.list('Trip').model.findOne({
            slug: locals.filters.trip,
        }).exec(function (err, results) {
            locals.data.trip = results;
            console.log(locals.data.trip);
            next(err);
        });

    });


    view.render('trip');
};

And, finally, here's the model:

let keystone = require('keystone');
let Types = keystone.Field.Types;

let Trip = new keystone.List('Trip', {
    map: { name: 'title' },
    singular: 'Trip',
    plural: 'Trips',
    autokey: { path: 'slug', from: 'title', unique: true },
});

Trip.add({
    title: { type: String, required: true },
    content: {
        extended: { type: Types.Html, wysiwyg: true, height: 400 },
        additional: { type: Types.Html, wysiwyg: true, height: 300 },
    },
    category: { type: Types.Relationship, ref: 'TripCategory' },
    duration: { type: Types.Html, wysiwyg: false },
    distance: { type: Types.Html, wysiwyg: false },
    price: { type: Number },
    images: { type: Types.CloudinaryImages },
    coverImage: { type: Types.CloudinaryImage },
});

Trip.register();

That's how it must work: enter image description here

That's how it works: enter image description here

By the way, I checked the link that was showed in the error, but I don't know where I must use allowProtoPropertiesByDefault (I guess I have to use exactly this code).

Here's the link: https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access


Solution

  • I had this problem after updating my keystonejs classic project.

    TL;DR this express-handlebars pull fixes it https://github.com/express-handlebars/express-handlebars/pull/53

    Update express-handlebars to 4.0.6 or above (I used 5.1.0 from 3.x and it worked fine) in your package.json file

    you'll then need to add the following to your 'custom engine' after extname: '.hbs' in keystone.js

      runtimeOptions: {
        allowProtoPropertiesByDefault: true,
        allowProtoMethodsByDefault: true
      }
    

    Voilà