Prototype access denied, the proper way to handle it? "x" is not an "own property" of its parent - express

Like many others I've been getting this error when using Sequelize with Express and Express-handlebars:
Handlebars: Access has been denied to resolve the property "first_name" 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 "last_name" 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
I have found some answers on how to get around this. ie: allowProtoMethods, or adding npm install #handlebars/allow-prototype-access
What I'm curious about is, is there a proper way to handle the data or exclude the proto methods from the sequelize response?
I may not be understanding the issue at hand properly, so if that's the case I apologize. I'm just looking for the "right" way to deal with this.
Edit: To clarify a little further, I'm seeking to do things in a way that will produce the most secure application.
From handlebarsjs.com:
Using these properties may open security holes.
UPDATE!
I'm still trying to work this issue out, but I've noticed an interesting behavior.
Nested objects seem to trigger this issue.
It seems to trigger when the data in a nested object is accessed/rendered on the html page (exa: {{contact.first_name}}
sometimes it will have nested dataValues objects within the object and sometimes it won't.
I'd provide an example including dataValues, but it hasn't displayed like that for a while.
Object being returned:
{
"id": 3,
"email": "email2#email.com",
"password": "$2b$10$fOGiJC6NgUTR4qIt7/R7vuwpaFb3PUl9ks2vHBEkLnOUmRN0tEFue",
"kind": "user",
"createdAt": "2020-08-16T04:37:58.000Z",
"updatedAt": "2020-08-16T04:37:58.000Z",
"Contact": {
"id": 3,
"first_name": "Jane",
"last_name": "Doe",
"gender": "female",
"city": "Long Beach",
"state": "CA",
"zip": 12345,
"phone_number": 1234567891,
"createdAt": "2020-08-16T04:37:58.000Z",
"updatedAt": "2020-08-16T04:37:58.000Z",
"UserId": 3
},
"Props": []
}
I'm not necessarily seeing any other explicit types of data that trigger this error message. (That's not to say that there aren't any, but so far every data type and script that I've passed hasn't caused a problem.)
Data I was having a problem with: This data is from a Sequelize query response shown above.
let hbsObject = {
user: data[0],
contact: data[0].Contact
};
Notes about what happened with this data:
I used a promise to chain several queries at once.
User was queried, and contact was included in that query, so there were nested objects/data in the response. (obviously)
When I tried to render the first and last names from the data I was receiving the error message.
Data that seems to have solved my error:
let user = {
id: data[0].id,
email: data[0].email,
kind: data[0].kind,
createdAt: data[0].createdAt,
updatedAt: data[0].updatedAt,
};
let hbsObject = {
user: user,
contact: data[0].Contact.dataValues,
};
It's strange because sometimes when you view the data in the console, dataValues will be visible, and sometimes it won't. However, when you access it as I showed above the error is removed.
Current Conclusion
The data you are seeking to access on the handlebars page via the handlebars object must not be in a nested object.
What does that mean?
It seems to mean that you must either deconstruct it prior to passing the data to the page either manually (like I did with user) or by sending the data from the object 1 level at a time (like I did with contact).
If anyone can build on this or expand additional information I would greatly appreciate it! I'll edit again if more information becomes available.
UPDATE2
An array of objects is inaccessible as it is a list of objects nested in an array. This makes {{#each x}} a challenge. Individual data has been accessible with the method above.
UPDATE3
I was unable to find any clear solution to this issue. In the end I just allowed the proto methods with the handlebars/allow-prototype-access package.
As long as you're the only one that has access to your template/you absolutely 100% trust whoever also has access to your template, then it shouldn't really be a problem. If that isn't the case, I'd suggest using something other than handlebars for now.

0
If you are using MySQL, sequelize, use raw query options {raw: true} and if you are using relationships, you can use {nest: true}, eg:
users = await User.findAll({
where: { username: "SimonAngatia" },
include: [{ model: Tweet, as: "Tweets" }],
raw: true,
nest: true,
}).catch(errorHandler);
refer here: Sequelize, convert entity to plain object

Related

Connectwise API missing property value gives no response

This question may very well be a general API question, but the API I am using is the Connectwise Tickets API.
I'm writing in VB and I'm getting my list of tickets(i) then I'm setting the following variable:
currentTicket = tickets(i)
So that I can reference value like currentTicket.Source.Name and save the info to a DB.
As long as the Connectwise user put something into the "Source" field, everything works fine. I can reference that property and log it to the database or whatever else I want to do. If they left it blank though, even trying to look at currentTicket.Source.Name stops my program in it's tracks. It doesn't crash or error out, it just doesn't go past the line of code referencing the empty field.
Since it won't even let me reference currentTicket.Source.Name for example, I am unable to check to see if currentTicket.Source.Name = "" or Is Nothing.
What am I missing? Is there a way to check and see if the property even exists for a given API response?
Any help would be appreciated.
EDIT:
OK so I decided to take the Ticket object and grab the raw json and send it to the command line output.
When a ticket has the source field filled in, this is what that section of the JSON looks like:
...
},
"servicelocation": {
"id":4,
"name":"remote",
"_info":{
"location_href":"https://API_url"
}
},
"source":{
"id":4,
"name":"Email Connector",
"_info": {
"source_href":"https://API_url"
}
},
"severity": "Medium",
"impact":"Medium",
...
When the source field in the application has been left blank, the JSON looks like this instead:
...
},
"servicelocation": {
"id":4,
"name":"remote",
"_info":{
"location_href":"https://API_url"
}
},
"severity": "Medium",
"impact":"Medium",
...
That behavior is probably normal, I'm obviously just missing the knowledge of how to deal with it. I feel like I should be able to test if the property of the object is non-existent the same way I test if it's null or "", using Tickets(i).Source.Name, but I get no exceptions, no errors, no crashes, the program just sits their waiting for a response to "What's Source Name's value?"
I mean I suppose I could parse out the entire JSON response, create my own private object, assign values as they exist and then set my own property values so I could then set mySourceName = "" When it doesn't exist in the JSON response, but that seems like a lot of work when I only care about like 10 fields and it's a pretty large json response.
Is that the normal way of doing things with APIs?

How can I access columns.roles in Power BI development?

Could not find this answer online, so decided to post the question then the answer.
I created a table in the capabilities.json file:
"dataRoles": [
{
"displayName": "Stakeholders",
"name": "roleIwant",
"kind": "GroupingOrMeasure"
}
...
"dataViewMappings": [
{
"table": {
"rows": {
"select": [
{
"for": {
"in": "roleIwant"
}
}
]
}
}
}
]
I realized that I could not simply set, for instance, legend data from the first category, because the first category comes from the first piece of data the user drags in, regardless of position. So if they set a bunch of different pieces of data in Power BI online, for instance, then remove one, the orders of everything get messed up. I thought the best way to settle this would be to identify the role of each column and go from there.
When you click on show Dataview, the hierarchy clearly shows:
...table->columns[0]->roles: { "roleIwant": true }
So I thought I could access it like:
...table.columns[0].roles.roleIwant
but that is not the case. I was compiling using pbiviz start from the command prompt, which gives me an error:
error TYPESCRIPT /src/visual.ts : (56,50) Property 'roleIwant' does not exist on type '{ [name: string]: boolean; }'.
Why can I not access this in this way? I was thinking because natively, roles does not contain the property roleIwant, which is true, but that shouldn't matter...
The solution is actually pretty simple. I got no 'dot' help (typing a dot after roles for suggestions), but you can use regular object properties for roles. The command for this case would be:
...table.columns[0].roles.hasOwnProperty("roleIwant")
And the functional code portion:
...
columns.forEach((column) =>{
if(column.roles.hasOwnProperty("roleIwant")){
roleIwantData = dataview.categorical.categories[columns.indexOf(column)].values;
})
If it has the property, it belongs to that role. From here, the data saved will contain the actual values of that role! The only thing I would add on here is that if a column is used for multiple roles, depending on how you code, you may want to do multiple if's to check for the different roles belonging to a column instead of if else's.
If anyone has any further advice on the topic, or a better way to do it, by all means. I searched for the error, all over for ways to access columns' roles, and got nothing, so hopefully this topic helps someone else. And sorry for the wordiness - I tend to talk a lot.

Unable to use Ember data with JSONAPI and fragments to support nested JSON data

Overview
I'm using Ember data and have a JSONAPI. Everything works fine until I have a more complex object (let's say an invoice for a generic concept) with an array of items called lineEntries. The line entries are not mapped directly to a table so need to be stored as raw JSON object data. The line entry model also contains default and computed values. I wish to store the list data as a JSON object and then when loaded back from the store that I can manipulate it as normal in Ember as an array of my model.
What I've tried
I've looked at and tried several approaches, the best appear to be (open to suggestions here!):
Fragments
Replace problem models with fragments
I've tried making the line entry model a fragment and then referencing the fragment on the invoice model as a fragmentArray. Line entries add to the array as normal but default values don't work (should they?). It creates the object and I can store it in the backend but when I return it, it fails with either a normalisation issue or a serialiser issue. Can anyone state the format the data be returned in? It's confusing as normalising the data seems to require JSONAPI but the fragment requires JSON serialiser. I've tried several combinations but no luck so far. My line entries don't have actual ids as the data is saved and loaded as a block. Is this an issue?
DS.EmbeddedRecordsMixin
Although not supported in JSONAPI, it sounds possible to use JSONAPI and then switch to JSONSerializer or RESTSerializer for the problem models. If this is possible could someone give me a working example and the JSON format that should be returned by the API? I have header authorisation and other such data so would I still be able to set this at the application level for all request not using my JSONAPI?
Ember-data-save-relationships
I found an add on here that provides an add on to do this. It seems more involved than the other approaches but when I've tried this I can send the data up by setting a the data as embedded. Great! But although it saves it doesn't unwrap it correct and I'm back with the same issues.
Custom serialiser
Replace the models serialiser with something that takes the data and sends it as plain JSON data and then deserialises back into something Ember can use. This sounds similar to the above but I do the heavy lifting. The only reason to do this is because all examples for the above solutions are quite light and don't really show how to set this up with an actual JSONAPI set up that would need it.
Where I am and what I need
Basically all approaches lead to saving the JSON fine but the return JSON from the server not being the correct format or the deserialisation failing but it's unclear what it should be or what needs to change without breaking the existing JSONAPI models that work fine.
If anyone know the format for return API data it may resolve this. I've tried JSONAPI with lineEntries returning the same format as it saved. I've tried placing relationship sections like the add on suggested and I've also tried placing relationship only data against the entries and an include section with all the references. Any help on this would be great as I've learned a lot through this but deadlines a looming and I can't see a viable solution that doesn't break as much as it fixes.
If you are looking for return format for relational data from the API server you need to make sure of the following:
Make sure the relationship is defined in the ember model
Return all successes with a status code of 200
From there you need to make sure you return relational data correctly. If you've set the ember model for the relationship to {async: true} you need only return the id of the relational model - which should also be defined in ember. If you do not set {async: true}, ember expects all relational data to be included.
return data with relationships in JSON API specification
Example:
models\unicorn.js in ember:
import DS from 'ember-data';
export default DS.Model.extend({
user: DS.belongsTo('user', {async: true}),
staticrace: DS.belongsTo('staticrace',{async: true}),
unicornName: DS.attr('string'),
unicornLevel: DS.attr('number'),
experience: DS.attr('number'),
hatchesAt: DS.attr('number'),
isHatched: DS.attr('boolean'),
raceEndsAt: DS.attr('number'),
isRacing: DS.attr('boolean'),
});
in routes\unicorns.js on the api server on GET/:id:
var jsonObject = {
"data": {
"type": "unicorn",
"id": unicorn.dataValues.id,
"attributes": {
"unicorn-name" : unicorn.dataValues.unicornName,
"unicorn-level" : unicorn.dataValues.unicornLevel,
"experience" : unicorn.dataValues.experience,
"hatches-at" : unicorn.dataValues.hatchesAt,
"is-hatched" : unicorn.dataValues.isHatched,
"raceEndsAt" : unicorn.dataValues.raceEndsAt,
"isRacing" : unicorn.dataValues.isRacing
},
"relationships": {
"staticrace": {
"data": {"type": "staticrace", "id" : unicorn.dataValues.staticRaceId}
},
"user":{
"data": {"type": "user", "id" : unicorn.dataValues.userId}
}
}
}
}
res.status(200).json(jsonObject);
In ember, you can call this by chaining model functions. For example when this unicorn goes to race in controllers\unicornracer.js:
raceUnicorn() {
if (this.get('unicornId') === '') {return false}
else {
return this.store.findRecord('unicorn', this.get('unicornId', { backgroundReload: false})).then(unicorn => {
return this.store.findRecord('staticrace', this.get('raceId')).then(staticrace => {
if (unicorn.getProperties('unicornLevel').unicornLevel >= staticrace.getProperties('raceMinimumLevel').raceMinimumLevel) {
unicorn.set('isRacing', true);
unicorn.set('staticrace', staticrace);
unicorn.set('raceEndsAt', Math.floor(Date.now()/1000) + staticrace.get('duration'))
this.set('unicornId', '');
return unicorn.save();
}
else {return false;}
});
});
}
}
The above code sends a PATCH to the api server route unicorns/:id
Final note about GET,POST,DELETE,PATCH:
GET assumes you are getting ALL of the information associated with a model (the example above shows a GET response). This is associated with model.findRecord (GET/:id)(expects one record), model.findAll(GET/)(expects an array of records), model.query(GET/?query=&string=)(expects an array of records), model.queryRecord(GET/?query=&string=)(expects one record)
POST assumes you at least return at least what you POST to the api server from ember , but can also return additional information you created on the apiServer side such as createdAt dates. If the data returned is different from what you used to create the model, it'll update the created model with the returned information. This is associated with model.createRecord(POST/)(expects one record).
DELETE assumes you return the type, and the id of the deleted object, not data or relationships. This is associated with model.deleteRecord(DELETE/:id)(expects one record).
PATCH assumes you return at least what information was changed. If you only change one field, for instance in my unicorn model, the unicornName, it would only PATCH the following:
{
data: {
"type":"unicorn",
"id": req.params.id,
"attributes": {
"unicorn-name" : "This is a new name!"
}
}
}
So it only expects a returned response of at least that, but like POST, you can return other changed items!
I hope this answers your questions about the JSON API adapter. Most of this information was originally gleamed by reading over the specification at http://jsonapi.org/format/ and the ember implementation documentation at https://emberjs.com/api/data/classes/DS.JSONAPIAdapter.html

RavenDB Authorization Bundle proper user of SecureFor

I am attempting to use RavenDB's authorization bundle to limit the results of a query (on WorkItems) by the permissions that have been explicitly set on WorkItem documents.
For example:
I have a user bob#bob.com with a userId of /users/1 and a WorkItem that has the following permissions set in the Meta-Data:
"Raven-Document-Authorization": {
"Tags": [],
"Permissions": [
{
"Operation": "/Operations/WorkItem/Search",
"User": "users/1",
"Role": null,
"Allow": true,
"Priority": 1
}
]
}
I would then expect the following code to limit a query (from Bob's perspective) to this one WorkItem, because that is all he has permission to.
using (var session = documentStore.OpenSession())
{
session.SecureFor("raven/authorization/users/1", "/Operations/WorkItem/Search");
var workItemsQuery = from wi in session.Query<WorkItem>()
select wi;
var debts = workItemsQuery.ToList();
// do something with the work items
}
I based my code on the following example from RavenDB's documentation (Context & User section): http://ravendb.net/docs/2.5/server/extending/bundles/authorization-bundle-design
What I am getting instead is WorkItems that have no explicit permissions set. This is very puzzling to me because if I run the following code:
using (var session = mDocumentStore.OpenSession())
{
var answer = session.Advanced.IsOperationAllowedOnDocument(userId, operation, securableId);
var allowed = answer.IsAllowed;
}
allowed is true.
One additional item of note, I am attempting to ignore or simply not use the authorization bundle's concept of role and I wonder if this is having some unintended effect.
It is very possible that I am misunderstanding their example, could anyone shed any light on this subject for me? Thanks in advance.
Also, I wondered if the issue I am encountering was related to this StackOverflow question: RavenDB: Raven Query not returning correct count with document authorization, but their issue seems to be with the count and not necessarily the actual results.
Just to tiddy up this question, I will provide an answer to what was causing my problem. The issue was related to the use of "raven/authorization/users/1" syntax. When I changed the search command to simply use, "users/1" it worked correctly.

How to add content and moreDetailsUrl for Google Search suggest?

I'm using GSA (version 6.14) and we would like to get an auto suggest function on our website. Works fine for basic requests, but it seems the GSA offers more functionality when you would be using user-added results. However, I can find nowhere a reference on how to add user-added results.
This is what the information tells me today :
/suggest?q=<query>&max=<num>&site=<collection>&client=<frontend>&access=p&format=rich
should return a response as below :
{
"query": "<query>",
"results": [
{ "name": "<term 1>", "type": "suggest"},
{ "name": "<term 2>", "type": "suggest"},
{ "name": "<term 3>", "type": "uar", "content": "Title of UAR",
"moreDetailsUrl": "URL of UAR"}
]
}
I am able to get results as the first 2 lines, but would like to get results as the last line also, so with content and a moreDetailsUrl. So maybe a very stupid question but I am not able to find the answer anywhere : How and where do I add this UAR ?
I actually want to understand if it's feasible to get metadata into the content part of the JSON, so if for instance an icon meta is available I'd like to have it included in the JSON so I can enrich my search results.
User Added Results are a OneBox that can be added to multiple frontends. See this: https://developers.google.com/search-appliance/documentation/614/admin_searchexp/ce_improving_search#uar
When done with Suggest, the data is fed from user entering 'keymatches' directly. What's different about them is that they are a direct link versus a suggested query. If you use the out of the box experience, you'll click a link to the url instead of running another query.