I am building a small REST API with node, hapi and sequelize. When attempting to create a new user without the required data, I expect validation errors. Instead, I receive database errors.
The model:
'use strict';
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('User',
{
email: {
type: DataTypes.STRING,
validate: {notEmpty: true, isEmail: true}
},
password: {
type: DataTypes.STRING,
validate: {notEmpty: true, min: 6}
},
name: {
type: DataTypes.STRING,
validate: {notEmpty: true}
},
is_active: {
type: DataTypes.BOOLEAN
},
api_key: {
type: DataTypes.STRING,
validate: {notEmpty: true}
}
},
{
classMethods: {
associate: function(models) {
// associations can be defined here
User.hasMany(models.Keeper);
}
},
timestamps: true,
createdAt: 'created',
updatedAt: 'modified',
deletedAt: false
}
);
return User;
};
The code:
exports.users = {
/* ... */
create: function(req, reply) {
models.User.create(req.payload)
.then(function(err, user) {
/* ... */
})
.catch(function(err) {
console.log(err);
});
reply('test');
},
/* ... */
};
The error:
{ [SequelizeDatabaseError: ER_NO_DEFAULT_FOR_FIELD: Field 'password' doesn't have a default value]
name: 'SequelizeDatabaseError',
message: 'ER_NO_DEFAULT_FOR_FIELD: Field \'password\' doesn\'t have a default value',
parent:
{ [Error: ER_NO_DEFAULT_FOR_FIELD: Field 'password' doesn't have a default value]
code: 'ER_NO_DEFAULT_FOR_FIELD',
errno: 1364,
sqlState: 'HY000',
index: 0,
sql: 'INSERT INTO `Users` (`id`,`email`,`modified`,`created`) VALUES (DEFAULT,\'email#email.com\',\'2015-04-24 04:35:49\',\'2015-04-24 04:35:49\');' },
original:
{ [Error: ER_NO_DEFAULT_FOR_FIELD: Field 'password' doesn't have a default value]
code: 'ER_NO_DEFAULT_FOR_FIELD',
errno: 1364,
sqlState: 'HY000',
index: 0,
sql: 'INSERT INTO `Users` (`id`,`email`,`modified`,`created`) VALUES (DEFAULT,\'email#email.com\',\'2015-04-24 04:35:49\',\'2015-04-24 04:35:49\');' },
sql: 'INSERT INTO `Users` (`id`,`email`,`modified`,`created`) VALUES (DEFAULT,\'email#email.com\',\'2015-04-24 04:35:49\',\'2015-04-24 04:35:49\');' }
I'm expecting a validation error for not passing a password, instead I'm getting a SQL error. Halp!
Validation will only happen if a value is already set for the field. So if the password field is null, the validation won't run.
To fix this, set allowNull on the column:
password: {
type: DataTypes.STRING,
allowNull: false,
validate: {notEmpty: true, min: 6}
},
The .catch() function you are using seems to be used in 'Database synchronization' according to the documentation. Since you already have the err parameter and the callback in your 'then' function, place your console log statement there. Like so:
/* ... */
create: function(req, reply) {
models.User.create(req.payload)
.then(function(err, user) {
if (err){
console.log(err);
}
})
reply('test');
},
/* ... */
The 'then' function is already 'catching' the validation errors if any.
Related
i have created a controller that can delete my car recors, but i do not know how to DELETE MULTIPLE RECORDS with postgresql. I hope anybody can help me and give me some ideas in order to make this. Below it is my controller but it only delete one, now i wanna make delete multiple records please help me
// delete a car
export async function deleteCar(req, res) {
try {
const car = await Car.findByIdAndDelete(req.params.car_id);
if (!car) {
return res.status(404).send();
}
res.send(car);
} catch (error) {
return res.status(500).json({
success: false,
message: "Server error. Please try again.",
error: error.message,
});
}
}
Model
import Sequelize from 'sequelize';
export const Car = sequelize.define("car", {
car_id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement:true,
},
name: {
type: Sequelize.STRING,
unique: true,
required: [true, 'Car name required'],
},
color: {
type: Sequelize.STRING,
unique: true,
required: [true, 'Car color required'],
},
brand: {
type: Sequelize.STRING,
unique: true,
required: [true, 'Car brand required'],
},
}, { sequelize, freezeTableName: true}
)
export default Car;
Routes
router.delete("/cars/:carId", deleteCar);
If you want to delete multiple record in Sequelize You can use this code instead:
// delete a car
export async function deleteCar(req, res) {
try {
//multipleIds = req.params.car_ids;
//you should send array of ids you want to delete in req.params.car_ids
//and delete the next line
let multipleIds = [100, 101, 102, 103]; // You can delete this line later
const car = await Car.destroy({ where: { id: multipleIds }});
//this delete cars with id 100, 101, 102, 103
if (!car) {
return res.status(404).send();
}
res.send(car);
} catch (error) {
return res.status(500).json({
success: false,
message: "Server error. Please try again.",
error: error.message,
});
}
}
After you find out how it works You can fill multipleIds variable dynamically
i have this model with username and email set uniqe to false
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
minlength: 3,
maxlength: 20,
unique: false,
},
email: {
type: String,
required: true,
minlength: 5,
maxlength: 64,
lowercase: true,
unique: false,
},
mailboxLink: {
type: String,
required: true,
unique: true,
default: nanoid(),
},
createdat: { type: String, default: dateJakarta },
});
and 1 user in my mongodb database
{"_id":{"$oid":"622eec9de7f66d1d633061e7"},"username":"jhon","email":"email#gmail.com","mailboxLink":"mfdYTDK","createdat":"2022-03-14 14:19:01","__v":0}
but when i'm trying to register the same username and email
userRouter.post("/register", async (request, response) => {
const newUser = new userSchema(request.body); // body: {username, email}
await newUser.save((err, user) => {
if (err) {
console.log(err);
} else {
const token = newUser.generateAuthToken();
response.status(201).json({
token,
user,
message: "Register successfully",
});
}
});
});
i got this error from console.log(err);
MongoServerError: E11000 duplicate key error collection: PigeonProjekt.users index: email_1 dup key: { email: "email#gmail.com" }
index: 0,
code: 11000,
keyPattern: { email: 1 },
keyValue: { email: 'email#gmail.com' }
could someone help me solve this problem.
If you can, try dropping the database or the collection itself then test again. If you first set the email field to unique: true and then inserted the user that you have in the database, but later changed the unique value of email to false in your schema, this will not update the collection itself. In short, rules in the database for email unique: true still apply and you need to remove them.
I want to create an experience array in User model with new data, and the problem is that I don't get saved data in exec function so I can push new data in array on frontend. This is what I got so far.
router.post('/:username/experience', function(req, res) {
const username = req.params.username;
User.findOneAndUpdate(
username, {
$push: {
experience: req.body
}
}, {
safe: true,
upsert: true
})
.exec(function (err, data) {
console.log(data, "------>");
});
})
This is my schema for experience, which is called in User model like experience: [ExperienceSchema].
const ExperienceSchema = new Schema({
title: {
type: String,
required: true
},
company: {
type: String,
required: true
},
from: {
type: Date,
},
to: {
type: Date,
},
workingNow: {
type: Boolean,
default: false
},
description: {
type: String
}
}, {
usePushEach: true
})
Since findOneAndUpdate returns the original document (state before update) you need to add new: true to the options in order to get the updated document.
options:
{
safe: true,
upsert: true,
new: true
}
I'm trying to add a new user to the users' table that I have in PostgreSQL database. there is no problem when I use findOne() method but when I use create() nothing happens. here is some of my configuration:
model(users.js)
var bcrypt = require('bcryptjs');
module.exports = {
tableName: "users",
attributes: {
id: {
type: 'number',
unique: true,
autoIncrement: true,
},
first_name: {
type: 'string',
required: true
},
last_name: {
type: 'string',
required: true
},
email: {
type: 'string',
required: true,
unique: true,
isEmail: true
},
password: {
type: 'string',
required: true
},
},
}
usersController.js
registerUser: function (req, res) {
bcrypt.hash(req.body.password, 10, function(err, hash) {
if (err) return res.send('An error occured', 500);
console.log(hash);
// Save user to the database
Users.create({
first_name: req.body.first_name,
last_name: req.body.last_name,
email: req.body.email,
password: hash
}).exec(function(err, user){
if (err) return res.send('An error occured', 500);
console.log(user)
})
});
}
and i set my datastore.js file to:
default: {
adapter: require('sails-postgresql'),
url: 'postgresql://username:password#host:5432/db-name',
},
and finally, in my models.js in config folder, i set migrate:'safe' and i commented the schema and attributes.
module.exports.models = {
// schema: false,
migrate: 'safe',
attributes: {
// createdAt: { type: 'number', autoCreatedAt: true, },
// updatedAt: { type: 'number', autoUpdatedAt: true, },
// id: { type: 'number', autoIncrement: true, },
//--------------------------------------------------------------------------
// /\ Using MongoDB?
// || Replace `id` above with this instead:
//
// ```
// id: { type: 'string', columnName: '_id' },
// ```
//--------------------------------------------------------------------------
},
dataEncryptionKeys: {
default: '/ZBj9EC29Xb+mNULkmFn3NuYUK9wDLJdWQ4U2lNR7+w='
},
cascadeOnDestroy: true
};
every thing seems to be ok but i don't know what the problem is?
I suspect my issue is something silly, but I can't find the error. I'm using mongodb to persist user data. Every seems to work fine but when I look the database I have id: null in every user record.
I don't want that id: null, I already have _id field.
$sails --version
0.11.0
My userController:
module.exports = {
create: function(req, res) {
User.create(req.params.all(), function userCreated(err, user) {
if(err) res.json(401, err);
res.json(200, user);
})
}
}
My user model:
module.exports = {
attributes: {
name: {
type: 'string',
required: true
},
email: {
type: 'string',
email: true,
required: true,
unique: true
},
password: {
type: 'string',
minLength: 6,
maxLength: 15,
columnName: 'encrypted_password',
required: true
},
toJSON: function() {
var obj = this.toObject();
delete obj.password;
return obj;
}
},
beforeCreate: function(values, next) {
require('bcrypt').hash(values.password, 10, function passwordEncrypted(err, encryptedPassword) {
if(err) console.log(err);
values.password = encryptedPassword;
next();
});
}
};
When I create a user from url like http://localhost:1337/user/create?name=theUser&email=user#mail.com&password=123456&role=admin everythink seems to be fine but in my mongodb I see this: (id: null)
{
name: "theUser",
email: "user#mail.com",
role: "admin",
id: null,
createdAt: ISODate("2015-04-27T18:34:42.678Z"),
updatedAt: ISODate("2015-04-27T18:34:42.678Z"),
encrypted_password: "$2a$10$iNt/OR8XhjijqRjkpoNW/eR70HTSDgVJ2WmNppqab79rZt213aywm",
_id: ObjectId("553e81429255e51f419a8ffc")
}
I'd tried with autoPK: false but nothing happens.
Thanks in advance.
As stated in waterline docs,
By default an attribute named id will be automatically added to your
model which will contain an auto-incrementing number unique to each
record. This will be your model's primary key and will be indexed when
available. You can override this if you would like to define your own
primary key factory or attribute.
primaryKey
Will set the primary key of the record. This should be used when autoPK is set to false.
attributes: {
uuid: {
type: 'string',
primaryKey: true,
required: true
}
}