There is object with a property time (22:30:00).
const schema = Joi.object.keys({
...
transactionDate: Joi.date().required(),
transactionTime: Joi.time().required(), // ???
...
});
How to validate a time field using Joi?
Try this way
const schema = Joi.object().keys({
...
transactionDate: Joi.string().regex(/^([0-9]{2})\:([0-9]{2})$/)
})
Hear I have used simple regex format.
You can also use this : ^([01]\d|2[0-3]):?([0-5]\d)$
for AM and PM \b((1[0-2]|0?[1-9]):([0-5][0-9])([AaPp][Mm]))
AM PM
Related
when creating a mongoose schema, and using enum in order to validate the values, is it case sensitive?
As in:
const mySchema = new Schema({
animal: {
type: String,
enum: ['cat', 'dog']
}
});
const myModel = db.model('animal', mySchema);
const animal1 = new myModel({
animal: 'CAT'
});
Will animal1 be saved or rejected?
Thanks in advance!
Mongoose has several inbuilt validators. Strings have enum as one of the validators. So enum creates a validator and checks if the value is given in an array & these are case sensitive so it will throw validation error, so you can use .toLowerCase() while saving the doc.
If only Mongoose had a way of manually validating a document. Oh wait, there is, and it's even documented.
console.log( animal1.validateSync() );
…
Error: animal validation failed: animal: `CAT` is not a valid enum value for path `animal`.
I have the following mongodb model:
const schema = new Schema({
timezone: {
type: String,
},
datetimeBaseOnTimezone: {
type: Date,
}
})
I want to update the datetimeBaseOnTimezone with the current Date for each document in database based on the current timezone of each document this using a single query.
Something like this:
await Model.updateMany({},(element) => ({
datetimeBaseOnTimezone: new Date(new Date().toLocaleString('en-US', { timeZone: element.timezone }))
}));
Is there any solution similar to this approach?
Starting with a few assumptions:
the datetimeBaseOnTimezone string has the same format for all documents
the timezone string contains an Olson timezone identifier or a UTC offset
you are using MongoDB 4.2 or newer
You could use the pipeline form of update, along with the $dateFromString operator, which might look something like:
Model.updateMany({},[{$set:{datetimeBaseOnTimezone:{$dateFromString:{
dateString:"$datetimeBaseOnTimezone",
format: <see dateFromString docs>,
timezone: "$timezone",
onError: "$datetimeBaseOnTimezone",
onNull: "$datetimeBaseOnTimezone"
}}}])
Is it possible to pass a string to hapi/joi and for it to process it and return a required format? For example consider the code below:
const acceptedCitiesSchema = Joi.object({
isCapitalCity: Joi.boolean().default(true),
cityName: Joi.string().valid('MyCity', 'YourCity').required(),
})
How can I make it that even if a user inputs 'myCity' or 'yourCity' joi automatically converts them to a format that the first word is capitalized('MyCity' and 'YourCity' respecively). And returns the desired results? Is it possible to achieve this using hapi/joi?
You can try the following:
const schema = Joi.object({
isCapitalCity: Joi.boolean().default(true),
cityName: Joi.string().valid('MyCity', 'YourCity').insensitive().required()
})
And while validating with schema, you can use the convert:true option as:
schema.validate({"cityName": "myCity"}, {"convert": true})
Alternatively, you can directly provide additional preferences to convert the Joi validated object in the schema:
const schema = Joi.object({
isCapitalCity: Joi.boolean().default(true),
cityName: Joi.string().valid('MyCity', 'YourCity').insensitive().prefs({convert:true}).required()
})
Here is a link to working example: https://repl.it/repls/HarmfulEvenPhases
Looking to prevent NoSQL injection attacks for a node.js app using mongodb.
var mongoose = require('mongoose'); // "^5.5.9"
var Schema = mongoose.Schema;
var historySchema = new Schema({
userId: {
type: String,
index: true,
},
message: {},
date: {
type: Date,
default: Date.now,
}
});
var history = mongoose.model('history', historySchema);
// the following is to illustrate the logic, not actual code
function getHistory(user){
history.find({userId: user}, function(err, docs) {
console.log(docs)
}
}
Based on this answer to a similar question, my understanding is that using mongoose and defining the field as string should prevent query injection. However, by changing the user input to a query object, it is possible to return all users. For example:
getHistory({$ne: 1}) // returns the history for all users
I am aware of other ways to prevent this type of attack before it gets to the mongoose query, like using mongo-sanitize. But I'd like to know if there's something wrong with the way I defined the schema or if one can't expect mongoose to convert inputs according to the schema.
Thanks in advance!
this part is good enough, you do not need anything else there. There is method that receives string and uses the string.
The best approach is to validate the input that can be modified (usually HTTP request) on top level before processing anything (I can recommend https://github.com/hapijs/joi its easy to use and you can check if there all required fields and if all fields are in correct format).
So put the validation into middleware just before it hits your controller. Or at the beginning of your controller.
From that point you are in full control of all the code and you believe what you got through your validation, so it cannot happen that someone pass object instead of string and get through.
Following the "skinny controllers, fat model" paradigm, it would be best to expose a custom validation schema from your model to be used in your controller for POST and PUT requests. This means that any data that attempts to enter your database will first be sanitized against a validation schema. Every Mongoose model should own its own validation schema.
My personal favorite for this is Joi. It's relatively simple and effective. Here is a link to the documentation: https://www.npmjs.com/package/#hapi/joi
A Joi schema permits type checking (i.e., Boolean vs. String vs. Number, etc), mandatory inputs if your document has the field required, and other type-specific enforcement such as "max" for numbers, enumerable values, etc.
Here is an example you'd include in your model:
const Joi = require('joi');
...
function validateHistory(history) {
const historySchema = {
userId: Joi.string(),
message: Joi.object(),
date: Joi.date()
}
return Joi.validate(history, historySchema);
}
...
module.exports.validate = validateHistory;
And then in your controller you can do:
const {
validate
} = require('../models/history');
...
router.post('/history', async (req, res) => {
const {
error
} = validate(req.body.data);
if (error) return res.status(400).send(error.details[0].message);
let history = new History({
userID: req.body.user,
message: req.body.message,
date: req.body.date
})
history = await history.save();
res.send(history);
});
*Note that in a real app this route would also have an authentication callback before handling the request.
I’m looking for the fastest way to get all objectIDs of a collection with a privacy value 'public'.
In this image, privacy's value is 'public', so node should give me the '_id' of this object (in this example '57bc4b9f466fab7c099a3f94').
My attempt:
var mongoose = require('mongoose');
mongoose.connect('localhost:27017/databasename');
var Schema = mongoose.Schema;
var collectionsNameSchema = new Schema({
updated: {type: Date },
privacy: { type: Object }
}, {collection: 'spots'});
var collectionsNameData = mongoose.model('collectionsNameData', collectionsNameSchema);
...
collectionsNameData.find({privacy: 'public'})
From what i see you have a problem in query to mongoDB.
Try like this.
collectionsNameData.find({'privacy.value': 'public'});
This should return desired result.
You also may want to use projection as second parameter in find to return only fields that you want. Keep in mind that _id returned by default.
Hope this helps.