401 unauthorized in NodeJS - node.js

I'm developing an application on MEAN stack which can upload an image from disk on application or we can send a image using chrome extension. Now I have done uploading an image from disk but when I'm trying to send image using chrome extension. On this url "http://localhost:9000/api/look/upload"; It gives an error 401 unauthorized
I'm attaching Route.js code, if any MEAN stack developer guide me where exactly is error? I will upload file as well. Thank You in advance
/**
* Main application routes
*/
'use strict';
var errors = require('./components/errors');
var auth = require('./auth/auth.service');
var path = require('path');
module.exports = function(app) {
// Insert routes below
app.use('/api/users', require('./api/user'));
app.use('/auth', require('./auth'));
app.use('/api/look', require('./api/look'));
app.use('/api/links', require('./api/imgScraper'));
app.use('/api/comments', require('./api/comments'));
app.post('/forgotpassword', require('./forgotpassword').reset);
// All undefined asset or api routes should return a 404
app.route('/:url(api|auth|components|app|bower_components|assets)/*')
.get(errors[404]);
app.route('/*')
.get(function(req, res) {
res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
});
};
module.exportstest = function(app) {
app.use('/api/looktest', require('./api/looktest'));
};
JSON CODE Is here:
JSON CODE:
{
"name": "IBR Extension",
"version": "1.3",
"description": "Demonstrate screenshot functionality in the chrome.tabs api.",
"background": {
"persistent": false,
"scripts": ["ExtensionWorking.js"]
},
"browser_action": {
"default_icon": "camera.png",
"default_title": "Take a screen shot!"
},
"permissions": [
"tabs",
"activeTab",
"downloads",
"<all_urls>"
],
"manifest_version": 2
}
XHR code is here:
function reportBug(){
var imageData = document.getElementById("canvas").toDataURL();
var xhttp = new XMLHttpRequest();
var params = "imageData=" + imageData;
var url = "http://localhost:9000/api/look/upload";
xhttp.open( "POST", url, true ); // false for synchronous request
xhttp.send( params );
return xhttp.responseText;
}
Upload function is here:
exports.upload = function(req, res) {
console.log('abc');
var newLook = new Look();
var fileimage = req.middlewareStorage.fileimage;
console.log(req.body + "test test");
newLook.image = '/assets/images/uploads/' + fileimage;
newLook.email = req.body.email;
newLook.linkURL = req.body.linkURL;
newLook.title = req.body.title;
newLook.description = req.body.description;
newLook.userName = req.body.name;
newLook._creator = req.body._creator;
newLook.createTime = Date.now();
newLook.upVotes = 0;
newLook.save(function(err, look) {
if(err) {
console.log('error saving look');
return res.send(500);
} else {
console.log(look);
res.status(200)
.send(look);
}
});
};

Related

Missing node(s) option error while trying to implement elasticSearch in node.js

I am getting the below error message while trying to implement Elasticsearch in node.js.
I have tried various solutions provided to similar problem but its still showing the same error message.
Similar problem (How can I fix error: ConfigurationError: Missing node(s) option for winston-elasticsearch?)
Additionally I am using the below npm package to implement elasticSearch:
https://www.npmjs.com/package/#elastic/elasticsearch
If someone can please help me resolve this issue.
Let me know if you require any further information from my end.
Please find below relevant codes.
router.js
const express = require('express');
const router = new express.Router();
const elastic = require('#elastic/elasticsearch');
const bodyParser = require('body-parser').json();
//const userSearch = require('../models/search');
const multer = require('multer');
var fs = require('fs');
var path = require('path');
var JSONStream = require('JSONStream');
//const elastic = require('mongoose-elasticsearch-xp');
const UserSearch = require('../models/search');
let productos = [
{
"sku": "1",
"name" : "Sillón 3 cuerpos",
"categories": ["sillon",
"sofa", "muebles", "living", "cuero"],
"description": "Hermoso sillón de cuero de 3 cuerpos"
},
{
"sku": "2",
"name": "Sillón 2 cuerpos",
"categories": ["sillon",
"sofa", "muebles", "living", "ecocuero"],
"description": "Hermoso sillón de ecocuero de 2 cuerpos"
},
{
"sku": "3",
"name": "Mesa de comedor redonda de vidrio",
"categories": ["mesa", "comedor", "vidrio"],
"description": "Moderna mesa de 110 cm de radio"
}
];
const elasticClient = new elastic.Client({
host : 'localhost:9200',
});
router.use((req, res, next)=>{
elasticClient.index({
index:'logs',
body:{
url: req.url,
method: req.method,
}
})
.then(res=>{
console. log ('Logs indexed')
})
.catch(err=>{
console. log(err)
});
next();
});
router.get('/products', (reg, res)=>{
let query = {
index: 'products'
}
if (req.query.product) query.q = "*${req.query.product)*";
elasticClient.search(query)
.then (resp=>{
return res.status (200). json({
products: resp.hits.hits
})
.catch(err=>{
console. log(err);
return res.status (500). json({
msg: 'Error',
err
});
});
});
});
module. exports = router;

Is uploading a file to S3 in NodeJS blocking?

I've been seeing performance issues on our application and I'm a bit unsure if uploading a file to S3 could block NodeJS.
I'm using express, formidable and aws-sdk.
Here's a middleware using formidable. This stores the file in req.file and continues to the next middleware that performs the upload to S3.
var formidable = require("formidable");
module.exports = function() {
return function(req, res, next) {
var form = new formidable.IncomingForm({
"keepExtensions": true,
"uploadDir": config.tempDir
});
form.parse(req, function(error, fields, files) {
if (error) {
return res.sendError("Error while parsing multipart-form " + error, 500);
}
req.files = files;
req.fields = fields;
next();
});
};
};
Here's the middleware that actually makes the request to S3 using AWS SDK
const AWS = require("aws-sdk");
const fs = require("fs");
const s3 = new AWS.S3(s3config.s3options);
const logger = require("logger");
function uploadFile(req, res, next) {
const requestId = getRequestIdFromRequestHeaders(req);
const file = options.file(req);
const contentType = options.contentType && options.contentType(req) || file.type;
const destinationPath = options.destinationPath(req);
req.s3uploaded = false;
logger.debug(requestId, "invoking uploadFile", contentType, destinationPath);
req.s3FilePath = "https://" + s3config.bucket + ".s3.amazonaws.com/" + destinationPath;
if (!options.writeConcern) {
logger.debug(requestId, "write concern not expected. Calling next");
next();
}
const stream = fs.createReadStream(file.path);
s3.upload({
"Bucket": s3config.bucket,
"ContentLength": file.size,
"Key": destinationPath,
"Body": stream,
"ContentType": contentType
}, s3config.s3options.uploadOptions, function(error) {
fs.unlink(file.path, error => {
if (error) {
logger.error(requestId, "Unable to remove file", file.path);
}
});
if (error) {
return next(error);
}
if (options.writeConcern) {
if (!req.s3uploaded) {
req.s3uploaded = true;
next();
}
}
}).on("httpUploadProgress", progress => {
logger.debug(requestId, "progress", progress.loaded, "of", progress.total);
if (progress.total !== undefined && progress.loaded === progress.total) {
logger.debug(requestId, "upload done, invoking next from httpUploadProgress");
if (!req.s3uploaded) {
req.s3uploaded = true;
next();
}
}
});
};
The documentation for the AWS SDK for JavaScript (v2) includes this statement on their Calling Services Asynchronously page (emphasis mine):
All requests made through the SDK are asynchronous. This is important to keep in mind when writing browser scripts. JavaScript running in a web browser typically has just a single execution thread. After making an asynchronous call to an AWS service, the browser script continues running and in the process can try to execute code that depends on that asynchronous result before it returns.

Not getting any response - Express Validator

I'm using the latest version of express-validator for validation.
I'm not getting any response, However Old method i.e checkBody is working fine while new method i.e check('keyName') is not working properly.
Below is my code.
package.json
"express-validator": "^5.0.3",
routes.js
var authValidator = require('./../validation/auth.validation');
var routes = require('express').Router();
routes.post('/login', [
authValidator.validateLogin,
authValidator.checkValidationResult ], function (req, res) {
console.log('3');
//res.send("Some other stuffs");
}
);
module.exports = routes;
auth.validation.js
module.exports.validateLogin = validateLogin;
module.exports.checkValidationResult = checkValidationResult;
const {check, validationResult} = require('express-validator/check');
const {matchedData, sanitize} = require('express-validator/filter');
var response = require('./../general/MyResponse');
var messages = require('./../general/messages');
function validateLogin(req, res, next) {
console.log('1');
return [
check('email').isLength({min: 1}).withMessage(messages.EMAIL_REQUIRED)
.isEmail().withMessage(messages.INVALID_EMAIL),
check('password').isLength({min: 1}).withMessage(messages.PASSWORD_REQUIRED),
]
}
function checkValidationResult(req, res, next) {
console.log('2');
var result = validationResult(req)
if (!result.isEmpty()) {
response.createResponse(
res, 400,
result.array()[0].msg,
{'error': result.array()[0].msg}, {}
)
} else {
next()
}
}
I've noticed that node js not able to go ahead from the function validateLogin in auth.validation.js.
Can anyone tell me what's wrong with above code.
Inside console, Only 1 is displaying.
I'm attaching screenShot for referance.
We need to use simple Array and don't need to create function.
Follow this link
Is it possible to do the validation in a separate file and not inline in the route? - GitHub for more details.
Code should be like this.
auth.validation.js
var response = require('./../general/MyResponse');
var messages = require('./../general/messages');
const {check, validationResult} = require('express-validator/check');
const {matchedData, sanitize} = require('express-validator/filter');
module.exports.validateLogin = [
check('email').isLength({min: 1}).withMessage(messages.EMAIL_REQUIRED).isEmail().withMessage(messages.INVALID_EMAIL),
check('password').isLength({ min: 1 }).withMessage(messages.PASSWORD_REQUIRED),
];
module.exports.checkValidationResult = checkValidationResult;
function checkValidationResult(req, res, next) {
console.log('2');
var result = validationResult(req)
if (!result.isEmpty()) {
response.createResponse(res, 400,
result.array()[0].msg,
{'error': result.array()[0].msg}, {}
)
} else {
next()
}
}
`
validateLogin and checkValidationResult are being applied as middlewares to your route. In middlewares you use next()method to call next middleware in the queue. Just like in your checkValidationResult.
In case of validateLogin, its not passing control to next middleware. But check method from express-validator v5 is itself a middleware method. Thus I guess it won't work correctly.
Please have a look at: https://github.com/ctavan/express-validator/issues/449
Try using following Code:
routes.js
var authValidator = require('./../validation/auth.validation');
var routes = require('express').Router();
var authValidations = authValidator.getAuthValidations();
routes.post('/login',
authValidations,
authValidator.checkValidationResult, function (req, res) {
console.log('3');
//res.send("Some other stuffs");
}
);
module.exports = routes;
auth.validations.js
module.exports.getAuthValidations = getAuthValidations;
module.exports.checkValidationResult = checkValidationResult;
const {check, validationResult} = require('express-validator/check');
const {matchedData, sanitize} = require('express-validator/filter');
var response = require('./../general/MyResponse');
var messages = require('./../general/messages');
function getAuthValidations(req, res, next) {
return [
check('email').isLength({min: 1}).withMessage(messages.EMAIL_REQUIRED)
.isEmail().withMessage(messages.INVALID_EMAIL),
check('password').isLength({min: 1}).withMessage(messages.PASSWORD_REQUIRED),
]
}
function checkValidationResult(req, res, next) {
console.log('2');
var result = validationResult(req)
if (!result.isEmpty()) {
response.createResponse(
res, 400,
result.array()[0].msg,
{'error': result.array()[0].msg}, {}
)
} else {
next()
}
}

AWS Lambda not firing Email via nodemailer, but does in the local development environment

I'm working on a aws-lambda which is supposed to shoot mail when an event is triggered. I using nodejs for this and below is the code:
"use strict";
exports.sendEmail = function(event, context, callback) {
var config = require('./config');
var fs = require('fs');
var _ = require('lodash');
if (_validSchema(event.payload)) {
var templatePath = config.schemaMapping[event.payload.emailDetails.emailType]["templatePath"]
var emailHTML = _getHTML(templatePath, event.payload.params)
if (emailHTML && templatePath) {
_sendSESEmail(_emailParams(event.payload.emailDetails), emailHTML)
context.succeed(JSON.stringify(_setResponse(200, [{
code: "11",
source: "Email template or Email params in payload",
message: "Please provide correct Email template and correct email params",
detail: "Template path is provided via config and Params via Payload"
}])));
} else
context.fail(JSON.stringify(_setResponse(400, [{
code: "01",
source: "Email template or Email params in payload",
message: "Please provide correct Email template and correct email params",
detail: "Template path is provided via config and Params via Payload"
}])));
} else {
context.fail(JSON.stringify(_setResponse(400, [{
code: "02",
source: "Payload schema",
message: "Please provide correct schema to validate and a payload validating it",
detail: "Payload is provided "
}])));
}
function _validSchema(payload) {
var schemaPath = config.schemaMapping[payload.emailDetails.emailType]["schemaPath"];
var payloadVerification = _verifyPayload(payload, schemaPath);
console.log(payloadVerification.valid);
return payloadVerification.valid;
}
function _emailParams(emailDetails) {
var details = {};
details.to = _.join(emailDetails.to, ',');
details.from = emailDetails.from;
details.cc = _.join(emailDetails.cc, ',');
details.bcc = _.join(emailDetails.bcc, ',');
details.attachments = emailDetails.attachments;
details.subject = emailDetails.subject;
return details;
}
function _verifyPayload(payload, schemaPath) {
var schema = JSON.parse(fs.readFileSync(schemaPath, 'utf8'));
var Validator = require('jsonschema').Validator;
var verifier = new Validator();
console.log(verifier.validate(payload, schema))
return verifier.validate(payload, schema);
}
function _setResponse(status_code, error_list) {
return {
status: status_code,
errors: error_list
};
}
function _sendSESEmail(email, emailHTML) {
var nodemailer = require('nodemailer');
var sesTransport = require('nodemailer-ses-transport');
var transporter = nodemailer.createTransport(sesTransport({
accessKeyId: config.SES.accessKeyId,
secretAccessKey: config.SES.secretAccessKey
}));
transporter.sendMail({
from: email.from,
to: email.to,
cc: email.cc,
bcc: email.bcc,
attachments: email.attachments,
subject: email.subject,
html: emailHTML
});
}
function _getHTML(templateFile, params) {
var ejs = require('ejs');
console.log({ params: params })
var baseHTML = fs.readFileSync(templateFile, 'ascii');
return ejs.render(baseHTML, { params: params });
}
}
Above code works fine when tested in the dev environment with the below code, but does not fire a mail when tested on aws-lamda.
"use strict";
var exports = require('./exports');
var bankDetailsSchemaSample = {
"payload": {
"emailDetails": {
"from": 'some#something.com',
"to": ['kunal#something.com'],
"subject": 'My Amazon SES Simple Email',
"html": '',
"cc": ['nimesh.verma#something.com'],
"bcc": ['lokesh.gour#something.com'],
"emailType": 'bankDetails',
"attachments": [{
"filename": 'test.md',
"path": 'https://raw.github.com/nodemailer/nodemailer/master/LICENSE'
}]
},
"params": {
"orderId": 1234567,
"firstName": "Nimesh",
}
}
}
var context = {
fail: function(x) { console.log(" Fail " + x) },
succeed: function(x) { console.log(" Success " + x) }
}
exports.sendEmail(bankDetailsSchemaSample, context, {})
I can't find out, why this is happening, I also tried it using nodemailer-smtp-transport instead of nodemailer-ses-transport but the same results were obtained. When nothing helped I tried using aws-sdk instead of nodemailer and nodemailer-ses-transport and the mail is fired in both dev environment as well via aws lamda testing.
// load aws sdk
exports.sendEmail = function(event, context, callback) {
var aws = require('aws-sdk');
// load aws config
aws.config.loadFromPath('config.json');
// load AWS SES
var ses = new aws.SES({ apiVersion: '2010-12-01' });
// send to list
var to = ['nimesh.verma#something.com']
// this must relate to a verified SES account
var from = 'some#something.com'
// this sends the email
// #todo - add HTML version
ses.sendEmail({
Source: from,
Destination: { ToAddresses: to },
Message: {
Subject: {
Data: 'A Message To You Rudy'
},
Body: {
Text: {
Data: 'Stop your messing around',
}
}
}
}, function(err, data) {
if (err) throw err
console.log('Email sent:');
});
}
Why is this happening?
The problem was that the context.succeed method should be placed in the callback of _sendSESEmail method.
The complete working code is present at: https://github.com/nimeshkverma/aws-lambda-node-mailer

Send PDF file from AngularJS to NodeJS

i need to send a PDF file from angularjs client to NodeJS service.
I did the angularjs service, and when i receive the file its a string like this:
%PDF-1.3
3 0 obj
<</Type /Page
/Parent 1 0 R
/Reso
How can i reconvert this string to PDF in NodeJS?
This is the client code:
var sendByEmail = function () {
$scope.generatingPdf = true;
$('#budget').show();
var pdf = new JsPDF('p', 'pt', 'letter');
var source = $('#budget')[0];
pdf.addHTML(source, 0, 0, function () {
var resultPdf = pdf.output();
BillService.sendByEmail("rbrlnx#gmail.com", resultPdf).then(function () {
});
$('#budget').hide();
});
};
var sendByEmail = function (email, file) {
var deferred = $q.defer();
var data = {
email: email,
file: file
};
BillService.sendByEmail(data, function (result) {
deferred.resolve(result);
}, function () {
deferred.reject();
});
return deferred.promise;
};
The server code controller its empty:
var sendByEmail = function (req, res, next) {
var file = req.body.file;
};
I experimented with this a while ago, and I came up with this. It's not production ready by a long shot maybe you find it useful. It's free of front end libraries (except Angular ofcourse), but assumes you're using Express 4x and body-parser.
The result:
In the browser:
On the server:
What you're seeing:
You're seeing a tiny node server, serving static index.html and angular files, and a POST route receiving a PDF in base64 as delivered by the HTML FileReader API, and saves it to disk.
Instead of saving to disk, you can send it as an email attachment. See for instance here or here for some info on that.
The example below assumes uploading a PDF by a user through a file input, but the idea is the same for all other ways of sending a document to your back end system. The most important thing is to send the pdf data as BASE64, because this is the format that most file writers and email packages use (as opposed to straight up binary for instance..). This also goes for images, documents etc.
How did I do that:
In your HTML:
<div pdfs>Your browser doesn't support File API.</div>
A directive called pdfs:
myApp.directive('pdfs', ['upload', function(upload) {
return {
replace: true,
scope: function() {
files = null;
},
template: '<input id="files" type="file">',
link: function(scope,element) {
element.bind('change', function(evt) {
scope.$apply(function() {
scope.files = evt.target.files;
});
});
},
controller: function($scope, $attrs) {
$scope.$watch('files', function(files) {
//upload.put(files)
if(typeof files !== 'undefined' && files.length > 0) {
for(var i = 0; i<files.length;i++) {
readFile(files[i])
}
}
}, true);
function readFile(file) {
var reader = new FileReader();
reader.addEventListener("loadend", function(evt) {
upload.post({name: file.name, data: reader.result})
})
if(reader.type = 'application/pdf') {
reader.readAsDataURL(file);
}
}
}
}
}]);
A tiny service:
myApp.service('upload', function($http) {
this.post = function(file) {
$http.post('/pdf', file);
}
});
And a node server:
var express = require('express');
var bodyParser = require('body-parser')
var fs = require("fs");
var app = express();
app.use(express.static('.'));
app.use( bodyParser.json({limit: '1mb'}) );
app.post('/pdf', function(req, res){
var name = req.body.name;
var pdf = req.body.data;
var pdf = pdf.replace('data:application/pdf;base64,', '');
res.send('received');
fs.writeFile(name, pdf, 'base64', function(err) {
console.log(err);
});
});
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
});

Resources