Using the following section of SimpleSchema with an Autoform, I have the following question:
Do I need to specify both allowedValues AND the autoform options? I think I found this example somewhere… but it seems like overkill to use both as the numbers 11,13, and 14 are listed twice. Do you need to do it this way to achieve proper validation, or could I drop the “allowedValues” and just use the autoform “Options”
Yes, I was thinking along those lines as well, however, this still seems like extra work. isn’t this probably something autoform could do internally? ie, take the values from the options and use them for the allowedvalues… ??
Neither of us know what would happen if you removed allowedValues… have you tried that as a first test?
But as of right now, I see your options are:
Workaround it (w/o accepting it as expected behaviour) - 1 min
Submit a PR with a well formed argument and work on a fork - 1-4 hrs
Create a issue on github and if aldeed thinks it makes sense, he’ll do it in his time. But this would mean breaking all existing forms by overriding any setting of allowedValues with options. - Indefinite
Before posting, I had tried removing allowedValues, and things still worked, but now I just ran a more extensive test:
Without AllowedValues, you still get the values in the drop down, but, if you hack the HTML page to pass a different value for one of the select options, it will go into the database without a validation error in the form… this was what I was afraid of… the autoForm Options just takes care of showing the correct values and labels in the drop down, but is not responsible for the validation.
I’ll post a note on the github repo about this… I think the best solution would be for autoform to only take the values from the options if allowedValues is unset… ie, your option 3 but with a twist so it doesn’t break all existing forms that are setting allowedValues directly.
Here’s what I ended up doing, based on @mordrax suggestion:
The ChartDictionary collection just contains misc. values used for validation, so I do a query into it for a certain “lookup_type”, sorting by the lookup_label, and for the allowedValues, I map the results into an array of just the ID numbers, and for the autoform options, I map the results into an array of labels and values.
AutoForm is a purely client side library, meaning even if you set the allowedValues properly, all that it does is make sure the values are accurate before updating minimongo, however, anyone can still bypass allowedValues by editing minimongo in their browser and that will still get synced to mongo.
This is why you always need to have server side validation no matter what safeguards, allowedValues, client UIs you might disable because they only interact with minimongo which the client has full control over. And this is also why I don’t particularly find allowedValues useful because to me, it’s just guiding the 99% of normal users which options already does.
I think of it as more of a regEx for lists/enums rather than a security feature.
My last reply got me thinking maybe allowedValues is ambiguously named and why it exists if it’s superseeded by options.
Reading the doco, it sounds like you use allowedValues as a shorthand if your label and value are the same and if you specify options (for when your label differs), then it overrides allowed values which confirms your tested behaviour.
In summary, you don’t need to specify allowedValues and it’s probably simpler to model your ChartDictionary directly in the format that options expects.
That’s a good question and unfortunately I’m not up to there yet but did a bit of reading (the part about Now that our collection has a schema... and realised that a collection with an attached schema which calls insert/update on either minimongo or mongo are validated.
I realised that I already tested this yesterday when I couldn’t insert a doc using webstorm shell because I hadn’t set a required field. Note: If you go into mongo shell, you can still insert any document you want because it doesn’t conform to the schema you’ve attached in your meteor code.
Therefore I’d like to amend what I said about server side validation to server side security.
In minimongo, you can open up chrome debug and start modifying collection data as per my last post. This will then sync with mongo (beauty of meteor). If you have a schema, the insert/update will be validated against it, and if it passes, you need security rules to block unauthorized access. I plan to use hooks and better (imo) deny rules to secure server insert/updates. It’ll be great if you could update with how you’re planning to do this so I can learn off you!
Well, for starters, I have autopublish and insecure removed, so something like Chart.insert from the browser console should fail. … now, I am providing a Meteor.method for something like “addChart”, and I’m trying to call this through the browser console, to see how it works. I can’t get the syntax right though…
if this is my method:
Meteor.methods({
addChart: function (chart) {
var rc = Chart.insert(chart);
return rc;
},
Then I’m having trouble calling it from Chrome:
Meteor.call('addChart', 'bla')
gives:
Exception while invoking method 'addChart' TypeError: Cannot use 'in' operator to search for '$pushAll' in bla
on the server,
and:
Exception while simulating the effect of invoking 'addChart' TypeError: Cannot use 'in' operator to search for '$pushAll' in hi
at SimpleSchema.clean (http://localhost:3000/packages/aldeed_simple-schema.js?e210968641793751997ffe233af33b53af8566e4:2549:21)
at doClean (http://localhost:3000/packages/aldeed_collection2.js?fdc7f0975dd1b3446ea4afd5f820cb1242a521af:291:12)
at doValidate (http://localhost:3000/packages/aldeed_collection2.js?fdc7f0975dd1b3446ea4afd5f820cb1242a521af:317:3)
at _.each.Mongo.Collection.(anonymous function) [as insert] (http://localhost:3000/packages/aldeed_collection2.js?fdc7f0975dd1b3446ea4afd5f820cb1242a521af:194:31)
at Meteor.methods.addChart (http://localhost:3000/shared.js?9df34a6360e5cfad1a2b6231b0f79619f76863b6:232:20)
at http://localhost:3000/packages/ddp.js?d1840d3ba04c65ffade261f362e26699b7509706:4269:25
ok, but in my Meteor.method, I’m taking a single parameter “chart” which I expect to be a json formatted document that I will insert to the Chart collection inside the method… so what I’m talking about is, how might some mischievous user in the browser console try to call my Meteor.methods directly… I’m trying to test the security of the application.
I know a user can do Chart.insert(’ some chart document’) in the console, but I’m wondering if I have insecure and autopublish off, could they still call the Metor.methods that I have available? (provided they know the name of them and how to call them properly)
You should never take a chart argument from the client and assume it’s correct. In fact, assume it’s incorrect and only take out the bits that you want.
Meteor.methods({
insertChart: function (chart) {
if (!chart) // handle null cases
var serverChart = {};
if (chart.status) {
// perform checking on status value
// everything's ok
serverChart.status = chart.status
}
Charts.insert(serverChart);
}
});
never insert whole objects by clients, it can contain anything. SimpleSchema goes a long way in specifying what you can insert. Actually, I just realised allowedValues is good for this case, because server inserts will check against schema and only insert values you deem valid.
Anyone can call Meteor.call(‘insertchart’, ‘blah’) from a browser console just like your js is doing.
what I’m wondering is, what is the actual syntax for calling a meteor.method from the browser console? my method takes a javascript json object, but I can’t seem to pass one in…
And, what I’ve also found by doing this, is that the simpleschema validation is happening even though I am doing the Meteor.call from the console. So, I think I am safe from users who might directly try to call my methods to insert records into the db, since it’s going to apply the same validation that simpleschema defines.
IE< if I leave out something required like lastname, it gives me this error:
debug.js:41 insert failed: Error: Last Name is required
at getErrorObject (http://localhost:3000/packages/aldeed_collection2.js?fdc7f0975dd1b3446ea4afd5f820cb1242a521af:409:15)
at doValidate (http://localhost:3000/packages/aldeed_collection2.js?fdc7f0975dd1b3446ea4afd5f820cb1242a521af:392:13)
at _.each.Mongo.Collection.(anonymous function) [as insert] (http://localhost:3000/packages/aldeed_collection2.js?fdc7f0975dd1b3446ea4afd5f820cb1242a521af:194:31)
at Meteor.methods.addChart (http://localhost:3000/shared.js?2780780cc1d3287a9d5d39714e3454df5dec8d05:233:20)
at http://localhost:3000/packages/ddp.js?d1840d3ba04c65ffade261f362e26699b7509706:4269:25
at _.extend.withValue (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:955:17)
at _.extend.apply (http://localhost:3000/packages/ddp.js?d1840d3ba04c65ffade261f362e26699b7509706:4260:54)
at _.extend.call (http://localhost:3000/packages/ddp.js?d1840d3ba04c65ffade261f362e26699b7509706:4138:17)
at <anonymous>:2:8
at Object.InjectedScript._evaluateOn (<anonymous>:905:140)
undefined
Agreed. The validation is applied when you call insert/update on a collection that’s got an attached schema on the server or client side.
However, that’s just data validation, you still need to do user verification (aka security, aka permission etc on server side). If you allow the user to pass in the chart object, they can overwrite other fields chart._id, chart.owner without you realising. Still perfectly valid.