yup validation with multiple fields - yup

I wanna validate fields with yup and react-hook-form. I wanna make sure at least one of the 2 fields will contain some value. For some reason the urls and instructions are undefined (see where it's printed) in the validation. Any ideas why this is happening?
When I submit the form values come in as:
{ meta,urls: Array(1), meta,instructions: "" }
Validation code:
const schema = yup.object({
processingType: yup.string(),
meta: yup.object().shape({
instructions: yup.string()
.when('urls', {
is: urls => {
console.log('HERE', urls)
return urls[0]?.url === ''
},
then: yup.string().required().min(1),
otherwise: yup.string()
}),
urls: yup.array().of(yup.object().shape({ url: yup.string() }))
.when('instructions', {
is: instructions => {
console.log('THERE', instructions);
return instructions === ''
},
then: yup.array().of(yup.object().shape({ url: yup.string() })).required().min(1),
otherwise: yup.object().shape({ url: yup.string() })
}),
}, ['instructions', 'urls'])
});
const defaultValues = {
processingType: '',
meta: {
instructions: '',
urls: [{ url: '' }],
}
};

Related

Mongoose model unique

I´m rather new to this..
If I dont want the user to be able to add duplicated countries to visitedCountry, shoulden unique true work?
Or are there any easy way to block that in the patch?
const User = mongoose.model('User', {
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
accessToken: {
type: String,
default: () => crypto.randomBytes(128).toString('hex')
},
visitedCountries:[ {
country: {
type: Object,
ref: "Country",
unique: true
},
comments: String
}]
})
app.patch('/countries', authenticateUser)
app.patch('/countries', async (req, res) => {
const { username, visitedCountry } = req.body
try {
const countryByAlphaCode = await Country.findOne({ alphaCode: visitedCountry }).lean()
const updatedUser = await User.findOneAndUpdate({ username: username, }, {
$push: {
visitedCountries: { country: countryByAlphaCode, comments: "no comments yet"}
},
}, { new: true })
res.json({ success: true, updatedUser })
} catch (error) {
res.status(400).json({ success: false, message: "Invalid request", error })
}
})
The options unique works for all documents. It prevents two (or more) documents from having the same value for your indexed field. It's often used for the email or username.
For your case, I recommend you to perform a check on the user data before you call findOneAndUpdate.

Mongoose | MongoDB | Default values not populating

I am trying to stick pre-populated data into my mongoDB database but the default data isn't getting in there when I send a POST request with the email and password only. Instead, all I'm seeing is an empty array titled 'thisiswhereIwantthetestdata'.
I tried adding default data at the top-level and that worked when I sent a POST request with the email and password only.
Any idea what I am doing wrong? Maybe something to do with the way I refer to [testSchema]?
const mongoose = require('mongoose');
const testSchema = new mongoose.Schema({
test: {
type: String,
default: 'default test'
},
test2: {
type: String,
default: 'default test 2'
}
})
const userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
},
thisiswhereIwantthetestdata: [testSchema]
});
You can accomplish this using a pre save hook like this:
User schema:
const mongoose = require("mongoose");
const testSchema = new mongoose.Schema({
test: {
type: String,
default: "default test"
},
test2: {
type: String,
default: "default test 2"
}
});
const userSchema = new mongoose.Schema({
email: {
type: String,
// unique: true,
required: true
},
password: {
type: String,
required: true
},
tests: [
{
type: testSchema,
default: testSchema
}
]
});
userSchema.pre("save", function(next) {
if (this.tests.length == 0) this.tests.push({});
next();
});
module.exports = mongoose.model("User", userSchema);
Sample route to create user:
router.post("/", async (req, res) => {
const result = await User.create(req.body);
res.send(result);
});
When you send a post request to the route with this body:
{
"email": "a#b.net",
"password": "123123"
}
Response will be like this meaning default values worked:
{
"_id": "5de6b94ad440d0337c8fd388",
"email": "a#b.net",
"password": "123123",
"tests": [
{
"test": "default test",
"test2": "default test 2",
"_id": "5de6b94ad440d0337c8fd389"
}
],
"__v": 0
}

make a path that increments the count

I'm trying to make a post request that will increment my schema using express and mongoose,
which is :
const ItemSchema = new Schema({
formName: String,
inputs: [
{
inputLabel: {
type: String,
required: true
},
inputType: {
type: String,
required: true,
enum: ['text', 'color', 'date', 'email', 'tel', 'number']
},
inputValue: {
type: String,
required: true
}
}
],
numOfSubs: { type: Number, default: 0 }
});
for my code purposes I want to make a route that will increase by 1 the numOfSubs everytime I use it,since there are a few listings, I have the ID so I need to search it, and I'm not sure how to write the path
router.post('/increase', (req, res) => {
"find and increase by 1 "
});
and I will use the fetch like so:
fetch('/api/items/increase', {
method: 'POST',
body: JSON.stringify({ _id }),//the ID I of the collection I want to increment
headers: {
'content-type': 'application/json'
}
});
try this using mongo $inc operator
router.post('/increase', (req, res, next) => {
const _id = req.body._id;
MyModel.findByIdAndUpdate(_id , { $inc: {numOfSubs: 1} }, { new: true }, (err,updateRes)=>{
if(err) return next(err);
return res.json({sucess: true});
});
});

MongoDB & Mongoose: unable to populate a user's posts with .populate()

I've searched this site for days looking through the many different but similar questions on this topic to no avail.
Here's what I'd like to happen. A user signs in and their posts are automatically linked to the users collection. Eventually I'd like to link posts to the profile it was posted to, but i"m not quite there yet. Here's what I've tried so far.
In the User Schema:
const UserSchema = new Schema({
posts: [{
type: Schema.Types.ObjectId,
ref: 'posts'
}],
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
...
});
module.exports = User = mongoose.model('users', UserSchema);
In the Post Schema:
const PostSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'users'
},
text: {
type: String,
required: true
},
name: {
type: String
},
...
});
module.exports = Post = mongoose.model('posts', PostSchema);
In my users api, here's how I'm signing the user in and attempting to populate the user's posts:
const User = require('../../models/User');
router.post('/login', (req, res) => {
const { errors, isValid } = validateLoginInput(req.body);
// Check Validation
if (! isValid) {
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
// Find user by email
User.findOne({ email })
.populate('posts')
.then(user => {
if (! user) {
errors.email = 'User not found';
return res.status(400).json(errors);
}
// Check password
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
// User Matched
// Create JWT Payload
const payload = {
id: user.id,
firstName: user.firstName,
lastName: user.lastName,
name: user.firstName + ' ' + user.lastName,
avatar: user.avatar,
posts: user.posts
};
jwt.sign(
payload,
keys.secretOrKey,
{ expiresIn: 3600 }, (err, token) => {
res.json({
success: true,
token: 'Bearer ' + token,
payload
});
});
} else {
errors.password = 'Password is incorrect';
return res.status(400).json(errors);
}
});
});
});
In the posts api, here's how the post is being submitted:
router.post('/', passport.authenticate('jwt', { session: false }), (req, res) => {
const { errors, isValid } = validatePostInput(req.body);
if (! isValid) {
// Return errors with 400 status
return res.status(400).json(errors)
}
const newPost = new Post({
text: req.body.text,
name: req.body.name,
avatar: req.body.avatar,
user: req.user.id
});
newPost.save().then(post => res.json(post));
});
Currently, all I'm seeing is an empty array and no errors. I've been spinning my wheels on this one for a couple days now so any help would be appreciated. Thanks!
I think you forgot to save the _id of your new post to the User model so that the populate() can lookup the posts to populate:
newPost.save().then(post => {
User.update({ _id: req.user.id }, { $push: { posts: post._id }}, (err) => {
res.json(post));
});
});

MongoDB Document Validation in Meteor?

How would one approach doing this (https://docs.mongodb.com/v3.2/core/document-validation/):
db.createCollection( "contacts",
{ validator: { $or:
[
{ phone: { $type: "string" } },
{ email: { $regex: /#mongodb\.com$/ } },
{ status: { $in: [ "Unknown", "Incomplete" ] } }
]
}
} )
In this:
// database.js
import { Mongo } from 'meteor/mongo';
export const Test = new Mongo.Collection('Test');
Thanks
you first need to define your schema in meteor.
Lists.schema = new SimpleSchema({
name: {type: String},
incompleteCount: {type: Number, defaultValue: 0},
userId: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true}
});
This example defines a schema with a few simple rules:
We specify that the name field of a list is required and must be a
string.
We specify the incompleteCount is a number, which on insertion is
set to 0 if not otherwise specified.
We specify that the userId, which is optional, must be a string that
looks like the ID of a user document.
It’s pretty straightforward to validate a document with a schema. We can write:
const list = {
name: 'My list',
incompleteCount: 3
};
Lists.schema.validate(list);
In this case, as the list is valid according to the schema, the validate() line will run without problems. If however, we wrote:
const list = {
name: 'My list',
incompleteCount: 3,
madeUpField: 'this should not be here'
};
Lists.schema.validate(list);
Then the validate() call will throw a ValidationError which contains details about what is wrong with the list document.