Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,21 @@ var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var expressHbs = require('express-handlebars');
var mongoose = require('mongoose');
var session = require('express-session');
var passport = require('passport');
var flash = require('connect-flash');
var validator = require('express-validator');
var MongoStore = require('connect-mongo')(session);

var routes = require('./routes/index');
var userRoutes = require('./routes/user');

var app = express();

mongoose.connect('localhost:27017/shopping');
require('./config/passport');

// view engine setup
app.engine('.hbs', expressHbs({defaultLayout: 'layout', extname: '.hbs'}));
app.set('view engine', '.hbs');
Expand All @@ -19,9 +29,27 @@ app.set('view engine', '.hbs');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(validator());
app.use(cookieParser());
app.use(session({
secret: 'mysupersecret',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection }),
cookie: { maxAge: 180 * 60 * 1000 }
}));
app.use(flash());
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));

app.use(function(req, res, next) {
res.locals.login = req.isAuthenticated();
res.locals.session = req.session;
next();
});

app.use('/user', userRoutes);
app.use('/', routes);

// catch 404 and forward to error handler
Expand Down
76 changes: 76 additions & 0 deletions config/passport.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
var passport = require('passport');
var User = require('../models/user');
var LocalStrategy = require('passport-local').Strategy;

passport.serializeUser(function (user, done) {
done(null, user.id);
});

passport.deserializeUser(function (id, done) {
User.findById(id, function (err, user) {
done(err, user);
});
});

passport.use('local.signup', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function (req, email, password, done) {
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Invalid password').notEmpty().isLength({min:4});
var errors = req.validationErrors();
if (errors) {
var messages = [];
errors.forEach(function(error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({'email': email}, function (err, user) {
if (err) {
return done(err);
}
if (user) {
return done(null, false, {message: 'Email is already in use.'});
}
var newUser = new User();
newUser.email = email;
newUser.password = newUser.encryptPassword(password);
newUser.save(function(err, result) {
if (err) {
return done(err);
}
return done(null, newUser);
});
});
}));

passport.use('local.signin', new LocalStrategy({
usernameField: 'email',
passwordField: 'password',
passReqToCallback: true
}, function(req, email, password, done) {
req.checkBody('email', 'Invalid email').notEmpty().isEmail();
req.checkBody('password', 'Invalid password').notEmpty();
var errors = req.validationErrors();
if (errors) {
var messages = [];
errors.forEach(function(error) {
messages.push(error.msg);
});
return done(null, false, req.flash('error', messages));
}
User.findOne({'email': email}, function (err, user) {
if (err) {
return done(err);
}
if (!user) {
return done(null, false, {message: 'No user found.'});
}
if (!user.validPassword(password)) {
return done(null, false, {message: 'Wrong password.'});
}
return done(null, user);
});
}));
41 changes: 41 additions & 0 deletions models/cart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module.exports = function Cart(oldCart) {
this.items = oldCart.items || {};
this.totalQty = oldCart.totalQty || 0;
this.totalPrice = oldCart.totalPrice || 0;

this.add = function(item, id) {
var storedItem = this.items[id];
if (!storedItem) {
storedItem = this.items[id] = {item: item, qty: 0, price: 0};
}
storedItem.qty++;
storedItem.price = storedItem.item.price * storedItem.qty;
this.totalQty++;
this.totalPrice += storedItem.item.price;
};

this.reduceByOne = function(id) {
this.items[id].qty--;
this.items[id].price -= this.items[id].item.price;
this.totalQty--;
this.totalPrice -= this.items[id].item.price;

if (this.items[id].qty <= 0) {
delete this.items[id];
}
};

this.removeItem = function(id) {
this.totalQty -= this.items[id].qty;
this.totalPrice -= this.items[id].price;
delete this.items[id];
};

this.generateArray = function() {
var arr = [];
for (var id in this.items) {
arr.push(this.items[id]);
}
return arr;
};
};
12 changes: 12 additions & 0 deletions models/order.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var schema = new Schema({
user: {type: Schema.Types.ObjectId, ref: 'User'},
cart: {type: Object, required: true},
address: {type: String, required: true},
name: {type: String, required: true},
paymentId: {type: String, required: true}
});

module.exports = mongoose.model('Order', schema);
11 changes: 11 additions & 0 deletions models/product.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var schema = new Schema({
imagePath: {type: String, required: true},
title: {type: String, required: true},
description: {type: String, required: true},
price: {type: Number, required: true}
});

module.exports = mongoose.model('Product', schema);
18 changes: 18 additions & 0 deletions models/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt-nodejs');

var userSchema = new Schema({
email: {type: String, required: true},
password: {type: String, required: true}
});

userSchema.methods.encryptPassword = function(password) {
return bcrypt.hashSync(password, bcrypt.genSaltSync(5), null);
};

userSchema.methods.validPassword = function(password) {
return bcrypt.compareSync(password, this.password);
};

module.exports = mongoose.model('User', userSchema);
45 changes: 45 additions & 0 deletions npm-debug.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'start' ]
2 info using npm@3.9.0
3 info using node@v5.6.0
4 verbose run-script [ 'prestart', 'start', 'poststart' ]
5 info lifecycle shopping-cart@0.0.0~prestart: shopping-cart@0.0.0
6 silly lifecycle shopping-cart@0.0.0~prestart: no script for prestart, continuing
7 info lifecycle shopping-cart@0.0.0~start: shopping-cart@0.0.0
8 verbose lifecycle shopping-cart@0.0.0~start: unsafe-perm in lifecycle true
9 verbose lifecycle shopping-cart@0.0.0~start: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/Users/maximilianschwarzmuller/development/node/tutorials/youtube/shopping-cart/node_modules/.bin:/usr/local/bin:/users/maximilianschwarzmuller/.composer/vendor/laravel:/Applications/anaconda/bin:/usr/local/mysql/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/git/bin
10 verbose lifecycle shopping-cart@0.0.0~start: CWD: /Users/maximilianschwarzmuller/development/node/tutorials/youtube/shopping-cart
11 silly lifecycle shopping-cart@0.0.0~start: Args: [ '-c', 'node ./bin/www' ]
12 silly lifecycle shopping-cart@0.0.0~start: Returned: code: 1 signal: null
13 info lifecycle shopping-cart@0.0.0~start: Failed to exec start script
14 verbose stack Error: shopping-cart@0.0.0 start: `node ./bin/www`
14 verbose stack Exit status 1
14 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:245:16)
14 verbose stack at emitTwo (events.js:100:13)
14 verbose stack at EventEmitter.emit (events.js:185:7)
14 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14)
14 verbose stack at emitTwo (events.js:100:13)
14 verbose stack at ChildProcess.emit (events.js:185:7)
14 verbose stack at maybeClose (internal/child_process.js:827:16)
14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5)
15 verbose pkgid shopping-cart@0.0.0
16 verbose cwd /Users/maximilianschwarzmuller/development/node/tutorials/youtube/shopping-cart
17 error Darwin 15.5.0
18 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "start"
19 error node v5.6.0
20 error npm v3.9.0
21 error code ELIFECYCLE
22 error shopping-cart@0.0.0 start: `node ./bin/www`
22 error Exit status 1
23 error Failed at the shopping-cart@0.0.0 start script 'node ./bin/www'.
23 error Make sure you have the latest version of node.js and npm installed.
23 error If you do, this is most likely a problem with the shopping-cart package,
23 error not with npm itself.
23 error Tell the author that this fails on your system:
23 error node ./bin/www
23 error You can get information on how to open an issue for this project with:
23 error npm bugs shopping-cart
23 error Or if that isn't available, you can get their info via:
23 error npm owner ls shopping-cart
23 error There is likely additional logging output above.
24 verbose exit [ 1, true ]
12 changes: 11 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,23 @@
"start": "node ./bin/www"
},
"dependencies": {
"bcrypt-nodejs": "0.0.3",
"body-parser": "~1.13.2",
"connect-flash": "^0.1.1",
"connect-mongo": "^1.2.0",
"cookie-parser": "~1.3.5",
"csurf": "^1.8.3",
"debug": "~2.2.0",
"express": "~4.13.1",
"express-handlebars": "^3.0.0",
"express-session": "^1.13.0",
"express-validator": "^2.20.5",
"hbs": "~3.1.0",
"mongoose": "^4.4.16",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0"
"passport": "^0.3.2",
"passport-local": "^1.0.0",
"serve-favicon": "~2.3.0",
"stripe": "^4.7.0"
}
}
38 changes: 38 additions & 0 deletions public/javascripts/checkout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Stripe.setPublishableKey('pk_test_m6ZWLYyvkUAqJzr1fvr1uRj2');

var $form = $('#checkout-form');

$form.submit(function (event) {
$('#charge-error').addClass('hidden');
$form.find('button').prop('disabled', true);
Stripe.card.createToken({
number: $('#card-number').val(),
cvc: $('#card-cvc').val(),
exp_month: $('#card-expiry-month').val(),
exp_year: $('#card-expiry-year').val(),
name: $('#card-name').val()
}, stripeResponseHandler);
return false;
});

function stripeResponseHandler(status, response) {
if (response.error) { // Problem!

// Show the errors on the form
$('#charge-error').text(response.error.message);
$('#charge-error').removeClass('hidden');
$form.find('button').prop('disabled', false); // Re-enable submission

} else { // Token was created!

// Get the token ID:
var token = response.id;

// Insert the token into the form so it gets submitted to the server:
$form.append($('<input type="hidden" name="stripeToken" />').val(token));

// Submit the form:
$form.get(0).submit();

}
}
Loading