ReCaptcha validation on Node.js - javascript

on my express server, g-recaptcha-response always return nothing. This is my code at the moment:
<div class=container-fluid id=mcenter>
<form id='monitstart' action="/monitstart" method="POST">
<input type="text" class="form-control" aria-label="..." name=>
<button class="g-recaptcha" data-sitekey="SITEKEYHERE" data-callback="onSubmit"></button>
</form>
</div>
and on my server
var express = require('express')
var router = express.Router()
var request = require('request')
router.post('/monitstart', function (req, res) {
request({url: "https://www.google.com/recaptcha/api/siteverify?secret=SECRETHERE&response=" + req.body['g-recaptcha-response']} + '&remoteip=' + req.connection.remoteAddress, function (err, response, body) {
req.send(body)
})
})
module.exports = router
And when I try to validate it, it give me a code 500 and say TypeError: Cannot read property 'g-recaptcha-response' of undefined

The correct answer, accepted by the OP during the short discussion below the question involves adding the body parsing middleware (the body-parser) to the pipeline so that the body property of the request object is correctly initialized before a value is read from there.

Related

How to receive data from a button in a form?

This seems very simple but I can't figure it out. I am trying to get back the value of a button so I can conditionally render a page template. I can't seem to capture the value of the button though.
Here is my js code.
app.get("/trades", (req, res) => { // line 465
let button_value = req.params.value;
console.log(button_value);
// res.render("activate_pause")
});
And here is my html/ejs markup:
<form action="/trades" methods="get, post" name="groups_button">
<button class="orange" type="submit" name="frontpage_trades_button" value="pause">Pause Campaigns</button>
<button type="submit" name="frontpage_trades_button" value="enable">Activate Campaigns</button>
</form>
The values 'pause' or 'enable' will be used to set a status of true or false, which will render the desired template ( or so I hope!). Can anyone help??
methods is not a valid attribute of the <form> element
console.log('Is method in <form>?: ', 'method' in HTMLFormElement.prototype);
console.log('Is methods in <form>?: ', 'methods' in HTMLFormElement.prototype);
So the first thing to do is to replace methods with method and set only one method (I'd suggest POST).
Then in the Node.js code, make sure you have the proper middleware in order to decode URL encoded forms:
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
This should allow you to retrieve the value of the clicked button, like this:
app.post("/trades", (req, res) => {
let button_value = req.body.frontpage_trades_button;
console.log(button_value);
// res.render("activate_pause")
});
u can use data attribute to take it
<button type="submit"id="x" name="frontpage_trades_button" data-value="enable">Activate Campaigns</button>
app.get("/trades", (req, res) => { // line 465
let button_value = req.params.value;
console.log($("#x").data("value"));
// res.render("activate_pause")
});

button should delete specific item on server side

I'm working on an app to track my expenses with javascript, nodejs , express and as templating engine handelbars.
So I have a div "list" which contains all expenses. ( i have an add button next to the div list, not visible on the pic)
Everytime a I add an expense , I add the div "obj" with a delete button ,a "B" button and some information about the expense.
here is the code in my html:
<div class="list">
{{#each expArr}}
<div id="obj" class="obj">
<form action="/removetodo" method="POST" >
<button class="btn2">X</button>
</form>
<button onclick="openNav()" class="btn">B</button>
<a>{{date}}</a> <n>{{name}}</n> <a>{{value}} </a>
{{description}}
</div>
{{/each}}
Now, my backend is runnning on a NodeJS server with express.
here is my index.js file :
var express = require('express');
var router = express.Router();
var expArr = [];
router.get('/', function(req, res, next) {
res.render('index' , {expArr: expArr} );
});
router.post('/addtodo', function (req, res, next) {
var exp = new Object();
exp.name = req.body.name;
exp.value = req.body.val;
exp.date = req.body.date;
exp.description = req.body.descr;
expArr.push(exp);
res.redirect('/');
});
router.post('/removetodo', function (req, res, next) {
expArr.pop();
res.redirect("/");
});
module.exports = router;
In addtodo I simply adding all the informtion to an array on the server (later I will add a database).
Now my question:
The delete button on every expense should delete the right expense.
In other words, I want ,by clicking the delete button , that the right entry in the array on the server deletes.
How do I do that?
Thanks!
you're storing everything in memory, taking that for granted, you can start by using a plain object rather then an array to store your data
expArr = {}
and then add a unique identifier like a hash or a date in ms for each instance
var exp = new Object();
exp.id = new Date().getUTCMilliseconds();
exp.name = req.body.name;
exp.value = req.body.val;
exp.date = req.body.date;
exp.description = req.body.descr;
expArr[exp.id] = exp;
now be sure to pass from the client the right id when you want to remove an expense
router.post('/removetodo', function (req, res, next) {
if(expArr[req.body.id]) {
delete expArr[req.body.id];
}
res.redirect("/");
});

Retrieve token/Create charge - Stripe

This might be a stupid question but here we go.
I've set up Stripe Elements (https://stripe.com/docs/elements) to collect credit card info, and tockenize it.
Now I'm trying to set up charges, but I'm unsure of how to set up my "server-side" code.
Submitting the form in my controller.js:
function stripeTokenHandler(token) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById('payment-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
https://stripe.com/docs/charges:
"On your server, grab the Stripe token in the POST parameters submitted by your form."
From my Nodecharge.js:
// Set your secret key: remember to change this to your live secret key in
production
// See your keys here: https://dashboard.stripe.com/account/apikeys
var stripe = require("stripe")("sk_test_111111111111111111");
// Token is created using Stripe.js or Checkout!
// Get the payment token ID submitted by the form:
var token = request.body.stripeToken; // Using Express
// Charge the user's card:
stripe.charges.create({
amount: 1000,
currency: "sek",
description: "Example charge",
source: token,
}, function(err, charge) {
// asynchronously called
});
My HTML-form:
<form action="/charge" method="post" id="payment-form">
<div class="form-row">
<label for="card-element">
Credit or debit card
</label>
<div id="card-element">
<!-- a Stripe Element will be inserted here. -->
</div>
<!-- Used to display form errors -->
<div id="card-errors" role="alert"></div>
</div>
<button>Submit Payment</button>
</form>
Submitting a payment with the test card, I get redirected to /charge with a 404.
I'm new to this, and I've obviously copy/pasted some code, but I'm trying hard to wrap my head around it, and I want to understand it, not just make it work.
I kinda get how the credit card info retrieval works with js, but I'm a bit confused when it comes to the charging/redirecting/404/.
I mean, this action-line points me to a non-existing page on my end, right? Do I need to create this page?
<form action="/charge" method="post" id="payment-form">
Sorry for the length of this post, please help me understand what's going on here, or what I need to fix.
Appreciate any help.
How are you serving your backend --- Express?
If you're seeing a 404 when you submit your form to /charge it sounds like you might not have a app.post route setup for /charge in Express.
You can read through the guide on routing for a little more detail
https://expressjs.com/en/guide/routing.html
If you want to see a simple working example, take a look at this (make sure to replace the pk_test and sk_test with your actual test keys):
var stripe = require("stripe")("sk_test_xxxyyyzzz");
var express = require('express'), bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false })
var app = express();
app.get('/',function(req, res) {
// for kicks, just sending checkout
res.send('<form action="/charge" method="POST">Buy it !<script src="https://checkout.stripe.com/checkout.js" class="stripe-button" data-key="pk_test_xxxyyyyzzzz"></script></form>')
});
app.post('/charge',urlencodedParser, function(req, res) {
// grab a token
var token = req.body.stripeToken;
// creating a charge, for real use add things like error handling
stripe.charges.create({
amount: 2000,
currency: "usd",
source: token, // obtained with Stripe.js
description: "Charge"
}, function(err, charge) {
res.send("You made a charge: "+ charge.id);
});
});
app.listen(5000)
To create source token via stripe, first need to refer stripe.js from stripe.com and it must be from stripe.com.
And then add below code to add your card info and generate a token.
var stripe = Stripe('Your stripe publisheable key');
var elements = stripe.elements;
stripe.createToken(elements[0], additionalData).then(function (result) {
example.classList.remove('submitting');
if (result.token) {
// If we received a token, show the token ID.
example.querySelector('.token').innerText = result.token.id;
example.classList.add('submitted');
}
Here, you will get a token, that will be necessary to create your customer. Use below code to create your customer. I used C#.NET
StripeConfiguration.SetApiKey("sk_test_JTJYT2SJCb3JjLQQ4I5ShDLD");
var options = new CustomerCreateOptions {
Description = "Customer for jenny.rosen#example.com",
SourceToken = "tok_amex"
};
var service = new CustomerService();
Customer customer = service.Create(options);
Now, you can get your required amount form this user from the card token you got from stripe like below:
StripeConfiguration.SetApiKey("sk_test_JTJYT2SJCb3JjLQQ4I5ShDLD");
var options = new ChargeCreateOptions {
Amount = 2000,
Currency = "aud",
Description = "Charge for jenny.rosen#example.com",
SourceId = "tok_amex" // obtained with Stripe.js, }; var service = new ChargeService();

Uploading file from form to server

I am currently working on a dashboard, and have been stuck for some couple of hours now... What I like to do is to have a form including 3 <input type="file"> (two of them allow multiple files, one not), and each of them posting to 3 different post-methods in the server. When I try to console log the request on the server side the data is empty ({}) . I do not understand why, can someone please help me solve this issue?
I am using angularjs, and nodejs btw.
This is what my current code is : (files and paths are dummy-names)
HTML:
<form role="form" enctype="multipart/form-data">
<div class="form-group">
<label for="file1">File1:</label>
<input type="file" id="file1" accept=".txt, .json" multiple>
</div>
<div class="form-group">
<label for="file2">File2:</label>
<input type="file" id="file2" accept=".json">
</div>
<div class="form-group">
<label for="file3">File3:</label>
<input type="file" id="file3" multiple>
</div>
<button type="button" ng-click="save()" class="btn btn-default"> Save</button>
</form>
JS:
module.exports = function($scope, $http) {
$scope.save = function () {
file1(document.getElementById('file1').files);
file2(document.getElementById('file2').files);
file3(document.getElementById('file3').files);
};
function file1(files) {
$http.post('/file1', {f: files}).success(function (res) {
//todo
});
};
function file2(files) {
$http.post('/file2', {f: files}).success(function (res) {
//todo
});
};
function file3(files) {
$http.post('/file3', {f: files}).success(function (res) {
//todo
});
};
}
Server.js
var express = require("express"),
fs = require("fs"),
bodyParser = require('body-parser'),
app.use(express.static("build"));
app.use(bodyParser());
app.post('/file1', function (req, res) {
console.log(req.body.f) // returns empty: {}
// like to move files to path: a/b/c
});
app.post('/file2', function (req, res) {
// like to move files to path: a/d/e
});
app.post('/file3', function (req, res) {
// like to move files to path: a/f/g
});
Update:
after receiving the answer from GrimurD, I have modified the server.js, but still struggling. Any takers?
var express = require("express"),
fs = require("fs"),
bodyParser = require('body-parser'),
multer = require('multer'), //<-- updated
upload = multer({ dest: './uploads/' }) //<-- updated
app.use(express.static("build"));
app.use(bodyParser());
app.use(multer({ dest: './uploads/' }).array()); // <-- updated
app.post('/file1', upload.array('file1'), function (req, res) {
console.log(req.body.f) // returns empty: {}
console.log(req.files); // returns undefined // <-- updated
// like to move files to path: a/b/c
});
app.post('/file2', upload.single('file2'), function (req, res) {
console.log(req.file); // returns undefined // <-- updated
// like to move files to path: a/d/e
});
app.post('/file3', upload.array('file3'), function (req, res) {
console.log(req.files); // returns undefined // <-- updated
// like to move files to path: a/f/g
});
When uploading a file the form must use multipart/form-data which body-parser doesn't support. You must use a specialized middleware to handle this type. Multer is one such that I have used with success.
You can get around this using FileReader.readAsDataURL(..) on the File objects in the input fields. I often like to use the multi-select ability on the file input type so that I can upload a bunch of files and do this async.
So what I normally do is access the files property on the input element and loop through them, then I use the FileReader.readAsDataURL to get the base64 of the binary for the files then passing the base64 to a webserivce method with a signature that accepts that a string param for the base64, convert the b64 to binary and you're back in business.
var fileRunner = {
files: [],
run: function(el) {
this.files = el.files;
this.read();
},
read: function() {
// begin the read operation
console.log(this.files.length);
for (var i = 0; i <= this.files.length - 1; i++) {
var reader = new FileReader();
reader.readAsDataURL(this.files[i]);
reader.onload = this.process
}
},
process: function(evt) {
var result = evt.target.result
if (result.length > 0) {
var parts = result.split(',')
var dataBsf = parts[parts.length - 1];
console.log(dataBsf);
//call method to pass the base 64 here.
}
}
};
<body>
<input id="fup" type="file" multiple="multiple" onchange="fileRunner.run(this)" />
</body>
I did not include a server side component to this because I think that should be agnostic and slightly out of scope here.
I am only logging the output to the console, but you would take the output and pump it to the web service.
Additionally, I referenced the input element in the event handler for the onchange using "this" because I had no idea how you wanted to handle it. Allowing the passing of an element provided a bit of loose assumptions on my part.

Sails.js req.files is empty and req.body.image is undefined

I've been trying to understand this since yesterday but I can't find any solutions, even by asking Google and StackOverFlow.
The problem is that I'm building a project inside which I have "Product" Model, Controller, and Views. On the new.ejs view, I have a form which contains a file tag (named image). So, on the controller, I try to get the image path by logging req.files.image.path in the console but req.files is empty. I also tried to display req.body.image which is undefined.
Here is the client-side code (views/product/new.ejs) :
(This is a Sails.js app)
Here is the client-side code (views/product/new) :
<div class='container'>
<form action='/product/create' role='form' class='form-signin' enctype="multipart/form-data" id='product-form'>
<div class='form-group'>
<label class='sr-only' for='name'>Name of the product</label>
<input type="text" class='form-control' placeholder="Name" name='name' id='name' />
</div>
<div class='form-group'>
<label class='sr-only' for='image'>Image of the product</label>
<input type="file" name='image' id='image' />
</div>
.
.
.etc...
and here is the server-side (api/controllers/ProductController.js) :
'create': function(req, res, next) {
// Include the node file module
var fs = require('fs');
console.log(req.files); //This logs : { } in the console
console.log(req.body.image); //This logs : undefined in the console
//Readfile with fs doesn't work cause req.files is empty
// fs.readFile(req.files.image.path, function(error, data) {
// //get image name
// var imageName = req.files.data.name;
// //if enable to get name
// if (!imageName) {
// console.log('error uploading image');
// res.redirect('/product/new');
// //Else if we have an image
// } else {
// //change the path to our own
// var newPath = __dirname + '/assets/images/products/fullsize/' + imageName;
// fs.writeFile(newPath, data, function(error) {
// console.log(newPath);
// //res.redirect('/product' + imageName);
// });
// }
// });
}
Thanks for your help.
Mat.
Also available here : https://github.com/balderdashy/sails/issues/1127
use method=post in your html form

Categories