Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

episode 17

  • Loading branch information...
commit bbb8e3aff90a02ca2d82e28d79daf2b5bd6ef247 1 parent 480ed88
alessioalex authored
View
12 making_modules/random_string.js
@@ -0,0 +1,12 @@
+module.exports = function(string_length) {
+ if(string_length == 0) {
+ string_length = 6;
+ }
+ var chars="abcdefghijklmnopqrstuwvxyz";
+ var randomString = '';
+ for(var i=0; i<string_length; i++) {
+ var rnum = Math.floor(Math.random() * chars.length);
+ randomString += chars.substring(rnum, rnum+1);
+ }
+ return randomString;
+}
View
22 making_modules/random_string_generator/index.js
@@ -0,0 +1,22 @@
+var RandomStringGenerator = function(string_length) {
+ this.string_length = string_length || 6;
+};
+
+RandomStringGenerator.prototype.generate = function() {
+ var chars="abcdefghijklmnopqrstuwvxyz";
+ var randomString = '';
+ for(var i=0; i<this.string_length; i++) {
+ var rnum = Math.floor(Math.random() * chars.length);
+ randomString += chars.substring(rnum, rnum+1);
+ }
+ return randomString;
+};
+
+module.exports = RandomStringGenerator;
+
+module.exports.create = function(string_length) {
+ return new RandomStringGenerator(string_length);
+};
+
+// for inheritance, open for extension
+module.exports._class = RandomStringGenerator;
View
211 mongodb_mongoose/app.js
@@ -0,0 +1,211 @@
+var express = require('express'),
+ form = require('connect-form'),
+ fs = require('fs'),
+ util = require('util');
+
+var app = express.createServer(
+ form({keepExtensions: true})
+);
+
+// switch between development and production like this:
+// NODE_ENV=development node app.js
+// OR
+// NODE_ENV=production node app.js
+
+var MemStore = express.session.MemoryStore;
+
+// this always executes, no matter of production or dev environment
+app.configure(function(){
+ // this logs in a Apache style
+ // app.use(express.logger());
+ app.use(express.bodyParser());
+ // this middleware will override our method
+ // with what we passed into the hidden variable _method
+ app.use(express.methodOverride());
+ // methodOverride must be after the bodyParser
+ app.use(express.static(__dirname + '/static'));
+ app.use(express.cookieParser());
+ app.use(express.session({secret: 'alessios', store: MemStore({
+ reapInterval: 60000 * 10
+ })}));
+});
+
+app.configure('development', function() {
+ app.use(express.logger());
+ // this is the error handler, uncomment #1 to see it in action
+ app.use(express.errorHandler({
+ dumpExceptions: true,
+ showStack : true
+ }))
+});
+
+app.configure('production', function() {
+ // this is the error handler for the production env
+ app.use(express.errorHandler({
+ dumpExceptions: false,
+ showStack: false
+ }));
+});
+
+function requiresLogin(req, res, next) {
+ if(req.session.user) {
+ next();
+ } else {
+ res.redirect('/sessions/new?redir=' + req.url);
+ }
+}
+
+app.set('views', __dirname + '/views');
+app.set('view engine', 'jade')
+// this is by default ->
+// app.set('view options', {layout: true});
+// if you don't want to have a layout though:
+// app.set('view options', {layout: false});
+
+//Registers dynamic view helpers. Dynamic view helpers are simply functions which accept req, res, and are evaluated against the Server instance before a view is rendered. The return value of this function becomes the local variable it is associated with.
+app.dynamicHelpers({
+ session: function(req, res){
+ return req.session;
+ },
+ flash: function(req, res){
+ return req.flash();
+ }
+});
+
+
+app.get('/', function(req, res) {
+ // #1
+ // throw new Error('this is just my custom error');
+ // res.send('some text');
+ res.render('root');
+});
+
+/* Sessions */
+
+app.get('/sessions/new', function(req, res) {
+ res.render('sessions/new', {locals: {
+ redir: req.query.redir
+ }});
+});
+
+app.get('/sessions/destroy', function(req, res) {
+ delete req.session.user;
+ res.redirect('/sessions/new');
+});
+
+var users = require('./users');
+
+app.post('/sessions', function(req, res) {
+ //console.log('User: ' + req.body.login + '; Pwd: ' + req.body.password);
+ users.authenticate(req.body.login, req.body.password, function(user){
+ if(user) {
+ req.session.user = user;
+ res.redirect(req.body.redir || '/');
+ } else {
+ req.flash('warn', 'Login failed');
+ res.render('sessions/new', {locals: {
+ redir: req.query.redir
+ }});
+ }
+ });
+});
+
+var products = require('./products');
+var photos = require('./photos');
+
+app.get('/products', function(req, res) {
+ res.render('products/index', {locals: {
+ products: products.all
+ }});
+});
+
+app.get('/products/new', requiresLogin, function(req, res){
+ res.render('products/new', {locals: {
+ product: req.body && req.body.product || products.new
+ }});
+});
+
+app.post('/products', requiresLogin, function(req, res) {
+ var id = products.insert(req.body.product);
+ console.log(products.find(id));
+ res.redirect('/products/' + id);
+});
+
+app.get('/products/:id', function(req, res) {
+ var product = products.find(req.params.id);
+ if(product != null) {
+ res.render('products/show', {locals: {
+ product: product
+ }});
+ } else {
+ res.send('404 - Product not found!')
+ }
+});
+
+app.get('/products/:id/edit', requiresLogin, function(req, res) {
+ var product = products.find(req.params.id);
+ if(product != null) {
+ photos.list(function(err, photo_list) {
+ if(err) {
+ throw err;
+ } else {
+ res.render('products/edit', {locals: {
+ product: product,
+ photos: photo_list
+ }});
+ }
+ });
+ } else {
+ res.send('404 - Product not found!')
+ }
+});
+
+app.put('/products/:id', requiresLogin, function(req,res) {
+ var id = req.params.id;
+ products.set(id, req.body.product);
+ // req.body.product comes from bodyParser
+ res.redirect('/products/' + id);
+});
+
+/* Photos */
+
+app.get('/photos', function(req, res) {
+ photos.list(function(err, photo_list) {
+ res.render('photos/index', {locals : {
+ photos: photo_list
+ }});
+ });
+});
+
+app.get('/photos/new', function(req, res) {
+ res.render('photos/new');
+});
+
+app.post('/photos', function(req, res) {
+ req.form.complete(function(err, fields, files) {
+ if(err) {
+ next(err);
+ } else {
+ ins = fs.createReadStream(files.photo.path);
+ ous = fs.createWriteStream(__dirname + '/static/uploads/photos/' + files.photo.filename);
+ util.pump(ins, ous, function(err) {
+ if(err) {
+ next(err);
+ } else {
+ res.redirect('/photos');
+ }
+ });
+ //console.log('\nUploaded %s to %s', files.photo.filename, files.photo.path);
+ //res.send('Uploaded ' + files.photo.filename + ' to ' + files.photo.path);
+ }
+ });
+});
+
+/* 404 redirect here */
+app.get('*', function(req, res) {
+ res.send('404 - no such page');
+});
+
+app.listen(4000);
+
+console.log('Server listening on port 4000');
View
13 mongodb_mongoose/photos.js
@@ -0,0 +1,13 @@
+var fs = require('fs'),
+ src_path = __dirname + '/static/uploads/photos/';
+
+module.exports.list = function(callback) {
+ fs.readdir(src_path, function(err, files) {
+ var ret_files = [];
+ files.forEach(function(file){
+ ret_files.push('/uploads/photos/' + file);
+ });
+ console.log(ret_files);
+ callback(err, ret_files);
+ });
+}
View
50 mongodb_mongoose/products.js
@@ -0,0 +1,50 @@
+products = [
+{
+ id: 1,
+ name: 'Mac Book Pro',
+ description: 'Apple 13 inch Mac Book Pro Notebook',
+ price: 1000
+},
+{
+ id: 2,
+ name: 'iPad',
+ description: 'Apple 64GB 3G iPad',
+ price: 899
+}
+];
+
+module.exports.all = products;
+
+module.exports.find = function(id) {
+ id = parseInt(id, 10);
+ var found = null;
+ productloop: for(product_index in products) {
+ var product = products[product_index];
+ if(product.id == id) {
+ found = product;
+ break productloop;
+ }
+ };
+ return found;
+}
+
+module.exports.set = function(id, product) {
+ id = parseInt(id, 10);
+ product.id = id;
+ products[id -1] = product;
+}
+
+module.exports.new = function() {
+ return {
+ name: '',
+ description: '',
+ price: 0
+ };
+}
+
+module.exports.insert = function(product) {
+ var id = products.length + 1;
+ product.id = id;
+ products[id-1] = product;
+ return id;
+}
View
85 mongodb_mongoose/run_dev_app.js
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the Spludo Framework.
+ * Copyright (c) 2009-2010 DracoBlue, http://dracoblue.net/
+ *
+ * Licensed under the terms of MIT License. For the full copyright and license
+ * information, please see the LICENSE file in the root folder.
+ */
+
+var child_process = require('child_process');
+var fs = require("fs");
+var sys = require("sys");
+
+dev_server = {
+
+ process: null,
+
+ files: [],
+
+ restarting: false,
+
+ "restart": function() {
+ this.restarting = true;
+ sys.debug('DEVSERVER: Stopping server for restart');
+ this.process.kill();
+ },
+
+ "start": function() {
+ var self = this;
+ sys.debug('DEVSERVER: Starting server');
+ self.watchFiles();
+
+ this.process = child_process.spawn(process.ARGV[0], ['app.js']);
+
+ this.process.stdout.addListener('data', function (data) {
+ process.stdout.write(data);
+ });
+
+ this.process.stderr.addListener('data', function (data) {
+ sys.print(data);
+ });
+
+ this.process.addListener('exit', function (code) {
+ sys.debug('DEVSERVER: Child process exited: ' + code);
+ this.process = null;
+ if (self.restarting) {
+ self.restarting = true;
+ self.unwatchFiles();
+ self.start();
+ }
+ });
+
+ },
+
+ "watchFiles": function() {
+ var self = this;
+
+ child_process.exec('find . | grep "\.js$"', function(error, stdout, stderr) {
+ var files = stdout.trim().split("\n");
+
+ files.forEach(function(file) {
+ self.files.push(file);
+ fs.watchFile(file, {interval : 500}, function(curr, prev) {
+ if (curr.mtime.valueOf() != prev.mtime.valueOf() || curr.ctime.valueOf() != prev.ctime.valueOf()) {
+ sys.debug('DEVSERVER: Restarting because of changed file at ' + file);
+ dev_server.restart();
+ }
+ });
+ });
+ });
+ },
+
+ "unwatchFiles": function() {
+ this.files.forEach(function(file) {
+ fs.unwatchFile(file);
+ });
+ this.files = [];
+ }
+}
+
+
+dev_server.start();
+
+
+
+
View
27 mongodb_mongoose/static/stylesheets/styles.css
@@ -0,0 +1,27 @@
+body {
+ font-family: Helvetica, Arial, Sans-Serif;
+ font-size: 16px;
+}
+#main {
+ width: 960px;
+ margin: 0 auto;
+ border: 1px solid #ddd;
+ padding: 1em;
+}
+#header {
+ float: right;
+ clear: both;
+}
+#user {
+ float: left;
+ margin-right: 1em;
+}
+#logout {
+ float: left;
+}
+#warn {
+ padding: 1em;
+ border: 1px solid red;
+ background: #fdd;
+ color: red;
+}
View
BIN  mongodb_mongoose/static/uploads/photos/logo_jquery_215x53.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  mongodb_mongoose/static/uploads/photos/nodejs_logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
16 mongodb_mongoose/users.js
@@ -0,0 +1,16 @@
+var users = {
+ 'pedro': {login: 'pedro', password: 'test', role: 'admin'},
+ 'alessio': {login: 'alessio', password: 'ronaldo', role: 'user'}
+};
+module.exports.authenticate = function(login, password, callback) {
+ var user = users[login];
+ if(!user) {
+ callback(null);
+ return;
+ }
+ if(user.password == password) {
+ callback(user);
+ return;
+ }
+ callback(null);
+}
View
15 mongodb_mongoose/views/layout.jade
@@ -0,0 +1,15 @@
+!!! 5
+html
+ head
+ link(rel='stylesheet',href='/stylesheets/styles.css')
+ title My template
+ body
+ #main
+ #header
+ - if(session.user)
+ #user= 'logged in as ' + session.user.login
+ #logout
+ a(href='/sessions/destroy') logout
+ - if(flash.warn)
+ p#warn= flash.warn
+ #container!= body
View
4 mongodb_mongoose/views/partials/photo_form.jade
@@ -0,0 +1,4 @@
+p
+ label(for='photo') Photo:
+p
+ input(type='file', name='photo')
View
9 mongodb_mongoose/views/partials/product.jade
@@ -0,0 +1,9 @@
+h2= product.name
+p= product.description
+p Price: #{product.price}
+p
+ a(href='/products/' + product.id) Details
+- if(product.photo)
+ p
+ img(src=product.photo)
+
View
20 mongodb_mongoose/views/partials/product_form.jade
@@ -0,0 +1,20 @@
+p
+ label(for='product_name') Name:
+p
+ input(type='text', id='product_name', name='product[name]', value=product.name)
+p
+ label(for='product_description') Description
+p
+ textarea(id='product_description', name='product[description]')= product.description
+p
+ label(for='product_price') Price:
+p
+ input(type='text', id='product_price', name='product[price]', value=product.price)
+p
+ label(for='product_photo') Photo:
+p
+ select(id='product_photo', name='product[photo]')
+ - each photo in photos
+ option(value=photo, selected=(product.photo == photo))= photo
+p
+ input(type='submit')
View
7 mongodb_mongoose/views/photos/index.jade
@@ -0,0 +1,7 @@
+h1 Photos:
+p
+ a(href='/photos/new') Create
+ul
+ - each photo in photos
+ li
+ img(src=photo)
View
4 mongodb_mongoose/views/photos/new.jade
@@ -0,0 +1,4 @@
+h1 New Photo
+form(action='/photos', method='POST', enctype='multipart/form-data')!= partial('../partials/photo_form')
+ p
+ input(type='submit')
View
5 mongodb_mongoose/views/products/edit.jade
@@ -0,0 +1,5 @@
+h1='Editing ' + product.name
+form(action='/products/' + product.id, method='POST')
+ input(type='hidden', name='_method', value='PUT')
+ div!= partial('../partials/product_form', {locals: {product: product}})
+
View
4 mongodb_mongoose/views/products/index.jade
@@ -0,0 +1,4 @@
+h1 Products:
+#products!= partial('../partials/product', {collection: products})
+p
+ a(href='/products/new') New
View
2  mongodb_mongoose/views/products/new.jade
@@ -0,0 +1,2 @@
+h1 New product
+form(action='/products', method='POST')!= partial('../partials/product_form', {locals: {product: product}})
View
7 mongodb_mongoose/views/products/show.jade
@@ -0,0 +1,7 @@
+h2= product.name
+p= product.description
+p Price: #{product.price}
+p
+ a(href='/products') Back
+p
+ a(href='/products/' + product.id + '/edit') Edit
View
2  mongodb_mongoose/views/root.jade
@@ -0,0 +1,2 @@
+h2 Hello
+p World
View
10 mongodb_mongoose/views/sessions/new.jade
@@ -0,0 +1,10 @@
+h1 Login
+form(action='/sessions', method='POST')
+ input(type='hidden', name='redir', value=redir)
+ p
+ label(for='login') Login:
+ input(type='text', name='login', id='login')
+ p
+ label(for='password') Password:
+ input(type='text', name='password', id='password')
+ input(type='submit')
Please sign in to comment.
Something went wrong with that request. Please try again.