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();
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
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à