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.
Related
bcryptjs version: "bcryptjs": "^2.4.3"
mongoose version: "mongoose": "^6.0.12"
I am trying to encrypt user password on user creation or password update. When I create a single user with User.create() everything works as intended (password is encrypted). When I use User.insertMany() the data is inserted successfully but the password is not encrypted. This is my schema:
const userSchema = mongoose.Schema(
{
name: {
type: String,
required: true
},
surname: {
type: String,
required: true
},
voterId: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true,
unique: true,
},
votedFor: [
{
type: mongoose.Schema.ObjectId,
ref: 'Election'
}
],
finishedVoting: {
type: Boolean,
required: true,
default: false
},
isAdmin: {
type: Boolean,
required: true,
default: false,
},
},
{
timestamps: true,
}
)
userSchema.pre('save', async function(next) {
// Only run this function if password was actually modified
if (!this.isModified('password')) return next();
// Hash the password with salt 10
this.password = await bcrypt.hash(this.password, 10);
next();
});
This is some sample data that I am trying to insert:
const voters = [
{
name: "Sherali",
surname: "Samandarov",
voterId: "194199",
password: "FA654644", //will be encrypted
isAdmin: false,
finishedVoting: false
// votedFor: [Object], //
},
{
name: "Sherali",
surname: "Samandarov",
voterId: "184183",
password: "MB454644", //will be encrypted
isAdmin: false,
finishedVoting: false
// votedFor: [Object], //
},
{
name: "Sherali",
surname: "Samandarov",
voterId: "194324",
password: "FA651684", //will be encrypted
isAdmin: false,
finishedVoting: false
// votedFor: [Object], //
}
]
I am guessing that userSchema.pre('save', ...) does not trigger on insertMany() for some reason
Solved.
I was able to solve the problem by following #victorkt's answer:
Use pre('validate') instead of pre('save') to set the value for the
required field. Mongoose validates documents before saving, therefore
your save middleware won't be called if there are validation errors.
Switching the middleware from save to validate will make your function
set the password field before it is validated.
So,
userSchema.pre('validate', async function(next) {
// Only run this function if password was actually modified
if (!this.isModified('password')) return next();
// Hash the password with salt 10
this.password = await bcrypt.hash(this.password, 10);
next();
});
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 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.
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
}
}
I have a schema setup like this:
var UserSchema = new Schema({
id: {type: String, required: true, unique: true, index: true, default: mongoose.Types.ObjectId},
name: { type: String, required: true },
email: { type: String, required: true, unique: true, index: true },
mobile: { type: String, unique: true, sparse: true },
password: { type: String, required: true }
});
Seems to work great except the email field is letting in duplicates, despite have unique:true set. I do the following:
User.create({
name: req.body.name,
email: req.body.email,
mobile: req.body.mobile,
password: password
}, function(err, user) {
if (err) return res.send({ invalid : true });
});
If req.body.email is a value that's already in the database, the query above should return err. But it doesn't, it creates the new user perfectly fine, resulting in duplicate emails in the database.
Why is this happening?
mongo and hence mongoose will assign an automatic id fields to your document. usually that is "_id".
Try removing the "id" from your schema to fix your issue.