I have this very basic model with just one field name that I want to validtate against a regex:
const Projects = new ProjectsCollection('projects');
Projects.schema = new SimpleSchema({
_id : {type: String, regEx: SimpleSchema.RegEx.Id},
name : {
type : String,
regEx: /^[a-zA-Z0-9]+((\s[a-zA-Z0-9]+)|(_[a-zA-Z0-9]+)|(-[a-zA-Z0-9]+)|(\.[a-zA-Z0-9]+))?$/
}
});
Projects.attachSchema(Projects.schema);
When the validation fails I get back a validation error saying that regex failed for Name which is undesirable for me because it's ambiguous and the user has no idea what exactly I need him to enter.
I tried adding the following with no success:
Projects.schema.messages({
"regEx name": [{
msg: "test error message"
}]
});
This one however..works but the problem is that I could have any other model with a name field and it will spit out the same error message for all of them (and I plan on having another model with a name field):
SimpleSchema.messages({
"regEx name": [{
msg: "test error message"
}]
});
I tried also with (no success):
SimpleSchema.messages({
"regEx projects.name": [{
msg: "test error message"
}]
});
I insert via methods and here's my insert code:
export const insert = new ValidatedMethod({
name : 'projects.insert',
mixins : [simpleSchemaMixin],
schema : Projects.simpleSchema().pick([
'name'
]),
schemaValidatorOptions: {
clean : true,
filter: false
},
run({name}) {
return Projects.insert({
name
}, null);
},
});
Any ideas on how am I supposed to configure my validation messages so that I can target them for specific fields?
See the documentation for the special case of regex messages:
In your case you should try:
Projects.schema.messages({
"regEx name": [
{
exp: /^[a-zA-Z0-9]+((\s[a-zA-Z0-9]+)|(_[a-zA-Z0-9]+)|(-[a-zA-Z0-9]+)|(\.[a-zA-Z0-9]+))?$/ ,
msg: "test error message"
}
]
});
This answer and question applies to v1 of meteor-simpl-schema
I had the same problem and this worked for me. I think that custom messages are instance based - are bound only to one simplSchema instance. Then in your validated-method, pick() will create a new SimplSchema instance, without your custom messages.
I needed to manually add a custom messages from the "parent" schema.
In your case like this:
const insertProjectSchema = Projects.schema.pick('name');
insertProjectSchema.messages(Projects.schema._messages);
export const insert = new ValidatedMethod({
name : 'projects.insert',
mixins : [simpleSchemaMixin],
schema : insertProjectSchema,
schemaValidatorOptions: {
clean : true,
filter: false
},
run({name}) {
return Projects.insert({
name
}, null);
},
});
Related
i have added "additionalProperties": false to schema scripts in postman. The "additionalProperties": false, worked fine and im getting error message when new fields are newly added to the json response and not covered by schema. But is there a script to specify what fields are added in the json?
No, I think you cannot.
I have tried using itv4 directly instead of using it through pm...
like below... The best I have obtained is the number of fields that are exceeding... but not the name.
const schema = {
"type": "object",
"properties": {
"code": { "type": "string" }
},
"additionalProperties": false
};
console.log(tv4.validate(body, schema))
console.log(tv4.validateResult(body, schema))
console.log(tv4.validateMultiple(body, schema));
pm.test("Explicitly ", function () {
let Ajv = require('ajv');
let ajv = Ajv()
let result = ajv.validate(schema, jsonData);
pm.expect(result, JSON.stringify(ajv.errors)).to.be.true;
});
this will show the additional property there is a bug for this already :
https://github.com/postmanlabs/postman-app-support/issues/9276
I have this server side validated method imports/api/Shops/server/methods.js:
export const shopGeocodeAddress = new ValidatedMethod({
name: 'shops.geocodeAddress',
validate: new SimpleSchema({
streetName: { type: String },
houseNumber: { type: Number },
city: { type: String },
state: { type: String },
country: { type: String },
zip: { type: String, optional: true },
}).validator(),
run({ streetName, houseNumber, city, state, country, zip }) {
...
...
...
...
return location;
},
});
To test validation error message on the client, I'm sending houseNumber as string which will get the method to fail, as it expects houseNumber as Number. So far so good. I'm getting a validation error on the server console like this:
I20190418-10:55:28.605(-3)? Exception while invoking method 'shops.geocodeAddress' { ClientError: House number must be of type Number
...
...
I20190418-10:55:28.608(-3)? errorType: 'ClientError',
I20190418-10:55:28.608(-3)? name: 'ClientError',
I20190418-10:55:28.608(-3)? error: 'validation-error',
I20190418-10:55:28.609(-3)? details:
I20190418-10:55:28.609(-3)? [ { name: 'houseNumber',
I20190418-10:55:28.609(-3)? value: NaN,
I20190418-10:55:28.609(-3)? type: 'expectedType',
I20190418-10:55:28.609(-3)? dataType: 'Number',
I20190418-10:55:28.609(-3)? message: 'House number debe ser del tipo Number' } ] }
But on the client I get only an internal server error like this:
details: undefined
error: 500
errorType: "Meteor.Error"
isClientSafe: true
message: "Internal server error [500]"
reason: "Internal server error"
Thus I can't indicate the client which type of error is, or which field must be changed in order for the method to be run correctly.
Is there a way to catch validation error on server methods and send them to the client?
Thanks in advise!
You can surround the s
schema.validator with a try/catch and throw a custom Meteor.Error that contains better understandable information.
You can do the same with the code inside run.
If you want to do this for every validated method, you may create a simple generator function:
const createMethod = options => new ValidatedMethod({
name: options.name,
validate(...args) {
try {
new SimpleSchema(options.schema).validate(...args)
} catch (e) {
throw new Meteor.Error('validationError', e.reason)
}
},
run(...args) {
try {
return options.run.call(this, ...args)
} catch (e) {
throw new Meteor.Error('methodError', e.reason)
}
}
})
Note that you may use e.reason || e.message
2 things:
A) You can write
city: String,
state: String,
zip: { type: String, optional: true }
...
B) You say "server side validated method". Your method needs to be in the common space reachable by both Server and Client. In the method you enclose everything into Server. You call the method from the client (and reach it) but run it on the Server:
export const shopGeocodeAddress = new ValidatedMethod({
name: 'shops.geocodeAddress',
validate: new SimpleSchema({
streetName: String,
houseNumber: Number,
city: String,
state: String,
country: String,
zip: { type: String, optional: true },
}).validator(),
run({ streetName, houseNumber, city, state, country, zip }) {
if (Meteor.isServer) {
...
...
...
...
return location;
}
},
});
Finally I used this answer on Meteor Forums https://forums.meteor.com/t/server-validated-method-doesnt-display-validation-error-on-client/48635/2?u=razor7
Basically I needed to create a new file to be run in server startup to route validation errors to client
import SimpleSchema from 'simpl-schema';
SimpleSchema.defineValidationErrorTransform((error) => {
const ddpError = new Meteor.Error(error.message);
ddpError.error = 'validation-error';
ddpError.details = error.details;
ddpError.reason = error.message;
return ddpError;
});
i am using firebase realtime DB with my ionic app and using angularfire2. I have data stored like:
"users" : {
"230A3lKQqWh0TczOGP8sbtMVpuF2" : {
"email" : "xxx#gmail.com",
"isAdmin" : false,
"name" : "Santosh Yadav",
"pic" : "https://graph.facebook.com/xxx/picture"
},
"oSEYj0zrkhPCk9r7uwyOOkHcqe53" : {
"email" : "yyy#gmail.com",
"isAdmin" : true,
"name" : "Vik Kumar",
"pic" : "https://graph.facebook.com/xxx/picture"
},
"tl3uvseaBeWVYFCTwSngUqcSokX2" : {
"email" : "zzz#gmail.com",
"isAdmin" : false,
"name" : "Neeti Singhal",
"pic" : "https://graph.facebook.com/xxx/picture"
}
}
We ended up to store more user data like date of birth and date of aniversary and when we try to update it as below:
createUser(user:User){
console.log('start of create user')
var payload = {
"name": user.name,
"email": user.email,
"pic" : user.pic,
"dob" : user.dob,
"anivDate" : user.anivDate,
}
return this.db.object('/users/' + user.uid).set(payload).then(
(resp) => console.log("user created")
).catch(
(err) => console.log("issues creating user:" + err)
)
}
It fails with error:
ERROR Error: Reference.set failed: First argument contains undefined in property 'users.oSEYj0zrkhPCk9r7uwyOOkHcqe53.anivDate'
at validateFirebaseData (validation.js:113)
at validation.js:140
at forEach (obj.js:46)
I understand the error that it is unable to set a property anivDate that does not exist in my firebase realtime DB. This will fix if i manually add the property into the db manually. But that is not a practical fix. So, what is the solution here?
To define the fix: i am expecting to add a new property if that does not exist else just update it.
For a quick fix, use the || operator to set a default value on undefined elements. Usage:
var payload = {
"anivDate": user.anivDate || "1970-01-01",
...
};
This sets anivDate to user.anivDate if it exists, 1970-01-01 if it does not. (This works, but in my opinion it is better practice to not have a anivDate property on a user if no such value exists, and check for that value's existence when accessing the data.)
For a more scalable/reliable fix, use Firebase's realtime database triggers to add async validating or default values to your new columns.
I have a CosmosDB setup using the Mongo API. I have a collection with a hashed shard on one of the field of the document. When I run commands like db.collection.remove or db.collection.deleteMany I get the following error.
Command deleteMany failed: query in command must target a single shard key.: {"message":"Command deleteMany failed: query in command must target a single shard key."}
I'm not sure how can I mention a shard key as part of the query considering I want the query to run across all the shards.
You need to provide shard key when you want to run commands like db.collection.remove or db.collection.deleteMany.
For example :
My data source as below:
[
{
"id" : "2",
"name" : "b"
},
{
"id" : "1",
"name" : "a"
}
]
And my shared key is "/name". Use db.coll.deleteMany({"name":"a"}) to delete specific shard.
Hope it helps you.
It should be ShardKey which you have chosen when you created cosmosDb collection.
FilterDefinition<Product> filter = Builders<Product>.Filter.Eq("id", 2);
=== 2 is my shardKey
await this._dbContext.GetProducts.DeleteOneAsync(filter);
return RedirectToAction("Index");
Kindly refer an image below , how does it look like in CosmosDB
Shard Key(Partition Key) has to be provided during specification of schema model in the code. Once its provided, we can perform regular operation like save, update and delete as usual.
Example:
const mySchema = new Schema({
requestId: { type: String, required: true },
data: String,
documents: [{ docId: String, name: String, attachedBy: String }],
updatedBy: {
type: {
name: { type: String, required: true },
email: { type: String, required: true },
}, required: true
},
createdDate: { type: Date, required: true },
updatedDate: { type: Date },
}, { shardKey: { requestId: 1 } }
);
In the above code we specified requestId as Shard Key, now we can perform any mongo operations
Example:
let request:any = await myModel.findById(requestId);
request.data ="New Data";
await request.save();
Hope that helps.
This works with all Mongo operations
I successfully update and delete an item from a StringSet in a dynamoDb table when called from my test app running on localhost.
I then upload the app to LightSail but now when I call the same function to update or delete an item it throws a ValidationException!:
{
"message": "Invalid UpdateExpression: Incorrect operand type for operator or
function; operator: DELETE, operand type: MAP",
"code": "ValidationException",
"time": "2018-01-03T13:20:14.919Z",
"requestId": "9HCQMH5RAUBRK1K7BNESNBUD5BVV4KQNSO5AEMVJF66Q9ASUAAJG",
"statusCode": 400,
"retryable": false,
"retryDelay": 10.381373865940402
}
Why? I have not made any changes to my code so why does this happen and how to solve it?
Here's the relevant code:
var documentClient = getDocumentClient();
var paramsSET = {
ExpressionAttributeNames:
{
"#StringSet": "Packages"
},
ExpressionAttributeValues:
{
":value": documentClient.createSet(['filler as SET cannot be empty',
app.packageName
])
},
Key:
{
"EmailAddress": app.emailAddress
},
ReturnValues: "ALL_NEW",
TableName: "Developers",
UpdateExpression: "ADD #StringSet :value"
// UpdateExpression: "DELETE #StringSet :value" ------ to delete value
};
// adds packagename to Packages SET in developers table - creates set if not exist
documentClient.update(paramsSET, function (err, data){}
I could not get it to work using the documentclient api.
finally used the old api and got it to work using dynamodb.updateItem see docs here
still have no idea why it works on localhost (accessing the same dynamodb tables) and not when live on LightSail!