How to check if data insert is not null with NodeJs? - javascript

I have a controller that when i insert data into the database it always inserted. Now i wanna check that if the data i create is null is must report an error.
Here is my code:
// create new car
export async function createCar (req, res) {
const car = new Car({
car_id: id,
name: req.body.name,
color: req.body.color,
brand: req.body.brand,
});
return car
.save()
.then((newCar) => {
return res.status(201).json({
success: true,
message: 'New car created successfully',
Car: newCar,
});
})
.catch((error) => {
console.log(error);
res.status(500).json({
success: false,
message: 'Server error. Please try again.',
error: error.message,
});
});
}
And i check on postman even i let Name is NULL is still inserted. Furthermore, how can i check that COLOR, BRAND if it's null must also report an error. Please help me.

Kato, please follow my boilerplate. I created it with the best practices, and it also provides high-end JOI request validation.
A boilerplate for building production-ready RESTful APIs using Node.js, ExpressJs, Mongoose and Joi (Request Validation)
Node-Express-Mongoose-Joi

For validate before insert
// Validate request
if (!req.body.name)
{
res.status(400).send
({
message: "Name can not be empty!"
});
return;
} else if (!req.body.color)
{
res.status(400).send
({
message: "Color can not be empty!"
});
return;
} else if (!req.body.brand)
{
res.status(400).send({
message: "Brand can not be empty!"
});
return;
}

Related

Postman says "Error: could not handle the request" when posting request to Firebase function

exports.createNotice = functions.https.onRequest((req, res) => {
if (req.method !== "POST") {
return res.status(400).json({ error: "Method not allowed" });
}
const newNotice = {
body: req.body.body,
userHandle: req.body.userHandle,
createdAt: admin.firestore().Timestamp.fromData(new Date()),
};
admin
.firestore()
.collection("notices")
.add(newNotice)
.then((doc) => {
res.json({ message: `document ${doc.id} created successfully` });
})
.catch((err) => {
res.status(500).json({ error: "something went wrong" });
console.error(err);
});
});
This is my function. When I deploy and try to post request on Postman like this:
{
"body": "New Notice",
"userHandle": "user"
}
It says Error: could not handle the request. I want it to update my database on Firebase. Creating a new notice collection. Can anyone Help me?
You have two mistakes in your code, when you create the Timestamp.
There is a typo: the method is fromDate() not fromData();
You need to call it as follows: admin.firestore.Timestamp.fromDate(new Date())
In addition note that you should do as follows for the first block in your code. No need to use return, see the doc.
if (req.method !== "POST") {
res.status(400).json({ error: "Method not allowed" });
}

Why doesn't findByIdAndUpdate update the document?

I have my problem with the following function
export function updateLine(req: Request, res: Response) {
if (!req.params.id || !req.body) return res.status(400).send({ message: 'Client has not sent params' });
Line.findByIdAndUpdate(req.params.id, req.body, async (err, lineUpdated) => {
console.log("req.params.id", req.params.id)
console.log("lineUpdated", lineUpdated)
console.log("req.body", req.body)
if (err) return res.status(409).send({ message: 'Internal error, probably error with params' });
if (!lineUpdated) return res.status(404).send({ message: 'Document not found' });
if (req.params.id !== lineUpdated.id) await Key.updateMany({ 'line': req.params.id }, { 'line': lineUpdated._id }).exec(err => {
if (err) return res.status(500).send({ message: 'Key Internal Server Error' });
});
return res.status(200).send({ data: lineUpdated });
});
}
What I'm trying to do is just update the document req.params.id with what contains req.body
The responses to the console.log () shown are as follows
req.params.id ACCSEH
lineUpdated {
_id: 'ACCSEH',
name: 'Accesorios (SEH)',
started: 2020-04-21T20:25:10.395Z,
__v: 0
}
req.body { id: 'ACCSEJ', name: 'Accesorios (SEH)' }
I am doing something wrong?
I already know that lineUpdated will return the function to me before the change. I mean when I do the query to see the change nothing has changed
enter image description here
Referring to the documentation:
The field name _id is reserved for use as a primary key; its value
must be unique in the collection, is immutable, and may be of any type
other than an array.
You can not change _id field once it is inserted into the collection
When finding and updating by ID you can't give it an ID in the object - you need to give it an object that has some combination of the other items (name, started, _v).

How to handle multiple errors in promise chain?

I'm using AWS Amplify for authentication and Stripe for the payment to create sign up page.
PROBLEM: I can't find a way to combine validations for Email and password section(from AWS Amplify) with payment info section(from Stripe).
My current code creates a Stripe token and call API(with valid payment info) then handles the error message from userSignupRequest which takes care of email and password fields.
How do I validate the email and password with payment info then create account in AWS and Stripe?
// Stripe payment process
this.props.stripe.createToken(
{
email: this.state.email
}
).then(result => {
// PROBLEM: Form server validation from Stripe
if(result.error){
return this.setState({ errors: { errorMsg: result.error.message }, isLoading: false })
}
// if success, create customer and subscription with result.token.id
const apiName = 'NameOfAPI';
const path = '/stripe/signup';
let myInit = {
body: {
"stripeToken": result.token.id,
"email": this.state.email
}
}
API.post(apiName , path, myInit).then(reponse => {
this.props.userSignupRequest(this.state.email, this.state.password, reponse).then(user => {
this.setState({
confirmAccount: true,
isLoading: false,
userEmail: this.state.email,
errors: {}
})
this.props.history.push('/signup#confirm-account')
}).catch(err => {
// PROBLEM: Form server validation
this.setState({ errors: { errorMsg: err.message }, isLoading: false })
})
}).catch(err => {
console.log(err)
this.setState({ errors: { errorMsg: err }, isLoading: false })
});
})
It seems like we have a very similar stack. My solution was to handle everything server-side. You'll need to give your lambda functions the appropriate IAM permissions to access Cognito. The code below is a little long. I use async/await, which really cleans things up for me. You'll need to use Lambda with node 8 to use async/await though.
I validate that everything matches the right format client-side (i.e. emails are really emails, passwords are the right length). I realized the only error that could come up is an "existing user" error from Cognito. The idea is: test if the user exists before you attempt to sign the person up with Stripe. There's no way to "test" if the user's credit card is valid with Stripe. It's all or nothing. If it's valid it will go through, if not, you'll get an error. If it goes through, you can then sign up the user with Cognito, knowing you should not get an error (you've validated the email and password client-side and, you know the use doesn't already exist).
For reference, here's the aws-sdk for cognito.
const AWS = require('aws-sdk');
const cognito = new AWS.CognitoIdentityServiceProvider({
region: "region",
userPoolId: "cognito_user_pool_id",
});
module.exports.signUpUser = (payload) => {
const usernamePayload = {
UserPoolId: "cognito_user_pool_id",
Username: payload.email,
};
// I use emails for usernames.
new Promise((resolve, reject) => {
cognito.adminGetUser(usernamePayload, (error, response) => {
if (error && error.code === 'UserNotFoundException') {
resolve(false);
} else if (error) {
reject(error);
} else {
// if adminGetUser doesn't fail, it means the username exists
resolve(true);
}
});
}).then((usernameExists) => {
if (!usernameExists) {
// run stripe API stuff
// always run before sign up below to catch stripe errors
// and return those errors to client
// before you sign up the user to Cognito
// since you've already verified the user does not exist
// it would be rare for an error to come up here
// as long as you validate passwords and emails client-side
const signUpPayload = {
ClientId: "cognito_user_pool_client_id",
Username: payload.email,
Password: payload.password,
UserAttributes: [
{
Name: 'email',
Value: payload.email,
},
],
};
new Promise((resolve, reject) => {
cognito.signUp(signUpPayload, (error, response) => {
if (error) {
reject(error);
} else {
resolve(response);
}
});
}).catch((error) => {
// you should hopefully encounter no errors here
// once you get everything setup correctly
console.log(error);
})
} else {
// means username already exists, send error to client
// saying username exists
}
}).catch((error) => {
// may want to dispatch this error to client
console.log(error);
});
return null;
};

Why getting error when updating MongoDb?

I am building backend with MEAN stack, but when I try to update document in the db i am getting an error:
topUp = function(name, amount, callback) {
User.updateOne(
{ "name" : name },
{ $set: { "wallet": amount } },
function(err, results) {
console.log(results);
callback();
});
};
TypeError: User.updateOne is not a function
But e.g. findOne() works fine:
User.findOne({
name: decoded.name
}, function(err, user) {
if (err) throw err;
i
f (!user) {
return res.status(403).send({success: false, msg: 'Authentication failed. User not found.'});
} else {
//res.json({success: true, info: {wallet: user.wallet, userPic: user.userPic}});
topUp(decoded.name, amount, function() {
User.close();
});
}
});
"User" is a Mongo model file.
I think it's not defined in the database driver that you might be using. I think you are using Mongoose and updateOne() is not available there. You cannot use all native mongodb functions with all drivers
There is an en existing enhancement request for this https://github.com/Automattic/mongoose/issues/3997 , but maybe the findByIdAndUpdate() method could be a close alternative.

Existing property return undefined

I started the implementation of a RESTful API usin node.js, express, and mongodb. Everything went well until now, I've a route to authenticate an user as follow:
apiRoutes.post('/authenticate', function(req, res) {
User.findOne({
nickname: req.body.nickname
}, function(err, user) {
if (err) throw err;
if (!user) {
res.json({
success: false,
message: 'Authentication failed. User not found.'
});
} else if (user) {
console.log(user);
console.log(user.nickname);
console.log(user.email);
console.log(user.password);
console.log(user.sexe);
if (user.password != req.body.password) {
res.json({
success: false,
message: 'Authentication failed. Wrong password.'
});
} else {
var token = jwt.sign(user, app.get('salt'), {
expiresInMinutes: 1440 // expires in 24 hours
});
res.json({
success: true,
token: token
});
}
}
});
});
The user is retrieved, and loged in the console as follow:
{ sexe: 'H',
email: 'MrPanda#gmail.com',
password: 'bambou',
nickname: 'MrPanda',
_id: 56cb703e7aef3f83c7dac0a7 }
which is perfect, but then, the three following consol.log return the three following lines:
MrPanda
MrPanda#gmail.com
undefined
H
I see absolutely no reason why the password is undefined at this point, I tried to change the attribute name to 'mdp', same issue... Any ideas ? Thanks
If you are using mongoose it does not return a plain JSON object. It is actually a special mongoose object and may not function how you expect.
You have two options:
Convert the mongoose object to a JSON object.
Add {lean: true} to the Users options parameter.
OR JSON.stringify(user)
OR user.toJSON()
Use the proper get() and set() methods (which you should be doing anyways).
user.get('password')
user.get('email')
user.get('name')
Try that and let me know if it doesn't work still.

Categories

Resources