UnhandledPromiseRejectionWarning: Error: Property 'password' doesn't exist. pg-promise - javascript

I am using pg-promise.
I am having an issue trying to insert the following Javascript array:
[ { email: 'test1#gmail.com', password: 'test2' },
{ email: 'tes2t#gmx.com', password: 'test'3 },
{ email: 'test4#gmail.com', password: 'test4' },
{ email: 'test4#yahoo.com.ar', password: 'test5' }]
Using the following:
async function insertDB(data){
const cs = new pgp.helpers.ColumnSet(['email', 'password'], {table: 'users'});
console.log(data)
const query = pgp.helpers.insert(data, cs);
db.none(query)
.then(data => {
logger.info(" Query success: ", data);
})
.catch(error => {
logger.warn(" Query error: ", error);
});
}
and I get
UnhandledPromiseRejectionWarning: Error: Property 'password' doesn't exist.
**data.password = undefined**
**data[0] = { email: 'test1#gmail.com', password: 'test2' }**
How can I insert this data into my postgresdb?

// should create columnsets only once:
const cs = new pgp.helpers.ColumnSet(['email', 'password'], {table: 'users'});
function insertDB(data) {
// wrapping it into a function is safer, for error-reporting via query methods:
const query = ()=> pgp.helpers.insert(data, cs);
db.none(query)
.then(data => {
// data = null always here, no point displaying it
logger.info('Query success:', data);
})
.catch(error => {
logger.warn('Query error:', error);
});
}
And your function doesn't need async in this case.
UnhandledPromiseRejectionWarning: Error: Property 'password' doesn't exist.
You are confusing the JavaScript compiler, declaring the function as async, and then throwing an error synchronously while generating the insert, due to missing property password.
And if you want to insert some records without password, with null, for example, define your columnset like this:
const cs = new pgp.helpers.ColumnSet([
'email',
{name: 'password', def: null}
], {table: 'users'});
Other than that, type ColumnSet is ultimately flexible, see the documentation for each contained Column.
EXTRA
And if you want to use server-side DEFAULT value for missing passwords, you can provide it, with the help of Custom Type Formatting:
const DEFAULT = {rawType: true, toPostgres: ()=> 'DEFAULT'};
And then your password column can be defined like this:
{name: 'password', def: DEFAULT}
And there are many alternatives, with properties init and mod supported by Column.

Related

Joi validation react .custom() validation in react

Hello I'm trying to add custom validation to my form using the Joi library.Basically i want to reach to an api and either return error message or not based on the data.
here is my Joi schema
const schema = Joi.object({
email: Joi.string()
.email({ tlds: { allow: false } })
.required(),
firstName: Joi.string().required(),
lastName: Joi.string().required(),
description: Joi.string().min(10).max(250).required().custom(isSad).message({'description.invalid':`the value provided in the description field is sad, please redact it`}),
});
the isSad function passed in the custom() argument
const isSad = (value,helpers) => {
fetch('api url',{
method: "POST",
headers: {
"apikey": "key"
},
body:value
}).then(data => {
return data.json()
}).then(data => {
if(data.Sad > 0.49) {
return helpers.error('description.invalid');
}
}).catch(error => {
console.log('logging the error in catch', error)
})
}
As far as I understand I'm sending 'description.invalid' to the .message() function in the schema where I should use it in the passed object to display a custom message, but for some reason I'm not getting the error message displayed. The field seems to be validated as valid which it shouldn't be in my case if the value received is > 0.49
EDIT: Tried using schema.validateAsync with .external() like so
const isSad = (value,helpers) => {
console.log('logging value',value)
console.log('logging helpers',helpers)
fetch('api',{
method: "POST",
headers: {
"apikey": "apikey"
},
body:value
}).then(data => {
return data.json()
}).then(data => {
if(data.Sad > 0.49) {
throw new Error('Ur description is sad please edit it')
}
}).catch(error => {
console.log('logging the error in catch', error)
})
}
and to the schema i just attach .external(isSad) like so
const schema = Joi.object({
email: Joi.string()
.email({ tlds: { allow: false } })
.required(),
firstName: Joi.string().required(),
lastName: Joi.string().required(),
description: Joi.string().min(10).max(250).required().external(isSad)
});
I also had to convert the code where I use the schema.validateAsync since it now returns data as HTTP response.BUT it still doesn't work I get no response whatsoever from the .external() and the description field is validated ( It's like the .external() is not there at all ).
Found an issue, it says that custom is only for synchronous functions, for async you need to use external.
EDIT1
If I understand it right, and please correct me if not, the problem is that error is not thrown, when it should.
In that case I have done the following. Changed the request and the data.
The console says: logging the error in catch Error: Ur description is sad please edit it. Which looks to me as the expected behavior.
const isSad = (value) => {
console.log("value: ", value);
fetch("https://api.coindesk.com/v1/bpi/currentprice.json", {
method: "GET"
})
.then((data) => data.json())
.then((data) => {
console.log("request data: ", data);
if (value.startsWith(data.chartName)) {
throw new Error("Ur description is sad please edit it");
}
})
.catch((error) => {
console.log("logging the error in catch", error);
});
};
const schema = Joi.object({
email: Joi.string()
.email({ tlds: { allow: false } })
.required(),
firstName: Joi.string().required(),
lastName: Joi.string().required(),
description: Joi.string().min(10).max(250).required().external(isSad)
});
schema.validateAsync({
email: "asf#adf.asdf",
firstName: "adfsdafsdf",
lastName: "asdfasdf",
description: "Bitcoin111"
});
I ended up using .validate() not .validateAsync() and made my own custom function check after Joi has already validated the form.

TypeError: Cannot use 'in' operator to search for 'userId'

So i was implementing a users model in my mvc and then i get a weird error saying
MongoClient constructor.
D:\node\node_modules\mongoose\lib\document.js:2022
if (path in this.$__.selected) {
^
TypeError: Cannot use 'in' operator to search for 'email' in saifkhan501721#gmail.com
at model.isSelected (D:\node\node_modules\←[4mmongoose←[24m\lib\document.js:2022:14)
at D:\node\node_modules\←[4mmongoose←[24m\lib\document.js:2195:14
at Array.filter (<anonymous>)
at _getPathsToValidate (D:\node\node_modules\←[4mmongoose←[24m\lib\document.js:2194:71)
at model.Document.$__validate (D:\node\node_modules\←[4mmongoose←[24m\lib\document.js:2365:23)
at D:\node\node_modules\←[4mkareem←[24m\index.js:369:33
←[90m at processTicksAndRejections (internal/process/task_queues.js:79:11)←[39m
i have no idea as to what is the reason behind the error is, is it a syntax error , logical error connection error or mispelling of a variable,well anyway here's my app.js
mongoose
.connect('mongodb+srv://turd_waffle:SaifKhan#cluster0.lltqs.mongodb.net/shop?retryWrites=true&w=majority')
.then((result) => {
User.findOne().then(user=>{
if(!user){
const user=new User({
name:'Saif',
email:'saifkhan501721#gmail.com',
cart:{
items:[]
}
})
user.save()
}
})//save() saves the documents(mostly used as a reference to generate a sample id in order to start a cluster working)
app.listen(3000)
})
.catch(err => {
console.log(err)
})
here's my user.js model to store users data in mongodb database
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
cart: {
items: [{
productId: {
type: Schema.Types.ObjectId,
ref: 'Product',
required: true
},
quantity: {
type: Number,
required: true
}
}]
},
})
userSchema.methods.addToCart = function(product) {
const cartProductIndex = this.cart.items.findIndex(cp => {
return cp.productId.toString() === product._id.toString();
})
let newQuantity = 1;
const updatedCartItems = [...this.cart.items];
if (cartProductIndex >= 0) {
newQuantity = this.cart.items[cartProductIndex].quantity + 1;
updatedCartItems[cartProductIndex].quantity = newQuantity
} else {
updatedCartItems.push({
productId: product._id,
quantity: newQuantity
})
}
const updatedCart = {
items: updatedCartItems
}
this.cart=updatedCart
return this.save()
}
module.exports = mongoose.model('User', userSchema)
can anyone please be kind enough to atleast tell me what the error above is trying to say i used app.use to create a user so i can store his id, email and name
app.use((req, res, next) => {
User.findById('5f788c080ba19e0f8c642202')
.then(user => {
req.user = new User(user.name, user.email, user.cart, user._id);
next();
})
.catch(err => console.log(err));
});
Strange issue. From the code you provided, the issue should not arise.
When I look at the code in mongoose, the only way that this could happen is if you would do something like:
new User("saifkhan501721#gmail.com")
Then this.$__.selected would be a string instead of an object (e.g. {email: "saifkhan501721#gmail.com"}) and path in this.$__.selected would cause your received type error.
Not knowing enough about your app, I would assume that there maybe is a bad User object created somewhere else / cached / or already in database. Maybe it would help to verify this using a clean database?
See the source code for reference. When I take a look at the code it seems like an oversight that it is not checked if this.$__.selected is a string, because in this case it does not fail early (e.g. Object.keys(this.$__.selected) will not cause an error).

Express mongodb find query results empty array

I'm trying to do an API call to my express server to fetch employees that work in the same place based on the location ID. However, the API call returns just an empty array while it does work in the command-line interface.
Employee model
module.exports = mongoose => {
var schema = mongoose.Schema(
{
first_name: String,
last_name: String,
address: {
housenumber: Number,
street: String,
city: String,
zip: Number,
country: String
},
phone: Number,
mobile: Number,
email: String,
enrollment_date: Date,
staff_id: Number,
location: { type : mongoose.Schema.ObjectId, ref : 'location' },
department: String,
function: String,
active: Boolean
},
{ timestamps: true }
);
schema.method("toJSON", function() {
const { __v, _id, ...object } = this.toObject();
object.id = _id;
return object;
});
const Employee = mongoose.model("employee", schema);
return Employee;
};
Employee routing for API
router.get("/location/:location_id", employees.findAllByLocation);
Employee controller handling above call
exports.findAllByLocation = (req, res) => {
Employee.find({ location: req.params.location_id })
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while retrieving Employees."
});
});
};
Dummy database data to test on
Postman API call result
However, trying to find the user with that location ID in the command line interface does work and gives the desired output.
[
So somehow it messes up and I can't seem to figure out why it's doing this. I did some research and found that it might have to do with the location being a reference as an ObjectId. So I tried wrapping the req.params.location_id to an ObjectId might fix it but that didn't work.
What's the best way to get this working?
In order to use promise chain, you have to return something and then returned value will be passed chained “then()” as data. In your example you should
return Employee.find({location:req.params.location_id})

REST API: PUT but no need all data in json

This is my controller to update put user data. The controller accepts up to 4 values. I would like to do so if I send only a name to this route, This will change only the name and the rest will remain unchanged. (it will not be empty). Is it possible to do this? Do I have to do it in redux-saga, i.e. if it is empty, give it up-to-date
// Update basic User's Data
exports.setUserdata = (req, res) => {
const id = req.params.userId;
User.update(
{
password: req.body.password,
name: req.body.name,
surname: req.body.surname,
email: req.body.email,
},
{ where: { id } },
)
.then(() => {
res.status(200).json({ success: true });
})
.catch(() => {
res.status(500).json({ error: 'Internal server error' });
});
};
Pass params you want to update and don't pass other keys.
If req.body contains only name key, you can just pick up those 4 keys from req.body.
const updateParams = _.pick(req.body, ['name', 'password', 'surname', 'email'])
User.update(updateParams, { where: { id } })
If req.body has other properties with value null or undefined, you can filter them after picking.
const updateParams = _.chain(req.body).pick(['name', 'password', 'surname', 'email']).filter().value()
User.update(updateParams, { where: { id } })
Of course it depends on the ORM you are using but I believe most ORM don't update attributes which are not passed at all.

Sequelize call structure

I'm working with sequelize and want to query my database using the following code:
models.user.findOne({ where: {email: req.body.email} }, (err, existingUser) => {
.... More code
}
But the code block wont run so i read the docs and the only example they give uses the following structure:
models.user.findOne({ where: {title: 'aProject'} }).then(project => {
.... Code
})
Did i do something wrong with the first example or am i just unable to use that structure?
Sequelize.js uses promises. When you use findOne, as an example, a promise is returned. So try the following:
models.user.findOne({
where: {
email: req.body.email
}).then(existingUser => {
//Do something
}).catch(err => {
//Do something with error
});
Sequelize>=1.7 query return a promise , to resolve it you need to use "then"
nb: you can use the model directly from the declaration instead of "models.user" like this:
const Userdb = sequelize.define('userdb', {
id : {
primaryKey: true,
autoIncrement:true,
allowNull:false,
type: Sequelize.INTEGER
},
email: {
type: Sequelize.STRING,
allowNull:false,
validation:{
isEmail:true
},
username: {
type: Sequelize.STRING,
allowNull:false,
min:6,
max:25,
notEmpty:true,
}
}
and to get a user by it's email you can do this :
Userdb.findOne({
where: {
email: req.body.email
}
}).then((result)=>{
if(results) // there is one user
{
// do something with resutls
}else{
// no user with that mail
}
})

Categories