How to make custom response using globalPipse in nestjs - javascript

I wrote an api in user.controller using dto of 'class-validator'.
#Post('/')
public async createUser(
#Res() res,
#Body() createUserDto: CreateUserDto,
) {
... do something
}
And I put useGlobalPipes in main.ts.
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
transform: true,
forbidNonWhitelisted: true,
transformOptions: {
enableImplicitConversion: true,
},
}),
);
When I request to the api, I get a response below.
{
"statusCode": 400,
"message": [
"userName should not be empty",
"userName must be a string",
],
"error": "Bad Request"
}
So far, it works without problem with nestjs.
But I want to get a custom response like this.
{
"code": 400,
"errorReason": [
"userName should not be empty",
"userName must be a string",
],
"msg": "Bad Request",
"success": false
}
Can I get this custom response maintaining the code above?
If it can do it, could you give me some advice or some code for this?
Thank you for reading my question.

In Nest, pipes are good for validation, transforming an incoming object, maybe talking to a database in some circumstances, and throwing errors if anything goes wrong. If you want to change the response, after an error is thrown, you'll need to look into using an ExceptionFilter Where you can do something like
#Catch()
export class CatchAllFilter implements ExceptionFilter {
catch(exception: Error, host: ArgumentHost) {
res
.status((exception.getStatus && exception.getStatus()) || 500)
.send({
(exception.getResponse && ...exception.getResponse()) || ...{ message: exception.message },
success: false
});
}
}
You're bound to get type errors with the above code, but it should lead you on the right track

Related

How do I valuate using an if else statement and express validator in my node app

I am trying to using express to run validation on some following parameters with the help of postman. Right now, postman is not giving me any response as it relate to my code, so I don't even know where the error is coming from. Kindly help me out. The route should accept JSON data containing a rule and data field to validate the rule against.
The following json file should return a success or 200 status code when the value for condition is greater than or equal to condition_value, I should get a 400 status response or failed when condition is less than or equal to condition_value judging by the parameter below when I input the data type in postman.
{
"rule": {
"field": "missions",
"condition": "50",
"condition_value": 30
},
"data": {
"name": "James Holden",
"crew": "Rocinante",
"age": 34,
"position": "Captain",
"missions": 45
}
}
Here is my validation code with the logic to check if condition is less than or greater than and equal to condition_value to either a 400 response or 200 response.
router.post(
"/validate_rule",
(req, res) => {
const SecondSchema = req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
throw new HttpError("Please kindly fill empty field", 400);
} else if (condition !== condition_value) {
res.status(400).json({
message:
"Error, Condition must be greater than or equal to condition_value",
});
} else if (condition <= condition_value) {
res.status(400).json({
message:
"Error, Condition must be greater than or equal to condition_values",
});
}
return res.status(200).json({
message: "Success",
});
}
);
I just realised I did req and response twice, first is before the validation code and then after again. After correcting this, I am still trying to figure out the logic or if else statement.

Meteor js: get full validation message with validatedmethod simpleschema

I am new to Meteor js and I am trying to create a form following the official guide http://guide.meteor.com/methods.html#method-form. It suggests to use mdg:validated-method package and aldeed:simple-schema for validation which are based on mdg:validation-error to return validation error messages to the client. The guide suggests this code then to handle validation
Invoices.methods.insert.call(data, (err, res) => {
if (err) {
if (err.error === 'validation-error') {
// Initialize error object
const errors = {
email: [],
description: [],
amount: []
};
// Go through validation errors returned from Method
err.details.forEach((fieldError) => {
// XXX i18n
errors[fieldError.name].push(fieldError.type);
});
// Update ReactiveDict, errors will show up in the UI
instance.errors.set(errors);
}
}
});
but the problem is that only fieldError.type, fieldError.name and first human readable message from simple-schema are available in err.error. I use translated messages and field labels in simple-schema to get nice understandable validation error messages. So getting just object property name with "required" is unacceptable, especially in the case when message includes min/max constraints for example. I could not find any way to get simple-schema's validation context to retrieve the full list of human readable errors.
So my question is can I get full error messages on the client and how?
Or maybe there are better ways to achieve what I am trying to do?
Thanks in advance
Hi! Recently I have encountered with the same problem.
So I just create pull request with some code enhancement to solve this issue. Now when you submit form and call validated-method from client side like following:
yourMethodName.call(data, (err) => {
if (err.error === 'validation-error') {
console.dir(err, 'error ')
}
});
You will see error object in the console:
{
"errorType": "ClientError",
"name": "ClientError",
"details": [
{
"name": "firstName",
"type": "required",
"message": "First name is required"
},
{
"name": "lastName",
"type": "required",
"message": "Last name is required"
},
{
"name": "phone",
"type": "required",
"message": "Phone is required"
},
{
"name": "email",
"type": "required",
"message": "Email is required"
}
],
"error": "validation-error"
}
So I just copy that from my console output.
In my case, the method is as follows:
export const yourMethodName = new ValidatedMethod({
name: 'my.awesome.method',
validate: new SimpleSchema({
firstName: { type: String },
lastName: { type: String },
phone: { type: Number },
email: { type: String, regEx: SimpleSchema.RegEx.Email }
}).validator({ clean: true }),
run(doc) {
YourCollection.insert(doc);
}
});
If my pull request will be accepted, you can easy use node-simple-schema (it is the next version of meteor-simple-schema).
If it won't you can use my fork.
Hope this helps!
EDIT: Now this feature available in official node-simple-schema package.

gapi.client.gmail.users.labels.create gives invalidArgument error

I am working on creating labels using JavaScript Gmail API.
function createLabel(userId, newLabelName, callback) {
var request = gapi.client.gmail.users.labels.create({
'userId': userId,
'label': {'name': newLabelName}
});
request.execute(callback);}
This is the code of Developer API Example
I am able to authenticate and even I'll get the label list but while creating the label I am getting the below error.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalidArgument",
"message": "Invalid request"
}
],
"code": 400,
"message": "Invalid request"
}
}
But when I am using the Try It example It's working but only difference is it's do the POST request with key={Your auth key} which the example provided won't attach that part to URL.
The data you send should be in the resource-parameter, and labelListVisibility and messageListVisibility are also mandatory fields:
function createLabel(userId, newLabelName, callback) {
gapi.client.gmail.users.labels.create({
userId: userId,
resource: {
name: newLabelName,
labelListVisibility: 'labelShow',
messageListVisibility: 'show'
}
}).execute(callback);
}

Production-quality error handling in node.js

I'm working on request error handling in a node.js server application. I have defined a callback function handling these errors:
app.use(function errorHandler(err, req, res, next) {
res.send(err, {status: err, message: 'error'});
}
);
which is fine for me as a developer, as it prints a stack trace like this:
{
"status": {
"stack": "Error\\\n at MongooseError.ValidationError (/home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/error/validation.js:22:16)\\\n at model.Document.invalidate (/home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/document.js:1216:32)\\\n at /home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/document.js:1090:18\\\n at validate (/home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/schematype.js:653:7)\\\n at /home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/schematype.js:681:9\\\n at Array.forEach (native)\\\n at SchemaString.SchemaType.doValidate (/home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/schematype.js:658:19)\\\n at /home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/document.js:1088:11\\\n at process._tickCallback (node.js:415:13)",
"message": "User validation failed",
"name": "ValidationError",
"errors": {
"email": {
"properties": {
"regexp": {},
"type": "regexp",
"message": "Path `{PATH}` is invalid ({VALUE}).",
"path": "email",
"value": "test#exa#mple.com"
},
"stack": "Error\\\n at MongooseError.ValidatorError (/home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/error/validator.js:25:16)\\\n at validate (/home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/schematype.js:652:13)\\\n at /home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/schematype.js:681:9\\\n at Array.forEach (native)\\\n at SchemaString.SchemaType.doValidate (/home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/schematype.js:658:19)\\\n at /home/osboxes/skipodium_rest_server/node_modules/mongoose/lib/document.js:1088:11\\\n at process._tickCallback (node.js:415:13)",
"message": "Path `email` is invalid (test#exa#mple.com).",
"name": "ValidatorError",
"kind": "regexp",
"path": "email",
"value": "test#exa#mple.com"
}
}
},
"message": "error"
}
However, I'd like to display it in a neat, user-friendly format for the production version, without leaking the entire stack trace. Now I could specify the error status and message in every request handling function, but there is still specific information, like above, that the entered email is invalid, and I don't feel like typing it by hand for every single field that is checked by validator. Is there any existing boilerplate that will do the job for me?
Mongoose validation errors are a pain to handle. My general approach is to only take the first error (let the user deal with one at a time) and send the path and message since the rest won't really contribute much additional meaning to a non-developer.
first = err.errors[Object.keys(err.errors)[0]]
res.send({
path: first.path,
message: first.message
});
I'd also recommend having a custom API-style error format that you stick with for all of your errors- it will make maintainability much easier.
I have a set of pre-defined error templates that I rely on- here's one.
// If the client missed a required parameter
exports.missingParam = function (res, domain, param) {
res.status(400).send({
status: "failed",
errors: [
{
status: "400",
domain: domain,
reason: "required",
message: "Required parameter: "+param,
locationType: "parameter",
location: param
}
]
});
}

login page not working (javascript, firebase)

HELP!
I'm not sure what's going on, but my login page isn't working. It simply reloads even though I'm entering valid user/password.
I think the problem is it's getting stuck on issues with my data-structure, security-rules, and app.js, but I'm at a loss.
I was provided a sinatra/ruby simple api to work with users & groups (just a small project).
here's the site:
https://starter-vicks9985.firebaseapp.com/index.html
here's the code:
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
{
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}
), console.log("success");
{
"rules": {
".read": true,
"users": {
"$user": {
//can add a message if authenticated
".write": "auth.uid === $user"
}
},
"rooms": {
"$room": {
"users": {
// can write to the users list only if ADMINISTRATOR
"$user": {
"write":"newData.parent().child(auth.uid).val() === 99"
}
}
}
},
"messages": {
"$room": {
"$message": {
//can add a message if they are a MEMBER (if there was message/chat capability)
".write": "(!data.exists() && newData.exists() && root.child('rooms/' + $room + '/users/' + auth.uid).val() >= 10)"
}
}
}
}
}
$(document).ready(function() {
/**
*Set initial firebase ref. Use set to write in first admin user.
*/
var ref = new Firebase("https://starter-vicks9985.firebaseio.com/");
ref.set({
"name": "Admin",
"email": "admin#example.com",
"password": "secret",
"admin": true
});
/** Get email address from loginform, format email, get password
* Firebase keys cannot have a period (.) in them, so this converts the emails to valid keys
*/
var emailAddress = function emailToKey(emailAddress){
return btoa(emailAddress);
};
var password = document.getElementById('password');
/**
* Authorize user with email and password, passing in values from form.
*/
ref.authWithPassword({
email : emailAddress,
password : password,
}, function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
return authData;
}
});
/**
* If user is logged in (valid), redirect to user profile
*/
ref.onAuth(function(authData) {
window.open="https://starter-vicks9985.firebaseio.com/userprofile/userprofile.html";
})
});
Like #Kato said, this is a code dump so please consider creating an mcve. Although, first check out my comments below.
The Code You Posted
After glancing at your code, I see some errors that I will point out:
1. Your jQuery post syntax is incorrect, and wouldn't work even if it was correct.
Most importantly, you are making a post request to a Ruby file. Firebase Hosting is not a server, it is hosting for static files.
See this answer by Frank. He says:
Firebase hosting is a product to serve so-called static application, which consist only of files that the client interprets. Firebase's servers will not interpret any code that you upload. So Firebase hosting is not suited to host your Ruby-on-Rails application.
To quote Firebase hosting's documentation:
We deliver all your static content (html, js, images, etc)
That being said, take a look at the jQuery documentation for $.post().
See my comments on your code:
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
// ^ What is this '/'?
{
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}
), console.log("success");
// ^ You are closing the function call, 'console.log' falls outside of it.
What it should look like:
$.post("https://starter-vicks9985.firebaseapp.com/main.rb", {
"name": "admin",
"email": "admin#example.com",
"password": "secret",
"admin": true,
"role-value": 99,
}, function() {
console.log("success");
});
2. What's even going on with the login functions?
Assuming you fix Uncaught SyntaxError: Unexpected token { in data-structure.js:14...
If you take a look at the console, you will see Uncaught Error: Firebase.authWithPassword failed: First argument must contain the key "email" with type "string".
That is because you are passing a function, emailAddress to .authWithPassword().
You declare emailAddress() like so:
var emailAddress = function emailToKey(emailAddress){
return btoa(emailAddress);
};
So the email parameter in the following is being passed emailAddress(), not a string that is an email address.
ref.authWithPassword({
email : emailAddress,
password : password,
}, function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
return authData;
}
});
Most importantly, all of these login functions are being called immediately after the page loads. Nothing in your code (app.js) waits for, and responds to, the submission of the form.
The Code on Your Website
I also went on your page, looked at your source code, and found some more issues.
1. Error in form HTML in index.html
<section class="loginform cf">
<form id= "login" form name="login" form type= "submit" accept-charset="utf-8">
<!-- extra^space ^duplicate "form"^ ^again, space -->
...
</form>
</section>
2. Syntax Errors in data-structures.js
Again, you have the same errors here as I described above ('/' and closing parentheses), but the object that you're passing the post is incorrectly formatted
$.post/("https://starter-vicks9985.firebaseapp.com/main.rb",
{
"users" //missing ':' after users
//the following objects do not have keys - should be {"users":{"someUserKey1":{...},"someUserKey2":{...}}} etc.
{
"name": "admin",
"email": "...",
"password": "...",
"admin": true,
"role-value": 99,
},
{
"name": "aaa",
...
},
{
"name": "bbb",
...
}
},
), console.log("success");
And the same things apply for the post call for "groups".
I hope that provides some clarity.
I would suggest reading over other answers here on StackOverflow, like:
jQuery AJAX submit form
jQuery form submit
And search for more answers like:
https://stackoverflow.com/search?q=jquery+form+submit
In conclusion, I'd suggest doing some more research and reading documentation :)

Categories

Resources