How to do conditional check express-validator 5.3.0? - javascript

export function valUPM() {
return (req: Request, _res: Response, next: NextFunction) => {
req
.checkBody(
"paymentType",
`paymentType: ${messages.getFromSession(req, "mustNotBeEmpty")}`
)
.notEmpty();
if (req.body.paymentType === "USP") {
req
.checkBody(
"storeId",
`storeId: ${messages.getFromSession(req, "mustNotBeEmpty")}`
)
.notEmpty();
} else if (req.body.paymentType === "CC") {
if (req.body.register) {
req
.checkBody(
"register",
`register: ${messages.getFromSession(req, "mustBeBoolean")}`
)
.isBoolean();
} else {
req
.checkBody(
"register",
`register: ${messages.getFromSession(req, "mustNotBeEmpty")}`
)
.notEmpty();
}
}
req.getValidationResult().then(errs => {
if (errs.isEmpty()) {
return next();
}
const error = new BFFError(
400,
"BadRequest",
1,
errs.array().map(error => {
return { [error.param]: error.msg };
})
);
return next(Error(JSON.stringify(error)));
});
};
}
After the change to API how to implement this type of logic in express validators
Calling req.checkBody or the required validation function inside an if loop did the trick like shown above but after change in API how can this be implemented
I tried a work around of checking the paymentTYpe as a custom validator and implementing the checks and throwing the message inside the custom validator but the keys change .
Using the current APi what is the proper way to do this as this will be useful for all the people who would want to update from 3.0.0s to latest express-validator API

Conditional validation support is not present yet in express-validator v5.x.x, but it is coming soon.
Here's the Pull Request, in case you would like to give your feedback on the API: https://github.com/express-validator/express-validator/pull/658
However, please note that the legacy API (the one that uses req.checkBody(), req.getValidationResult(), etc, hasn't been removed from express-validator yet.
You can keep using it in v5.x.x just as you would in v3.x.x. It's just not recommended to do so, as it's deprecated and might be removed when v6 is due (not yet!).
All docs are here, side by side with the newer APIs docs.
Disclaimer: I'm an express-validator maintainer.

Related

React Admin parseResponse doesn't trigger when query returns error

I'm using React Admin and ra-data-graphQl, when I update something in my UserEdit component all works perfect, BUT, when I need to handle the error message from the API, I don't know where catch it.
This is my Update query:
case 'UPDATE': {
const updateParams = { ...params };
return {
query: gql`mutation updateUser($id: ID!, $data: UpdateUser!) {
data: updateUser(id: $id,input:$data) {
${buildFieldsGraphQL(updateFields)}
}
}`,
variables: {
...updateParams,
id: updateParams.data.uuid,
data: {
...updateParams.data,
},
},
parseResponse: (response) => {
console.log('tr response: ', response);
},
};
}
When the API returns an error, it never reach the console.log.
I was searching a list with options here (https://github.com/marmelab/react-admin/tree/master/packages/ra-data-graphql#options) searching something like "parseError", but I did not find nothing similar.
I need to catch the error and show a message in the UserEdit form.
Reading the link that I share in this post, it say this:
but must return an object matching the options of the ApolloClient query method with an additional parseResponse function.
I understand that I should go to the link in the word "query" and check if there is something like "parserError", but the link is broken:
https://www.apollographql.com/docs/react/reference/index.html#ApolloClient.query
Any help?
Ok, its easier. By adding the onFailure function I can handle the error.

Implementing a custom ember-simple-auth Authenticator

Firstly, I am not a seasoned JS Developer, so please excuse obvious mistakes that I could have made.
I am trying to implement a custom Authenticator for authenticating a user with Keycloak using the OAuth2 Password Grant which requires the client_id be passed as part of the request body.
import OAuth2PasswordGrant from 'ember-simple-auth/authenticators/oauth2-password-grant';
export default OAuth2PasswordGrant.extend({
serverTokenEndpoint: 'http://localhost:8080/something/token',
makeRequest(url, data, headers = {}) {
data.client_id = 'my-app';
return this._super(url, data, headers);
}
});
I have a controller that uses this Authenticator by calling this action:
actions: {
authenticate() {
let {username, password} = this.getProperties('username', 'password');
this.get('session').authenticate('authenticator:oauth2', username, password).then(() => {
// Do something
}).catch((response) => {
// Show error
});
}
}
This causes Firefox to hang and gives me an unresponsive script message.
If I remove the return from the makeRequest() method, I can see from the browser debugger that the call to Keycloak actually returns correctly with the object that contains my token etc. However ember inspector shows some errors related to unresolved promises. But I guess that's because I'm no longer returning the promise.
What am I doing wrong here?
How can I fix the unresponsive script issue?
Is there another way for me to achieve my goal?
Edit 1: This is when I remove the return
Here is the actual object that is returned:
{
"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJTRUNSd09fMlZWdGhxUVBUWnFxNHlqX0tKekxnOElSTjBrQkx5UTlacklrIn0.eyJqdGkiOiI1NDgzZDdkMi0zMDdhLTQyZjItYWUxZC0xYTZjMTZjOTM2ZjAiLCJleHAiOjE1MDgzMzE5MjAsIm5iZiI6MCwiaWF0IjoxNTA4MzMxNjIwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvc2Z4LWl0cmFuc2Zlci13ZWItYWdlbnQiLCJhdWQiOiJhZ2VudC13ZWItYXBwIiwic3ViIjoiMzZiMWY4OWMtNGYwMC00OTU1LWE0YzMtZWQ0NzZmZDU2OGM3IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiYWdlbnQtd2ViLWFwcCIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6IjQwODMxZWFhLTRmMmEtNDk2ZS05NDVkLTdiZWIxN2U0NmU0NCIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDo0MjAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJ1bWFfYXV0aG9yaXphdGlvbiIsImJhY2stb2ZmaWNlLWFnZW50Il19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwibmFtZSI6IlVtYXIgS2hvbHZhZGlhIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidW1hciIsImdpdmVuX25hbWUiOiJVbWFyIiwiZmFtaWx5X25hbWUiOiJLaG9sdmFkaWEiLCJlbWFpbCI6InVtYXJAYWlydmFudGFnZS5jby56YSJ9.eUJFklRiRjQPOC1rQLcqrljsSWmGXCpNNKqLJGAcvbnbwx8X0T1iqrmpFdyMN3EKRrIfTZyYRfcTEbpcBEjZcZtgDY9V0Ntvt4pvpUx_8Ey6I8xZQolHVwferjM30puLqG8MImADUimNrj3ghbJbAaCOJktIKgLnTIhDbkNb-8lzgbyq-rEP6lYAWjQ2OuOZnc8NQQ9CJiR9M1SB79SEmY2iQW9E_J8xo8BgZQ0GUBrhaWPo-Kn4RnlEcRNzVnlLHQKi5FM7Zpov3SMQUbAeLat38V41y09ap2XVCy7MfL_7-TrSlMx0TLrhWqPgA5aaXbmsT9_vKOoXNZoJ9bWCuA",
"expires_in":300,
"refresh_expires_in":1800,
"refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJTRUNSd09fMlZWdGhxUVBUWnFxNHlqX0tKekxnOElSTjBrQkx5UTlacklrIn0.eyJqdGkiOiIxNTUwNDIyZS02OThkLTQ5N2ItODZmYi00YmY5MTFlMTcwYzYiLCJleHAiOjE1MDgzMzM0MjAsIm5iZiI6MCwiaWF0IjoxNTA4MzMxNjIwLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvc2Z4LWl0cmFuc2Zlci13ZWItYWdlbnQiLCJhdWQiOiJhZ2VudC13ZWItYXBwIiwic3ViIjoiMzZiMWY4OWMtNGYwMC00OTU1LWE0YzMtZWQ0NzZmZDU2OGM3IiwidHlwIjoiUmVmcmVzaCIsImF6cCI6ImFnZW50LXdlYi1hcHAiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI0MDgzMWVhYS00ZjJhLTQ5NmUtOTQ1ZC03YmViMTdlNDZlNDQiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsidW1hX2F1dGhvcml6YXRpb24iLCJiYWNrLW9mZmljZS1hZ2VudCJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX19.XgYSZWwfaHeY1yZZuwnQ5bj-0IHP4UEmiPTqaeCE1KVyjl3kZz3HJVisndtcKPr05kalS-M_NqU0TaYvbcZ_zesJRIga5sz4gGRqObUmUCUJoQ_iWoOhbM2SutiVnlfgJDACvOxegIcSvakZTgQsEcSweio_0kMFqi-2DYzFp6Rl0TpQ8vALLkc7rEOonUGyt7S4qQzkT-xB1_ZDlSVfm6mC-QKYNZhtqBT18P7MKxBhEgwrJtCytA_4ft7qNAbgvZ3kUohcbhzxGvtHej5RKHNI2wTzwK3IWHbkLWNndxSk_Lzj2-lCx380VpTkVpiDJfq5umjskOmI13dyPF7paA",
"token_type":"bearer",
"not-before-policy":0,
"session_state":"40831eaa-4f2a-496e-945d-7beb17e46e44"
}
This is what ember inspector (Promises) shows:
Here is the stacktrace from the Promise:
Ember Inspector ($E): authenticate/<#http://localhost:4200/assets/vendor.js:77927:9
initializePromise#http://localhost:4200/assets/vendor.js:63591:7
Promise#http://localhost:4200/assets/vendor.js:64067:35
authenticate#http://localhost:4200/assets/vendor.js:77919:14
authenticate#http://localhost:4200/assets/vendor.js:78528:14
authenticate#http://localhost:4200/assets/vendor.js:79420:14
authenticate#http://localhost:4200/assets/sfx-itransfer-web-agent.js:855:9
join#http://localhost:4200/assets/vendor.js:20249:24
run$1.join#http://localhost:4200/assets/vendor.js:37657:12
makeClosureAction/</<#http://localhost:4200/assets/vendor.js:29073:16
exports.flaggedInstrument#http://localhost:4200/assets/vendor.js:37087:14
makeClosureAction/<#http://localhost:4200/assets/vendor.js:29072:15
submit/<#http://localhost:4200/assets/vendor.js:70453:20
tryCatch#http://localhost:4200/assets/vendor.js:63549:14
invokeCallback#http://localhost:4200/assets/vendor.js:63562:15
publish#http://localhost:4200/assets/vendor.js:63532:9
#http://localhost:4200/assets/vendor.js:54458:16
invoke#http://localhost:4200/assets/vendor.js:19948:17
flush#http://localhost:4200/assets/vendor.js:19827:25
flush#http://localhost:4200/assets/vendor.js:20019:25
end#http://localhost:4200/assets/vendor.js:20128:26
run#http://localhost:4200/assets/vendor.js:20212:21
join#http://localhost:4200/assets/vendor.js:20219:24
run$1.join#http://localhost:4200/assets/vendor.js:37657:12
handleEvent/<#http://localhost:4200/assets/vendor.js:58233:18
exports.flaggedInstrument#http://localhost:4200/assets/vendor.js:37087:14
handleEvent#http://localhost:4200/assets/vendor.js:58232:17
_Mixin$create.handleEvent#http://localhost:4200/assets/vendor.js:57385:12
_bubbleEvent#http://localhost:4200/assets/vendor.js:57685:14
setupHandler/<#http://localhost:4200/assets/vendor.js:57619:20
dispatch#http://localhost:4200/assets/vendor.js:5546:16
add/elemData.handle#http://localhost:4200/assets/vendor.js:5355:6
Actually you solution looks like right.
I guess you have a problem in server response or mismatch request methods GET/POST. To solve this try to debug promise inside makeRequest.
return new RSVP.Promise((resolve, reject) => {
fetch(url, options).then((response) => {
response.text().then((text) => { //<-- here debug text
let json = text ? JSON.parse(text) : {};
if (!response.ok) { //<-- and here debug response
response.responseJSON = json;
reject(response);
} else {
resolve(json);
}
});
}).catch(reject);
So if problem will here, just rewrite whole method of makeRequest and add you own promise with custom fetch.
Another way is to write custom Authenticator, overriding authenticate, restore and (optionally) invalidate methods as wrote in documentation: https://github.com/simplabs/ember-simple-auth#implementing-a-custom-authenticator

Getting PUT routes to work in Angular

I'm seeking some wisdom from the Angular community. I am working on a simple project using the MEAN stack. I have set up my back-end api and everything is working as expected. Using Postman, I observe expected behavior for both a GET and PUT routes to retrieve/update a single value - a high score - which is saved in it's own document in its own collection in a MongoDB. So far so good.
Where things go off track is when trying to access the PUT api endpoint from within Angular. Accessing the GET endpoint is no problem, and retrieving and displaying data works smoothly. However, after considerable reading and searching, I am stll unable to properly access the PUT endpoint and update the high score data when that event is triggered by gameplay. Below are the snippets of code that I believe to be relevant for reference.
BACK-END CODE:
SCHEMA:
const _scoreSchema = {
name: { type: String, required: true },
value: { type: Number, "default": 0 }
};
ROUTES:
router
.route('/api/score/:highScore')
.put(scoreController.setHighScore);
CONTROLLER:
static setHighScore(req, res) {
scoreDAO
.setHighScore(req.params.highScore)
.then(highScore => res.status(200).json(highScore))
.catch(error => res.status(400).json(error));
}
DAO:
scoreSchema.statics.setHighScore = (value) => {
return new Promise((resolve, reject) => {
score
.findOneAndUpdate(
{"name": "highScore"},
{$set: {"value": value} }
)
.exec(function(err, response) {
err ? reject(err)
: resolve(response);
});
});
}
ANGULAR CODE:
CONTROLLER:
private _updateHighScore(newHighScore): void {
console.log('score to be updated to:', newHighScore)
this._gameService
.updateHighScore(newHighScore);
}
SERVICE:
updateHighScore(newHighScore: Number): Observable<any> {
console.log(newHighScore);
let url = '/api/score/' + newHighScore;
let _scoreStringified = JSON.stringify({value: newHighScore});
let headers = new Headers();
headers.append("Content-Type", "application/json");
return this._http
.put(url , _scoreStringified, {headers})
.map((r) => r.json());
}
Note that the console.log(newHighScore) in the last block of code above correctly prints the value of the new high score to be updated, it's just not being written to the database.
The conceptual question with PUT routes in angular is this: If the api is already set up such that it receives all the information it needs to successfully update the database (via the route param) why is it required to supply all of this information again in the Angular .put() function? It seems like reinventing the wheel and not really utilizing the robust api endpoint that was already created. Said differently, before digging into the docs, I naively was expecting something like .put(url) to be all that was required to call the api, so what is the missing link in my logic?
Thanks!

Ember Understand execution flow between route/controller

I have a "box" route/controller as below;
export default Ember.Controller.extend({
initialized: false,
type: 'P',
status: 'done',
layouts: null,
toggleFltr: null,
gridVals: Ember.computed.alias('model.gridParas'),
gridParas: Ember.computed('myServerPars', function() {
this.set('gridVals.serverParas', this.get('myServerPars'));
this.filterCols();
if (!this.get('initialized')) {
this.toggleProperty('initialized');
} else {
Ember.run.scheduleOnce('afterRender', this, this.refreshBox);
}
return this.get('gridVals');
}),
filterCols: function()
{
this.set('gridVals.layout', this.get('layouts')[this.get('type')]);
},
myServerPars: function() {
// Code to set serverParas
return serverParas;
}.property('type', 'status', 'toggleFltr'),
refreshBox: function(){
// Code to trigger refresh grid
}
});
My route looks like;
export default Ember.Route.extend({
selectedRows: '',
selectedCount: 0,
rawResponse: {},
model: function() {
var compObj = {};
compObj.gridParas = this.get('gridParas');
return compObj;
},
activate: function() {
var self = this;
self.layouts = {};
var someData = {attr1:"I"};
var promise = this.doPost(someData, '/myService1', false); // Sync request (Is there some way I can make this work using "async")
promise.then(function(response) {
// Code to use response & set self.layouts
self.controllerFor(self.routeName).set('layouts', self.layouts);
});
},
gridParas: function() {
var self = this;
var returnObj = {};
returnObj.url = '/myService2';
returnObj.beforeLoadComplete = function(records) {
// Code to use response & set records
return records;
};
return returnObj;
}.property(),
actions: {
}
});
My template looks like
{{my-grid params=this.gridParas elementId='myGrid'}}
My doPost method looks like below;
doPost: function(postData, requestUrl, isAsync){
requestUrl = this.getURL(requestUrl);
isAsync = (isAsync == undefined) ? true : isAsync;
var promise = new Ember.RSVP.Promise(function(resolve, reject) {
return $.ajax({
// settings
}).success(resolve).error(reject);
});
return promise;
}
Given the above setup, I wanted to understand the flow/sequence of execution (i.e. for the different hooks).
I was trying to debug and it kept hopping from one class to another.
Also, 2 specific questions;
I was expecting the "activate" hook to be fired initially, but found out that is not the case. It first executes the "gridParas" hook
i.e. before the "activate" hook. Is it because of "gridParas"
specified in the template ?
When I do this.doPost() for /myService1, it has to be a "sync" request, else the flow of execution changes and I get an error.
Actually I want the code inside filterCols() controller i.e.
this.set('gridVals.layout', this.get('layouts')[this.get('type')]) to
be executed only after the response has been received from
/myService1. However, as of now, I have to use a "sync" request to do
that, otherwise with "async", the execution moves to filterCols() and
since I do not have the response yet, it throws an error.
Just to add, I am using Ember v 2.0
activate() on the route is triggered after the beforeModel, model and afterModel hooks... because those 3 hooks are considered the "validation phase" (which determines if the route will resolve at all). To be clear, this route hook has nothing to do with using gridParas in your template... it has everything to do with callling get('gridParas') within your model hook.
It is not clear to me where doPost() is connected to the rest of your code... however because it is returning a promise object you can tack on a then() which will allow you to essentially wait for the promise response and then use it in the rest of your code.
Simple Example:
this.doPost().then((theResponse) => {
this.doSomethingWith(theResponse);
});
If you can simplify your question to be more clear and concise, i may be able to provide more info
Generally at this level you should explain what you want to archive, and not just ask how it works, because I think you fight a lot against the framework!
But I take this out of your comment.
First, you don't need your doPost method! jQuerys $.ajax returns a thenable, that can be resolved to a Promise with Ember.RSVP.resolve!
Next: If you want to fetch data before actually rendering anything you should do this in the model hook!
I'm not sure if you want to fetch /service1, and then with the response you build a request to /service2, or if you can fetch both services independently and then show your data (your grid?) with the data of both services. So here are both ways:
If you can fetch both services independently do this in your routes model hook:
return Ember.RSVP.hash({
service1: Ember.RSVP.resolve($.ajax(/*your request to /service1 with all data and params, may use query-params!*/).then(data => {
return data; // extract the data you need, may transform the response, etc.
},
service2: Ember.RSVP.resolve($.ajax(/*your request to /service2 with all data and params, may use query-params!*/).then(data => {
return data; // extract the data you need, may transform the response, etc.
},
});
If you need the response of /service1 to fetch /service2 just do this in your model hook:
return Ember.RSVP.resolve($.ajax(/*/service1*/)).then(service1 => {
return Ember.RSVP.resolve($.ajax(/*/service2*/)).then(service2 => {
return {
service1,
service2
}; // this object will then be available as `model` on your controller
});
});
If this does not help you (and I really think this should fix your problems) please describe your Problem.

Server side validation in Express compatible with a single page Angular application

I would like to perform server side validation, preferably with expressValidator. When saving a resource, I check to see if it is valid. If it's not valid what should I return?
There are examples:
http://blog.ijasoneverett.com/2013/04/form-validation-in-node-js-with-express-validator/
https://github.com/ctavan/express-validator
Unfortunately, I can't figure out my answer from that.
In Angular, I am using the $resource service. When I do a save, and there is a validation error, how should the server send this back? Note, this is a single page application.
Also, how should I handle this on the client side? Is this technically a success call?
Please, I am not looking for any instant, ajax, check per field solution. I want to submit save, if there is a problem, I would like to return the errors so that Angular can handle them. This does not need to be the perfect solution, just something to set me on the right track.
I am not handing the Angular code in an special way at the moment:
Controller:
$scope.saveTransaction = function (transaction) {
transactionData.saveTransaction(transaction);
}
Service
saveTransaction: function(transaction) {
return resource.save(transaction);
}
The server side code looks as follows:
app.post('/api/transactions', function (req, res) {
var transaction;
req.assert('amount', 'Enter an amount (numbers only with 2 decimal places, e.g. 25.50)').regex(/^\d+(\.\d{2})?$/);
var errors = req.validationErrors();
var mapped = req.validationErrors(true);
if (mapped) {console.log("MAPPED")};
//console.log(mapped);
if(!errors) {
console.log("Passed");
transaction = new TransactionModel({
date: req.body.date,
description: req.body.description,
amount: req.body.amount
});
transaction.save(function (err) {
if (!err) {
return console.log("created");
} else {
return console.log("err");
}
return res.send(transaction);
})
}
else {
console.log("Errors");
res.send(errors);
// res.render('Transaction', {
// title: 'Invalid Transaction',
// message: '',
// errors: errors
// });
}
});
You could send and handle "better" errors:
SERVER
res.json(500, errors)
CLIENT
resource.save(tran).then(function(){
//it worked
},
function(response) {
//it did not work...
//see response.data
});

Categories

Resources