How "equals" in express-validator works? - express

I have to validate two fields are equals. In this case both passwords are the same. The problem it is that the "equals" from express-validator is not working.
This is the code:
app.post('/register', [
isNotLogged,
check('email', 'The email must be a valid one').isEmail(),
check('nickname', 'The nickname must be filled').notEmpty(),
check('password', 'The password must contain minimum eight characters, at least one letter and one number')
.matches("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$"),
//This is not working
check('passwordConfirm', 'The passwords must match').equals('password'),
validateResults
], register)

Unfortunately Express-Validator doesn't work with Validator.js's equals(), you'll have to use one of Express-Validator's middlewares and not its Validator.js affility.
Here is an example straight from Express-Validator's website which seems fit your use case:
body('oldPassword')
// if the new password is provided...
.if((value, { req }) => req.body.newPassword)
// OR
.if(body('newPassword').exists())
// ...then the old password must be too...
.notEmpty()
// ...and they must not be equal.
.custom((value, { req }) => value !== req.body.newPassword);
You do not need to use Express-Validator's check middleware as you are throwing away your ability to utilise Validator.js's validators. Instead of check you could use isEmail() and exists() (an Express-Validator validator). Also, you don't need to have your middlewares as part of an array (although you can):
app.post('/register',
isNotLogged,
body('email').isEmail().withMessage('The email must be a valid one').bail().trim(),
body('nickname').exists({ checkNull: true }).withMessage('The nickname must be filled').bail().trim(),
body('password').trim().if((value, { req }) => (typeof req.body.passwordConfirm !== 'undefined')).bail().custom((value, { req }) => value !== req.body.passwordConfirm).withMessage('The email must be a valid one').bail().trim().matches("^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$"),
validateResults,
register
);
Here the body() function would come from const { body } = require('express-validator') theres a few others similar for query paramaters, header parameters ect, all are documented here.
I also used some trim()s and bails()s just to be safe. You can read up on those here and here.

I solve this problem like this:
code before:
const registrar = async (req, res) => {
await check('password').isLength({ min:6}).withMessage('password short ').run(req);
await check('repetir_password').equals('password').withMessage('password diferente?').run(req);
let resultado = validationResult(req);
res.json(resultado.array());
};
after:
correct code: change
'password'
by
req.body.password
const registrar = async (req, res) => {
await check('password').isLength({ min: 6 }).withMessage('password corta ').run(req);
await check('repetir_password').equals(req.body.password).withMessage('password diferente?').run(req);
let resultado = validationResult(req);
res.json(resultado.array());
};

Related

Can not res.send() (error: "Cannot set headers after they are sent to the client") after I do query to database PostgrSQL

I know, it sounds really wierd, but it's true.
I was sitting and making an API on node.js, but when I began to test it, I was surprised to find out that nearly in beginning of query treatment when the first res.status().send() reached, VS Code drop a "Cannot set headers after they are sent to the client" error.
How I realize that database query is guilty? I used "res.finished" property to check out when it "sent to client" and discovered that res.finished changes from "false" to "true" exactly after db query.
Who knows what it can be? I had done the same API thing with MySQL database and it went nice, but now I'm using PostgreSQL, so things start to happen.
I export "PostgreSQL manager" class from typescript file
PostgreSQL_Manager.ts:
module.exports = {
PostgreSQL_db_manager
}
Import and initialize it in index.ts:
index.ts
const PostgreSQL_mngr = require('./PostgreSQL_Manager.ts').PostgreSQL_db_manager;
const db = new PostgreSQL_mngr;
And then, if I comment the statement with query to database, res.finished stay false (I tried it with readRows (SELECT) and with createRows(INSERT INTO)):
Piece of index.ts code:
console.log('res.finished : ', res.finished);
//let nickval : any = await db.readRows('users', 'nickname', `nickname = \'${nickname}\'`);
//await db.createRows('test', '(color, odor, taste, quantity)', '(\'meaningless\', \'absent\', \'sadness\', 0)');
console.log('res.finished : ', res.finished);
Piece of Terminal:
res.finished : false
res.finished : false
But when I uncomment database query, it becomes this:
Piece of index.ts code:
console.log('res.finished : ', res.finished);
//let nickval : any = await db.readRows('users', 'nickname', `nickname = \'${nickname}\'`);
await db.createRows('test', '(color, odor, taste, quantity)', '(\'meaningless\', \'absent\', \'sadness\', 0)');
console.log('res.finished : ', res.finished);
Piece of Terminal:
res.finished : false
Postgres: Rows were created...
res.finished : true
Code of db.createRows in postgres manager class looks like this:
public async createRows(table : string, columns: string | string[], values: string | string[]) : Promise<void> {
let createPromise = new Promise<void> ((resolve, reject) => {
this.db.query(`INSERT INTO ${table} ${columns} VALUES ${values};`, (err) => {
if(err) throw err;
console.log('Postgres: Rows were created...');
resolve();
});
});
await createPromise;
}
Edit 1:
There is error occurs (This function called from app.post, nickname, email and password has string values):
async function validationUsers (res : any, email : string = undefined, password : string = undefined, nickname : string = undefined) : Promise<boolean> {
console.log('f:validationUsers email : ', email);
console.log('f:validationUsers password : ', password);
console.log('f:validationUsers : nickname', nickname);
//validation: nickname and email
if(nickname) {
console.log('res.finished : ', res.finished);
//let nickval : any = await db.readRows('users', 'nickname', `nickname = \'${nickname}\'`);
await db.createRows('test', '(color, odor, taste, quantity)', '(\'meaningless\', \'absent\', \'sadness\', 0)');
console.log('res.finished : ', res.finished);
/* if(nickval[0] !== undefined) {
console.log('frofkofro');
res.status(410).send('Nickname already exists');
res.end();
return false;
} */
}
//validation: email
if(email) {
let emailval : any = await db.readRows('users', 'email', `email = \'${email}\'`);
console.log('f:validationUsers if(email) emailval[0] : ', emailval[0]);
if(emailval[0] !== undefined) {
console.log("?00");
res.send('Email already exists');
res.end();
return false;
}
}
//validation: password
if(password) {
let passwordval = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,100}$/;
if(!password.match(passwordval)) {
console.log('password BAM!!!');
res.status(412).send('Password does not match the criteria'); <-- **THIS STRING**
console.log('password BOOM!!!');
//res.end();
return false;
}
}
console.log('End of f:validationUsers');
return true;
}
Edit 2:
Can it be some problem with pool.query or pool connection to database from "pg" library for PostgreSQL? Or maybe problem with ts-node compiler?
So, I really don't understand what's going on.
I don't know if it's important, but I use ts-node for compile and render typescript
Edit 3:
OKAY, so I started in new ts file new server with the same 5000 port and run THIS:
app1.get('/db', async (req : any, res : any) => {
console.log('res.finished : ', res.finished);
await db1.createRows('test', '(color, odor, taste, quantity)', '(\'meaningless\', \'absent\', \'sadness\', 0)');
console.log('res.finished : ', res.finished);
res.status(200).send('All is fine this is send');
res.end();
});
And result in console:
Connected to database as pool successfully...
Server started on port 5000
res.finished : false
Postgres: Rows were created...
res.finished : false
And POSTMAN received res.send(). wtf??????
The error 'Headers already sent...' happens when your PostgreSQL code sends multiple results using res.send().
I assume the res.send() part is within PostgreSQL manager, which looks like a tested and true library - so what is happening to make it send two answers to one query?
I have no experience with Typescript and pSQL, but I have worked with pSQL and remember hitting this same snag years ago.
PostgreSQL supported (and I imagine it still supports) multiple query mode, such as, UPDATE b SET a=2 WHERE c; SELECT a FROM b. Those are two statements, and the reason why some exploits can even work.
And, just like it happened to me once, even if the second one has zero length and apparently is not even a query, in your code
`INSERT INTO ${table} ${columns} VALUES ${values};`
your PostgreSQL Manager just might think that there are two statements.
So, try removing that apparently harmless ';' at the end and see whether it solves the problem. I wasn't using your libraries, but for me, that did it.
I would say that the error is comming from here :
res.send('Email already exists');
res.end();
Indeed if you node's doc reads :
The res.end() function is used to end the response process. This method actually comes from the Node core, specifically the response.end() method of HTTP.ServerResponse. Use to quickly end the response without any data.
given that you already responsed 'Email already exists' express.js, you recieve the error message Cannot set headers after they are sent to the client (it just means you have already sent a response)
I think just removing res.end(); would fix your issue.
Okay, it's really strange and wierd. I have middleware function app.use and it looked something like that:
app.use(async function (req : any, res : any, next : any) {
console.log(smthng);
get('header') stuff;
if (cond) {
// this is not executed because condition was false in all my situation
} else {
// this is executed in all cases of this thread
req.name = undefined;
next();
}
next()
})
As you see, in the end of middleware function was next(). So, I removed JUST THIS NEXT AND:
Terminal:
res.finished : false
Postgres: Rows were read...
[]
res.finished : false
res.finished : false
Postgres: Rows were read...
[]
f:validationUsers if(email) emailval[0] : undefined
res.finished : false
password BAM!!!
password BOOM!!!
I do not know what happened, I think this is deepsea shizophrenic hyperfluid flows under complier with some crossroad between db promise, middleware and res.send()

Cypress get the text of an API response parameter

I want to get the number from the URL located in an API response.
For that I get the URL, but I don't know how to convert that in to text to extract the number.
cy.intercept('GET', 'http://viasphere.localhost/documents/page_elements/client/**',).as('response')
goTo.plusClientsButton()
cy.wait('#response', {timeout: 10000})
cy.get('#response').then( xhr => {
const link = xhr.request.headers.referer
cy.log(link)
link has the value: http://viasphere.localhost/documents/page_elements/client/19537
Obviosly const link = xhr.request.headers.referer.text() is not working...
You have to add .replace(/^\D+/g, '') to extract the number from the url.
cy.intercept(
'GET',
'http://viasphere.localhost/documents/page_elements/client/**'
).as('response')
goTo.plusClientsButton()
cy.wait('#response', {timeout: 10000})
cy.get('#response').then((xhr) => {
const client_id = xhr.request.headers.referer.replace(/^\D+/g, '')
cy.log(client_id) //prints 19537
})
Alternatively to the .then() Alapan Das provided, you can use cypress commands to perform the same actions.
cy.intercept('GET', 'http://viasphere.localhost/documents/page_elements/client/**',).as('response')
goTo.plusClientsButton()
cy.wait('#response', {timeout: 10000})
// can access request.headers.referer from .wait()
.its('request.headers.referer')
// returns 'http://viasphere.localhost/documents/page_elements/client/'
.invoke('replace', /^D+/g, '')
// now you have the link and can print it
.then(cy.log)

req.query returns nothing

Trying to get variable from http://localhost:3000/categories/subcategories?category_id=13 but req.query returns empty result.
app.get('/subcategories', (req, res) => {
let category_id = req.query.category_id
console.log(req.query)
db.query('SELECT subcategory_name FROM subcategories WHERE category_id=(?)',
[category_id],
(err, result) =>{
res.send({category_id})
});
})
Is this possibly a problem with the way I've set up my server?
See how you are passing the data , directly entering the data or from another URL you are passing the data.
Ensuring you are not sending data via req.body. Ref :
Empty req.query on ExpressJS
or check res.send({category_id}) . Try printing res.send({"category_id": category_id}) . or see console.log(JSON.stringify(req.query))
Or Extract Query Parameters Without Express
const url = require('url');
const querystring = require('querystring');
let rawUrl = 'https://stackabuse.com/?page=2&limit=3';
let parsedUrl = url.parse(rawUrl);
let parsedQs = querystring.parse(parsedUrl.query);
https://stackabuse.com/get-query-strings-and-parameters-in-express-js/

Vue.js Nuxt - cannot access Array (value evaluated upon first expanding error)

I have the following function which gives me an array called URLs
const storageRef = this.$fire.storage.ref().child(fileName)
try {
const snapshot = storageRef.put(element).then((snapshot) => {
snapshot.ref.getDownloadURL().then((url) => {
urls.push(url)
})
})
console.log('File uploaded.')
} catch (e) {
console.log(e.message)
}
});
console.log(urls)
console.log("about to run enter time with imageurls length " + urls.length)
When I run console.log(URLs) initially I do see the array like the following
[]
0: "testvalue"
length: 1
__proto__: Array(0)
However, there is a small information icon stating
This value was evaluated upon first expanding. The value may have changed since.
Because of this, when I try to get the length of URLs, I get zero, meaning the value is being updated.
Does anyone know what's happening? I am using Vue.JS/Nuxt.

matching and verifying Express 3/Connect 2 session keys from socket.io connection

I have a good start on a technique similar to this in Express 3
http://notjustburritos.tumblr.com/post/22682186189/socket-io-and-express-3
the idea being to let me grab the session object from within a socket.io connection callback, storing sessions via connect-redis in this case.
So, in app.configure we have
var db = require('connect-redis')(express)
....
app.configure(function(){
....
app.use(express.cookieParser(SITE_SECRET));
app.use(express.session({ store: new db }));
And in the app code there is
var redis_client = require('redis').createClient()
io.set('authorization', function(data, accept) {
if (!data.headers.cookie) {
return accept('Sesssion cookie required.', false)
}
data.cookie = require('cookie').parse(data.headers.cookie);
/* verify the signature of the session cookie. */
//data.cookie = require('cookie').parse(data.cookie, SITE_SECRET);
data.sessionID = data.cookie['connect.sid']
redis_client.get(data.sessionID, function(err, session) {
if (err) {
return accept('Error in session store.', false)
} else if (!session) {
return accept('Session not found.', false)
}
// success! we're authenticated with a known session.
data.session = session
return accept(null, true)
})
})
The sessions are being saved to redis, the keys look like this:
redis 127.0.0.1:6379> KEYS *
1) "sess:lpeNPnHmQ2f442rE87Y6X28C"
2) "sess:qsWvzubzparNHNoPyNN/CdVw"
and the values are unencrypted JSON. So far so good.
The cookie header, however, contains something like
{ 'connect.sid': 's:lpeNPnHmQ2f442rE87Y6X28C.obCv2x2NT05ieqkmzHnE0VZKDNnqGkcxeQAEVoeoeiU' }
So now the SessionStore and the connect.sid don't match, because the signature part (after the .) is stripped from the SessionStore version.
Question is, is is safe to just truncate out the SID part of the cookie (lpeNPnHmQ2f442rE87Y6X28C) and match based on that, or should the signature part be verified? If so, how?
rather than hacking around with private methods and internals of Connect, that were NOT meant to be used this way, this NPM does a good job of wrapping socket.on in a method that pulls in the session, and parses and verifies
https://github.com/functioncallback/session.socket.io
Just use cookie-signature module, as recommended by the comment lines in Connect's utils.js.
var cookie = require('cookie-signature');
//assuming you already put the session id from the client in a var called "sid"
var sid = cookies['connect.sid'];
sid = cookie.unsign(sid.slice(2),yourSecret);
if (sid == "false") {
//cookie validation failure
//uh oh. Handle this error
} else {
sid = "sess:" + sid;
//proceed to retrieve from store
}