I create a login and logout function with Node.js and Angular.js which is token based. The token I am saving into window storage.
The problem is if I logout it just logout for one browser and also if I loggedin it not recognize if I am already loggedin. I think I have to extend my programm.
My question is how can I delete the storage for every open browser where I loggedin? Or schould I ask within my code if I am loggedin and how could I do this?
Thanks in advance!
NODE.JS CODE
app.post('/logout', function(req, res){
jwt.verify(req.body.token, 'secretKey', function(err, decoded) {
console.log("Decoded " + decoded);
if(decoded._id != null){
User.findOne({
_id : decoded._id
}, function(err, user) {
if (err) {
console.log('Error occured', err);
} else {
if (user) {
res.end();
}
}
});
}else{
Console.log("Could not logout");
}
});
});
app.post('/login', function(req, res) {
User.findOne({
email : req.body.email
}, function(err, user) {
if (err) {
console.log('Error occured', err);
} else {
if (user) {
// check if password matches
if (req.body.password != undefined) {
var hashPWCheck = bcrypt.compareSync(req.body.password, user.password);
// true
//console.log(hashPWCheck);
if (!(hashPWCheck)) {
res.json({
success : false,
message : 'Authentication failed. Wrong password.'
});
console.log('Authentication failed. Wrong password.');
} else {
var token = jwt.sign(user, 'secretKey', {
expiresInMinutes : 60 // expires in 1 Minute
});
res.json({token : token, email : user.email});
console.log("Token created & sent to Client(UserCtrlLogin): " + token);
}
} else {
console.log("Password is required!");
}
} else {
console.log("Incorect E-Mail");
}
}
});
});
ANGULAR.js Code
app.controller('UserCtrlLogin', function($scope, $http, $window, $location, $rootScope) {
$scope.logout = function(){
var sessionlogout = $window.sessionStorage.getItem('token');
var formData = {
token : sessionlogout
};
$http.post('/logout', formData).success(function(data, status, headers, config) {
if(status == 200){
$rootScope.isAlive = false;
$rootScope.ali = false;
$window.sessionStorage.removeItem('token');
}else{
$window.sessionStorage.removeItem('token');
$rootScope.isAlive = false;
}
});
};
$scope.signin = function() {
var formData = {
email : $scope.email,
password : $scope.password
};
// $window.sessionStorage.removeItem('token');
$http.post('/login', formData).success(function(data, status, headers, config) {
console.log('Data: ' + data.email);
//console.log('Status: ' + status);
if (status == 200) {
if(data.email == "goekguel.ali#gmail.com"){
$rootScope.ali = true;
}
$rootScope.isAlive = true;
$window.sessionStorage.setItem('token', data.token);
console.log("Token saved into Storage from Server(Node.js function /login)");
}
}).error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
$window.sessionStorage.removeItem('token');
});
};
});
You need to save tokens in the database, and if you log in or log out in one browser you have to mark token as valid/invalid, and in another browser it's required to check token status on backend.
P.s. See satellizer, it's just my recommendation for front-end auth module.
Related
I have the below controller which I use to manage the login system on my app. Is working in all cases except the one when I insert the wrong username.
I have inserted the below conditional statement to handle the error:
if (error === null) {
res.status(401).render('login', {
message: 'Email or Password is incorrect'
})
}
But when I insert it, I receive the following message on the terminal:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
const jwt = require('jsonwebtoken');
const mysql = require('mysql');
const bcrypt = require('bcryptjs');
const { promisify } = require('util');
var db_config = {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME
};
var connection;
function handleDisconnect() {
connection = mysql.createConnection(db_config); // Recreate the connection, since
// the old one cannot be reused.
connection.connect(function (err) { // The server is either down
if (err) { // or restarting (takes a while sometimes).
console.log('error when connecting to db:', err);
setTimeout(handleDisconnect, 2000); // We introduce a delay before attempting to reconnect,
} // to avoid a hot loop, and to allow our node script to
}); // process asynchronous requests in the meantime.
// If you're also serving http, display a 503 error.
connection.on('error', function (err) {
console.log('db error', err);
if (err.code === 'PROTOCOL_CONNECTION_LOST') { // Connection to the MySQL server is usually
handleDisconnect(); // lost due to either server restart, or a
} else { // connnection idle timeout (the wait_timeout
throw err; // server variable configures this)
}
});
}
handleDisconnect();
// code in case the user leave the login space empty
exports.login = async (req, res) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).render('login', {
message: 'Please provide an email and password'
})
}
connection.query('SELECT * FROM login WHERE email=?', [email], async (error, results) => {
// conditional statement to handle the wrong username error
if (error === null) {
res.status(401).render('login', {
message: 'Email or Password is incorrect'
})
}
//conditional if statement to compare password in database and password inserted by the client
if (!results || !(await bcrypt.compare(password, results[0].password))) {
res.status(401).render('login', {
message: 'Email or Password is incorrect'
}) //conditional statement to fetch the id of the client and signign in with sign() function
} else {
const id = results[0].id;
const token = jwt.sign({ id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRES_IN
});
// console.log('the token is:' + token);
const cookieOptions = {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000 // 24 hours converted in milliseconds to set the expiration cookies to 24 hours
),
httpOnly: true
}//setting of cookies on the browser and redirecting to the user interface page
res.cookie('jwt', token, cookieOptions);
res.status(200).redirect('/ui');
}
});
} catch (error) {
console.log("this is the error:", error)
}
}
exports.register = (req, res) => {
// Destructor
const { name, email, password, passwordConfirm } = req.body;
//query that order to MySQL to get the user email only once
connection.query('SELECT email FROM login WHERE email = ?', [email], async (error, results) => {
if (error) {
console.log(error);
}
if (results.length > 0) {
return res.render('register', {
message: 'That email is already in use'
})
} else if (password !== passwordConfirm) {
return res.render('register', {
message: 'Password do not match'
});
}
let hashedPassword = await bcrypt.hash(password, 8);
// console.log(hashedPassword);
connection.query('INSERT INTO login SET ?', { name: name, email: email, password: hashedPassword }, (error, results) => {
if (error) {
console.log(error);
} else {
// console.log(results);
return res.render('register', {
message: 'User registered'
});
}
})
});
}
exports.isLoggedIn = async (req, res, next) => {
// console.log(req.cookies);
if (req.cookies.jwt) {
try {
//1)verify the token
decoded = await promisify(jwt.verify)(req.cookies.jwt,
process.env.JWT_SECRET
);
//2) Check if the user still exists
connection.query('SELECT * FROM login WHERE id = ?', [decoded.id], (error, result) => {
// console.log(result);
if (!result) {
return next();
}
req.user = result[0];
return next();
});
} catch (error) {
console.log(error);
return next();
}
} else {
next();
}
}
exports.logout = async (req, res) => {
res.clearCookie('jwt');
res.status(200).redirect('/');
}
Thanks in advance for suggestions or correction to the right path.
Do not forget to return the response or the function will continue.
return res.status(401).render('login', {
message: 'Email or Password is incorrect'
});
You need to halt the execution of the function by putting the return keyword or the code will run through the other statements.
if (error === null) {
return res.status(401).render('login', {
message: 'Email or Password is incorrect'
})
}
Or
if (error === null) {
res.status(401).render('login', {
message: 'Email or Password is incorrect'
})
return
}
I got it, or at least is working. I deleted the first if statement and modify the remain one as below. instead of !results I edited it to results == "" . So if results is empty it will render the login with te alert message.
if (results == "" || !(await bcrypt.compare(password, results[0].password))) {
res.status(401).render('login', {
message: 'Email or Password is incorrect'
}) //conditio
I have recently been developing a MERN application and I have recently came into the trouble that express is saying that I am setting headers after they are sent.
I am using mongo db and trying to update a user profile.
I have tried to comment out my res.send points to find the issue but I have failed to do so.
Here is my post method for updating the user profile:
app.post("/api/account/update", (req, res) => {
const { body } = req;
// Validating and Checking Email
if (body.email) {
var email = body.email;
email = email.toLowerCase();
email = email.trim();
body.email = email;
User.find(
{
email: body.email
},
(err, previousUsers) => {
if (previousUsers.length > 0) {
return res.send({
success: false,
message:
"Error: There is already another account with that email address"
});
} else {
}
}
);
}
// Validating Names Function
function checkName(name) {
var alphaExp = /^[a-zA-Z]+$/;
if (!name.match(alphaExp)) {
return res.send({
success: false,
message: "Error: Names cannot contain special characters or numbers"
});
}
}
checkName(body.firstName);
checkName(body.lastName);
// Making sure that all fields cannot be empty
if (!body.email && !body.firstName && !body.lastName) {
return res.send({
success: false,
message: "Error: You cannot submit nothing"
});
}
// Getting User ID from the current session
UserSession.findById(body.tokenID, function(err, userData) {
// Finding User ID using the current users session token
if (userData.isDeleted) {
return res.send({
success: false,
message:
"Error: Session token is no longer valid, please login to recieve a new one"
});
}
// Deleting the token ID from the body object as user table entry doesnt store tokens
delete body.tokenID;
// Finding the user profile and updating fields that are present
User.findByIdAndUpdate(userData.userId, body, function(err, userInfo) {
if (!err) {
return res.send({
success: true,
message: "Success: User was updated successfully"
});
}
});
});
});
This is the call that I am doing to the backend of the site:
onUpdateProfile: function(fieldsObj) {
return new Promise(function(resolve, reject) {
// Get Session Token
const obj = getFromStorage("the_main_app");
// Defining what fields are getting updated
fieldsObj.tokenID = obj.token;
// Post request to backend
fetch("/api/account/update", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(fieldsObj)
})
.then(res => {
console.log("Verify Token - Res");
return res.json();
})
.then(json => {
console.log("Verify Token JSON", json);
if (json.success) {
window.location.href = `/manage-account?success=${json.success}`;
} else {
window.location.href = `/manage-account?success=${json.success}`;
}
});
});
}
Here is my error message that I am getting:
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:491:11)
at ServerResponse.setHeader (_http_outgoing.js:498:3)
at ServerResponse.header (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\express\lib\response.js:767:10)
at ServerResponse.send (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\express\lib\response.js:267:15)
at ServerResponse.send (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\express\lib\response.js:158:21)
at C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\routes\api\account.js:270:22
at C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\mongoose\lib\model.js:4641:16
at process.nextTick (C:\Users\kieran.corkin\Desktop\Projects\Mern Template Final\mern-cra-and-server\server\node_modules\mongoose\lib\query.js:2624:28)
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
[nodemon] app crashed - waiting for file changes before starting...
Can anyone help me with this?
EDIT
I have changed my code, this seems to now work however I feel like its a little messy when put together. Any refactoring tips?
Code:
app.post("/api/account/update", (req, res) => {
// Preform checks on data that is passed through
const { body } = req;
var messages = {
ExistedUser:
"Error: There is already another account with that email address",
NameFormat: "Error: Names cannot contain special characters or numbers",
BlankInputs: "Error: You cannot submit nothing",
accountLoggedOut:
"Error: Session token is no longer valid, please login to recieve a new one",
successfullyUpdated: "Success: User was updated successfully"
};
var usersFound;
if (body.email) {
var email = body.email;
email = email.toLowerCase();
email = email.trim();
body.email = email;
User.find(
{
email: body.email
},
(err, UserCount) => {
usersFound = UserCount;
}
);
}
function capitalize(text) {
return text.replace(/\b\w/g, function(m) {
return m.toUpperCase();
});
}
if (body.firstName) {
body.firstName = capitalize(body.firstName);
}
if (body.lastName) {
body.lastName = capitalize(body.lastName);
}
//Making sure that all fields cannot be empty
if (!body.email && !body.firstName && !body.lastName) {
return res.send({
success: false,
message: messages.BlankInputs
});
}
// Getting User ID from the current session
UserSession.findById(body.tokenID, function(err, userData) {
// Finding User ID using the current users session token
if (userData.isDeleted) {
return res.end({
success: false,
message: messages.accountLoggedOut
});
}
if (userData) {
// Deleting the token ID from the body object as user table entry doesnt store tokens
delete body.tokenID;
// Finding the user profile and updating fields that are present
User.findByIdAndUpdate(userData.userId, body, function(err, userInfo) {
if (userInfo) {
if (!usersFound.length > 0) {
return res.send({
success: true,
message: messages.successfullyUpdated
});
} else {
return res.send({
success: false,
message: messages.ExistedUser
});
}
}
});
}
});
});
You're calling res.send() twice. res.send() ends the process. You ought to refactor such that you call res.write() and only call res.send() when you're done.
This StackOverflow link describes the difference in more detail. What is the difference between res.send and res.write in express?
I believe this is happening, as you're trying to send a response after the first / initial response has already been sent to the browser. For example:
checkName(body.firstName);
checkName(body.lastName);
Running this function twice is going to try and yield 2 different "response" messages.
The product of a single route, should ultimately be a single response.
Thanks for all your help on this issue.
Here is my final code that allowed it to work.
I have also tried to "refactor" it too. Let me know if you'd do something else.
app.post("/api/account/update", (req, res) => {
const { body } = req;
console.log(body, "Logged body");
// Defining objects to be used at the end of request
var updateUserInfo = {
userInfo: {},
sessionToken: body.tokenID
};
var hasErrors = {
errors: {}
};
// Checking that there is at least one value to update
if (!body.email && !body.firstName && !body.lastName) {
var blankError = {
success: false,
message: "Error: You cannot change your details to nothing"
};
hasErrors.errors = { ...hasErrors.errors, ...blankError };
} else {
console.log("Normal Body", body);
clean(body);
console.log("Cleaned Body", body);
updateUserInfo.userInfo = body;
delete updateUserInfo.userInfo.tokenID;
}
// Function to check if object is empty
function isEmpty(obj) {
if (Object.keys(obj).length === 0) {
return true;
} else {
return false;
}
}
// Function to remove objects from body if blank
function clean(obj) {
for (var propName in obj) {
if (obj[propName] === "" || obj[propName] === null) {
delete obj[propName];
}
}
}
// Checking and Formatting Names Given
function capitalize(text) {
return text.replace(/\b\w/g, function(m) {
return m.toUpperCase();
});
}
if (body.firstName) {
body.firstName = capitalize(body.firstName);
}
if (body.lastName) {
body.lastName = capitalize(body.lastName);
}
// Checking and formatting email
if (body.email) {
body.email = body.email.toLowerCase();
body.email = body.email.trim();
// Checking for email in database
User.find({ email: body.email }, (err, EmailsFound) => {
if (EmailsFound.length > 0) {
var EmailsFoundErr = {
success: false,
message: "There is already an account with that email address"
};
hasErrors.errors = { ...hasErrors.errors, ...EmailsFoundErr };
}
});
}
// Getting User Session Token
UserSession.findById(updateUserInfo.sessionToken, function(err, userData) {
// Finding User ID using the current users session token
if (userData.isDeleted) {
var userDeletedError = {
success: false,
message:
"Your account is currently logged out, you must login to change account details"
};
hasErrors.errors = { ...hasErrors.errors, ...userDeletedError };
} else {
// Finding the user profile and updating fields that are present
User.findByIdAndUpdate(
userData.userId,
updateUserInfo.userInfo,
function(err, userInfo) {
// userInfo varable contains user db entry
if (err) {
var updateUserError = {
success: false,
message: "Error: Server Error"
};
hasErrors.errors = {
...hasErrors.errors,
...updateUserError
};
}
if (isEmpty(hasErrors.errors)) {
res.send({
success: true,
message: "Success: You have updated your profile!"
});
} else {
res.send({
success: false,
message: hasErrors.errors
});
}
}
);
}
});
});
Background: I am creating an app using node/express as my backend, mongo as the database, and angular as the front end. I am using jsonwebtoken to authenticate the user. Once the user logs in, a token is stored in the local storage, which is used to authenticate all requests. After the user logs in,
the name and username is retrieved via Auth.getUser(), which is an angular factory method that gets data from the backend. Each request
Problem: I am unable to get the user to redirect to the home page, because the following code does not run:
vm.login = function() {
vm.error = '';
Auth.login(vm.loginData.username, vm.loginData.password)
.then(function(data) {
Auth.getUser()
.then(function(data) {
vm.user = data.data;
});
if (data.success) {
$location.path('/');
} else {
vm.error = data.message;
console.log(vm.error);
}
});
}
I do not get redirected to the homepage, although I also do not get any message either in the dev console or my terminal.
When I check the local storage via the dev console, I do not have the token. However, I am able to login/signup/post data successfully using POSTMAN. I think the problem can be fleshed out via the following steps:
1. The user logs in, and the token is stored in the local storage
2. Auth.getUser() is suppose to request for the user data from the backend.
3.Each request requires the token to be verified via the jsonwebtoken.verify() method.
4.For some reason, the token is not sent to my backend, so this does not run:
api.use(function(req,res,next) {
console.log('someone tried to access a secure page');
var token =
req.body.token || req.param('token') || req.headers['x-access-token'];
if (token) {
//code
} else {
res.status(403).send({ success: false, message: "No Token Provided"});
Here are what I deem the relevant files:
backend:
var mongoose = require('mongoose');
var User = require('../models/user.js');
var Story = require('../models/story.js');
var config = require('../../config/config.js');
var jsonWebToken = require('jsonwebtoken');
var sessionSecret = config.sessionSecret;
function createToken(user) {
var token = jsonWebToken.sign({
id: user._id,
name: user.name,
username: user.username
}, sessionSecret, {expiresInMinutes: 1440});
return token;
}
module.exports = function(app, express) {
var api = express.Router();
api.post('/login', function(req,res) {
User.findOne({username: req.body.username})
.select('password').exec(function(err, user) {
if (err) {
res.send(err);
return;
} else {
if (!user) {
res.send('user does not exist!');
} else {
var isPasswordValid = user.comparePassword(req.body.password);
if (!isPasswordValid) {
res.send('wrong password!');
} else {
var token = createToken(user);
res.json(
{success:true,
message:'successfully logged in!',
token: token});
}
}
}
})
});
api.use(function(req,res,next) {
console.log('someone tried to access a secure page');
var token =
req.body.token || req.param('token') || req.headers['x-access-token'];
if (token) {
jsonWebToken.verify(token, sessionSecret, function(err, decoded) {
if(err) {
res.status(403).send({ success: false, message: "Failed to authenticate user"});
} else {
//
req.decoded = decoded;
next();
}
});
} else {
**//*****the message sent to my frontend*********
res.status(403).send({ success: false, message: "No Token Provided"});
}
});
api.get('/me', function(req,res) {
res.send(req.decoded);
})
app.use('/api', api);
}
frontend:
Angular factory: retrieves data from the backend
var authService = angular.module('authService', []);
authService.factory('Auth', function($http, $location, $q, AuthToken) {
var authFactory = {};
authFactory.login = function(username,password) {
return $http.post('/api/login', {
username: username,
password: password
}).success(function(data) {
AuthToken.setToken(data.token);
return data;
})
}
authFactory.getUser = function() {
if (AuthToken.getToken()) {
return $http.get('/api/me');
} else {
return $q.reject({message: 'unable to get data'});
}
}
return authFactory;
});
authService.factory('AuthToken', function($window) {
var authTokenFactory = {};
authTokenFactory.getToken = function() {
return $window.localStorage.getItem('token');
}
authTokenFactory.setToken = function(token) {
if (token) {
$window.localStorage.setItem('token', token);
} else {
$window.localStorage.removeItem('token');
}
}
return authTokenFactory;
});
authService.factory('AuthInterceptor', function($q, $location, AuthToken) {
var interceptorFactory = {};
interceptorFactory.request = function(config) {
var token = AuthToken.getToken();
if(token) {
config.headers['x-access-token'] = token;
}
return config;
};
interceptorFactory.responseError = function(response) {
if (response.status === 403) {
$location.path('/login');
return $q.reject(response);
}
}
});
mainController:
angular.module('MainController', [])
.controller('mainController', ['$rootScope','$location','Auth', function($rootScope,$location, Auth) {
var vm = this;
vm.isLoggedIn = Auth.isLogged();
$rootScope.$on('$routeChangeStart', function() {
vm.isLoggedIn = Auth.isLogged();
Auth.getUser().then(function(data) {
vm.user = data.data;
})
})
vm.login = function() {
vm.error = '';
Auth.login(vm.loginData.username, vm.loginData.password)
.then(function(data) {
Auth.getUser()
.then(function(data) {
vm.user = data.data;
});
if (data.success) {
$location.path('/');
} else {
vm.error = data.message;
console.log(vm.error);
}
});
}
index.html:
<!DOCTYPE html>
<html ng-app="myApp">
<base href="/">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script src="https://code.angularjs.org/1.4.0-rc.1/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.0-rc.1/angular-route.min.js"></script>
<!--angular services -->
<script src="app/auth/authService.js"></script>
<!--angular controllers -->
<script src="app/controllers/mainController.js"></script>
<script src="app/app.routes.js"></script>
<script src="app/app.js"></script>
</head>
<body>
<div class="container">
<div ng-view></div>
</div>
</body>
</html>
login.html:
<div class="container" ng-controller="mainController as login">
<form method="post" ng-submit="login.login()">
username: <input type="text" name="username" ng-model="login.loginData.username">
password: <input type="password" name="password" ng-model="login.loginData.password">
<button type="submit" class="btn btn-success">submit</button>
</form>
</div>
further code will be made available upon request. I will be truly grateful for any help as I have spent countless hours trying to solve this problem.
I guess the redirection is happening before the getting the data:
vm.login = function() {
vm.error = '';
Auth.login(vm.loginData.username, vm.loginData.password)
.then(function(resp) { // <------changed the arg to 'resp'
Auth.getUser()
.then(function(data) {
vm.user = data.data;
if (resp.success) { // <------put the condition here with 'resp'
$location.path('/');
} else {
vm.error = resp.message;
console.log(vm.error);
}
});
});
}
Another change i can suggest you to use .then() instead of .success() here:
return $http.post('/api/login', {
username: username,
password: password
}).then(function(data) { // <--------change to `.then()`
AuthToken.setToken(data.token);
return data;
})
I can't add metadata to the customer object when creating a new subscription/customer with stripe. Update: The problem I'm having is that the metadata does not save to the customer object. I don't see it in stripe in the logs/events.
// Stripe Response Handler
$scope.stripeCallback = function (code, result) {
result.email = $scope.email;
result.metadata = {'team': $scope.team};
if (result.error) {
window.alert('it failed! error: ' + result.error.message);
} else {
$http.post('/charge', result)
.success(function(data, status, headers, config) {
alert('success');
})
.error(function(data, status, headers, config) {
// console.log(status);
alert('error');
});
}
};
//on the server
app.post('/charge', function(req, res) {
var stripeToken = req.body.id;
var email = req.body.email;
var team = req.body.team;
subscribeUser(stripeToken, res, email, team);
});
// for subscriptions:
function subscribeUser(token, res, email, team){
stripe.customers.create({
card: token,
plan: '001',
email: email,
metadata: team
}, function(err, customer) {
var cust = customer.id;
// you'll probably want to store a reference (customer.id) to the customer
if (err) {
res.send({
ok: false, message: 'There was a problem processing your card (error: ' + JSON.stringify(err) + ')'});
} else {
res.send({
ok: true, message: 'You have been subscribed to a plan!'});
}
});
}
Any ideas would be much appreciated.
In case this helps somebody else, I made a few dumb mistakes:
You need to be sure you are added it to the metadata property
result.metadata = {'team': $scope.team};
You need to make sure you grab the metadata
var team = req.body.metadata;
You need to pass it in as metadata
metadata: team
I've been trying to handle a responded error message with jQuery on Sails.
I'm using a js file(login.js) to login website and using another js file named SessionController to hold my logic code.
Firstly, a jquery POST method in my login.js file is sending a request.
Secondly, deliberately, i'm trying to enter wrong username or password. But I can't handle error messages in the POST method.
The below codes return 'Forbidden' as error parameter and 'null' as xhr.getResponseHeader('error'). But I've expected "Username error" or "Password error".
What should I do? I'm open to advices...
My login.js file
$(document).ready(function(){
$("#btn-login").click(function() {
var username = $("#username").val();
var password = $("#password").val();
if(!username) {
} else if(!password) {
} else {
// alert('It"s continuing to POST');
$.post(
'/login',
{ username: username, password: password },
function() {
window.location = "/user/show/"
}).fail(function(xhr, textStatus, error){
alert('xhr.statusText: ' + xhr.statusText);
alert('textStatus: ' + textStatus);
alert('error: ' + error);
// $("#popupPaddedMessage").text("Error: " + xhr.getResponseHeader('error'));
// $("#popupPadded").popup("open", { positionTo: "window" });
});
}
});
});
My SessionController js file
module.exports = {
create: function(req, res, next) {
User.native(function(err, collectionUser) {
if(err) { return err; };
if(!collectionUser) { return err; };
collectionUser
.find({'username' : req.param('username')})
.nextObject(function (err, user) {
if(err) {
res.send(500, { error: "Database error"});
};
if(!user) {
res.send(400, { error: "Username error"});
};
if(user) {
if(user.password === req.param('password')) {
req.session.user = user;
res.send(user);
//res.redirect('/user/show/' + user[0]._id);
} else {
res.send(400, { error: "Password error"});
}
};
});
});
}
};