sequelize validation violation - validation

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!

Related

Array validation not working for PATCH in mongoose

This is my mongoose schema. but when i send PATCH req from client. the options (array) validation not work. but others field's validation work.
I search in online but dont get the problem. How can I slove it. Thank you.
const optionsValidator = function (options) {
console.log("Validating options...");
const MinLength = 2;
const MaxLength = 6;
const MCQCode = 0;
// checking options are required or not for the question;
if (this.questionType !== MCQCode) {
throw new Error("Options are required only for MCQ");
}
if (options.length < MinLength) {
throw new Error(`At least ${MinLength} options are required`);
}
if (options.length > MaxLength) {
throw new Error(`Maximum ${MaxLength} options can be created`);
}
// make options lower case before checking uniqueness of the options
const lowerOptions = options.map((option) => option.toLowerCase());
if (lowerOptions.length !== new Set(lowerOptions).size) {
throw new Error("Options are not unique");
}
// options are validated
return true;
};
const questionSchema = new Schema({
quesId: { type: String, required: [true, "Id_required"] },
title: { type: String, required: [true, "title_required"] },
questionType: {
type: Number,
default: 0,
},
options: {
type: [String],
default: undefined,
required: function () {
return this.questionType === 0 && !this.options;
},
validate: {
validator: optionsValidator,
message: (props) => props.reason.message,
},
},
});
const updatedData = { ...questionData };
let optionsData;
if (updatedData.options) {
data = await Question.findById(id);
optionsData = {
$push: { options: { $each: updatedData.options } },
};
delete updatedData.options;
}
exports.patchQuestion = async (id, questionData) => {
return (result = await Question.findOneAndUpdate(
{ _id: id },
{ ...optionsData, $set: updatedData },
{ new: true, runValidators: true }
));
}
The is the PATCH request send form client.
{ "options": ["A","A"] }

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

Why is my mongoose schema not validating?

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.

how to set many-to-many relation in graphql mutation?

I may be missing something, but can not find any information on Apollo docs about the way to set a many-to-many relation when creating a new entry.
When the relation is one-to-many it is as simple as setting the ID of the one-side of the relationship in the many-side object.
But let's pretend I am working with Books and Authors, how would I write a graphql query that creates a Book for one (or many?) Authors?
This should probably happen at the API layer on the GraphQL server (i.e. schema). For many-to-many relationships, you should have a "join" type to denote the BookAuthor many-to-many relationship, and then add an entry to that join type.
Essentially then you'll have a type called Book, another called Author, and finally one more called BookAuthor. And you can add a few mutations to be able to manage that relationship. Perhaps...
addToBookAuthorConnection
updateBookAuthorConnection
removeFromBookAuthorConnection
This is a conventional setup using a Relay-spec compliant API. You can read more about how to structure your API for many-to-many relationships here.
Then, you only need to call the addToBookAuthorConnection mutation from Apollo instead to be able to add to that many-to-many connection on your frontend.
Hope this helps!
If u r using apollo graph server with one to many relations then connectors.js, resolvers.js and schema.js files as given formats
schema.js
const typeDefinitions = `
type Author {
authorId: Int
firstName: String
lastName: String
posts: [Post]
}
type Post {
postId: Int
title: String
text: String
views: Int
author: Author
}
input postInput{
title: String
text: String
views: Int
}
type Query {
author(firstName: String, lastName: String): [Author]
posts(postId: Int, title: String, text: String, views: Int): [Post]
}
type Mutation {
createAuthor(firstName: String, lastName: String, posts:[postInput]): Author
updateAuthor(authorId: Int, firstName: String, lastName: String, posts:[postInput]): String
}
schema {
query: Query
mutation:Mutation
}
`;
export default [typeDefinitions];
resolvers.js
import { Author } from './connectors';
import { Post } from './connectors';
const resolvers = {
Query: {
author(_, args) {
return Author.findAll({ where: args });
},
posts(_, args) {
return Post.findAll({ where: args });
}
},
Mutation: {
createAuthor(_, args) {
console.log(args)
return Author.create(args, {
include: [{
model: Post,
}]
});
},
updateAuthor(_, args) {
var updateProfile = { title: "name here" };
console.log(args.authorId)
var filter = {
where: {
authorId: args.authorId
},
include: [
{ model: Post }
]
};
Author.findOne(filter).then(function (product) {
Author.update(args, { where: { authorId: args.authorId } }).then(function (result) {
product.posts[0].updateAttributes(args.posts[0]).then(function (result) {
//return result;
})
});
})
return "updated";
},
},
Author: {
posts(author) {
return author.getPosts();
},
},
Post: {
author(post) {
return post.getAuthor();
},
},
};
export default resolvers;
connectors.js
import rp from 'request-promise';
var Sequelize = require('sequelize');
var db = new Sequelize('test', 'postgres', 'postgres', {
host: '192.168.1.168',
dialect: 'postgres',
pool: {
max: 5,
min: 0,
idle: 10000
}
});
const AuthorModel = db.define('author', {
authorId: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, field: "author_id" },
firstName: { type: Sequelize.STRING, field: "first_name" },
lastName: { type: Sequelize.STRING, field: "last_name" },
},{
freezeTableName: false,
timestamps: false,
underscored: false,
tableName: "author"
});
const PostModel = db.define('post', {
postId: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, field: "post_id" },
text: { type: Sequelize.STRING },
title: { type: Sequelize.STRING },
views: { type: Sequelize.INTEGER },
},{
freezeTableName: false,
timestamps: false,
underscored: false,
tableName: "post"
});
AuthorModel.hasMany(PostModel, {
foreignKey: 'author_id'
});
PostModel.belongsTo(AuthorModel, {
foreignKey: 'author_id'
});
const Author = db.models.author;
const Post = db.models.post;
export { Author, Post };

createuser validation error on method with aldeed collection2

Folks,
I need help. I've been at this for sometime now and cant seem to figure it out. It should be simple. I'm using the aldeed collection2 and I cant seem to get past validation error being thrown by the create user account method. My schema is pretty standard, attached to meteor.users collection:
Schema={}
//SimpleSchema.debug = true;
Schema.UserProfile = new SimpleSchema({
picture: {
type: String,
optional: true
},
updatedAt: {
type: Date,
autoValue: function() {
if (this.isUpdate) {
return new Date();
}
},
denyInsert: true,
optional: true
},
roles: {
type: String,
optional: true
}
});
Schema.User = new SimpleSchema({
_id: {
type: String,
regEx: SimpleSchema.RegEx.Id,
optional: true,
denyUpdate: true
},
emails: {
type: [Object],
optional: true
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email,
label: ""
},
"emails.$.verified": {
type: Boolean,
optional: true
},
createdAt: {
optional: true,
type: Date,
autoValue: function() {
if (this.isInsert) {
return new Date;
} else if (this.isUpsert) {
return {$setOnInsert: new Date};
} else {
this.unset();
}
}
},
profile: {
type: Schema.UserProfile,
optional: true
},
services: {
type: Object,
optional: true,
blackbox: true
},
// Option 2: [String] type
// If you are sure you will never need to use role groups, then
// you can specify [String] as the type
roles: {
type: [String],
optional: true,
autoValue: function() {
if (this.isInsert) {
return ['user'];
} else if (this.isUpsert) {
return {$setOnInsert: ['user']};
} else {
this.unset();
}
}
},
password: {
type: String,
label: "Password",
min: 6
}
});
/* Attach schema to Meteor.users collection */
Meteor.users.attachSchema(Schema.User);
The method on my server for creating the user is like below:
Accounts.config({
forbidClientAccountCreation : true
});
//creates user on server
Meteor.methods({
createNewUserAccount: function(userdata) {
var userId;
check(userdata, Schema.User);
//console.log(userdata);
userId = Accounts.createUser({
email: userdata.emails[0].address,
password: userdata.password,
profile: userdata.profile
});
//console.log(userId);
return userId;
}
});
Accounts.onCreateUser(function(options, userdata) {
//user.profile = {};
// we wait for Meteor to create the user before sending an email
//need to address the exception when existing email is tried for signing up
Meteor.setTimeout(function () {
Accounts.sendVerificationEmail(userdata._id);
}, 2 * 1000);
return userdata;
});
for my client, I have the following signup.js
Template.signup.events({
'submit form': function(e){
// Prevent form from submitting.
e.preventDefault();
//console.log(doc);
user = {
'email.$.address': $('[name="emails.0.address"]').val(),
password: $('[name="password"]').val()
};
Meteor.call('createNewUserAccount', user, function(error) {
if (error) {
return alert(error.reason);
} else {
Router.go('/');
}
});
}
Does anyone know what I'm doing wrong? The schema does not validate the email address.I get the error:
email.0.address is not allowed by the schema
You're creating an object:
user = {
'email.$.address': $('[name="emails.0.address"]').val(),
password: $('[name="password"]').val()
};
The key is the literal string 'email.$.address'
So when you do:
userId = Accounts.createUser({
email: userdata.emails[0].address,
password: userdata.password,
profile: userdata.profile
});
The email key can't find userdata.emails[0] because there is no emails key. Instead, the key is 'email.$.address'. Also, the schema does not have a key called email.$.address. It has one called emails.$.address
Try:
Template.signup.events({
'submit form': function(e){
// Prevent form from submitting.
e.preventDefault();
//console.log(doc);
user = {
'emails.$.address': $('[name="emails.0.address"]').val(),
password: $('[name="password"]').val()
};
Meteor.call('createNewUserAccount', user, function(error) {
if (error) {
return alert(error.reason);
} else {
Router.go('/');
}
});
}
Then
//creates user on server
Meteor.methods({
createNewUserAccount: function(userdata) {
var userId;
check(userdata, Schema.User);
//console.log(userdata);
userId = Accounts.createUser({
email: userdata['emails.$.address'],
password: userdata.password,
profile: userdata.profile
});
//console.log(userId);
return userId;
}
});

Resources