Why is my mongoose schema not validating? - validation

I am trying to validate my data with mongoose schema. But its not working, and I have no idea why.
This is my Schema
var mongoose = require("mongoose");
var UserSchema = new mongoose.Schema({
username: { type: String, min: 3, max: 30, required: true },
password: { type: String, min: 6, required: true }
});
mongoose.model("User", UserSchema);
This is where I call the post
router.post('/signup', (req, res) => {
const user = new User({
username: "Marcel",
password: "12345"
})
user.save().then(function(){
res.json({
message: '✅'
})
}).catch(function(){
res.json({
message: '❌'
})
})
})
I have given the password a minimum of 6 characters, but with the example user I give 5 characters, so it should not work, but it does. Can someone help me?

You have used the validators min and max, which are for the Number type.
Try using minlength and maxlength instead, which are for the String type:
var UserSchema = new mongoose.Schema({
username: { type: String, minlength: 3, maxlength: 30, required: true },
password: { type: String, minlength: 6, required: true }
});
I hope this helps.

Related

Prisma cannot create a user type because of array argument?

this is my InputType in schema.graphql:
input RegisterInput {
birthday: String!
email: String!
firstName: String!
gender: String!
interests: [String!]!
lastName: String!
password: String!
}
and this is my mutation:
const RegisterInput = inputObjectType({
name: 'RegisterInput',
definition(t) {
t.string('birthday', { nullable: false });
t.string('email', { nullable: false });
t.string('firstName', { nullable: false });
t.string('lastName', { nullable: false });
t.string('gender', { nullable: false });
t.string('password', { nullable: false });
t.list.field('interests', {
type: 'String',
nullable: false,
});
},
});
const Mutation = objectType({
name: 'Mutation',
definition(t) {
t.field('register', {
type: User,
args: {
data: arg({ type: RegisterInput }),
},
resolve: async (
_root,
{ data: { password, interests, ...userData } },
{ prisma }
) => {
const hashedPassword = await bcrypt.hash(password, 10);
const user = await prisma.user.create({
data: {
...userData,
interests: [...interests],
password: hashedPassword,
},
});
return user;
},
});
my interests is just an array of strings, .e.g: ['abcd', 'def']
but i got this error:
Unknown arg `0` in data.interests.0 for type UserCreateInterestInput. Available args:
type UserCreateInterestsInput {
set?: List<String>
}
that error will repeat depending of how many items is in the array, e.g.: Unknown arg '1' and so on, same error message, how do i fix this?
You must provide a list of strings to set argument, such as:
type UserCreateInterestsInput {
set?: List<String>
}
Refer to this issue for more information.
const Mutation = objectType({
name: 'Mutation',
definition(t) {
t.field('register', {
type: User,
args: {
data: arg({ type: RegisterInput }),
},
resolve: async (
_root,
{ data: { password, interests, ...userData } },
{ prisma }
) => {
const hashedPassword = await bcrypt.hash(password, 10);
const user = await prisma.user.create({
data: {
...userData,
interests: {set: interests},
password: hashedPassword,
},
});
return user;
},
});
Hope this helps
Happened to me earlier, turns out it was a query mistake.
mutation {
createFruit(data:{
name: "Banana",
images: {
set: ["image_1.img", "image_2.img"]
}
}) {
name
images
}
}
Note it's not images: ["image_1.img", "image_2.img"]
fyi with prisma you can do t.model.interest() when defining objectType

How to set argument optional in Graphql?

In my mongodb model, name is required but i want to make it optional in graphql. How can i do this?
updateExercise: {
type: ExerciseType,
args: {
id: {type: new GraphQLNonNull(GraphQLString)},
username: {type: new GraphQLString},
description: {type: new GraphQLString},
duration: {type: new GraphQLInt},
date: {type: new GraphQLString}
},
resolve(parent, args) {
Exercise.findByIdAndUpdate(args.id)
.then(exercise => {
exercise.username = args.username,
exercise.description = args.description,
exercise.duration = args.duration,
exercise.date = args.date
exercise.save()
.then( () => 'Succesfully Updated')
.catch( e => console.log(e) )
})
}
}
You are misusing the findByIdAndUpdate function. It should probably be used in this way:
const SomeType = new GraphQLObjectType({
updateExercise: {
type: ExerciseType,
args: {
id: {type: new GraphQLNonNull(GraphQLString)},
username: {type: GraphQLString},
description: {type: GraphQLString},
duration: {type: GraphQLInt},
date: {type: GraphQLString}
},
resolve(parent, args) {
return Exercise.findByIdAndUpdate(args.id, {
username: args.username || undefined,
description: args.description,
duration: args.duration,
date: args.date
}).then(() => 'Succesfully Updated')
.catch(e => console.log(e))
})
}
}
});
We use a little trick in JS to short-circuit the returned value. This will supply undefined for the username property when args.username is null. If you are in an environment where you are not sure if undefined as been reassigned you can use void 0 instead. If you are using a new TypeScript or EcmaScript version you can use the newer ?? operator instead of ||.

GraphQL mutator with required args

I am writing a mutation for a GraphQL schema:
const Schema = new GraphQLSchema({
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: () => ({
person: {
type: GraphQLString,
args: {
name: {type: GraphQLString},
school: {type: GraphQLString},
},
resolve: mutatePerson,
},
}),
}),
});
I want to ensure that mutatePerson will only work if both name and school arguments are present. How can I check that?
The GraphQLNonNull type wrapper is used to specify both fields and arguments as non-null. For fields, that means the value of the field in the query results cannot be null. For arguments, that means that the argument cannot be left out or have a value of null. So your code just needs to look more like this:
args: {
name: {
type: new GraphQLNonNull(GraphQLString),
},
school: {
type: new GraphQLNonNull(GraphQLString),
},
},
it is better to do it as follow (in the model) if you want to reject empty Strings like "", it is different from Null, this way you can reject both Null and empty "".
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const buinessSchema = new Schema({
name: { type: String, required: true, unique: true },
address: { type: String, required: true },
phone: { type: String, required: true },
email: { type: String, required: true },
website: { type: String, required: true },
currency: { type: String, required: true },
aboutus: { type: String, required: true },
terms: String,
slogan: String,
logo: { type: String, required: true }
});
module.exports = mongoose.model("Buiness", buinessSchema);

sequelize validation violation

I am developing a project in which admins can add chat rooms and those have five fields: (id, creator (admin who created it), name, slug and createdAt) and I am receiving this error Unhandled rejection SequelizeValidationError: notNull Violation: name cannot be null.
//models/user.js
var Sequelize = require('sequelize');
var passportLocalSequelize = require('passport-local-sequelize');
var env = process.env.NODE_ENV || 'development';
var config = require(__dirname + '/../config/config.json')[env];
var mydb = new Sequelize(config.database, config.username, config.password, config);
// We do not need additional features for our users, so we just use the default user model
// provided by Passport
var User = passportLocalSequelize.defineUser(mydb,
{
email: { type: Sequelize.STRING, allowNull: false, unique: true }
},{}
);
//Function at a prototype level for performance optimization
User.Instance.prototype.$Model.findByEmail = function(email, done){
var parameters = {};
parameters.email = email;
var user = this.findOne({where: parameters});
user.then(function(usr) {
done(null, usr);
});
}
mydb.authenticate().then(function(done)
{
if(mydb.sync({force: false}))
done();
}).catch(function(error,user)
{
console.log(error);
});
module.exports = User;
//models/chat.js
var Sequelize = require('sequelize');
var env = process.env.NODE_ENV || 'development';
var config = require(__dirname + '/../config/config.json')[env];
var User = require('./user');
var mydb = new Sequelize(config.database, config.username, config.password, config);
var Chat = mydb.define('Chat',
{
id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true },
name: { type: Sequelize.STRING, unique: true, allowNull: false,
validate: {
notNull: { args: true, msg: "You must enter a name" }
},
set: function(val) {
val = val.toLowerCase().trim();
this.setDataValue('title', val );
this.setDataValue('slug', val.split(" ").join("_"));
}
},
slug: { type: Sequelize.STRING, unique: true, allowNull: false },
creator: { type: Sequelize.INTEGER, references: { model: User, key: 'id' }}
},
{
timestamps: true,
updatedAt: false // I only want the field createdAt
}
)
mydb.authenticate().then(function(done){
if(mydb.sync({force: false}))
done()
}).catch(function(err, chat){
console.log(err);
});
module.exports = Chat;
//routes/admin.js
router.post("/dashboard",isAuthenticated, function(req,res){
if (req.body.chatName) {
try{
console.log(req.body.chatName);
console.log(Chat.create({ name: req.body.chatName, creator: req.user.id }));
}
catch (e){
console.log(e.message);
}
}
});
I only copied and pasted the function which manages the chat rooms creation, console.log(req.body.chatName); prints correctly the entered name
From the sequelize docs:
// setting allowNull to false will add NOT NULL to the column, which means an error will be
// thrown from the DB when the query is executed if the column is null
In your Chat table you set
name: { type: Sequelize.STRING, unique: true, allowNull: false,
validate: {
notNull: { args: true, msg: "You must enter a name" }
},
set: function(val) {
val = val.toLowerCase().trim();
this.setDataValue('title', val );
this.setDataValue('slug', val.split(" ").join("_"));
}
},
for the user field, where allowNull is false.
So the error you're getting is directly from the db instead of your message in the validate property. Get rid of the allowNull property, keep the validation, and you should be good. A little late, but hope this clears things up!

How can I validate a unique field when I edit an object with sequelize

I use the following code to validate the uniqueness of the user's pseudo when I create the user object. The problem is that when I edit a user object I need to retrieve the current user.id. How can I do that?
pseudo: {
type: DataTypes.STRING(150),
allowNull: false,
validate: {
len: {args: [3, 150], msg: "Pseudo shall contains at least 3 characters"},
isUnique: function(value, next) {
User.find({
where: {pseudo: value},
attributes: ['id']
}).done(function(error, user) {
if (error)
return next(error);
if (user)
return next('Pseudo already in use!');
next();
});
}
}
I did it this way:
pseudo: {
type: DataTypes.STRING(150),
allowNull: false,
validate: {
len: {args: [3, 150], msg: "Pseudo shall contains at least 3 characters"},
isUnique: function(value, next) {
var id = this.getDataValue('id');
User.find({
where: {pseudo: value},
attributes: ['id']
}).done(function(error, user) {
if (error)
return next(error);
if (user && user.id !== id)
return next('Pseudo already in use!');
next();
});
}
}
},

Resources