├── .gitignore ├── README.md ├── ejercicios ├── blog │ ├── package.json │ ├── public │ │ └── css │ │ │ ├── normalize.css │ │ │ └── styles.css │ ├── server.js │ ├── simpleAuth.js │ └── views │ │ ├── layout.jade │ │ ├── new-post.jade │ │ ├── post-detail.jade │ │ └── post-list.jade ├── code.js ├── cp.js ├── cuentalineas.js ├── digg_clone │ ├── app.js │ ├── bin │ │ └── start │ ├── models │ │ ├── comment.js │ │ ├── index.js │ │ ├── post.js │ │ ├── user.js │ │ └── utils.js │ ├── package.json │ ├── public │ │ ├── assets │ │ │ ├── javascripts │ │ │ │ ├── libs │ │ │ │ │ ├── jquery-1.9.0.min.js │ │ │ │ │ └── modernizr-2.6.1.min.js │ │ │ │ └── script.js │ │ │ └── stylesheets │ │ │ │ ├── mixins.css │ │ │ │ └── screen.css │ │ ├── code.js │ │ ├── img │ │ │ └── loading.gif │ │ ├── index.html │ │ └── lib │ │ │ ├── backbone.js │ │ │ ├── jquery.js │ │ │ ├── prelude.js │ │ │ └── underscore.js │ ├── routes │ │ ├── comments.js │ │ ├── posts.js │ │ ├── resources.js │ │ └── users.js │ └── simpleauth.js ├── esqueletoSimpleAuth.js ├── events.js ├── fakePromise.js ├── flashMessages.js ├── fsstatpromise.js ├── hola-mundo.js ├── hola.js ├── nodefcall.js ├── nodefcallPromise.js ├── nodeinvoke.js ├── nodeinvokePromise.js ├── promiseGarden1.js ├── public │ └── test.txt ├── readAllfiles.js ├── readFilePromise.js ├── reloj.js ├── simpleAuth.js ├── slowLogger.js ├── static.js ├── staticPromise.js ├── staticPromise2.js ├── staticPromise3.js └── test.js ├── soluciones ├── tema1 │ ├── abtesting │ │ ├── config.js │ │ ├── public │ │ │ ├── A │ │ │ │ ├── css │ │ │ │ │ └── styles.css │ │ │ │ ├── foto.jpg │ │ │ │ ├── images │ │ │ │ │ ├── avatar.png │ │ │ │ │ ├── icon.png │ │ │ │ │ └── logo.png │ │ │ │ └── index.html │ │ │ ├── B │ │ │ │ ├── css │ │ │ │ │ └── styles.css │ │ │ │ ├── foto.jpg │ │ │ │ ├── images │ │ │ │ │ ├── avatar.png │ │ │ │ │ ├── icon.png │ │ │ │ │ └── logo.png │ │ │ │ └── index.html │ │ │ ├── C │ │ │ │ ├── css │ │ │ │ │ └── styles.css │ │ │ │ ├── foto.jpg │ │ │ │ ├── images │ │ │ │ │ ├── avatar.png │ │ │ │ │ ├── icon.png │ │ │ │ │ └── logo.png │ │ │ │ └── index.html │ │ │ ├── D │ │ │ │ ├── css │ │ │ │ │ └── styles.css │ │ │ │ ├── images │ │ │ │ │ ├── avatar.png │ │ │ │ │ ├── icon.png │ │ │ │ │ └── logo.png │ │ │ │ └── index.html │ │ │ ├── statsPage.html │ │ │ └── success.png │ │ └── server.js │ ├── captcha │ │ ├── client.js │ │ ├── package.json │ │ ├── server.js │ │ └── templates │ │ │ └── form.html │ ├── discarded │ │ └── transfer │ │ │ ├── package.json │ │ │ ├── public │ │ │ ├── client.html │ │ │ └── source.html │ │ │ ├── server.js │ │ │ └── templates │ │ │ ├── client-waiting.html │ │ │ └── waiting.html │ ├── httpWorld.js │ ├── simpleRouting │ │ ├── 1 │ │ │ └── simpleRouting.js │ │ ├── 2 │ │ │ ├── joust.jpg │ │ │ └── simpleRouting.js │ │ ├── 3 │ │ │ ├── public │ │ │ │ └── joust.jpg │ │ │ └── simpleRouting.js │ │ └── 4 │ │ │ └── simpleRouting.js │ ├── tiles │ │ ├── package.json │ │ ├── public │ │ │ ├── client.js │ │ │ ├── dimension.png │ │ │ ├── index.html │ │ │ ├── jquery.js │ │ │ └── map.jpg │ │ └── server.js │ └── watermark │ │ ├── package.json │ │ ├── public │ │ ├── mark.png │ │ └── programador.png │ │ └── server.js ├── tema2 │ ├── gitversionedserver │ │ ├── package.json │ │ ├── server.js │ │ └── simpleRoute.js │ ├── logger │ │ ├── access.log │ │ ├── public │ │ │ └── test.txt │ │ └── server.js │ └── versionedserver │ │ ├── package.json │ │ ├── server.js │ │ └── simpleRoute.js ├── tema3 │ ├── blogAuth │ │ ├── package.json │ │ ├── public │ │ │ └── css │ │ │ │ ├── normalize.css │ │ │ │ └── styles.css │ │ ├── server.js │ │ ├── simpleauth.js │ │ └── views │ │ │ ├── layout.jade │ │ │ ├── login.jade │ │ │ ├── new-post.jade │ │ │ ├── post-detail.jade │ │ │ ├── post-list.jade │ │ │ └── register.jade │ └── simpleAuthModule │ │ ├── app.js │ │ ├── package.json │ │ ├── public │ │ └── login.html │ │ └── simpleauth.js ├── tema4 │ └── urlshort │ │ ├── .gitignore │ │ ├── package.json │ │ ├── public │ │ └── css │ │ │ ├── normalize.css │ │ │ └── styles.css │ │ ├── server.js │ │ ├── simpleauth.js │ │ └── views │ │ ├── layout.jade │ │ ├── login.jade │ │ ├── register.jade │ │ ├── url-form.jade │ │ ├── url-index.jade │ │ └── url-show.jade ├── tema5 │ ├── digg_clone_bluebird │ │ ├── app.js │ │ ├── bin │ │ │ └── start │ │ ├── data │ │ │ └── db │ │ │ │ └── .gitinclude │ │ ├── models │ │ │ ├── comment.js │ │ │ ├── index.js │ │ │ ├── post.js │ │ │ ├── user.js │ │ │ └── utils.js │ │ ├── package.json │ │ ├── public │ │ │ ├── assets │ │ │ │ ├── javascripts │ │ │ │ │ ├── libs │ │ │ │ │ │ ├── jquery-1.9.0.min.js │ │ │ │ │ │ └── modernizr-2.6.1.min.js │ │ │ │ │ └── script.js │ │ │ │ └── stylesheets │ │ │ │ │ ├── mixins.css │ │ │ │ │ └── screen.css │ │ │ ├── code.js │ │ │ ├── img │ │ │ │ └── loading.gif │ │ │ ├── index.html │ │ │ └── lib │ │ │ │ ├── backbone.js │ │ │ │ ├── jquery.js │ │ │ │ ├── prelude.js │ │ │ │ └── underscore.js │ │ ├── routes │ │ │ ├── comments.js │ │ │ ├── posts.js │ │ │ └── users.js │ │ └── simpleauth.js │ └── diggclone │ │ ├── package.json │ │ ├── public │ │ ├── assets │ │ │ ├── javascripts │ │ │ │ ├── libs │ │ │ │ │ ├── jquery-1.9.0.min.js │ │ │ │ │ └── modernizr-2.6.1.min.js │ │ │ │ └── script.js │ │ │ └── stylesheets │ │ │ │ ├── mixins.css │ │ │ │ └── screen.css │ │ ├── build │ │ │ ├── assets │ │ │ │ ├── javascripts │ │ │ │ │ ├── libs │ │ │ │ │ │ ├── jquery-1.9.0.min.js │ │ │ │ │ │ └── modernizr-2.6.1.min.js │ │ │ │ │ └── script.js │ │ │ │ └── stylesheets │ │ │ │ │ ├── mixins.css │ │ │ │ │ └── screen.css │ │ │ ├── detail.html │ │ │ ├── index.html │ │ │ └── listado.html │ │ ├── code.js │ │ ├── img │ │ │ └── loading.gif │ │ ├── index.html │ │ ├── lib │ │ │ ├── backbone.js │ │ │ ├── jquery.js │ │ │ ├── prelude.js │ │ │ ├── pure.js │ │ │ ├── solipsist.js │ │ │ └── underscore.js │ │ └── login.html │ │ ├── server.js │ │ └── simpleauth.js └── tema6 │ ├── chat_v1 │ ├── app.js │ ├── bin │ │ └── start │ ├── npm-debug.log │ ├── package.json │ └── public │ │ ├── assets │ │ ├── images │ │ │ └── avatar.jpg │ │ ├── javascripts │ │ │ ├── libs │ │ │ │ ├── jquery-1.9.0.min.js │ │ │ │ └── modernizr-2.6.1.min.js │ │ │ └── script.js │ │ └── stylesheets │ │ │ └── screen.css │ │ ├── chat.html │ │ ├── code.js │ │ └── login.html │ └── chat_v2 │ ├── app.js │ ├── bin │ └── start │ ├── chat.js │ ├── package.json │ └── public │ ├── assets │ ├── images │ │ └── avatar.jpg │ ├── javascripts │ │ ├── libs │ │ │ ├── jquery-1.9.0.min.js │ │ │ └── modernizr-2.6.1.min.js │ │ └── script.js │ └── stylesheets │ │ └── screen.css │ ├── chat.html │ ├── code.js │ └── login.html ├── tema0.pdf ├── tema1.pdf ├── tema1 ├── abtesting │ ├── config.js │ ├── public │ │ ├── A │ │ │ ├── css │ │ │ │ └── styles.css │ │ │ ├── foto.jpg │ │ │ ├── images │ │ │ │ ├── avatar.png │ │ │ │ ├── icon.png │ │ │ │ └── logo.png │ │ │ └── index.html │ │ ├── B │ │ │ ├── css │ │ │ │ └── styles.css │ │ │ ├── foto.jpg │ │ │ ├── images │ │ │ │ ├── avatar.png │ │ │ │ ├── icon.png │ │ │ │ └── logo.png │ │ │ └── index.html │ │ ├── C │ │ │ ├── css │ │ │ │ └── styles.css │ │ │ ├── foto.jpg │ │ │ ├── images │ │ │ │ ├── avatar.png │ │ │ │ ├── icon.png │ │ │ │ └── logo.png │ │ │ └── index.html │ │ ├── D │ │ │ ├── css │ │ │ │ └── styles.css │ │ │ ├── images │ │ │ │ ├── avatar.png │ │ │ │ ├── icon.png │ │ │ │ └── logo.png │ │ │ └── index.html │ │ ├── statsPage.html │ │ └── success.png │ └── server.js ├── captcha │ ├── client.js │ ├── package.json │ ├── server.js │ └── templates │ │ └── form.html ├── tiles │ ├── package.json │ ├── public │ │ ├── client.js │ │ ├── dimension.png │ │ ├── index.html │ │ ├── jquery.js │ │ └── map.jpg │ └── server.js └── watermark │ ├── package.json │ ├── public │ ├── mark.png │ └── programador.png │ └── server.js ├── tema2.pdf ├── tema2 ├── fakePromise.js └── versionedserver │ ├── package.json │ ├── server.js │ └── simpleRoute.js ├── tema3.pdf ├── tema3 ├── blog │ ├── package.json │ ├── public │ │ └── css │ │ │ ├── normalize.css │ │ │ └── styles.css │ ├── server.js │ └── views │ │ ├── layout.jade │ │ ├── new-post.jade │ │ ├── post-detail.jade │ │ └── post-list.jade ├── blogAuth │ ├── package.json │ ├── public │ │ └── css │ │ │ ├── normalize.css │ │ │ └── styles.css │ ├── server.js │ ├── simpleauth.js │ └── views │ │ ├── layout.jade │ │ ├── login.jade │ │ ├── new-post.jade │ │ ├── post-detail.jade │ │ ├── post-list.jade │ │ └── register.jade └── simpleAuthModule │ ├── app.js │ ├── package.json │ ├── public │ └── login.html │ └── simpleauth.js ├── tema4.pdf ├── tema4 ├── blogAuthRedis │ ├── package.json │ ├── public │ │ └── css │ │ │ ├── normalize.css │ │ │ └── styles.css │ ├── pubsub.js │ ├── server.js │ ├── simpleauth.js │ ├── test.js │ └── views │ │ ├── layout.jade │ │ ├── login.jade │ │ ├── new-post.jade │ │ ├── post-detail.jade │ │ ├── post-list.jade │ │ └── register.jade └── urlshort │ ├── .gitignore │ ├── package.json │ ├── public │ └── css │ │ ├── normalize.css │ │ └── styles.css │ ├── server.js │ ├── simpleauth.js │ └── views │ ├── layout.jade │ ├── login.jade │ ├── register.jade │ ├── url-form.jade │ ├── url-index.jade │ └── url-show.jade ├── tema5.pdf ├── tema5 ├── digg_clone │ ├── app.js │ ├── bin │ │ └── start │ ├── models │ │ ├── comment.js │ │ ├── index.js │ │ ├── post.js │ │ ├── user.js │ │ └── utils.js │ ├── package.json │ ├── public │ │ ├── assets │ │ │ ├── javascripts │ │ │ │ ├── libs │ │ │ │ │ ├── jquery-1.9.0.min.js │ │ │ │ │ └── modernizr-2.6.1.min.js │ │ │ │ └── script.js │ │ │ └── stylesheets │ │ │ │ ├── mixins.css │ │ │ │ └── screen.css │ │ ├── code.js │ │ ├── img │ │ │ └── loading.gif │ │ ├── index.html │ │ └── lib │ │ │ ├── backbone.js │ │ │ ├── jquery.js │ │ │ ├── prelude.js │ │ │ └── underscore.js │ ├── routes │ │ ├── comments.js │ │ ├── posts.js │ │ ├── resources.js │ │ └── users.js │ └── simpleauth.js └── digg_clone_bluebird │ ├── app.js │ ├── bin │ └── start │ ├── data │ └── db │ │ └── .gitinclude │ ├── models │ ├── comment.js │ ├── index.js │ ├── post.js │ ├── user.js │ └── utils.js │ ├── package.json │ ├── public │ ├── assets │ │ ├── javascripts │ │ │ ├── libs │ │ │ │ ├── jquery-1.9.0.min.js │ │ │ │ └── modernizr-2.6.1.min.js │ │ │ └── script.js │ │ └── stylesheets │ │ │ ├── mixins.css │ │ │ └── screen.css │ ├── code.js │ ├── img │ │ └── loading.gif │ ├── index.html │ └── lib │ │ ├── backbone.js │ │ ├── jquery.js │ │ ├── prelude.js │ │ └── underscore.js │ ├── routes │ ├── comments.js │ ├── posts.js │ └── users.js │ └── simpleauth.js ├── tema6.pdf └── tema6 └── chat ├── app.js ├── bin └── start ├── npm-debug.log ├── package.json └── public ├── assets ├── images │ └── avatar.jpg ├── javascripts │ ├── libs │ │ ├── jquery-1.9.0.min.js │ │ └── modernizr-2.6.1.min.js │ └── script.js └── stylesheets │ └── screen.css ├── chat.html ├── code.js └── login.html /.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude vim temp files 2 | *.swp 3 | *.swo 4 | # Databases 5 | *.sqlite 6 | # Exclude OS X folder attributes 7 | .DS_Store 8 | # Exclude npm packages 9 | node_modules 10 | # Exclude REDIS dumps 11 | dump.rdb 12 | Vagrantfile 13 | .vagrant 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Materiales del curso de Node.js 2 | 3 | Más información en https://redradix.com/cursos/node-js/ 4 | -------------------------------------------------------------------------------- /ejercicios/blog/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-simpleblog", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "bluebird": "^2.10.2", 7 | "body-parser": "*", 8 | "express": "*", 9 | "hiredis": "*", 10 | "jade": "*", 11 | "lodash": "^3.10.1", 12 | "method-override": "*", 13 | "node-uuid": "^1.4.3", 14 | "q": "*", 15 | "redis": "^2.1.0", 16 | "serve-favicon": "^2.3.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ejercicios/blog/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype 2 | html(lang='es') 3 | head 4 | meta(charset='utf-8') 5 | title Lista de Posts 6 | meta(name='description', content='') 7 | meta(property='og:image', content='') 8 | // Fonts 9 | link(href='http://fonts.googleapis.com/css?family=Roboto:400,300,500,700,400italic,300italic', rel='stylesheet', type='text/css') 10 | // Frameworks 11 | link(rel='stylesheet', href='/css/normalize.css') 12 | // Stylesheets 13 | link(rel='stylesheet', href='/css/styles.css', media='screen') 14 | body.post-list 15 | header 16 | .top 17 | h1 Mi Blog 18 | .newpost 19 | a(href='/posts/new') Nuevo Post 20 | block nav 21 | block content 22 | -------------------------------------------------------------------------------- /ejercicios/blog/views/new-post.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.new-post.container 5 | h1.section-title= post.id? "Editar Post" : "Nuevo Post" 6 | form.new-post-form(action=post.id? "/posts/#{post.id}?_method=PUT" : "/posts", method="POST") 7 | label(for='title') Título 8 | input.title(type='text', name='title', value=post.title) 9 | label(for='post-title') Contenido 10 | textarea.post-content(name='content', placeholder='')= post.content 11 | if post.id 12 | input(type="hidden",name="_method",value="PUT") 13 | input.button(type='submit', value='Publicar') 14 | -------------------------------------------------------------------------------- /ejercicios/blog/views/post-detail.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block nav 4 | nav.menu 5 | ul 6 | li 7 | a(href='/posts') Volver 8 | li 9 | a(href='/posts/#{post.id}/edit') Editar 10 | li 11 | form(action="/posts/#{post.id}?_method=DELETE",method="POST",id="form-delete") 12 | input(type="hidden",name="_method",value="DELETE") 13 | a(href='#',onclick="document.getElementById('form-delete').submit()") Eliminar 14 | 15 | block content 16 | section.posts 17 | article.post 18 | .container 19 | h1.post-title= post.title 20 | p= post.content 21 | aside.metadata 22 | | Por 23 | a(href='#')  Default User 24 | span.sep   |   25 | | 0 visitas 26 | -------------------------------------------------------------------------------- /ejercicios/blog/views/post-list.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.posts 5 | each post in posts 6 | article.post 7 | .container 8 | h2.post-title 9 | a(href='/posts/#{post.id}')= post.title 10 | p.summary= post.content.slice(0, 150) 11 | aside.metadata 12 | | Por 13 | a(href='#')  Default User 14 | span.sep   |   15 | | 0 visitas 16 | -------------------------------------------------------------------------------- /ejercicios/code.js: -------------------------------------------------------------------------------- 1 | var Reloj = require("./reloj").Reloj; 2 | var reloj = new Reloj(); 3 | 4 | reloj.on("segundo", function(fecha) { 5 | console.log("Un segundo! son las:", fecha); 6 | reloj.removeAllListeners("segundo"); 7 | }); 8 | -------------------------------------------------------------------------------- /ejercicios/cp.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | 3 | var origen = process.argv[2], 4 | dest = process.argv[3]; 5 | 6 | var readStream = fs.createReadStream(origen, { flags: "r", autoClose: true}); 7 | var writeStream = fs.createWriteStream(dest, { flags: "w"}); 8 | 9 | // readStream.on("data", writeStream.write.bind(writeStream)); 10 | // readStream.on("end", writeStream.end.bind(writeStream)); 11 | 12 | readStream.on("data", function(chunk) { 13 | writeStream.write(chunk); 14 | }); 15 | 16 | readStream.on("end", function() { 17 | writeStream.end(); 18 | }); 19 | -------------------------------------------------------------------------------- /ejercicios/cuentalineas.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | 3 | var readStream = fs.createReadStream(process.argv[2], 4 | { flags: "r", 5 | autoClose: true }); 6 | 7 | var contenido = ""; 8 | 9 | readStream.on("data", function(chunk) { 10 | contenido += chunk; 11 | }); 12 | 13 | readStream.on("end", function() { 14 | console.log(contenido.split("\n").length - 1); 15 | }); 16 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/app.js: -------------------------------------------------------------------------------- 1 | /* Modules */ 2 | 3 | var express = require('express'); 4 | var path = require('path'); 5 | var favicon = require('static-favicon'); 6 | var logger = require('morgan'); 7 | var cookieParser = require('cookie-parser'); 8 | var cookieSession = require('cookie-session'); 9 | var bodyParser = require('body-parser'); 10 | var methodOverride = require('method-override'); 11 | var Q = require('q'); 12 | var auth = require('./simpleauth'); 13 | var MongoClient = require('mongodb').MongoClient; 14 | var ObjectID = require('mongodb').ObjectID; 15 | var models = require('./models'); 16 | 17 | var app = express(); 18 | 19 | /* Config */ 20 | 21 | var client = Q.ninvoke(MongoClient, 22 | 'connect', 23 | 'mongodb://127.0.0.1:27017/diggclone'); 24 | 25 | models.setClient(client); 26 | 27 | client.fail(function(e) { 28 | console.log('ERROR conectando a Mongo: ', e); 29 | }); 30 | 31 | function extend() { 32 | var args = [].slice.call(arguments); 33 | return args.reduce(function(acc, el) { 34 | for (var k in el) { acc[k] = el[k]; } 35 | return acc; 36 | }); 37 | } 38 | 39 | Q.longStackSupport = true; 40 | 41 | app.set('views', path.join(__dirname, 'views')); 42 | app.set('view engine', 'jade'); 43 | 44 | app.use(favicon()); 45 | app.use(logger('dev')); 46 | app.use(bodyParser.json()); 47 | app.use(methodOverride()); 48 | app.use(bodyParser.urlencoded()); 49 | app.use(cookieParser()); 50 | app.use(cookieSession({secret: 'asdf'})); 51 | app.use(express.static(path.join(__dirname, 'public'))); 52 | 53 | /* Auth */ 54 | 55 | auth.setStrategy({ 56 | serializeUser: function(user) { 57 | }, 58 | deserializeUser: function(userToken, cb) { 59 | }, 60 | checkCredentials: function(username, pass, cb) { 61 | } 62 | }); 63 | 64 | /* Routing */ 65 | 66 | app.use('/', require('./routes/users')); 67 | app.use('/posts', require('./routes/posts')); 68 | app.use('/comments', require('./routes/comments')); 69 | 70 | /* Errors */ 71 | 72 | app.use(function(req, res, next) { 73 | res.send(404); 74 | }); 75 | 76 | app.use(function(err, req, res, next) { 77 | res.send(500); 78 | }); 79 | 80 | module.exports = app; 81 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/bin/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var app = require('../app'); 3 | var port = process.env.PORT || 3000; 4 | 5 | var server = app.listen(port, function() { 6 | console.log('Express server listening on port ' + port); 7 | }); 8 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/models/comment.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/ejercicios/digg_clone/models/comment.js -------------------------------------------------------------------------------- /ejercicios/digg_clone/models/index.js: -------------------------------------------------------------------------------- 1 | module.exports = exports = Object.create(require('./utils')); 2 | 3 | exports.user = require('./user'); 4 | exports.post = require('./post'); 5 | exports.comment = require('./comment'); 6 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/models/post.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/ejercicios/digg_clone/models/post.js -------------------------------------------------------------------------------- /ejercicios/digg_clone/models/user.js: -------------------------------------------------------------------------------- 1 | var op = require('./utils').op; 2 | var user = op.bind({}, "users"); 3 | 4 | // ejemplo 5 | user.checkCredentials = function(email, password) { 6 | return user("findOne", {email: email, password: password}); 7 | }; 8 | 9 | 10 | module.exports = user; 11 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/models/utils.js: -------------------------------------------------------------------------------- 1 | var Q = require("q"); 2 | 3 | var client = null; 4 | 5 | exports.setClient = function(mongoClient) { 6 | client = mongoClient; 7 | }; 8 | 9 | exports.op = function op(colname) { 10 | var args = [].slice.call(arguments, 1); 11 | return client 12 | .then(function(db) { 13 | // 1) primero necesito el objeto db 14 | // 2) db.collection(colname) => el "puntero" a la coleccion 15 | // 3) args = algo como: ["findOne", {a: 1}] 16 | // 4) Al final, la llamada es equivalente a hacer: 17 | // Q.ninvoke(col, "findOne", {a: 1}) 18 | return Q.ninvoke.apply(Q, [db.collection(colname)].concat(args)); 19 | }) 20 | .fail(function(err) { 21 | console.log("[MongoDB]", err); 22 | throw err; 23 | }); 24 | }; 25 | 26 | exports.makeOp = function(col) { 27 | var args = [].slice.call(arguments, 1); 28 | return function () { return col.apply({}, args); }; 29 | }; 30 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-digg", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/start" 7 | }, 8 | "dependencies": { 9 | "express": "~4.0.0", 10 | "static-favicon": "~1.0.0", 11 | "morgan": "~1.0.0", 12 | "cookie-parser": "~1.0.1", 13 | "body-parser": "~1.0.0", 14 | "debug": "~0.7.4", 15 | "jade": "~1.3.0", 16 | "q": "~1.0.1", 17 | "method-override": "~1.0.0", 18 | "cookie-session": "~1.0.1", 19 | "mongodb": "~1.4.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/public/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | 3 | $('.add > a').on('click', function(){ 4 | $(this).parent('.add').toggleClass('active'); 5 | }); 6 | 7 | 8 | 9 | 10 | }); 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/public/assets/stylesheets/mixins.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/ejercicios/digg_clone/public/assets/stylesheets/mixins.css -------------------------------------------------------------------------------- /ejercicios/digg_clone/public/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/ejercicios/digg_clone/public/img/loading.gif -------------------------------------------------------------------------------- /ejercicios/digg_clone/routes/comments.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var resources = require('./resources'); 3 | var auth = require('../simpleauth'); 4 | 5 | var commentsController = { 6 | index: function(req, res) { 7 | }, 8 | show: function(req, res) { 9 | }, 10 | create: function(req, res) { 11 | }, 12 | update: function(req, res) { 13 | }, 14 | "delete": function(req, res) { 15 | }, 16 | vote: function(req, res) { 17 | }, 18 | param: function(req, res, next, postId) { 19 | } 20 | }; 21 | 22 | var router = express.Router(); 23 | router.use(auth.requiresToken); 24 | resources(router, 'comments', commentsController); 25 | router.post('/:commentsid/vote/:vote', commentsController.vote); 26 | 27 | module.exports = router; 28 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/routes/posts.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var resources = require('./resources'); 3 | var auth = require('../simpleauth'); 4 | 5 | var postsController = { 6 | index: function(req, res) { 7 | }, 8 | show: function(req, res) { 9 | }, 10 | create: function(req, res) { 11 | }, 12 | update: function(req, res) { 13 | }, 14 | "delete": function(req, res) { 15 | }, 16 | vote: function(req, res) { 17 | }, 18 | param: function(req, res, next, postId) { 19 | } 20 | }; 21 | 22 | var router = express.Router(); 23 | router.use(auth.requiresToken); 24 | resources(router, 'posts', postsController); 25 | router.post('/:postsid/vote/:vote', postsController.vote); 26 | 27 | module.exports = router; 28 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/routes/resources.js: -------------------------------------------------------------------------------- 1 | module.exports = function (router, name, controller) { 2 | if (controller.index) router.get("/", controller.index); 3 | if (controller["new"]) router.get("/new", controller["new"]); 4 | if (controller.create) router.post("/", controller.create); 5 | if (controller.show) router.get("/:"+name+"id", controller.show); 6 | if (controller.edit) router.get("/:"+name+"id/edit", controller.edit); 7 | if (controller.update) router.put("/:"+name+"id", controller.update); 8 | if (controller["delete"]) router["delete"]("/:"+name+"id", controller["delete"]); 9 | if (controller.param) router.param(name + "id", controller.param); 10 | }; 11 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var resources = require('./resources'); 3 | var auth = require('../simpleauth'); 4 | 5 | var usersController = { 6 | create: function(req, res) { 7 | }, 8 | me: function(req, res) { 9 | }, 10 | login: function(req, res) { 11 | } 12 | }; 13 | 14 | var router = express.Router(); 15 | router.post('/session', auth.createSession(), usersController.login); 16 | router.post('/users', usersController.create); 17 | router.get('/me', auth.requiresToken, usersController.me); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /ejercicios/digg_clone/simpleauth.js: -------------------------------------------------------------------------------- 1 | function extend() { 2 | var args = [].slice.call(arguments) 3 | return args.reduce(function(acc, el) { 4 | for (var k in el) { acc[k] = el[k] } 5 | return acc; 6 | }) 7 | } 8 | 9 | strategy = { 10 | serializeUser: function(user) { 11 | }, 12 | deserializeUser: function(userId, cb) { 13 | }, 14 | checkCredentials: function(username, pass, done) { 15 | } 16 | } 17 | 18 | exports.setStrategy = function(customStrategy) { 19 | strategy = extend({}, strategy, customStrategy) 20 | } 21 | 22 | exports.createSession = function(options) { 23 | var config = { 24 | username: "username", 25 | password: "password", 26 | } 27 | config = extend({}, config, options) 28 | return function(req, res, next) { 29 | var username = req.body[config.username], 30 | pass = req.body[config.password] 31 | strategy.checkCredentials(username, pass, function(err, user) { 32 | if (!err && user) { 33 | req.user = user 34 | next() 35 | /* res.redirect(config.redirect) */ 36 | } else { 37 | console.log("Credenciales incorrectas") 38 | res.send(401, {error: "Username o contraseña incorrectos"}) 39 | } 40 | }) 41 | } 42 | } 43 | 44 | exports.requiresToken = function(req, res, next) { 45 | var token = req.param("token") 46 | if (token !== undefined) { 47 | strategy.deserializeUser(token, function(user) { 48 | if (!user) { 49 | console.log("El usuario no existe!") 50 | res.send(401, {error: "No autorizado"}) 51 | } else { 52 | req.user = user 53 | next() 54 | } 55 | }) 56 | } else { 57 | console.log("No existe token...") 58 | res.send(401, {error: "No autorizado"}) 59 | } 60 | } 61 | 62 | exports.withToken = function(app, cb) { 63 | function createAuthRouting(verb) { 64 | return function() { 65 | var route = arguments[0], 66 | args = [].slice.call(arguments, 1) 67 | return app[verb].apply(app, [route, exports.requiresToken].concat(args)) 68 | } 69 | } 70 | var routeVerbs = Object.create(app); 71 | ["get", "post", "put", "delete"].forEach(function(v) { 72 | routeVerbs[v] = createAuthRouting(v) 73 | }); 74 | cb(routeVerbs) 75 | } 76 | -------------------------------------------------------------------------------- /ejercicios/esqueletoSimpleAuth.js: -------------------------------------------------------------------------------- 1 | var express = require("express"), 2 | app = express(); 3 | 4 | // Datos 5 | 6 | var users = [{email: "a@b.c", pass: "asdf"}]; 7 | 8 | // Estrategia 9 | 10 | var strategy = { 11 | serializeUser: function(user) { 12 | return users.indexOf(user); 13 | }, 14 | deserializeUser: function(id, cb) { 15 | cb(users[id]); 16 | }, 17 | checkCredentials: function(login, pass, cb) { 18 | var user = users.find(function(u) { 19 | return u.email === login && u.pass === pass; 20 | }); 21 | cb(user); 22 | } 23 | }; 24 | 25 | // Auth 26 | 27 | var auth = { 28 | createSession: function(options) { 29 | }, 30 | requiresSession: function(req, res, next) { 31 | }, 32 | destorySession: function(req, res, next) { 33 | } 34 | }; 35 | 36 | 37 | app.get("/login", auth.createSession({redirect: "/secret"})); 38 | 39 | app.get("/secret", auth.requiresSession, function(req, res) { 40 | }); 41 | 42 | app.get("/logout", auth.destroySession); 43 | -------------------------------------------------------------------------------- /ejercicios/events.js: -------------------------------------------------------------------------------- 1 | var EventEmitter = require("events").EventEmitter, 2 | inherits = require("util").inherits; 3 | 4 | function Tambor() { 5 | var self = this; 6 | setInterval(function() { 7 | self.emit("pom!"); 8 | }, 1000); 9 | }; 10 | inherits(Tambor, EventEmitter); 11 | 12 | var tambor1 = new Tambor(); 13 | 14 | tambor1.on("pom!", function() { 15 | console.log("El tambor suena!"); 16 | }); 17 | -------------------------------------------------------------------------------- /ejercicios/fakePromise.js: -------------------------------------------------------------------------------- 1 | var Q = require("q") 2 | 3 | exports.gimmePromise = function() { 4 | var defer = Q.defer(), 5 | promise = defer.promise; 6 | promise.resolve = defer.resolve.bind(defer); 7 | promise.reject = defer.reject.bind(defer); 8 | return promise; 9 | } 10 | -------------------------------------------------------------------------------- /ejercicios/flashMessages.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var express = require("express"), 4 | cookieParser = require("cookie-parser"), 5 | app = express(); 6 | 7 | app.use(cookieParser("asdfasdf")); 8 | app.use(function(req, res, next) { 9 | var message = req.cookies.message; 10 | res.cookie("message", ""); 11 | req.flash = { 12 | message: function(msg) { 13 | if (msg) { 14 | res.cookie("message", msg); 15 | } else { 16 | return message; 17 | } 18 | } 19 | }; 20 | next(); 21 | }); 22 | 23 | // Esto es para Santiago: 24 | app.use(function(req, res, next) { 25 | var realSend = res.send; 26 | res.send = function() { 27 | console.log(arguments); 28 | return realSend.apply(res, arguments); 29 | }; 30 | next(); 31 | }); 32 | 33 | app.get("/test", function(req, res) { 34 | var random = Math.random(); 35 | if (random > 0.5) { 36 | req.flash.message("Mayor!"); 37 | } else { 38 | req.flash.message("Menor!"); 39 | } 40 | res.redirect("/test2"); 41 | }); 42 | 43 | app.get("/test2", function(req, res) { 44 | var message = req.flash.message(); 45 | res.send(200, req.flash.message()); 46 | }); 47 | 48 | app.listen(3000); 49 | -------------------------------------------------------------------------------- /ejercicios/fsstatpromise.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"), 2 | Q = require("q"); 3 | 4 | function fsReadDir(path) { 5 | var defer = Q.defer(); 6 | fs.readdir(path, function(err, result) { 7 | return err? defer.reject(err) : defer.resolve(result); 8 | }); 9 | return defer.promise; 10 | } 11 | -------------------------------------------------------------------------------- /ejercicios/hola-mundo.js: -------------------------------------------------------------------------------- 1 | var http = require("http"), 2 | url = require("url"), 3 | inspect = require("util").inspect; 4 | 5 | var server = http.createServer(); 6 | 7 | server.on("request", function(req, res) { 8 | var urlData = url.parse(req.url, true); 9 | res.end(inspect(urlData, {colors: false})); 10 | }); 11 | 12 | server.listen(3000); 13 | -------------------------------------------------------------------------------- /ejercicios/hola.js: -------------------------------------------------------------------------------- 1 | var start = Date.now(); 2 | 3 | setTimeout(function() { 4 | for (var i=Number.MAX_VALUE; i--;) { 5 | Math.pow(12345, 123455); 6 | } 7 | }, 100); 8 | 9 | setInterval(function() { 10 | var now = Date.now(); 11 | console.log("Han pasado", now - start, "ms"); 12 | start = now; 13 | console.log("Hola otra vez, Mundo del futuro!"); 14 | }, 1000); 15 | -------------------------------------------------------------------------------- /ejercicios/nodefcall.js: -------------------------------------------------------------------------------- 1 | function nodefcall(fn) { 2 | var args = [].slice.call(arguments, 1), 3 | defer = Q.defer(); 4 | 5 | fn.apply({}, args.concat(function(err) { 6 | var resultArgs = [].slice.call(arguments, 1); 7 | if (err) { 8 | defer.reject(err); 9 | } else { 10 | defer.resolve.apply(defer, resultArgs); 11 | } 12 | })); 13 | 14 | return defer.promise; 15 | } 16 | -------------------------------------------------------------------------------- /ejercicios/nodefcallPromise.js: -------------------------------------------------------------------------------- 1 | var Promise = Promise || require('bluebird'); 2 | function nodefcall(fn) { 3 | //argumentos sin el primero (fn) 4 | var args = [].slice.call(arguments, 1); 5 | 6 | return new Promise(function(resolve, reject){ 7 | fn.apply({}, args.concat(function(err, res) { 8 | if (err) { 9 | reject(err); 10 | } else { 11 | resolve(res); 12 | } 13 | })); 14 | }); 15 | } 16 | 17 | 18 | var fs = require('fs'); 19 | 20 | nodefcall(fs.readdir, '.') 21 | .then(function(res){ 22 | console.log(res); 23 | }); 24 | 25 | nodefcall(fs.stat, '.') 26 | .then(console.log.bind(console)); -------------------------------------------------------------------------------- /ejercicios/nodeinvoke.js: -------------------------------------------------------------------------------- 1 | var Q = require("q"), 2 | fs = require("fs"); 3 | 4 | function nodeinvoke(obj, method) { 5 | var args = [].slice.call(arguments, 2), 6 | fn = obj[method]; 7 | return nodefcall(fn.bind.apply(fn, [obj].concat(args))); 8 | return defer.promise; 9 | } 10 | 11 | nodeinvoke(fs, "readFile", "./nodeinvoke.js") 12 | .then(function(content) { 13 | console.log(content); 14 | }); 15 | 16 | nodefcall(fs.readFile.bind(fs), "./nodeinvoke.js"); 17 | -------------------------------------------------------------------------------- /ejercicios/nodeinvokePromise.js: -------------------------------------------------------------------------------- 1 | var Promise = Promise || require('bluebird'); 2 | var fs = require("fs"); 3 | 4 | function nodefcall(fn) { 5 | //argumentos sin el primero (fn) 6 | var args = [].slice.call(arguments, 1); 7 | 8 | return new Promise(function(resolve, reject){ 9 | fn.apply({}, args.concat(function(err, res) { 10 | if (err) { 11 | reject(err); 12 | } else { 13 | resolve(res); 14 | } 15 | })); 16 | }); 17 | } 18 | 19 | function nodeinvoke(obj, method) { 20 | var args = [].slice.call(arguments, 2), 21 | fn = obj[method]; 22 | return nodefcall(fn.bind.apply(fn, [obj].concat(args))); 23 | //return defer.promise; 24 | } 25 | 26 | nodeinvoke(fs, "readFile", "./nodeinvoke.js", "ascii") 27 | .then(function(content) { 28 | console.log(content); 29 | }); 30 | 31 | nodefcall(fs.readFile.bind(fs), "./nodeinvoke.js"); 32 | -------------------------------------------------------------------------------- /ejercicios/promiseGarden1.js: -------------------------------------------------------------------------------- 1 | var fakePromise = require("./fakePromise"); 2 | 3 | var promise = fakePromise.gimmePromise(); 4 | 5 | promise 6 | .then(function() { 7 | return "hola"; 8 | }) 9 | .then(function(msg) { 10 | console.log(msg); 11 | return "mundo"; 12 | }) 13 | .then(function(msg) { 14 | console.log(msg); 15 | }); 16 | -------------------------------------------------------------------------------- /ejercicios/public/test.txt: -------------------------------------------------------------------------------- 1 | asdfasdfasdf 2 | -------------------------------------------------------------------------------- /ejercicios/readAllfiles.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var fs = require("fs"), 4 | Q = require("q"); 5 | 6 | function fileExistsPromise(path) { 7 | var defer = Q.defer(); 8 | fs.exists(path, function(exists) { 9 | return exists? defer.resolve(true) : defer.reject(new Error("no existe!")); 10 | }); 11 | return defer.promise; 12 | } 13 | 14 | function readFilePromise(path) { 15 | return fileExistsPromise(path) 16 | .then(function() { 17 | var defer = Q.defer(); 18 | fs.readFile(path, function(err, data) { 19 | return err? defer.reject(err) : defer.resolve(data); 20 | }); 21 | return defer.promise; 22 | }); 23 | } 24 | 25 | function readAllFiles() { 26 | var promises = Array.protoype.map.call(arguments, readFilePromise); 27 | return Q.all(promises); 28 | } 29 | 30 | var files = process.argv.slice(2); 31 | 32 | readAllFiles.apply({}, files).then(function(contents) { 33 | console.log(contents.join("\n\n\n")); 34 | }); 35 | -------------------------------------------------------------------------------- /ejercicios/readFilePromise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var Q = require("q"), 4 | fs = require("fs"); 5 | 6 | function readFilePromise(ruta) { 7 | var defer = Q.defer(); 8 | 9 | fs.readFile(ruta, function(err, data) { 10 | if (err) { 11 | defer.reject(err); 12 | } else { 13 | defer.resolve(data); 14 | } 15 | }); 16 | 17 | return defer.promise; 18 | } 19 | 20 | readFilePromise("./readFilePromise.js") 21 | .then(function(content) { 22 | console.log("Leido correctamente!"); 23 | console.log(content.toString()); 24 | }, function(err) { 25 | console.log("Error!!!"); 26 | console.log(err); 27 | }); 28 | -------------------------------------------------------------------------------- /ejercicios/reloj.js: -------------------------------------------------------------------------------- 1 | var EventEmitter = require("events").EventEmitter, 2 | inherits = require("util").inherits; 3 | 4 | function Reloj() { 5 | this.emit("segundo", new Date()); 6 | } 7 | inherits(Reloj, EventEmitter); 8 | 9 | exports.Reloj = Reloj; 10 | -------------------------------------------------------------------------------- /ejercicios/simpleAuth.js: -------------------------------------------------------------------------------- 1 | function extend() { 2 | var args = [].slice.call(arguments) 3 | return args.reduce(function(acc, el) { 4 | for (var k in el) { acc[k] = el[k] } 5 | return acc; 6 | }) 7 | } 8 | 9 | strategy = { 10 | serializeUser: function(user) { 11 | }, 12 | deserializeUser: function(userId, cb) { 13 | }, 14 | checkCredentials: function(username, pass, done) { 15 | } 16 | } 17 | 18 | exports.setStrategy = function(customStrategy) { 19 | strategy = extend({}, strategy, customStrategy) 20 | } 21 | 22 | exports.createSession = function(options) { 23 | var config = { 24 | username: "username", 25 | password: "password", 26 | } 27 | config = extend({}, config, options) 28 | return function(req, res, next) { 29 | var username = req.body[config.username], 30 | pass = req.body[config.password] 31 | strategy.checkCredentials(username, pass, function(err, user) { 32 | if (!err && user) { 33 | req.user = user 34 | next() 35 | /* res.redirect(config.redirect) */ 36 | } else { 37 | console.log("Credenciales incorrectas") 38 | res.send(401, {error: "Username o contraseña incorrectos"}) 39 | } 40 | }) 41 | } 42 | } 43 | 44 | exports.requiresToken = function(req, res, next) { 45 | var token = req.param("token") 46 | if (token !== undefined) { 47 | strategy.deserializeUser(token, function(user) { 48 | if (!user) { 49 | console.log("El usuario no existe!") 50 | res.send(401, {error: "No autorizado"}) 51 | } else { 52 | req.user = user 53 | next() 54 | } 55 | }) 56 | } else { 57 | console.log("No existe token...") 58 | res.send(401, {error: "No autorizado"}) 59 | } 60 | } 61 | 62 | exports.withToken = function(app, cb) { 63 | function createAuthRouting(verb) { 64 | return function() { 65 | var route = arguments[0], 66 | args = [].slice.call(arguments, 1) 67 | return app[verb].apply(app, [route, exports.requiresToken].concat(args)) 68 | } 69 | } 70 | var routeVerbs = Object.create(app); 71 | ["get", "post", "put", "delete"].forEach(function(v) { 72 | routeVerbs[v] = createAuthRouting(v) 73 | }); 74 | cb(routeVerbs) 75 | } 76 | -------------------------------------------------------------------------------- /ejercicios/slowLogger.js: -------------------------------------------------------------------------------- 1 | var express = require("express"), 2 | app = express(); 3 | 4 | var stats = { times: 0, mean: 0, total: 0 }; 5 | 6 | app.use(function(req, res, next) { 7 | var stamp = Date.now(); 8 | res.on("finish", function() { 9 | var time = Date.now() - stamp; 10 | stats.times++; 11 | stats.total += time; 12 | stats.mean = stats.total / stats.times; 13 | if (time - stats.mean > 300) { 14 | console.log(" --> ", Date.now() - stamp); 15 | } 16 | }); 17 | next(); 18 | }); 19 | 20 | 21 | app.get("/fast", function(req, res) { 22 | res.send(200, "ok"); 23 | }); 24 | 25 | app.get("/slow", function(req, res) { 26 | setTimeout(function() { 27 | res.send(200, "ok"); 28 | }, 1000); 29 | }); 30 | 31 | app.listen(3000); 32 | -------------------------------------------------------------------------------- /ejercicios/static.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var http = require("http"), 4 | url = require("url"), 5 | fs = require("fs"); 6 | 7 | var cache = {}, 8 | maxAge = 2000; 9 | 10 | function readFile(path, cb) { 11 | console.log(" >> Leyendo el fichero:", path); 12 | fs.exists(path, function(exists) { 13 | if (exists) { 14 | fs.readFile(path, cb); 15 | } else { 16 | cb(new Error("El fichero no existe!")); 17 | } 18 | }); 19 | } 20 | 21 | function getFile(path, cb) { 22 | var cachedFile = cache[path]; 23 | if (cachedFile && (Date.now() - cachedFile.stamp) < maxAge) { 24 | cb(null, cachedFile.data); 25 | } else { 26 | readFile(path, function(err, data) { 27 | if (err) { return cb(err); } 28 | cache[path] = { data: data, stamp: Date.now() }; 29 | cb(null, data); 30 | }); 31 | } 32 | } 33 | 34 | var server = http.createServer(function(req, res) { 35 | var urlData = url.parse(req.url); 36 | getFile("." + urlData.pathname, function(err, data) { 37 | if (err) { 38 | res.writeHead(404); 39 | res.end(err.message); 40 | } else { 41 | res.writeHead(200); 42 | res.end(data); 43 | } 44 | }); 45 | }); 46 | 47 | server.listen(3001); 48 | -------------------------------------------------------------------------------- /ejercicios/staticPromise.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var http = require("http"), 4 | url = require("url"), 5 | fs = require("fs"); 6 | 7 | var cache = {}, 8 | maxAge = 2000; 9 | 10 | function fileExistsPromise(path) { 11 | var defer = Q.defer(); 12 | fs.exists(path, function(exists) { 13 | return exists? defer.resolve(true) : defer.reject(new Error("no existe!")); 14 | }); 15 | return defer.promise(); 16 | } 17 | 18 | function readFilePromise(path) { 19 | return fileExistsPromise(path) 20 | .then(function() { 21 | fs.readFile(path, function(err, data) { 22 | if (err) throw err; 23 | return data; 24 | }); 25 | }); 26 | } 27 | 28 | function getFile(path) { 29 | var defer = Q.defer(), 30 | promise = defer.promise, 31 | cachedFile = cache[path]; 32 | 33 | if (cachedFile && (Date.now() - cachedFile.stamp) < maxAge) { 34 | defer.resolve(cachedFile.data); 35 | } else { 36 | pormise = readFilePromise(path) 37 | .then(function(data) { 38 | cache[path] = { data: data, stamp: Date.now() }; 39 | return data; 40 | }); 41 | } 42 | return promise; 43 | } 44 | 45 | var server = http.createServer(function(req, res) { 46 | var urlData = url.parse(req.url), 47 | filePath = "./public" + urlData.pathname; 48 | 49 | getFile(path) 50 | .then(function(data) { 51 | }) 52 | .fail(function(err) { 53 | }); 54 | }); 55 | 56 | server.listen(3000); 57 | -------------------------------------------------------------------------------- /ejercicios/staticPromise2.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var http = require("http"), 4 | url = require("url"), 5 | fs = require("fs"), 6 | Q = require("q"); 7 | 8 | var cache = {}, 9 | maxAge = 2000; 10 | 11 | function fileExistsPromise(path) { 12 | var defer = Q.defer(); 13 | fs.exists(path, function(exists) { 14 | return exists? defer.resolve(true) : defer.reject(new Error("no existe!")); 15 | }); 16 | return defer.promise; 17 | } 18 | 19 | function readFilePromise(path) { 20 | var defer = Q.defer(); 21 | fs.readFile(path, function(err, data) { 22 | return err? defer.reject(err) : defer.resolve(data); 23 | }); 24 | return defer.promise; 25 | } 26 | 27 | var server = http.createServer(function(req, res) { 28 | var urlData = url.parse(req.url), 29 | filePath = "./public" + urlData.pathname; 30 | fileExistsPromise(filePath) 31 | .then(function() { 32 | return readFilePromise(filePath); 33 | }) 34 | .then(function(data) { 35 | res.writeHead(200); 36 | res.end(data.toString()); 37 | }) 38 | .fail(function(err) { 39 | res.writeHead(404); 40 | res.end(err.message); 41 | }); 42 | }); 43 | 44 | server.listen(3000); 45 | -------------------------------------------------------------------------------- /ejercicios/staticPromise3.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var http = require("http"), 4 | url = require("url"), 5 | fs = require("fs"), 6 | Q = require("q"); 7 | 8 | var cache = {}, 9 | maxAge = 2000; 10 | 11 | function fileExistsPromise(path) { 12 | var defer = Q.defer(); 13 | fs.exists(path, function(exists) { 14 | return exists? defer.resolve(true) : defer.reject(new Error("no existe!")); 15 | }); 16 | return defer.promise; 17 | } 18 | 19 | function readFilePromise(path) { 20 | return fileExistsPromise(path) 21 | .then(function() { 22 | var defer = Q.defer(); 23 | fs.readFile(path, function(err, data) { 24 | return err? defer.reject(err) : defer.resolve(data); 25 | }); 26 | return defer.promise; 27 | }); 28 | } 29 | 30 | var server = http.createServer(function(req, res) { 31 | var urlData = url.parse(req.url), 32 | filePath = "./public" + urlData.pathname; 33 | 34 | readFilePromise(filePath) 35 | .then(function(data) { 36 | res.writeHead(200); 37 | res.end(data.toString()); 38 | }) 39 | .fail(function(err) { 40 | res.writeHead(404); 41 | res.end(err.message); 42 | }); 43 | }); 44 | 45 | server.listen(3000); 46 | -------------------------------------------------------------------------------- /ejercicios/test.js: -------------------------------------------------------------------------------- 1 | function fcall(fn) { 2 | var args = [].slice.call(arguments, 1); 3 | return fn.apply({}, args); 4 | } 5 | 6 | function suma(a, b) { 7 | return a + b; 8 | } 9 | 10 | function siete() { 11 | return 7; 12 | } 13 | 14 | fcall(siete); // 7 15 | 16 | fcall(suma, 1, 2); // 3 17 | 18 | obj = { 19 | hola: function() { 20 | console.log(this.mensaje); 21 | }, 22 | mensaje: "hola" 23 | }; 24 | 25 | var metodo = obj.hola; 26 | metodo.apply(obj, []); 27 | -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cases: ["A", "B", "C", "D"] 3 | } 4 | -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/A/css/styles.css: -------------------------------------------------------------------------------- 1 | body{margin: 0; padding: 0; background: #f1f1f1; font-family: 'Montserrat', sans-serif; font-weight: 400; color: #5f6060;} 2 | 3 | .wrapper{position: relative; width: 430px; margin: 100px auto 0; text-align: center;} 4 | .logo{margin: 12px 0;} 5 | 6 | #profile{background: #fff; padding: 26px;} 7 | #profile h1{margin: 30px 0 2px; font-weight: 700; font-size: 28px; color: #424242;} 8 | #profile h2{margin: 0 0 40px; font-weight: 400; font-size: 20px; color: #777;} 9 | #profile .button{display: block; width: 272px; height: 56px; margin: 0 auto; background: #cb2128; border-bottom: 4px solid #901a1c; color: #fff; text-decoration: none; text-transform: uppercase; text-align: left;} 10 | #profile .button img{vertical-align: middle;} 11 | #profile .button span{display: inline-block; vertical-align: middle; font-size: 22px; padding: 0 38px;} -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/A/foto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/A/foto.jpg -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/A/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/A/images/avatar.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/A/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/A/images/icon.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/A/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/A/images/logo.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/A/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | Avatar 18 |

Josh Hemsley

19 |

Savannah, GA

20 | Follow me 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/B/css/styles.css: -------------------------------------------------------------------------------- 1 | body{margin: 0; padding: 0; background: #f1f1f1; font-family: 'Montserrat', sans-serif; font-weight: 400; color: #5f6060;} 2 | 3 | .wrapper{position: relative; width: 430px; margin: 100px auto 0; text-align: center;} 4 | .logo{margin: 12px 0;} 5 | 6 | #profile{background: #fff; padding: 26px;} 7 | #profile h1{margin: 30px 0 2px; font-weight: 700; font-size: 28px; color: #424242;} 8 | #profile h2{margin: 0 0 40px; font-weight: 400; font-size: 20px; color: #777;} 9 | #profile .button{display: block; width: 272px; height: 56px; margin: 0 auto; background: #365d98; border-bottom: 4px solid #1d305e; color: #fff; text-decoration: none; text-transform: uppercase; text-align: left;} 10 | #profile .button img{vertical-align: middle;} 11 | #profile .button span{display: inline-block; vertical-align: middle; font-size: 22px; padding: 0 38px;} -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/B/foto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/B/foto.jpg -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/B/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/B/images/avatar.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/B/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/B/images/icon.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/B/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/B/images/logo.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/B/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | Avatar 18 |

Josh Hemsley

19 |

Savannah, GA

20 | Follow me 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/C/css/styles.css: -------------------------------------------------------------------------------- 1 | body{margin: 0; padding: 0; background: #f1f1f1; font-family: 'Montserrat', sans-serif; font-weight: 400; color: #5f6060;} 2 | 3 | .wrapper{position: relative; width: 430px; margin: 100px auto 0; text-align: center;} 4 | .logo{margin: 12px 0;} 5 | 6 | #profile{background: #fff; padding: 26px;} 7 | #profile h1{margin: 30px 0 2px; font-weight: 700; font-size: 28px; color: #424242;} 8 | #profile h2{margin: 0 0 40px; font-weight: 400; font-size: 20px; color: #777;} 9 | #profile .button{display: block; width: 272px; height: 56px; margin: 0 auto; background: #2eabe2; border-bottom: 4px solid #0570b4; color: #fff; text-decoration: none; text-transform: uppercase; text-align: left;} 10 | #profile .button img{vertical-align: middle;} 11 | #profile .button span{display: inline-block; vertical-align: middle; font-size: 22px; padding: 0 38px;} -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/C/foto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/C/foto.jpg -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/C/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/C/images/avatar.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/C/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/C/images/icon.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/C/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/C/images/logo.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/C/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | Avatar 18 |

Josh Hemsley

19 |

Savannah, GA

20 | Follow me 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/D/css/styles.css: -------------------------------------------------------------------------------- 1 | body{margin: 0; padding: 0; background: #f1f1f1; font-family: 'Montserrat', sans-serif; font-weight: 400; color: #5f6060;} 2 | 3 | .wrapper{position: relative; width: 430px; margin: 100px auto 0; text-align: center;} 4 | .logo{margin: 12px 0;} 5 | 6 | #profile{background: #fff; padding: 26px;} 7 | #profile h1{margin: 30px 0 2px; font-weight: 700; font-size: 28px; color: #424242;} 8 | #profile h2{margin: 0 0 40px; font-weight: 400; font-size: 20px; color: #777;} 9 | #profile .button{display: block; width: 272px; height: 56px; margin: 0 auto; background: #e94e8a; border-bottom: 4px solid #ae2859; color: #fff; text-decoration: none; text-transform: uppercase; text-align: left;} 10 | #profile .button img{vertical-align: middle;} 11 | #profile .button span{display: inline-block; vertical-align: middle; font-size: 22px; padding: 0 38px;} -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/D/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/D/images/avatar.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/D/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/D/images/icon.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/D/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/D/images/logo.png -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/D/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | Avatar 18 |

Josh Hemsley

19 |

Savannah, GA

20 | Follow me 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /soluciones/tema1/abtesting/public/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/abtesting/public/success.png -------------------------------------------------------------------------------- /soluciones/tema1/captcha/client.js: -------------------------------------------------------------------------------- 1 | var http = require("http") 2 | , url = require("url") 3 | , fs = require("fs") 4 | 5 | function rand(a, b) { 6 | var top = b ? (b - a) : a, 7 | delta = b ? a : 0; 8 | return Math.floor(Math.random() * top + delta); 9 | } 10 | 11 | function randomString(length) { 12 | var base = 36; 13 | return rand(Math.pow(base, length)).toString(base); 14 | } 15 | 16 | var store = {}, 17 | captchaServer = "http://localhost:3000"; 18 | 19 | function generateId() { 20 | var id = randomString(10); 21 | while (id in store) { id = randomString(10); } 22 | return id; 23 | } 24 | 25 | var routes = { 26 | "/form": function(req, res) { 27 | fs.readFile("./templates/form.html", function(err, template) { 28 | if (err) { 29 | res.writeHead(500); 30 | return res.end("Oops!"); 31 | } 32 | var response = ""; 33 | http.get(captchaServer + "/captcha", function(getResponse) { 34 | getResponse.on("data", function(data) { 35 | response += data; 36 | }); 37 | getResponse.on("end", function() { 38 | var html, id; 39 | try { 40 | response = JSON.parse(response); 41 | id = generateId(); 42 | store[id] = response; 43 | html = template.toString() 44 | .replace("#captcha-url#", captchaServer + response.url) 45 | .replace("#id#", id); 46 | res.end(html); 47 | } catch(e) { 48 | res.writeHead(500); 49 | res.end("Oops!"); 50 | } 51 | }) 52 | }); 53 | }) 54 | }, 55 | "/validate": function(req, res, urlData) { 56 | var id = urlData.query.id, 57 | code = urlData.query.captcha, 58 | data = store[id]; 59 | if (!data || data.code != code) { 60 | res.end("No.. Otra vez") 61 | } else { 62 | res.end("OK! Otra vez") 63 | } 64 | } 65 | } 66 | 67 | var server = http.createServer(function(req, res) { 68 | var urlData = url.parse(req.url, true), 69 | path = urlData.pathname; 70 | if (path in routes) { 71 | return routes[path](req, res, urlData); 72 | } else { 73 | res.writeHead(404); 74 | res.end("No existe"); 75 | } 76 | }); 77 | 78 | server.listen(3001); 79 | -------------------------------------------------------------------------------- /soluciones/tema1/captcha/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-captcha", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "canvas": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /soluciones/tema1/captcha/templates/form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Form 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /soluciones/tema1/discarded/transfer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-transfer", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "mustache": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /soluciones/tema1/discarded/transfer/public/client.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/discarded/transfer/public/client.html -------------------------------------------------------------------------------- /soluciones/tema1/discarded/transfer/public/source.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/discarded/transfer/public/source.html -------------------------------------------------------------------------------- /soluciones/tema1/discarded/transfer/templates/client-waiting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | Tu token es {{token}} 5 |

6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /soluciones/tema1/discarded/transfer/templates/waiting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | Tu token es {{token}} 5 |

6 |

7 | Tienes {{clients}} clientes esperando. 8 |

9 |
10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /soluciones/tema1/httpWorld.js: -------------------------------------------------------------------------------- 1 | var http = require("http"), 2 | , server = http.createServer() 3 | 4 | server.on("request", function(req, res) { 5 | res.end("Hello, world!") 6 | }) 7 | 8 | server.listen(3000) 9 | -------------------------------------------------------------------------------- /soluciones/tema1/simpleRouting/1/simpleRouting.js: -------------------------------------------------------------------------------- 1 | var http = require("http") 2 | , url = require("url"); 3 | 4 | var server = http.createServer(), 5 | routes = { 6 | "/miruta": function(req, res) { 7 | res.end("Hola!") 8 | } 9 | }; 10 | 11 | server.on("request", function(req, res) { 12 | var urlData = url.parse(req.url), 13 | path = urlData.pathname; 14 | if (path in routes) { 15 | return routes[path](req, res) 16 | } else { 17 | res.writeHead(404) 18 | res.end("Not found!") 19 | } 20 | }) 21 | 22 | server.listen(3000) 23 | -------------------------------------------------------------------------------- /soluciones/tema1/simpleRouting/2/joust.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/simpleRouting/2/joust.jpg -------------------------------------------------------------------------------- /soluciones/tema1/simpleRouting/2/simpleRouting.js: -------------------------------------------------------------------------------- 1 | /* Leer y devolver un fichero */ 2 | 3 | var http = require("http") 4 | , url = require("url") 5 | , fs = require("fs"); 6 | 7 | var server = http.createServer(), 8 | routes = { 9 | "/miruta": function(req, res) { 10 | fs.readFile("./joust.jpg", function(err, data) { 11 | if (err) { 12 | res.writeHead(500); 13 | res.end("Ha ocurrido algo malo") 14 | } 15 | res.end(data) 16 | }) 17 | } 18 | }; 19 | 20 | server.on("request", function(req, res) { 21 | var urlData = url.parse(req.url), 22 | path = urlData.pathname; 23 | if (path in routes) { 24 | return routes[path](req, res) 25 | } else { 26 | res.writeHead(404) 27 | res.end("Not found!") 28 | } 29 | }) 30 | 31 | server.listen(3000) 32 | -------------------------------------------------------------------------------- /soluciones/tema1/simpleRouting/3/public/joust.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/simpleRouting/3/public/joust.jpg -------------------------------------------------------------------------------- /soluciones/tema1/simpleRouting/3/simpleRouting.js: -------------------------------------------------------------------------------- 1 | /* Leer y devolver un fichero */ 2 | 3 | var http = require("http") 4 | , url = require("url") 5 | , fs = require("fs"); 6 | 7 | var server = http.createServer(); 8 | 9 | server.on("request", function(req, res) { 10 | var urlData = url.parse(req.url), 11 | path = urlData.pathname, 12 | filePath = "./public" + path; 13 | fs.exists(filePath, function(exists) { 14 | if (exists) { 15 | fs.readFile("./public" + path, function(err, data) { 16 | if (err) { 17 | res.writeHead(500); 18 | res.end("Ha ocurrido algo malo"); 19 | } else { 20 | res.end(data); 21 | } 22 | }) 23 | } else { 24 | res.writeHead(404); 25 | res.end("No existe!") 26 | } 27 | }) 28 | }) 29 | 30 | server.listen(3000) 31 | -------------------------------------------------------------------------------- /soluciones/tema1/simpleRouting/4/simpleRouting.js: -------------------------------------------------------------------------------- 1 | /* Leer y devolver un fichero */ 2 | 3 | var http = require("http") 4 | , url = require("url") 5 | , fs = require("fs"); 6 | 7 | var server = http.createServer(), 8 | cache = {}; 9 | 10 | server.on("request", function(req, res) { 11 | var urlData = url.parse(req.url), 12 | path = urlData.pathname, 13 | filePath = "./public" + path; 14 | if (filePath in cache) { 15 | console.log(" * cache hit: %s", filePath); 16 | res.end(cache[filePath]) 17 | } else { 18 | fs.exists(filePath, function(exists) { 19 | if (exists) { 20 | console.log("-> %s existe! Leyendo el fichero...", filePath); 21 | fs.readFile("./public" + path, function(err, data) { 22 | if (err) { 23 | res.writeHead(500); 24 | res.end("Ha ocurrido algo malo"); 25 | } else { 26 | cache[filePath] = data; 27 | res.end(data); 28 | } 29 | }) 30 | } else { 31 | res.writeHead(404); 32 | res.end("No existe!") 33 | } 34 | }) 35 | } 36 | }) 37 | 38 | server.listen(3000) 39 | -------------------------------------------------------------------------------- /soluciones/tema1/tiles/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-captcha", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "canvas": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /soluciones/tema1/tiles/public/dimension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/tiles/public/dimension.png -------------------------------------------------------------------------------- /soluciones/tema1/tiles/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Canvas Map 5 | 33 | 34 | 35 | 36 |
37 |
38 |
39 |
40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /soluciones/tema1/tiles/public/map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/tiles/public/map.jpg -------------------------------------------------------------------------------- /soluciones/tema1/tiles/server.js: -------------------------------------------------------------------------------- 1 | var http = require("http"), 2 | url = require("url"), 3 | fs = require("fs"), 4 | Canvas = require("canvas"), 5 | Image = Canvas.Image; 6 | 7 | var publicDir = "./public", 8 | tileSize = 100, 9 | cache = {}; 10 | 11 | function extract_tile(imgData, coords, res, filePath) { 12 | var img, 13 | canvas, 14 | ctx, 15 | stream, 16 | origin; 17 | if (imgData === null) { 18 | img = cache[filePath]; 19 | } else { 20 | img = new Image(); 21 | img.src = new Buffer(imgData, "binary"); 22 | cache[filePath] = img; 23 | } 24 | canvas = new Canvas(tileSize, tileSize); 25 | ctx = canvas.getContext("2d"); 26 | origin = { 27 | x: Math.min(img.width-tileSize, Math.floor(coords.x/tileSize)*tileSize), 28 | y: Math.min(img.height-tileSize, Math.floor(coords.y/tileSize)*tileSize) 29 | }; 30 | origin.x = Math.max(0, origin.x); 31 | origin.y = Math.max(0, origin.y); 32 | ctx.drawImage(img, origin.x, origin.y, tileSize, tileSize, 0, 0, tileSize, tileSize); 33 | stream = canvas.pngStream(); 34 | stream.pipe(res) 35 | /* 36 | stream.on("data", res.write.bind(res)); 37 | stream.on("end", res.end.bind(res)); 38 | */ 39 | } 40 | 41 | var server = http.createServer(function(req, res) { 42 | var urlData = url.parse(req.url, true), 43 | path = urlData.pathname, 44 | coords = {x: urlData.query.x || 0, y: urlData.query.y || 0}, 45 | filePath = publicDir + path; 46 | if (cache[filePath]) { 47 | return extract_tile(null, coords, res, filePath); 48 | } 49 | fs.exists(filePath, function(exsits) { 50 | if (!exsits) { 51 | res.writeHead(404); 52 | return res.end("No existe!"); 53 | /* Error */ 54 | } 55 | fs.readFile(filePath, function(err, data) { 56 | if (err) { throw err; } 57 | if (path.match(/jpg$/)) { 58 | extract_tile(data, coords, res, filePath); 59 | } else { 60 | res.end(data); 61 | } 62 | }); 63 | }); 64 | }) 65 | .listen(3000); 66 | -------------------------------------------------------------------------------- /soluciones/tema1/watermark/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-captcha", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "canvas": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /soluciones/tema1/watermark/public/mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/watermark/public/mark.png -------------------------------------------------------------------------------- /soluciones/tema1/watermark/public/programador.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema1/watermark/public/programador.png -------------------------------------------------------------------------------- /soluciones/tema1/watermark/server.js: -------------------------------------------------------------------------------- 1 | var Canvas = require("canvas") 2 | , Image = Canvas.Image 3 | , http = require("http") 4 | , url = require("url") 5 | , fs = require("fs"); 6 | 7 | function watermark(imageData, res) { 8 | var img = new Image, 9 | canvas, 10 | ctx; 11 | img.src = new Buffer(imageData, "binary"); 12 | canvas = new Canvas(img.width, img.height); 13 | ctx = canvas.getContext("2d"); 14 | ctx.drawImage(img, 0, 0, img.width, img.height); 15 | fs.readFile("./public/mark.png", function(err, markData) { 16 | if (err) { 17 | res.writeHead(500); 18 | return res.end("Oops.."); 19 | } 20 | var mark = new Image(), 21 | stream, 22 | timesH, 23 | thimesV; 24 | mark.src = new Buffer(markData, "binary"); 25 | ctx.globalAlpha = 0.2; 26 | timesH = Math.ceil(img.width/mark.width); 27 | timesV = Math.ceil(img.height/mark.height); 28 | for (var i=0; i", 5 | "description": "Servidor de ficheros con versionado", 6 | "main": "./server", 7 | "dependencies" : { 8 | "Q": "*" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /soluciones/tema2/gitversionedserver/simpleRoute.js: -------------------------------------------------------------------------------- 1 | var url = require("url"); 2 | 3 | var routes = {}; 4 | 5 | module.exports = { 6 | get: function(route, cb) { 7 | routes[route] = cb; 8 | }, 9 | listen: function(httpServer, port) { 10 | httpServer.on("request", function(req, res) { 11 | req.url = url.parse(req.url, true); 12 | if (req.url.pathname in routes) { 13 | routes[req.url.pathname](req, res); 14 | } else if ("default" in routes) { 15 | routes["default"](req, res); 16 | } else { 17 | res.writeHead(500); 18 | res.end("Error: La ruta " + req.url.pathname + " no está registrada"); 19 | } 20 | }); 21 | httpServer.listen(port); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /soluciones/tema2/logger/access.log: -------------------------------------------------------------------------------- 1 | [1378749838906] 127.0.0.1 pidió / 2 | [1378749838907] / no existe 3 | [1378749876889] 127.0.0.1 pidió /test.txt 4 | [1378749876890] /test.txt servido correctamente 5 | -------------------------------------------------------------------------------- /soluciones/tema2/logger/public/test.txt: -------------------------------------------------------------------------------- 1 | Test 2 | -------------------------------------------------------------------------------- /soluciones/tema2/logger/server.js: -------------------------------------------------------------------------------- 1 | var http = require("http"), 2 | url = require("url"), 3 | fs = require("fs") 4 | 5 | var publicPath = "./public"; 6 | 7 | http.createServer(function(req, res) { 8 | var path = url.parse(req.url).pathname, 9 | filePath = publicPath + path; 10 | 11 | var log = fs.open("./access.log", "a", function(err, fd) { 12 | if (err) { 13 | // Error 14 | } 15 | var buffer = new Buffer("[" + Date.now() + "] " + req.connection.remoteAddress + " pidió " + path + "\n", "utf-8") 16 | fs.write(fd, buffer, 0, buffer.length, null, function(err, written, buf) { 17 | if (err) { 18 | // Error 19 | } 20 | if (written != buffer.length) { 21 | // Log Error 22 | } 23 | fs.exists(filePath, function(exists) { 24 | if (exists) { 25 | var buffer = new Buffer("[" + Date.now() + "] " + path + " servido correctamente\n", "utf-8"); 26 | fs.write(fd, buffer, 0, buffer.length, null, function(err, written, buf) { 27 | fs.readFile(filePath, function(err, file) { 28 | if (err) { 29 | // Error 30 | } 31 | fs.close(fd, function(err) { 32 | if (err) { 33 | // Error 34 | } 35 | res.end(file); 36 | }) 37 | }) 38 | }) 39 | } else { 40 | // Error 41 | var buffer = new Buffer("[" + Date.now() + "] " + path + " no existe\n", "utf-8"); 42 | fs.write(fd, buffer, 0, buffer.length, null, function(err, written, buf) { 43 | fs.close(fd, function(err) { 44 | if (err) { 45 | // Error 46 | } 47 | res.writeHead(404); 48 | res.end("No existe"); 49 | }) 50 | }) 51 | } 52 | }) 53 | }); 54 | }); 55 | }) 56 | .listen(3000) 57 | -------------------------------------------------------------------------------- /soluciones/tema2/versionedserver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-versionserver", 3 | "version": "0.0.1", 4 | "author": "Elías Alonso ", 5 | "description": "Servidor de ficheros con versionado", 6 | "main": "./server", 7 | "dependencies" : { 8 | "Q": "*" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /soluciones/tema2/versionedserver/simpleRoute.js: -------------------------------------------------------------------------------- 1 | var url = require("url"); 2 | 3 | var routes = {}; 4 | 5 | module.exports = { 6 | get: function(route, cb) { 7 | routes[route] = cb; 8 | }, 9 | listen: function(httpServer, port) { 10 | httpServer.on("request", function(req, res) { 11 | req.url = url.parse(req.url, true); 12 | if (req.url.pathname in routes) { 13 | routes[req.url.pathname](req, res); 14 | } else if ("default" in routes) { 15 | routes["default"](req, res); 16 | } else { 17 | res.writeHead(500); 18 | res.end("Error: La ruta " + req.url.pathname + " no está registrada"); 19 | } 20 | }); 21 | httpServer.listen(port); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /soluciones/tema3/blogAuth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-simpleblog", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "jade": "*", 7 | "express": "*", 8 | "method-override": "^1.0.0", 9 | "cookie-parser": "^1.0.1", 10 | "morgan": "^1.0.1", 11 | "cookie-session": "^1.0.2", 12 | "body-parser": "^1.0.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /soluciones/tema3/blogAuth/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype 2 | html(lang='es') 3 | head 4 | meta(charset='utf-8') 5 | title Lista de Posts 6 | meta(name='description', content='') 7 | meta(property='og:image', content='') 8 | // Fonts 9 | link(href='http://fonts.googleapis.com/css?family=Roboto:400,300,500,700,400italic,300italic', rel='stylesheet', type='text/css') 10 | // Frameworks 11 | link(rel='stylesheet', href='/css/normalize.css') 12 | // Stylesheets 13 | link(rel='stylesheet', href='/css/styles.css', media='screen') 14 | body.post-list 15 | header 16 | .top 17 | h1 Mi Blog 18 | .newpost 19 | a(href='/posts/new') Nuevo Post 20 | .logout 21 | a(href='/logout') Logout 22 | block nav 23 | block content 24 | -------------------------------------------------------------------------------- /soluciones/tema3/blogAuth/views/login.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Login 6 | form.login-form(action="/session", method="POST") 7 | label(for='email') email 8 | input.email(type='email', name='username') 9 | label(for='password') contraseña 10 | input.password(type='password', name='password') 11 | input.button.login(type='submit', value='Login') 12 | 13 | section.register 14 | a(href="/register") Registrate 15 | -------------------------------------------------------------------------------- /soluciones/tema3/blogAuth/views/new-post.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.new-post.container 5 | h1.section-title= post.date? "Editar Post" : "Nuevo Post" 6 | form.new-post-form(action=post.date? "/posts/#{post.id}":"/posts", method="POST") 7 | label(for='title') Título 8 | input.title(type='text', name='title', value=post.title) 9 | label(for='post-title') Contenido 10 | textarea.post-content(name='content', placeholder='')= post.content 11 | if post.date 12 | input(type="hidden",name="_method",value="put") 13 | input.button(type='submit', value='Publicar') 14 | -------------------------------------------------------------------------------- /soluciones/tema3/blogAuth/views/post-detail.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block nav 4 | nav.menu 5 | ul 6 | li 7 | a(href='/posts') Volver 8 | li 9 | a(href='/posts/#{post.id}/edit') Editar 10 | li 11 | form(action="/posts/#{post.id}",method="POST",id="form-delete") 12 | input(type="hidden",name="_method",value="delete") 13 | a(href='#',onclick="document.getElementById('form-delete').submit()") Eliminar 14 | 15 | block content 16 | section.posts 17 | article.post 18 | .container 19 | h1.post-title= post.title 20 | p= post.content 21 | aside.metadata 22 | | Por 23 | a(href='#')  Default User 24 | span.sep   |   25 | | 0 visitas 26 | -------------------------------------------------------------------------------- /soluciones/tema3/blogAuth/views/post-list.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.posts 5 | each post in posts 6 | article.post 7 | .container 8 | h2.post-title 9 | a(href='/posts/#{post.id}')= post.title 10 | p.summary= post.content.slice(0, 150) 11 | aside.metadata 12 | | Por 13 | a(href='#')  Default User 14 | span.sep   |   15 | | 0 visitas 16 | -------------------------------------------------------------------------------- /soluciones/tema3/blogAuth/views/register.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Registro de Usuario 6 | form.login-form(action="/register", method="POST") 7 | label(for='email') email 8 | input.email(type='email', name='username') 9 | label(for='password') contraseña 10 | input.password(type='password', name='password') 11 | label(for='password') confirmación 12 | input.password(type='password', name='passwordconfirm') 13 | input.button.login(type='submit', value='Enviar') 14 | 15 | section.register 16 | a(href="/login") ¿Ya tienes usuario? 17 | -------------------------------------------------------------------------------- /soluciones/tema3/simpleAuthModule/app.js: -------------------------------------------------------------------------------- 1 | /* Dependencies */ 2 | 3 | var express = require("express") 4 | , env = process.env.NODE_ENV || "development" 5 | , auth = require("./simpleauth") 6 | , logger = require("morgan") 7 | , bodyParser = require("body-parser") 8 | , cookieParser = require("cookie-parser") 9 | , cookieSession = require("cookie-session") 10 | 11 | var users = [ 12 | { 13 | id: 0, 14 | username: "node@redradix.com", 15 | pass: "redradix" 16 | } 17 | ] 18 | 19 | auth.setStrategy({ 20 | serializeUser: function(user) { 21 | return user.id 22 | }, 23 | deserializeUser: function(userId, cb) { 24 | if (userId in users) { 25 | cb(users[userId]) 26 | } else { 27 | cb(false) 28 | } 29 | }, 30 | checkCredentials: function(username, pass, cb) { 31 | console.log(username, pass) 32 | var user = users.filter(function(i) { return i.username === username })[0] 33 | if (!user || user.pass !== pass) { 34 | cb(null, false); 35 | } else { 36 | cb(null, user) 37 | } 38 | }, 39 | loginRoute: "/login.html" 40 | }) 41 | 42 | var app = express() 43 | 44 | app.set('port', process.env.PORT || 3000) 45 | app.use(logger('dev')) 46 | app.use(bodyParser.json()) 47 | app.use(bodyParser.urlencoded({extended: false})) 48 | 49 | 50 | app.use(cookieParser('secret')) 51 | app.use(cookieSession({keys: ['secret']})) 52 | 53 | app.use(express.static(__dirname + '/public')) 54 | 55 | /* Rutas */ 56 | 57 | app.get('/', function(req, res) { 58 | res.redirect('/login.html'); 59 | }) 60 | 61 | app.post("/session", auth.createSession({ redirect: "/ok" })) 62 | 63 | app.get("/ok", auth.requiresSession, function(req, res) { 64 | res.end("OK!") 65 | }) 66 | 67 | app.get("/secret", auth.requiresSession, function(req, res) { 68 | res.end("Hola, " + req.user.username) 69 | }) 70 | 71 | app.get("/logout", auth.requiresSession, function(req, res) { 72 | auth.destroySession(res) 73 | res.redirect("/login.html") 74 | }) 75 | 76 | app.listen(3000) 77 | 78 | /* TODO: Explain sessions and implement it properly using express sessions */ 79 | -------------------------------------------------------------------------------- /soluciones/tema3/simpleAuthModule/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-simpleauth", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "express": "*", 7 | "lodash": "*", 8 | "morgan": "*", 9 | "body-parser": "*", 10 | "method-override": "*", 11 | "cookie-parser": "*", 12 | "cookie-session": "*" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /soluciones/tema3/simpleAuthModule/public/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |

7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /soluciones/tema3/simpleAuthModule/simpleauth.js: -------------------------------------------------------------------------------- 1 | var _ = require("lodash") 2 | 3 | strategy = { 4 | serializeUser: function(user) { 5 | }, 6 | deserializeUser: function(userId, cb) { 7 | }, 8 | checkCredentials: function(username, pass, done) { 9 | }, 10 | loginRoute: "/login" 11 | } 12 | 13 | exports.setStrategy = function(customStrategy) { 14 | strategy = _.extend({}, strategy, customStrategy) 15 | } 16 | 17 | exports.createSession = function(options) { 18 | var config = { 19 | username: "username", 20 | password: "password", 21 | redirect: "/me", 22 | failRedirect: strategy.loginRoute 23 | } 24 | config = _.extend({}, config, options) 25 | return function(req, res, next) { 26 | var username = req.body[config.username], 27 | pass = req.body[config.password] 28 | strategy.checkCredentials(username, pass, function(err, user) { 29 | if (!err && user) { 30 | res.cookie("user", strategy.serializeUser(user), {signed: true, maxAge: 1000*60*60*24*7}) 31 | res.redirect(config.redirect) 32 | } else { 33 | console.log("Credenciales incorrectas") 34 | res.redirect(config.failRedirect) 35 | } 36 | }) 37 | } 38 | } 39 | 40 | exports.requiresSession = function(req, res, next) { 41 | if (req.signedCookies.user) { 42 | strategy.deserializeUser(req.signedCookies.user, function(user) { 43 | if (!user) { 44 | console.log("El usuario no existe!") 45 | res.clearCookie("user") 46 | res.redirect(strategy.loginRoute) 47 | } else { 48 | req.user = user 49 | next() 50 | } 51 | }) 52 | } else { 53 | console.log("No existe la sesión...") 54 | res.redirect(strategy.loginRoute) 55 | } 56 | } 57 | 58 | exports.destroySession = function(res) { 59 | res.clearCookie("user") 60 | } 61 | -------------------------------------------------------------------------------- /soluciones/tema4/urlshort/.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude vim temp files 2 | *.swp 3 | *.swo 4 | # Databases 5 | *.sqlite 6 | # Exclude OS X folder attributes 7 | .DS_Store 8 | # Exclude npm packages 9 | node_modules 10 | # Exclude REDIS dumps 11 | dump.rdb 12 | Vagrantfile 13 | .vagrant 14 | -------------------------------------------------------------------------------- /soluciones/tema4/urlshort/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-urlshort", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "q": "*", 7 | "jade": "*", 8 | "express": "*", 9 | "hiredis": "*", 10 | "redis": "*", 11 | "serve-favicon": "*", 12 | "body-parser": "*", 13 | "method-override": "*", 14 | "cookie-parser": "*", 15 | "cookie-session": "*", 16 | "morgan": "^1.0.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /soluciones/tema4/urlshort/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype 2 | html(lang='es') 3 | head 4 | meta(charset='utf-8') 5 | title Url Shortener 6 | meta(name='description', content='') 7 | meta(property='og:image', content='') 8 | // Fonts 9 | link(href='http://fonts.googleapis.com/css?family=Roboto:400,300,500,700,400italic,300italic', rel='stylesheet', type='text/css') 10 | // Frameworks 11 | link(rel='stylesheet', href='/css/normalize.css') 12 | // Stylesheets 13 | link(rel='stylesheet', href='/css/styles.css', media='screen') 14 | body.post-list 15 | header 16 | .top 17 | h1 Url Shortener 18 | block buttons 19 | block nav 20 | block content 21 | -------------------------------------------------------------------------------- /soluciones/tema4/urlshort/views/login.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Login 6 | form.login-form(action="/session", method="POST") 7 | label(for='email') Email 8 | input.email(type='email', name='username') 9 | label(for='password') Contraseña 10 | input.password(type='password', name='password') 11 | input.button.login(type='submit', value='Login') 12 | 13 | section.register 14 | a(href="/register") Registrate 15 | -------------------------------------------------------------------------------- /soluciones/tema4/urlshort/views/register.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Registro de Usuario 6 | form.login-form(action="/register", method="POST") 7 | label(for='email') email 8 | input.email(type='email', name='username') 9 | label(for='password') contraseña 10 | input.password(type='password', name='password') 11 | label(for='password') confirmación 12 | input.password(type='password', name='passwordconfirm') 13 | input.button.login(type='submit', value='Enviar') 14 | 15 | section.register 16 | a(href="/login") ¿Ya tienes usuario? 17 | -------------------------------------------------------------------------------- /soluciones/tema4/urlshort/views/url-form.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block buttons 4 | .newpost 5 | a(href='/urls/new') Nueva URL 6 | .logout 7 | a(href='/logout') Logout 8 | 9 | block nav 10 | nav.menu 11 | ul 12 | li 13 | a(href='/urls') Volver 14 | 15 | block content 16 | section.login 17 | .section-title 18 | h1= url.code? "Editar URL "+url.code : "Nueva URL" 19 | form.login-form(action=url.code? "/urls/#{url.code}" : "/urls", method="POST") 20 | input(type="text", name="original", placeholder="url", value=url.original, style="height:45px; margin-top:13px; width:480px") 21 | if url.code 22 | input(type="hidden", name="_method", value="put") 23 | input.button(type="submit") 24 | -------------------------------------------------------------------------------- /soluciones/tema4/urlshort/views/url-index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block buttons 4 | .newpost 5 | a(href='/urls/new') Nueva URL 6 | .logout 7 | a(href='/logout') Logout 8 | 9 | block content 10 | section.url-list.container 11 | table 12 | thead 13 | th.long URL original 14 | th Creado 15 | th URL corta 16 | th Visitas 17 | th Detalles 18 | each url in urls 19 | tr 20 | td: a(href=url.original)= url.original 21 | if url.date 22 | - var d = new Date(url.date) 23 | td #{d.getDate()}/#{d.getMonth()}/#{d.getFullYear()} 24 | else 25 | td -- 26 | td: a(href="/#{url.code}") http://#{host}/#{url.code} 27 | td= url.visits 28 | td: a(href="/urls/#{url.code}") Detalles 29 | -------------------------------------------------------------------------------- /soluciones/tema4/urlshort/views/url-show.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block buttons 4 | .newpost 5 | a(href='/urls/new') Nueva URL 6 | .logout 7 | a(href='/logout') Logout 8 | 9 | block nav 10 | nav.menu 11 | ul 12 | li 13 | a(href='/urls') Volver 14 | li 15 | a(href='/urls/#{url.code}/edit') Editar 16 | li 17 | form(action="/urls/#{url.code}",method="POST",id="form-delete") 18 | input(type="hidden",name="_method",value="delete") 19 | a(href='#',onclick="document.getElementById('form-delete').submit()") Eliminar 20 | 21 | block content 22 | section.login 23 | .section-title 24 | h1 http://#{host}/#{url.code} 25 | h4= url.original 26 | p Visitas: #{url.visits} 27 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/bin/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var app = require('../app'); 3 | var port = process.env.PORT || 3000; 4 | 5 | var server = app.listen(port, function() { 6 | console.log('Express server listening on port ' + port); 7 | }); 8 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/data/db/.gitinclude: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema5/digg_clone_bluebird/data/db/.gitinclude -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/models/comment.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils'); 2 | var ObjectID = require('mongodb').ObjectID; 3 | 4 | var Comment = { 5 | getByPostId: function(postId){ 6 | var collection = utils.collection('comments'); 7 | return collection.find({ 'post_id': postId }) 8 | .sort([['date', 1]]) 9 | .toArrayAsync(); 10 | }, 11 | getById: function(commentId){ 12 | var collection = utils.collection('comments'); 13 | return collection.findOneAsync({ _id: ObjectID(commentId )}); 14 | }, 15 | save: function(comment){ 16 | var collection = utils.collection('comments'); 17 | return collection.saveAsync(comment); 18 | } 19 | } 20 | 21 | module.exports = Comment; -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/models/index.js: -------------------------------------------------------------------------------- 1 | module.exports = exports = Object.create(require('./utils')); 2 | 3 | exports.user = require('./user'); 4 | exports.post = require('./post'); 5 | exports.comment = require('./comment'); 6 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/models/post.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils'); 2 | var ObjectID = require('mongodb').ObjectID; 3 | 4 | var COLNAME = 'posts'; 5 | var PAGE_SIZE = 10; 6 | 7 | var Post = { 8 | getPostsBySection: function(section, page){ 9 | var page = page || 0; 10 | var collection = utils.collection(COLNAME); 11 | var cursor = collection.find({}).limit(PAGE_SIZE).skip(PAGE_SIZE*(page)); 12 | switch(section){ 13 | case 'hottest': 14 | cursor = cursor.sort([['votes', -1]]); 15 | break; 16 | case 'latest': 17 | cursor = cursor.sort([['date', -1]]); 18 | } 19 | return cursor.toArrayAsync(); 20 | }, 21 | getById: function(id){ 22 | var collection = utils.collection(COLNAME); 23 | return collection.findOneAsync({ _id: ObjectID(id)}); 24 | }, 25 | save: function(post){ 26 | var collection = utils.collection(COLNAME); 27 | return collection.saveAsync(post); 28 | }, 29 | } 30 | 31 | 32 | module.exports = Post; 33 | 34 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/models/user.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils'); 2 | 3 | var User = { 4 | checkCredentials: function(email, password) { 5 | var collection = utils.collection('users'); 6 | return collection.find({ email: email, password: password }).limit(1).toArrayAsync(); 7 | }, 8 | getUserByToken: function(token){ 9 | var collection = utils.collection('users'); 10 | return collection.findOneAsync({ token: token }); 11 | }, 12 | save: function(userdata){ 13 | var collection = utils.collection('users'); 14 | userdata.token = Date.now().toString(16); 15 | return collection.saveAsync(userdata); 16 | } 17 | } 18 | 19 | 20 | module.exports = User; 21 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/models/utils.js: -------------------------------------------------------------------------------- 1 | var Promise = require('bluebird'); 2 | 3 | var client = null; 4 | 5 | exports.setClient = function(mongoClient) { 6 | client = mongoClient; 7 | }; 8 | 9 | exports.getClient = function(){ 10 | return client; 11 | } 12 | 13 | exports.collection = function(name){ 14 | return client.collection(name); 15 | } 16 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-digg", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/start" 7 | }, 8 | "dependencies": { 9 | "bluebird": "^2.10.2", 10 | "body-parser": "~1.0.0", 11 | "cookie-parser": "~1.0.1", 12 | "cookie-session": "~1.0.1", 13 | "debug": "~0.7.4", 14 | "express": "~4.0.0", 15 | "jade": "~1.3.0", 16 | "method-override": "~1.0.0", 17 | "mongodb": "~1.4.2", 18 | "morgan": "~1.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/public/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | 3 | $('.add > a').on('click', function(){ 4 | $(this).parent('.add').toggleClass('active'); 5 | }); 6 | 7 | 8 | 9 | 10 | }); 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/public/assets/stylesheets/mixins.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema5/digg_clone_bluebird/public/assets/stylesheets/mixins.css -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/public/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema5/digg_clone_bluebird/public/img/loading.gif -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/routes/comments.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var auth = require('../simpleauth'); 3 | 4 | var Comment = require('../models/comment'); 5 | var Post = require('../models/post'); 6 | 7 | var commentsController = { 8 | index: function(req, res) { 9 | var postId = req.query.post_id; 10 | Comment.getByPostId(postId).then(function(comments){ 11 | res.send(comments); 12 | }); 13 | }, 14 | create: function(req, res) { 15 | console.log('Create comment', req.body); 16 | //cargar el post primero para ver si existe 17 | Post.getById(req.body.post_id).then(function(post){ 18 | if(!post){ 19 | return res.status(404).end(); 20 | } 21 | var newComment = req.body; 22 | newComment.date = Date.now(); 23 | newComment.user = { 24 | name: req.user.name, 25 | id: req.user.id 26 | } 27 | delete newComment.token; 28 | Comment.save(newComment).then(function(comment){ 29 | //tengo que sumar comentario al post 30 | post.ncomments++; 31 | Post.save(post).then(function(post){ 32 | res.status(201).send(comment); 33 | }); 34 | }) 35 | .catch(function(err){ 36 | console.log('Error saving comment', err); 37 | res.status(400).end(); 38 | }); 39 | }) 40 | .catch(function(err){ 41 | res.status(404); 42 | }) 43 | 44 | }, 45 | vote: function(req, res) { 46 | req.comment.votes++; 47 | Comment.save(req.comment).then(function(comment){ 48 | res.send(comment); 49 | }); 50 | }, 51 | param: function(req, res, next, commentId) { 52 | Comment.getById(commentsId).then(function(comment){ 53 | if(comment){ 54 | req.comment = comment; 55 | next(); 56 | } 57 | else { 58 | res.status(404).end(); 59 | } 60 | }) 61 | } 62 | }; 63 | 64 | var router = express.Router(); 65 | router.use(auth.requiresToken); 66 | router.get('/', commentsController.index); 67 | router.post('/', commentsController.create); 68 | router.post('/:commentId/vote/:vote', commentsController.vote); 69 | router.param('commentId', commentsController.param); 70 | 71 | module.exports = router; 72 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/routes/posts.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var auth = require('../simpleauth'); 3 | 4 | var Post = require('../models').post; 5 | 6 | var postsController = { 7 | index: function(req, res) { 8 | Post.getPostsBySection(req.query.s, req.query.page).then(function(posts){ 9 | res.send(posts); 10 | }); 11 | }, 12 | show: function(req, res) { 13 | res.send(req.post); 14 | }, 15 | create: function(req, res) { 16 | var postData = req.body; 17 | //set the user who created it 18 | postData.user = req.user; 19 | postData.date = Date.now(); 20 | 21 | Post.save(postData).then(function(newPost){ 22 | res.status(201).send(newPost); 23 | }); 24 | }, 25 | update: function(req, res) { 26 | Post.save(req.body).then(function(post){ 27 | console.log('Post updated', post); 28 | res.status(200).send(post); 29 | }) 30 | }, 31 | "delete": function(req, res) { 32 | //no implementado en la UI 33 | }, 34 | vote: function(req, res) { 35 | //ya tenemos el post en req.post 36 | var updatedPost = req.post; 37 | console.log('Voting on', req.post); 38 | if(req.params.vote === 'up'){ 39 | updatedPost.votes++; 40 | } 41 | if(req.params.vote === 'down'){ 42 | updatedPost.votes--; 43 | } 44 | Post.save(updatedPost).then(function(post){ 45 | res.status(200).send(post); 46 | }); 47 | }, 48 | param: function(req, res, next, postId) { 49 | Post.getById(postId).then(function(post){ 50 | console.log('Post param', post); 51 | if(post){ 52 | req.post = post; 53 | next(); 54 | } 55 | else { 56 | res.status(404).end(); 57 | } 58 | }) 59 | } 60 | }; 61 | 62 | var router = express.Router(); 63 | router.use(auth.requiresToken); 64 | 65 | router.param('postId', postsController.param); 66 | router.get('/', postsController.index); 67 | router.post('/', postsController.create); 68 | router.get('/:postId', postsController.show); 69 | router.put('/:postId', postsController.update); 70 | router.delete('/:postId', postsController.delete); 71 | router.post('/:postId/vote/:vote', postsController.vote); 72 | 73 | 74 | module.exports = router; 75 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var auth = require('../simpleauth'); 3 | 4 | var User = require('../models/user'); 5 | 6 | var usersController = { 7 | create: function(req, res) { 8 | console.log('Register user', req.body); 9 | if(req.body.password !== req.body.passwordconfirm){ 10 | res.status(400).send('Passwords no coinciden'); 11 | } 12 | else { 13 | User.save({ 14 | email: req.body.username, 15 | name: req.body.name, 16 | date: Date.now(), 17 | password: req.body.password 18 | }).then(function(user){ 19 | delete user.password; 20 | res.status(200).send(user); 21 | }) 22 | } 23 | }, 24 | me: function(req, res) { 25 | res.status(200).send(req.user); 26 | }, 27 | login: function(req, res) { 28 | res.status(200).send(req.user); 29 | } 30 | }; 31 | 32 | var router = express.Router(); 33 | router.post('/session', auth.createSession(), usersController.login); 34 | router.post('/users', usersController.create); 35 | router.get('/me', auth.requiresToken, usersController.me); 36 | 37 | module.exports = router; 38 | -------------------------------------------------------------------------------- /soluciones/tema5/digg_clone_bluebird/simpleauth.js: -------------------------------------------------------------------------------- 1 | function extend() { 2 | var args = [].slice.call(arguments) 3 | return args.reduce(function(acc, el) { 4 | for (var k in el) { acc[k] = el[k] } 5 | return acc; 6 | }) 7 | } 8 | 9 | var strategy = { 10 | serializeUser: function(user) { 11 | }, 12 | deserializeUser: function(userId, cb) { 13 | }, 14 | checkCredentials: function(username, pass, done) { 15 | } 16 | } 17 | 18 | exports.setStrategy = function(customStrategy) { 19 | strategy = extend({}, strategy, customStrategy) 20 | } 21 | 22 | exports.createSession = function(options) { 23 | var config = { 24 | username: "username", 25 | password: "password", 26 | } 27 | config = extend({}, config, options) 28 | return function(req, res, next) { 29 | var username = req.body[config.username], 30 | pass = req.body[config.password] 31 | strategy.checkCredentials(username, pass, function(err, user) { 32 | if (!err && user) { 33 | req.user = user 34 | next() 35 | /* res.redirect(config.redirect) */ 36 | } else { 37 | console.log("Credenciales incorrectas") 38 | res.send(401, {error: "Username o contraseña incorrectos"}) 39 | } 40 | }) 41 | } 42 | } 43 | 44 | exports.requiresToken = function(req, res, next) { 45 | var token = req.param("token") 46 | if (token !== undefined) { 47 | strategy.deserializeUser(token, function(user) { 48 | if (!user) { 49 | console.log("El usuario no existe!") 50 | res.send(401, {error: "No autorizado"}) 51 | } else { 52 | req.user = user 53 | next() 54 | } 55 | }) 56 | } else { 57 | console.log("No existe token...") 58 | res.send(401, {error: "No autorizado"}) 59 | } 60 | } 61 | 62 | exports.withToken = function(app, cb) { 63 | function createAuthRouting(verb) { 64 | return function() { 65 | var route = arguments[0], 66 | args = [].slice.call(arguments, 1) 67 | return app[verb].apply(app, [route, exports.requiresToken].concat(args)) 68 | } 69 | } 70 | var routeVerbs = Object.create(app); 71 | ["get", "post", "put", "delete"].forEach(function(v) { 72 | routeVerbs[v] = createAuthRouting(v) 73 | }); 74 | cb(routeVerbs) 75 | } 76 | -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-digg", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "body-parser": "^1.12.0", 7 | "cookie-parser": "^1.3.4", 8 | "cookie-session": "^1.1.0", 9 | "express": "*", 10 | "jade": "*", 11 | "method-override": "^2.3.1", 12 | "mongodb": "*", 13 | "morgan": "^1.5.1", 14 | "q": "*", 15 | "validator": "*" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/public/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | 3 | $('.add > a').on('click', function(){ 4 | $(this).parent('.add').toggleClass('active'); 5 | }); 6 | 7 | 8 | 9 | 10 | }); 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/public/assets/stylesheets/mixins.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema5/diggclone/public/assets/stylesheets/mixins.css -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/public/build/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | 3 | $('.add > a').on('click', function(){ 4 | $(this).parent('.add').toggleClass('active'); 5 | }); 6 | 7 | 8 | 9 | 10 | }); 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/public/build/assets/stylesheets/mixins.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema5/diggclone/public/build/assets/stylesheets/mixins.css -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/public/build/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Gamifik 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |

Pages

20 |
21 |

/detail.html

22 |

/

23 |

/listado.html

24 |
25 |
26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/public/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema5/diggclone/public/img/loading.gif -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/public/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |

7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /soluciones/tema5/diggclone/simpleauth.js: -------------------------------------------------------------------------------- 1 | function extend() { 2 | var args = [].slice.call(arguments) 3 | return args.reduce(function(acc, el) { 4 | for (var k in el) { acc[k] = el[k] } 5 | return acc; 6 | }) 7 | } 8 | 9 | strategy = { 10 | serializeUser: function(user) { 11 | }, 12 | deserializeUser: function(userId, cb) { 13 | }, 14 | checkCredentials: function(username, pass, done) { 15 | } 16 | } 17 | 18 | exports.setStrategy = function(customStrategy) { 19 | strategy = extend({}, strategy, customStrategy) 20 | } 21 | 22 | exports.createSession = function(options) { 23 | var config = { 24 | username: "username", 25 | password: "password", 26 | } 27 | config = extend({}, config, options) 28 | return function(req, res, next) { 29 | var username = req.body[config.username], 30 | pass = req.body[config.password] 31 | strategy.checkCredentials(username, pass, function(err, user) { 32 | if (!err && user) { 33 | req.user = user 34 | next() 35 | /* res.redirect(config.redirect) */ 36 | } else { 37 | console.log("Credenciales incorrectas") 38 | res.send(401, {error: "Username o contraseña incorrectos"}) 39 | } 40 | }) 41 | } 42 | } 43 | 44 | exports.requiresToken = function(req, res, next) { 45 | var token = req.param("token") 46 | if (token !== undefined) { 47 | strategy.deserializeUser(token, function(user) { 48 | if (!user) { 49 | console.log("El usuario no existe!") 50 | res.send(401, {error: "No autorizado"}) 51 | } else { 52 | req.user = user 53 | next() 54 | } 55 | }) 56 | } else { 57 | console.log("No existe token...") 58 | res.send(401, {error: "No autorizado"}) 59 | } 60 | } 61 | 62 | exports.withToken = function(app, cb) { 63 | function createAuthRouting(verb) { 64 | return function() { 65 | var route = arguments[0], 66 | args = [].slice.call(arguments, 1) 67 | return app[verb].apply(app, [route, exports.requiresToken].concat(args)) 68 | } 69 | } 70 | var routeVerbs = Object.create(app); 71 | ["get", "post", "put", "delete"].forEach(function(v) { 72 | routeVerbs[v] = createAuthRouting(v) 73 | }); 74 | cb(routeVerbs) 75 | } 76 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('static-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var cookieSession = require('cookie-session'); 7 | var bodyParser = require('body-parser'); 8 | var crypto = require('crypto'); 9 | 10 | var app = express(); 11 | var server = require('http').createServer(app); 12 | var io = require('socket.io').listen(server); 13 | 14 | // setup 15 | 16 | app.set('views', path.join(__dirname, 'views')); 17 | app.set('view engine', 'jade'); 18 | 19 | app.use(favicon()); 20 | app.use(logger('dev')); 21 | app.use(bodyParser.json()); 22 | app.use(bodyParser.urlencoded()); 23 | app.use(cookieParser()); 24 | app.use(cookieSession({secret: 'asdf'})); 25 | app.use(express.static(path.join(__dirname, 'public'))); 26 | 27 | // utilidades 28 | 29 | function gravatar(email, s) { 30 | var baseUrl = "http://www.gravatar.com/avatar/", 31 | parEmail = email.toLowerCase().trim(), 32 | hash = crypto.createHash("md5").update(parEmail).digest("hex"); 33 | return baseUrl + hash + (s? "s="+s : ""); 34 | } 35 | 36 | // rutas 37 | 38 | app.post('/session', function(req, res) { 39 | req.session.nick = req.body.nick; 40 | req.session.avatar = gravatar(req.body.gravatar, 50); 41 | res.redirect('/chat.html'); 42 | }); 43 | 44 | app.get('/me', function(req, res) { 45 | res.send({name: req.session.nick, avatar: req.session.avatar}); 46 | }); 47 | 48 | app.use(function(req, res) { 49 | res.redirect('/login.html'); 50 | }); 51 | 52 | // sockets 53 | 54 | io.sockets.on('connection', function(socket) { 55 | socket.on('send:message', function(user, msgData) { 56 | socket.broadcast.emit('posted:message', user, msgData); 57 | }); 58 | }); 59 | 60 | // exports 61 | 62 | module.exports = server; 63 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/bin/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var server = require('../app'); 4 | server.listen(process.env.PORT || 3000); 5 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/npm-debug.log: -------------------------------------------------------------------------------- 1 | 0 info it worked if it ends with ok 2 | 1 verbose cli [ 'node', '/usr/local/bin/npm', 'start' ] 3 | 2 info using npm@1.4.3 4 | 3 info using node@v0.10.26 5 | 4 verbose run-script [ 'prestart', 'start', 'poststart' ] 6 | 5 info prestart application-name@0.0.1 7 | 6 info start application-name@0.0.1 8 | 7 verbose unsafe-perm in lifecycle true 9 | 8 info application-name@0.0.1 Failed to exec start script 10 | 9 error application-name@0.0.1 start: `node ./bin/www` 11 | 9 error Exit status 8 12 | 10 error Failed at the application-name@0.0.1 start script. 13 | 10 error This is most likely a problem with the application-name package, 14 | 10 error not with npm itself. 15 | 10 error Tell the author that this fails on your system: 16 | 10 error node ./bin/www 17 | 10 error You can get their info via: 18 | 10 error npm owner ls application-name 19 | 10 error There is likely additional logging output above. 20 | 11 error System Darwin 13.1.0 21 | 12 error command "node" "/usr/local/bin/npm" "start" 22 | 13 error cwd /Users/werelax/courses/material-nodejs/tema7/chat 23 | 14 error node -v v0.10.26 24 | 15 error npm -v 1.4.3 25 | 16 error code ELIFECYCLE 26 | 17 verbose exit [ 1, true ] 27 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "application-name", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/start" 7 | }, 8 | "dependencies": { 9 | "express": "~4.0.0", 10 | "static-favicon": "~1.0.0", 11 | "morgan": "~1.0.0", 12 | "cookie-parser": "~1.0.1", 13 | "body-parser": "~1.0.0", 14 | "debug": "~0.7.4", 15 | "jade": "~1.3.0", 16 | "cookie-session": "~1.0.1", 17 | "socket.io": "~0.9.16" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/public/assets/images/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema6/chat_v1/public/assets/images/avatar.jpg -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/public/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | $('.new').on('click', function(){ 3 | $(this).parents('.actions').toggleClass('active'); 4 | }); 5 | }); 6 | 7 | var Chat = { 8 | newMessage: function(msg) { 9 | if (this.handler) this.handler(msg); 10 | }, 11 | registerHandler: function(fn) { 12 | this.handler = fn; 13 | }, 14 | postMsg: function(from, msg) { 15 | var template = $("#other-message").html(); 16 | var code = template 17 | .replace("%avatar%", from.avatar) 18 | .replace("%name%", from.name) 19 | .replace("%content%", msg.text) 20 | .replace("%time%", msg.date); 21 | var $messages = $(".messages").append(code); 22 | $("body").stop().animate({ scrollTop: $messages.height() }, 400); 23 | }, 24 | showMyMsg: function(from, msg) { 25 | var template = $("#my-message").html(); 26 | var code = template 27 | .replace("%avatar%", from.avatar) 28 | .replace("%name%", from.name) 29 | .replace("%content%", msg.text) 30 | .replace("%time%", msg.date); 31 | var $messages = $(".messages").append(code); 32 | $("body").stop().animate({ scrollTop: $messages.height() }, 400); 33 | } 34 | }; 35 | 36 | $("form.new-message").submit(function(e) { 37 | e.preventDefault(); 38 | var textarea = $(this).find("textarea"); 39 | Chat.newMessage(textarea.val()); 40 | textarea.val(""); 41 | }); 42 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/public/chat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Sala 12 | 13 | 14 | 15 | 16 | 17 | 29 | 30 | 42 | 43 | 44 | 45 | 46 |
47 |
48 |

Chat

49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | 57 | 58 |
59 |
60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/public/code.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | var socket = io.connect("http://localhost:3000/"), 4 | me = $.get("/me"); 5 | 6 | Chat.registerHandler(function(msg) { 7 | var msgData = { text: msg, date: new Date() }; 8 | me.then(function(me) { 9 | socket.emit("send:message", me, msgData); 10 | Chat.showMyMsg(me, msgData); 11 | }); 12 | }); 13 | 14 | socket.on("posted:message", function(user, msgData) { 15 | Chat.postMsg(user, msgData); 16 | }); 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v1/public/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Login 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |

Login

21 | 22 | 23 | 24 | 25 | 28 |
29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v2/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var logger = require('morgan'); 4 | var cookieParser = require('cookie-parser'); 5 | var cookieSession = require('cookie-session'); 6 | var bodyParser = require('body-parser'); 7 | var crypto = require('crypto'); 8 | 9 | var app = express(); 10 | var server = require('http').createServer(app); 11 | 12 | // setup 13 | 14 | app.set('views', path.join(__dirname, 'views')); 15 | app.set('view engine', 'jade'); 16 | 17 | app.use(logger('dev')); 18 | app.use(bodyParser.json()); 19 | app.use(bodyParser.urlencoded()); 20 | app.use(cookieParser()); 21 | app.use(cookieSession({secret: 'asdf'})); 22 | app.use(express.static(path.join(__dirname, 'public'))); 23 | 24 | // utilidades 25 | 26 | function gravatar(email, s) { 27 | var baseUrl = "http://www.gravatar.com/avatar/", 28 | parEmail = email.toLowerCase().trim(), 29 | hash = crypto.createHash("md5").update(parEmail).digest("hex"); 30 | return baseUrl + hash + (s? "s="+s : ""); 31 | } 32 | 33 | // rutas 34 | 35 | app.post('/session', function(req, res) { 36 | req.session.nick = req.body.nick; 37 | req.session.avatar = gravatar(req.body.gravatar, 50); 38 | res.redirect('/chat.html'); 39 | }); 40 | 41 | app.get('/me', function(req, res) { 42 | res.send({name: req.session.nick, avatar: req.session.avatar}); 43 | }); 44 | 45 | app.use(function(req, res) { 46 | res.redirect('/login.html'); 47 | }); 48 | 49 | // sockets 50 | 51 | var chatServer = require('./chat')(server); 52 | 53 | // exports 54 | 55 | module.exports = server; 56 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v2/bin/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var server = require('../app'); 4 | server.listen(process.env.PORT || 3000); 5 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v2/chat.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var request = require('request'); 3 | 4 | //Usamos una factoría para configurarlo todo 5 | // server -> http.server instance 6 | module.exports = function(server){ 7 | //montamos socket.io sobre el servidor HTTP 8 | var io = require('socket.io').listen(server); 9 | 10 | io.on('connection', function(socket){ 11 | var interval; 12 | 13 | //Atender mensaje "hello" 14 | socket.on('hello', function(client){ 15 | console.log(client.name + ' se ha unido al chat'); 16 | 17 | //mandar mensaje aleatorio cada 15 segundos 18 | interval = setInterval(function(){ 19 | sendRandomJoke(socket, client.name); 20 | }, 15000); 21 | 22 | //mandar uno nada más conectar 23 | sendRandomJoke(socket, client.name); 24 | 25 | }); 26 | 27 | //recibir mensajes 28 | socket.on('message', function(msg, cb){ 29 | socket.broadcast.emit('message', msg); 30 | //callback, si existe 31 | if(typeof(cb)==='function'){ 32 | cb(); 33 | } 34 | }); 35 | 36 | socket.on('disconnect', function(){ 37 | console.log('client disconnected!'); 38 | clearInterval(interval); 39 | }); 40 | 41 | }); 42 | } 43 | 44 | //Una función que nos envía una broma estilo Chuck Norris aleatoria 45 | //al socket que recibe como argumento. En lugar de Chuck usará el nombre 46 | //del cliente conectado 47 | function sendRandomJoke(socket, name){ 48 | var cappedName = name.charAt(0).toUpperCase() + name.slice(1); 49 | request.get('http://api.icndb.com/jokes/random?firstName=' + cappedName + '&lastName=', function(err,response,body){ 50 | body = JSON.parse(body); 51 | socket.emit('message', { 52 | from: { 53 | name: 'Bot', 54 | avatar: '/assets/images/avatar.jpg' 55 | }, 56 | message: { 57 | date: Date.now(), 58 | text: body.value.joke 59 | } 60 | }); 61 | }); 62 | 63 | 64 | } -------------------------------------------------------------------------------- /soluciones/tema6/chat_v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "application-name", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/start" 7 | }, 8 | "dependencies": { 9 | "body-parser": "^1.0.2", 10 | "cookie-parser": "^1.0.1", 11 | "cookie-session": "^1.0.2", 12 | "debug": "^0.7.4", 13 | "express": "^4.0.0", 14 | "jade": "^1.3.1", 15 | "morgan": "^1.0.1", 16 | "request": "^2.64.0", 17 | "socket.io": "^1.3.7", 18 | "static-favicon": "~1.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v2/public/assets/images/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/soluciones/tema6/chat_v2/public/assets/images/avatar.jpg -------------------------------------------------------------------------------- /soluciones/tema6/chat_v2/public/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | $('.new').on('click', function(){ 3 | $(this).parents('.actions').toggleClass('active'); 4 | }); 5 | }); 6 | 7 | var Chat = { 8 | newMessage: function(msg) { 9 | if (this.handler) this.handler(msg); 10 | }, 11 | registerHandler: function(fn) { 12 | this.handler = fn; 13 | }, 14 | postMsg: function(from, msg) { 15 | var template = $("#other-message").html(); 16 | var code = template 17 | .replace("%avatar%", from.avatar) 18 | .replace("%name%", from.name) 19 | .replace("%content%", msg.text) 20 | .replace("%time%", new Date(msg.date).toLocaleTimeString()); 21 | var $messages = $(".messages").append(code); 22 | $("body").stop().animate({ scrollTop: $messages.height() }, 400); 23 | }, 24 | showMyMsg: function(from, msg) { 25 | var template = $("#my-message").html(); 26 | var code = template 27 | .replace("%avatar%", from.avatar) 28 | .replace("%name%", from.name) 29 | .replace("%content%", msg.text) 30 | .replace("%time%", new Date(msg.date).toLocaleTimeString()); 31 | var $messages = $(".messages").append(code); 32 | $("body").stop().animate({ scrollTop: $messages.height() }, 400); 33 | } 34 | }; 35 | 36 | $("textarea.js-input").keyup(function(e){ 37 | if(e.keyCode === 13 && !e.shiftKey){ 38 | e.preventDefault(); 39 | $("form.new-message").submit(); 40 | } 41 | }); 42 | 43 | 44 | $("form.new-message").submit(function(e) { 45 | e.preventDefault(); 46 | var textarea = $(this).find("textarea"); 47 | Chat.newMessage(textarea.val()); 48 | textarea.val(""); 49 | }); 50 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v2/public/code.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | var me; 3 | //lo primero, obtener mis datos enviados en el login 4 | $.get('/me').then(function(data){ 5 | me = data; 6 | startChat(); 7 | }); 8 | 9 | function startChat(){ 10 | //conectar socket 11 | var socket = io.connect(''); 12 | socket.on('connect', function(){ 13 | 14 | console.log('Conectado al servidor'); 15 | socket.emit('hello', me); 16 | 17 | socket.on('message', function(msg){ 18 | console.log('Recibido', msg); 19 | Chat.postMsg(msg.from, msg.message); 20 | 21 | }); 22 | 23 | Chat.registerHandler(function(msg){ 24 | if(msg.indexOf('/join') === 0){ 25 | //it's a join command! 26 | var channel = msg.split(' '); 27 | if(channel.length !== 2){ 28 | alert("Usa /join "); 29 | return; 30 | } 31 | else { 32 | channel = channel[1]; 33 | socket.join(channel); 34 | return; 35 | } 36 | // var payload = { 37 | // from: me, 38 | // channel: msg.split(' ')[1] 39 | // } 40 | } 41 | var payload = { 42 | from: me, 43 | message: { date: Date.now(), text: msg } 44 | }; 45 | 46 | socket.emit('message', payload, function(){ 47 | //mensaje recibido 48 | Chat.showMyMsg(payload.from, payload.message); 49 | }); 50 | }); 51 | }); 52 | } 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /soluciones/tema6/chat_v2/public/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Login 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |

Login

21 | 22 | 23 | 24 | 25 | 28 |
29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /tema0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema0.pdf -------------------------------------------------------------------------------- /tema1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1.pdf -------------------------------------------------------------------------------- /tema1/abtesting/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cases: ["A", "B", "C", "D"] 3 | } 4 | -------------------------------------------------------------------------------- /tema1/abtesting/public/A/css/styles.css: -------------------------------------------------------------------------------- 1 | body{margin: 0; padding: 0; background: #f1f1f1; font-family: 'Montserrat', sans-serif; font-weight: 400; color: #5f6060;} 2 | 3 | .wrapper{position: relative; width: 430px; margin: 100px auto 0; text-align: center;} 4 | .logo{margin: 12px 0;} 5 | 6 | #profile{background: #fff; padding: 26px;} 7 | #profile h1{margin: 30px 0 2px; font-weight: 700; font-size: 28px; color: #424242;} 8 | #profile h2{margin: 0 0 40px; font-weight: 400; font-size: 20px; color: #777;} 9 | #profile .button{display: block; width: 272px; height: 56px; margin: 0 auto; background: #cb2128; border-bottom: 4px solid #901a1c; color: #fff; text-decoration: none; text-transform: uppercase; text-align: left;} 10 | #profile .button img{vertical-align: middle;} 11 | #profile .button span{display: inline-block; vertical-align: middle; font-size: 22px; padding: 0 38px;} -------------------------------------------------------------------------------- /tema1/abtesting/public/A/foto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/A/foto.jpg -------------------------------------------------------------------------------- /tema1/abtesting/public/A/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/A/images/avatar.png -------------------------------------------------------------------------------- /tema1/abtesting/public/A/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/A/images/icon.png -------------------------------------------------------------------------------- /tema1/abtesting/public/A/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/A/images/logo.png -------------------------------------------------------------------------------- /tema1/abtesting/public/A/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | Avatar 18 |

Josh Hemsley

19 |

Savannah, GA

20 | Follow me 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tema1/abtesting/public/B/css/styles.css: -------------------------------------------------------------------------------- 1 | body{margin: 0; padding: 0; background: #f1f1f1; font-family: 'Montserrat', sans-serif; font-weight: 400; color: #5f6060;} 2 | 3 | .wrapper{position: relative; width: 430px; margin: 100px auto 0; text-align: center;} 4 | .logo{margin: 12px 0;} 5 | 6 | #profile{background: #fff; padding: 26px;} 7 | #profile h1{margin: 30px 0 2px; font-weight: 700; font-size: 28px; color: #424242;} 8 | #profile h2{margin: 0 0 40px; font-weight: 400; font-size: 20px; color: #777;} 9 | #profile .button{display: block; width: 272px; height: 56px; margin: 0 auto; background: #365d98; border-bottom: 4px solid #1d305e; color: #fff; text-decoration: none; text-transform: uppercase; text-align: left;} 10 | #profile .button img{vertical-align: middle;} 11 | #profile .button span{display: inline-block; vertical-align: middle; font-size: 22px; padding: 0 38px;} -------------------------------------------------------------------------------- /tema1/abtesting/public/B/foto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/B/foto.jpg -------------------------------------------------------------------------------- /tema1/abtesting/public/B/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/B/images/avatar.png -------------------------------------------------------------------------------- /tema1/abtesting/public/B/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/B/images/icon.png -------------------------------------------------------------------------------- /tema1/abtesting/public/B/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/B/images/logo.png -------------------------------------------------------------------------------- /tema1/abtesting/public/B/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | Avatar 18 |

Josh Hemsley

19 |

Savannah, GA

20 | Follow me 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tema1/abtesting/public/C/css/styles.css: -------------------------------------------------------------------------------- 1 | body{margin: 0; padding: 0; background: #f1f1f1; font-family: 'Montserrat', sans-serif; font-weight: 400; color: #5f6060;} 2 | 3 | .wrapper{position: relative; width: 430px; margin: 100px auto 0; text-align: center;} 4 | .logo{margin: 12px 0;} 5 | 6 | #profile{background: #fff; padding: 26px;} 7 | #profile h1{margin: 30px 0 2px; font-weight: 700; font-size: 28px; color: #424242;} 8 | #profile h2{margin: 0 0 40px; font-weight: 400; font-size: 20px; color: #777;} 9 | #profile .button{display: block; width: 272px; height: 56px; margin: 0 auto; background: #2eabe2; border-bottom: 4px solid #0570b4; color: #fff; text-decoration: none; text-transform: uppercase; text-align: left;} 10 | #profile .button img{vertical-align: middle;} 11 | #profile .button span{display: inline-block; vertical-align: middle; font-size: 22px; padding: 0 38px;} -------------------------------------------------------------------------------- /tema1/abtesting/public/C/foto.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/C/foto.jpg -------------------------------------------------------------------------------- /tema1/abtesting/public/C/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/C/images/avatar.png -------------------------------------------------------------------------------- /tema1/abtesting/public/C/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/C/images/icon.png -------------------------------------------------------------------------------- /tema1/abtesting/public/C/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/C/images/logo.png -------------------------------------------------------------------------------- /tema1/abtesting/public/C/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | Avatar 18 |

Josh Hemsley

19 |

Savannah, GA

20 | Follow me 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tema1/abtesting/public/D/css/styles.css: -------------------------------------------------------------------------------- 1 | body{margin: 0; padding: 0; background: #f1f1f1; font-family: 'Montserrat', sans-serif; font-weight: 400; color: #5f6060;} 2 | 3 | .wrapper{position: relative; width: 430px; margin: 100px auto 0; text-align: center;} 4 | .logo{margin: 12px 0;} 5 | 6 | #profile{background: #fff; padding: 26px;} 7 | #profile h1{margin: 30px 0 2px; font-weight: 700; font-size: 28px; color: #424242;} 8 | #profile h2{margin: 0 0 40px; font-weight: 400; font-size: 20px; color: #777;} 9 | #profile .button{display: block; width: 272px; height: 56px; margin: 0 auto; background: #e94e8a; border-bottom: 4px solid #ae2859; color: #fff; text-decoration: none; text-transform: uppercase; text-align: left;} 10 | #profile .button img{vertical-align: middle;} 11 | #profile .button span{display: inline-block; vertical-align: middle; font-size: 22px; padding: 0 38px;} -------------------------------------------------------------------------------- /tema1/abtesting/public/D/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/D/images/avatar.png -------------------------------------------------------------------------------- /tema1/abtesting/public/D/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/D/images/icon.png -------------------------------------------------------------------------------- /tema1/abtesting/public/D/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/D/images/logo.png -------------------------------------------------------------------------------- /tema1/abtesting/public/D/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | Avatar 18 |

Josh Hemsley

19 |

Savannah, GA

20 | Follow me 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tema1/abtesting/public/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/public/success.png -------------------------------------------------------------------------------- /tema1/abtesting/server.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/abtesting/server.js -------------------------------------------------------------------------------- /tema1/captcha/client.js: -------------------------------------------------------------------------------- 1 | var http = require("http") 2 | , url = require("url") 3 | , fs = require("fs") 4 | 5 | function rand(a, b) { 6 | var top = b ? (b - a) : a, 7 | delta = b ? a : 0; 8 | return Math.floor(Math.random() * top + delta); 9 | } 10 | 11 | function randomString(length) { 12 | var base = 36; 13 | return rand(Math.pow(base, length)).toString(base); 14 | } 15 | 16 | var store = {}, 17 | captchaServer = "http://localhost:3000"; 18 | 19 | function generateId() { 20 | var id = randomString(10); 21 | while (id in store) { id = randomString(10); } 22 | return id; 23 | } 24 | 25 | var routes = { 26 | "/form": function(req, res) { 27 | fs.readFile("./templates/form.html", function(err, template) { 28 | if (err) { 29 | res.writeHead(500); 30 | return res.end("Oops!"); 31 | } 32 | var response = ""; 33 | http.get(captchaServer + "/captcha", function(getResponse) { 34 | getResponse.on("data", function(data) { 35 | response += data; 36 | }); 37 | getResponse.on("end", function() { 38 | var html, id; 39 | try { 40 | response = JSON.parse(response); 41 | id = generateId(); 42 | store[id] = response; 43 | html = template.toString() 44 | .replace("#captcha-url#", captchaServer + response.url) 45 | .replace("#id#", id); 46 | res.end(html); 47 | } catch(e) { 48 | res.writeHead(500); 49 | res.end("Oops!"); 50 | } 51 | }) 52 | }); 53 | }) 54 | }, 55 | "/validate": function(req, res, urlData) { 56 | var id = urlData.query.id, 57 | code = urlData.query.captcha, 58 | data = store[id]; 59 | if (!data || data.code != code) { 60 | res.end("No.. Otra vez") 61 | } else { 62 | res.end("OK! Otra vez") 63 | } 64 | } 65 | } 66 | 67 | var server = http.createServer(function(req, res) { 68 | var urlData = url.parse(req.url, true), 69 | path = urlData.pathname; 70 | if (path in routes) { 71 | return routes[path](req, res, urlData); 72 | } else { 73 | res.writeHead(404); 74 | res.end("No existe"); 75 | } 76 | }); 77 | 78 | server.listen(3001); 79 | -------------------------------------------------------------------------------- /tema1/captcha/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-captcha", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "canvas": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tema1/captcha/templates/form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Form 5 | 6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /tema1/tiles/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-captcha", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "canvas": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tema1/tiles/public/dimension.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/tiles/public/dimension.png -------------------------------------------------------------------------------- /tema1/tiles/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Canvas Map 5 | 33 | 34 | 35 | 36 |
37 |
38 |
39 |
40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /tema1/tiles/public/map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/tiles/public/map.jpg -------------------------------------------------------------------------------- /tema1/tiles/server.js: -------------------------------------------------------------------------------- 1 | var http = require("http"), 2 | url = require("url"), 3 | fs = require("fs"), 4 | Canvas = require("canvas"), 5 | Image = Canvas.Image; 6 | 7 | var publicDir = "./public", 8 | tileSize = 100, 9 | cache = {}; 10 | 11 | function extract_tile(imgData, coords, res, filePath) { 12 | var img, 13 | canvas, 14 | ctx, 15 | stream, 16 | origin; 17 | if (imgData === null) { 18 | img = cache[filePath]; 19 | } else { 20 | img = new Image(); 21 | img.src = new Buffer(imgData, "binary"); 22 | cache[filePath] = img; 23 | } 24 | canvas = new Canvas(tileSize, tileSize); 25 | ctx = canvas.getContext("2d"); 26 | origin = { 27 | x: Math.min(img.width-tileSize, Math.floor(coords.x/tileSize)*tileSize), 28 | y: Math.min(img.height-tileSize, Math.floor(coords.y/tileSize)*tileSize) 29 | }; 30 | origin.x = Math.max(0, origin.x); 31 | origin.y = Math.max(0, origin.y); 32 | ctx.drawImage(img, origin.x, origin.y, tileSize, tileSize, 0, 0, tileSize, tileSize); 33 | stream = canvas.pngStream(); 34 | stream.pipe(res) 35 | /* 36 | stream.on("data", res.write.bind(res)); 37 | stream.on("end", res.end.bind(res)); 38 | */ 39 | } 40 | 41 | var server = http.createServer(function(req, res) { 42 | var urlData = url.parse(req.url, true), 43 | path = urlData.pathname, 44 | coords = {x: urlData.query.x || 0, y: urlData.query.y || 0}, 45 | filePath = publicDir + path; 46 | if (cache[filePath]) { 47 | return extract_tile(null, coords, res, filePath); 48 | } 49 | fs.exists(filePath, function(exsits) { 50 | if (!exsits) { 51 | /* Error */ 52 | res.writeHead(404); 53 | return res.end("No existe!"); 54 | } 55 | fs.readFile(filePath, function(err, data) { 56 | if (err) { throw err; } 57 | if (path.match(/jpg$/)) { 58 | extract_tile(data, coords, res, filePath); 59 | } else { 60 | res.end(data); 61 | } 62 | }); 63 | }); 64 | }) 65 | .listen(3000); 66 | -------------------------------------------------------------------------------- /tema1/watermark/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-watermark", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "canvas": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tema1/watermark/public/mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/watermark/public/mark.png -------------------------------------------------------------------------------- /tema1/watermark/public/programador.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema1/watermark/public/programador.png -------------------------------------------------------------------------------- /tema1/watermark/server.js: -------------------------------------------------------------------------------- 1 | var Canvas = require("canvas") 2 | , Image = Canvas.Image 3 | , http = require("http") 4 | , url = require("url") 5 | , fs = require("fs"); 6 | 7 | function watermark(imageData, res) { 8 | var img = new Image, 9 | canvas, 10 | ctx; 11 | img.src = new Buffer(imageData, "binary"); 12 | canvas = new Canvas(img.width, img.height); 13 | ctx = canvas.getContext("2d"); 14 | ctx.drawImage(img, 0, 0, img.width, img.height); 15 | fs.readFile("./public/mark.png", function(err, markData) { 16 | if (err) { 17 | res.writeHead(500); 18 | return res.end("Oops.."); 19 | } 20 | var mark = new Image(), 21 | stream, 22 | timesH, 23 | thimesV; 24 | mark.src = new Buffer(markData, "binary"); 25 | ctx.globalAlpha = 0.2; 26 | timesH = Math.ceil(img.width/mark.width); 27 | timesV = Math.ceil(img.height/mark.height); 28 | for (var i=0; i", 5 | "description": "Servidor de ficheros con versionado", 6 | "main": "./server", 7 | "dependencies" : { 8 | "Q": "*" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tema2/versionedserver/server.js: -------------------------------------------------------------------------------- 1 | var http = require("http"), 2 | fs = require("fs"), 3 | url = require("url"), 4 | path = require("path"), 5 | Q = require("q"), 6 | format = require("util").format, 7 | routes = require("./simpleRoute"); 8 | 9 | /* Global state */ 10 | 11 | var version = 0, 12 | cache = [], 13 | baseDir = path.resolve(__dirname, process.argv[2] || "./"); 14 | 15 | /* FS Utils */ 16 | 17 | function listFiles(path) { 18 | // ??? 19 | } 20 | 21 | var somethingChanged = (function() { 22 | var lastChange = 0; 23 | return function(fileList) { 24 | // ??? 25 | }; 26 | }()); 27 | 28 | function readAllFiles(fileList) { 29 | // ??? 30 | } 31 | 32 | /* Update */ 33 | 34 | setInterval(function() { 35 | // ??? 36 | }, 500); 37 | 38 | /* Routes */ 39 | 40 | routes.get("/", function(req, res) { 41 | // ??? 42 | }); 43 | 44 | routes.get("/list", function(req, res) { 45 | // ??? 46 | }); 47 | 48 | routes.get("default", function(req, res) { 49 | // ??? 50 | }); 51 | 52 | routes.listen(http.createServer(), 3456); 53 | -------------------------------------------------------------------------------- /tema2/versionedserver/simpleRoute.js: -------------------------------------------------------------------------------- 1 | var url = require("url"); 2 | 3 | var routes = {}; 4 | 5 | module.exports = { 6 | get: function(route, cb) { 7 | routes[route] = cb; 8 | }, 9 | listen: function(httpServer, port) { 10 | httpServer.on("request", function(req, res) { 11 | req.url = url.parse(req.url, true); 12 | if (req.url.pathname in routes) { 13 | routes[req.url.pathname](req, res); 14 | } else if ("default" in routes) { 15 | routes["default"](req, res); 16 | } else { 17 | res.writeHead(500); 18 | res.end("Error: La ruta " + req.url.pathname + " no está registrada"); 19 | } 20 | }); 21 | httpServer.listen(port); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /tema3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema3.pdf -------------------------------------------------------------------------------- /tema3/blog/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-simpleblog", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "jade": "*", 7 | "express": "*", 8 | "method-override": "^1.0.0", 9 | "cookie-parser": "^1.0.1", 10 | "morgan": "^1.0.1", 11 | "cookie-session": "^1.0.2", 12 | "body-parser": "^1.0.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tema3/blog/server.js: -------------------------------------------------------------------------------- 1 | var express = require("express") 2 | , app = express() 3 | , logger = require("morgan") 4 | , bodyParser = require("body-parser") 5 | , cookieParser = require("cookie-parser") 6 | , cookieSession = require("cookie-session") 7 | 8 | app.use(bodyParser.json()) 9 | app.use(bodyParser.urlencoded({extended: false})) 10 | app.use(cookieParser("secreto")); 11 | app.use(cookieSession({secret: "asdf"})); 12 | app.set("views", "./views"); 13 | app.set("view engine", "jade"); 14 | 15 | 16 | function extend() { 17 | var args = [].slice.call(arguments); 18 | return args.reduce(function(acc, el) { 19 | for (var k in el) { acc[k] = el[k]; } 20 | return acc; 21 | }); 22 | } 23 | 24 | /* Models */ 25 | 26 | var Post = function(data) { 27 | data = extend({}, {title: "", content: "", date: Date.now(), views: 0}, data); 28 | extend(this, data); 29 | } 30 | extend(Post, { 31 | _posts: [], 32 | _id: 0, 33 | find: function(id) { 34 | return this._posts.filter(function(p) { return p.id == id })[0]; 35 | }, 36 | getAll: function() { 37 | return this._posts; 38 | } 39 | }); 40 | extend(Post.prototype, { 41 | save: function() { 42 | this.id = Post._id++; 43 | Post._posts.push(this); 44 | }, 45 | update: function() { 46 | var posts = Post._posts; 47 | for (var i=0,_len=posts.length; i<_len; i++) if (posts[i].id === this.id) { 48 | posts.splice(i, 1, this); 49 | break; 50 | } 51 | }, 52 | delete: function() { 53 | var posts = Post._posts; 54 | for (var i=0,_len=posts.length; i<_len; i++) if (posts[i].id === this.id) { 55 | posts.splice(i, 1); 56 | break; 57 | } 58 | } 59 | }); 60 | 61 | 62 | /* Tu código aquí! */ 63 | 64 | 65 | 66 | app.use(express.static(__dirname + "/public")); 67 | app.listen(3000); 68 | 69 | /* Populate */ 70 | 71 | var post = new Post({title: "Prueba", content: "Esto es una prueba"}); 72 | post.save(); 73 | -------------------------------------------------------------------------------- /tema3/blog/views/layout.jade: -------------------------------------------------------------------------------- 1 | !!! 5 2 | html(lang='es') 3 | head 4 | meta(charset='utf-8') 5 | title Lista de Posts 6 | meta(name='description', content='') 7 | meta(property='og:image', content='') 8 | // Fonts 9 | link(href='http://fonts.googleapis.com/css?family=Roboto:400,300,500,700,400italic,300italic', rel='stylesheet', type='text/css') 10 | // Frameworks 11 | link(rel='stylesheet', href='/css/normalize.css') 12 | // Stylesheets 13 | link(rel='stylesheet', href='/css/styles.css', media='screen') 14 | body.post-list 15 | header 16 | .top 17 | h1 Mi Blog 18 | .newpost 19 | a(href='/posts/new') Nuevo Post 20 | block nav 21 | block content 22 | -------------------------------------------------------------------------------- /tema3/blog/views/new-post.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.new-post.container 5 | h1.section-title= post.date? "Editar Post" : "Nuevo Post" 6 | form.new-post-form(action=post.date? "/posts/#{post.id}":"/posts", method="POST") 7 | label(for='title') Título 8 | input.title(type='text', name='title', value=post.title) 9 | label(for='post-title') Contenido 10 | textarea.post-content(name='content', placeholder='')= post.content 11 | if post.date 12 | input(type="hidden",name="_method",value="put") 13 | input.button(type='submit', value='Publicar') 14 | -------------------------------------------------------------------------------- /tema3/blog/views/post-detail.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block nav 4 | nav.menu 5 | ul 6 | li 7 | a(href='/posts') Volver 8 | li 9 | a(href='/posts/#{post.id}/edit') Editar 10 | li 11 | form(action="/posts/#{post.id}",method="POST",id="form-delete") 12 | input(type="hidden",name="_method",value="delete") 13 | a(href='#',onclick="document.getElementById('form-delete').submit()") Eliminar 14 | 15 | block content 16 | section.posts 17 | article.post 18 | .container 19 | h1.post-title= post.title 20 | p= post.content 21 | aside.metadata 22 | | Por 23 | a(href='#')  Default User 24 | span.sep   |   25 | | 0 visitas 26 | -------------------------------------------------------------------------------- /tema3/blog/views/post-list.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.posts 5 | each post in posts 6 | article.post 7 | .container 8 | h2.post-title 9 | a(href='/posts/#{post.id}')= post.title 10 | p.summary= post.content.slice(0, 150) 11 | aside.metadata 12 | | Por 13 | a(href='#')  Default User 14 | span.sep   |   15 | | 0 visitas 16 | -------------------------------------------------------------------------------- /tema3/blogAuth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-simpleblog", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "express": "*", 7 | "lodash": "*", 8 | "morgan": "*", 9 | "body-parser": "*", 10 | "method-override": "*", 11 | "cookie-parser": "*", 12 | "cookie-session": "*" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tema3/blogAuth/simpleauth.js: -------------------------------------------------------------------------------- 1 | var _ = require("lodash") 2 | 3 | var strategy = { 4 | serializeUser: function(user) { 5 | }, 6 | deserializeUser: function(userId, cb) { 7 | }, 8 | checkCredentials: function(username, pass, done) { 9 | }, 10 | loginRoute: "/login.html" 11 | } 12 | 13 | var cookieName = 'user'; 14 | 15 | exports.setStrategy = function(customStrategy) { 16 | strategy = _.extend({}, strategy, customStrategy) 17 | } 18 | 19 | exports.createSession = function(options) { 20 | var defaultConfig = { 21 | username: "username", 22 | password: "password", 23 | redirect: '/secret', 24 | failRedirect: '/' 25 | } 26 | config = _.extend({}, defaultConfig, options); 27 | return function(req, res, next) { 28 | var username = req.body[config.username], 29 | password = req.body[config.password]; 30 | 31 | strategy.checkCredentials(username, password, function(err, user) { 32 | if (user && !err) { 33 | res.cookie(cookieName, strategy.serializeUser(user), {signed: true, maxAge: 1000*60*60*24*7}); 34 | res.redirect(config.redirect); 35 | } else { 36 | console.log("error al checkear credenciales"); 37 | res.redirect(config.failRedirect); 38 | } 39 | }); 40 | } 41 | } 42 | 43 | exports.requiresSession = function(req, res, next) { 44 | if (req.signedCookies[cookieName]) { 45 | strategy.deserializeUser(req.signedCookies[cookieName], function(err, user) { 46 | if(err) { 47 | res.clearCookie(cookieName); 48 | return res.sendStatus(500); 49 | } 50 | req.user = user; 51 | next(); 52 | }); 53 | } else { 54 | next(strategy.loginRoute); 55 | } 56 | } 57 | 58 | exports.destroySession = function(res) { 59 | res.clearCookie(cookieName); 60 | } 61 | -------------------------------------------------------------------------------- /tema3/blogAuth/views/layout.jade: -------------------------------------------------------------------------------- 1 | !!! 5 2 | html(lang='es') 3 | head 4 | meta(charset='utf-8') 5 | title Lista de Posts 6 | meta(name='description', content='') 7 | meta(property='og:image', content='') 8 | // Fonts 9 | link(href='http://fonts.googleapis.com/css?family=Roboto:400,300,500,700,400italic,300italic', rel='stylesheet', type='text/css') 10 | // Frameworks 11 | link(rel='stylesheet', href='/css/normalize.css') 12 | // Stylesheets 13 | link(rel='stylesheet', href='/css/styles.css', media='screen') 14 | body.post-list 15 | header 16 | .top 17 | h1 Mi Blog 18 | .newpost 19 | a(href='/posts/new') Nuevo Post 20 | .logout 21 | a(href='/logout') Logout 22 | block nav 23 | block content 24 | -------------------------------------------------------------------------------- /tema3/blogAuth/views/login.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Login 6 | form.login-form(action="/session", method="POST") 7 | label(for='email') Email 8 | input.email(type='email', name='username') 9 | label(for='password') Contraseña 10 | input.password(type='password', name='password') 11 | input.button.login(type='submit', value='Login') 12 | 13 | section 14 | a(href="/register") Registrate 15 | -------------------------------------------------------------------------------- /tema3/blogAuth/views/new-post.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.new-post.container 5 | h1.section-title= post.date? "Editar Post" : "Nuevo Post" 6 | form.new-post-form(action=post.date? "/posts/#{post.id}":"/posts", method="POST") 7 | label(for='title') Título 8 | input.title(type='text', name='title', value=post.title) 9 | label(for='post-title') Contenido 10 | textarea.post-content(name='content', placeholder='')= post.content 11 | if post.date 12 | input(type="hidden",name="_method",value="put") 13 | input.button(type='submit', value='Publicar') 14 | -------------------------------------------------------------------------------- /tema3/blogAuth/views/post-detail.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block nav 4 | nav.menu 5 | ul 6 | li 7 | a(href='/posts') Volver 8 | li 9 | a(href='/posts/#{post.id}/edit') Editar 10 | li 11 | form(action="/posts/#{post.id}",method="POST",id="form-delete") 12 | input(type="hidden",name="_method",value="delete") 13 | a(href='#',onclick="document.getElementById('form-delete').submit()") Eliminar 14 | 15 | block content 16 | section.posts 17 | article.post 18 | .container 19 | h1.post-title= post.title 20 | p= post.content 21 | aside.metadata 22 | | Por 23 | a(href='#')  Default User 24 | span.sep   |   25 | | 0 visitas 26 | -------------------------------------------------------------------------------- /tema3/blogAuth/views/post-list.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.posts 5 | each post in posts 6 | article.post 7 | .container 8 | h2.post-title 9 | a(href='/posts/#{post.id}')= post.title 10 | p.summary= post.content.slice(0, 150) 11 | aside.metadata 12 | | Por 13 | a(href='#')  Default User 14 | span.sep   |   15 | | 0 visitas 16 | -------------------------------------------------------------------------------- /tema3/blogAuth/views/register.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Registro de Usuario 6 | form.login-form(action="/register", method="POST") 7 | label(for='email') Email 8 | input.email(type='email', name='username') 9 | label(for='password') Contraseña 10 | input.password(type='password', name='password') 11 | label(for='password') Confirma tu contraseña 12 | input.password(type='password', name='passwordconfirm') 13 | input.button.login(type='submit', value='Enviar') 14 | 15 | section 16 | a(href="/login") ¿Ya tienes usuario? 17 | -------------------------------------------------------------------------------- /tema3/simpleAuthModule/app.js: -------------------------------------------------------------------------------- 1 | /* Dependencies */ 2 | 3 | var express = require("express") 4 | , env = process.env.NODE_ENV || "development" 5 | , auth = require("./simpleauth") 6 | , logger = require("morgan") 7 | , bodyParser = require("body-parser") 8 | , cookieParser = require("cookie-parser") 9 | , cookieSession = require("cookie-session") 10 | 11 | var users = [ 12 | { 13 | id: 0, 14 | username: "node@redradix.com", 15 | pass: "redradix" 16 | } 17 | ] 18 | 19 | auth.setStrategy({ 20 | serializeUser: function(user) { 21 | return user.username; 22 | }, 23 | deserializeUser: function(userId, cb) { 24 | var user = users.map(function(u) { 25 | if (u.username === userId) { 26 | return u; 27 | } 28 | })[0]; 29 | user ? cb(null, user) : cb(404); 30 | }, 31 | checkCredentials: function(username, pass, cb) { 32 | var user = users.map(function(u) { 33 | console.log(u); 34 | if (u.username === username && u.pass === pass) { 35 | return u; 36 | } 37 | })[0]; 38 | console.log('user', user) 39 | user ? cb(null, user) : cb(404); 40 | }, 41 | loginRoute: "/login.html" 42 | }) 43 | 44 | var app = express() 45 | 46 | app.set('port', process.env.PORT || 3000) 47 | app.use(logger('dev')) 48 | app.use(bodyParser.json()) 49 | app.use(bodyParser.urlencoded({extended: false})) 50 | app.use(cookieParser('secret')) 51 | app.use(cookieSession({keys: ['secret']})) 52 | 53 | app.use(express.static(__dirname + '/public')) 54 | 55 | /* Rutas */ 56 | 57 | app.get('/', function(req, res) { 58 | res.redirect('/login.html'); 59 | }) 60 | 61 | app.post("/session", auth.createSession({ redirect: "/ok" })) 62 | 63 | app.get("/ok", auth.requiresSession, function(req, res) { 64 | res.end("OK!") 65 | }) 66 | 67 | app.get("/secret", auth.requiresSession, function(req, res) { 68 | res.end("Hola, " + req.user.username) 69 | }) 70 | 71 | app.get("/logout", auth.requiresSession, function(req, res) { 72 | auth.destroySession(res) 73 | res.redirect("/login.html") 74 | }) 75 | 76 | app.listen(3000); 77 | -------------------------------------------------------------------------------- /tema3/simpleAuthModule/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-simpleauth", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "express": "*", 7 | "lodash": "*", 8 | "morgan": "*", 9 | "body-parser": "*", 10 | "method-override": "*", 11 | "cookie-parser": "*", 12 | "cookie-session": "*" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tema3/simpleAuthModule/public/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |

7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /tema3/simpleAuthModule/simpleauth.js: -------------------------------------------------------------------------------- 1 | var _ = require("lodash") 2 | 3 | var strategy = { 4 | serializeUser: function(user) { 5 | }, 6 | deserializeUser: function(userId, cb) { 7 | }, 8 | checkCredentials: function(username, pass, done) { 9 | }, 10 | loginRoute: "/login.html" 11 | } 12 | 13 | var cookieName = 'user'; 14 | 15 | exports.setStrategy = function(customStrategy) { 16 | strategy = _.extend({}, strategy, customStrategy) 17 | } 18 | 19 | exports.createSession = function(options) { 20 | var defaultConfig = { 21 | username: "username", 22 | password: "password", 23 | redirect: '/secret', 24 | failRedirect: '/' 25 | } 26 | config = _.extend({}, defaultConfig, options); 27 | return function(req, res, next) { 28 | var username = req.body[config.username], 29 | password = req.body[config.password]; 30 | 31 | strategy.checkCredentials(username, password, function(err, user) { 32 | if (user && !err) { 33 | res.cookie(cookieName, strategy.serializeUser(user), {signed: true, maxAge: 1000*60*60*24*7}); 34 | res.redirect(config.redirect); 35 | } else { 36 | console.log("error al checkear credenciales"); 37 | res.redirect(config.failRedirect); 38 | } 39 | }); 40 | } 41 | } 42 | 43 | exports.requiresSession = function(req, res, next) { 44 | if (req.signedCookies[cookieName]) { 45 | strategy.deserializeUser(req.signedCookies[cookieName], function(err, user) { 46 | if(err) { 47 | res.clearCookie(cookieName); 48 | return res.sendStatus(500); 49 | } 50 | req.user = user; 51 | next(); 52 | }); 53 | } else { 54 | next(strategy.loginRoute); 55 | } 56 | } 57 | 58 | exports.destroySession = function(res) { 59 | res.clearCookie(cookieName); 60 | } 61 | -------------------------------------------------------------------------------- /tema4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema4.pdf -------------------------------------------------------------------------------- /tema4/blogAuthRedis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-simpleblog", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "bluebird": "^2.10.2", 7 | "body-parser": "^1.0.2", 8 | "cookie-parser": "^1.0.1", 9 | "cookie-session": "^1.0.2", 10 | "express": "*", 11 | "jade": "*", 12 | "method-override": "^1.0.0", 13 | "morgan": "^1.0.1", 14 | "redis": "^2.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tema4/blogAuthRedis/pubsub.js: -------------------------------------------------------------------------------- 1 | var redis = require("redis"), 2 | client1 = redis.createClient(), 3 | client2 = redis.createClient(), 4 | msg_count = 0; 5 | 6 | client1.on("subscribe", function (channel, count) { 7 | //publish stuff when the subscription is ready 8 | client2.publish("a nice channel", "I am sending a message."); 9 | client2.publish("a nice channel", "I am sending a second message."); 10 | client2.publish("a nice channel", "I am sending my last message."); 11 | }); 12 | 13 | client1.on("message", function (channel, message) { 14 | console.log("client1 channel " + channel + ": " + message); 15 | msg_count += 1; 16 | if (msg_count === 3) { 17 | client1.unsubscribe(); 18 | client1.end(); 19 | client2.end(); 20 | } 21 | }); 22 | 23 | client1.subscribe("a nice channel"); -------------------------------------------------------------------------------- /tema4/blogAuthRedis/test.js: -------------------------------------------------------------------------------- 1 | var Promise = require('bluebird'), 2 | client = require('redis').createClient(); 3 | 4 | 5 | client.subscribeAsync('foo').then(function(msg){ 6 | console.log('Mensaje!!!', msg); 7 | }); 8 | 9 | 10 | client.publishAsync('foo', 'hola mundo'); -------------------------------------------------------------------------------- /tema4/blogAuthRedis/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype 2 | html(lang='es') 3 | head 4 | meta(charset='utf-8') 5 | title Lista de Posts 6 | meta(name='description', content='') 7 | meta(property='og:image', content='') 8 | // Fonts 9 | link(href='http://fonts.googleapis.com/css?family=Roboto:400,300,500,700,400italic,300italic', rel='stylesheet', type='text/css') 10 | // Frameworks 11 | link(rel='stylesheet', href='/css/normalize.css') 12 | // Stylesheets 13 | link(rel='stylesheet', href='/css/styles.css', media='screen') 14 | body.post-list 15 | header 16 | .top 17 | h1 Mi Blog 18 | .newpost 19 | a(href='/posts/new') Nuevo Post 20 | .logout 21 | a(href='/logout') Logout 22 | block nav 23 | block content 24 | -------------------------------------------------------------------------------- /tema4/blogAuthRedis/views/login.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Login 6 | form.login-form(action="/session", method="POST") 7 | label(for='email') email 8 | input.email(type='email', name='username') 9 | label(for='password') contraseña 10 | input.password(type='password', name='password') 11 | input.button.login(type='submit', value='Login') 12 | 13 | section.register 14 | a(href="/register") Registrate 15 | -------------------------------------------------------------------------------- /tema4/blogAuthRedis/views/new-post.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.new-post.container 5 | h1.section-title= post.date? "Editar Post" : "Nuevo Post" 6 | form.new-post-form(action=post.date? "/posts/#{post.id}":"/posts", method="POST") 7 | label(for='title') Título 8 | input.title(type='text', name='title', value=post.title) 9 | label(for='post-title') Contenido 10 | textarea.post-content(name='content', placeholder='')= post.content 11 | if post.date 12 | input(type="hidden",name="_method",value="put") 13 | input.button(type='submit', value='Publicar') 14 | -------------------------------------------------------------------------------- /tema4/blogAuthRedis/views/post-detail.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block nav 4 | nav.menu 5 | ul 6 | li 7 | a(href='/posts') Volver 8 | li 9 | a(href='/posts/#{post.id}/edit') Editar 10 | li 11 | form(action="/posts/#{post.id}",method="POST",id="form-delete") 12 | input(type="hidden",name="_method",value="delete") 13 | a(href='#',onclick="document.getElementById('form-delete').submit()") Eliminar 14 | 15 | block content 16 | section.posts 17 | article.post 18 | .container 19 | h1.post-title= post.title 20 | p= post.content 21 | aside.metadata 22 | | Por 23 | a(href='#')  Default User 24 | span.sep   |   25 | | 0 visitas 26 | -------------------------------------------------------------------------------- /tema4/blogAuthRedis/views/post-list.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.posts 5 | each post in posts 6 | article.post 7 | .container 8 | h2.post-title 9 | a(href='/posts/#{post.id}')= post.title 10 | p.summary= post.content.slice(0, 150) 11 | aside.metadata 12 | | Por 13 | a(href='#')  Default User 14 | span.sep   |   15 | | 0 visitas 16 | -------------------------------------------------------------------------------- /tema4/blogAuthRedis/views/register.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Registro de Usuario 6 | form.login-form(action="/register", method="POST") 7 | label(for='email') email 8 | input.email(type='email', name='username') 9 | label(for='password') contraseña 10 | input.password(type='password', name='password') 11 | label(for='password') confirmación 12 | input.password(type='password', name='passwordconfirm') 13 | input.button.login(type='submit', value='Enviar') 14 | 15 | section.register 16 | a(href="/login") ¿Ya tienes usuario? 17 | -------------------------------------------------------------------------------- /tema4/urlshort/.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude vim temp files 2 | *.swp 3 | *.swo 4 | # Databases 5 | *.sqlite 6 | # Exclude OS X folder attributes 7 | .DS_Store 8 | # Exclude npm packages 9 | node_modules 10 | # Exclude REDIS dumps 11 | dump.rdb 12 | Vagrantfile 13 | .vagrant 14 | -------------------------------------------------------------------------------- /tema4/urlshort/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-urlshort", 3 | "version": "0.0.1", 4 | "private": true, 5 | "dependencies": { 6 | "q": "*", 7 | "jade": "*", 8 | "express": "*", 9 | "hiredis": "*", 10 | "redis": "*", 11 | "body-parser": "*", 12 | "method-override": "*", 13 | "cookie-parser": "*", 14 | "cookie-session": "*" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tema4/urlshort/views/layout.jade: -------------------------------------------------------------------------------- 1 | !!! 5 2 | html(lang='es') 3 | head 4 | meta(charset='utf-8') 5 | title Url Shortener 6 | meta(name='description', content='') 7 | meta(property='og:image', content='') 8 | // Fonts 9 | link(href='http://fonts.googleapis.com/css?family=Roboto:400,300,500,700,400italic,300italic', rel='stylesheet', type='text/css') 10 | // Frameworks 11 | link(rel='stylesheet', href='/css/normalize.css') 12 | // Stylesheets 13 | link(rel='stylesheet', href='/css/styles.css', media='screen') 14 | body.post-list 15 | header 16 | .top 17 | h1 Url Shortener 18 | block buttons 19 | block nav 20 | block content 21 | -------------------------------------------------------------------------------- /tema4/urlshort/views/login.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Login 6 | form.login-form(action="/session", method="POST") 7 | label(for='email') Email 8 | input.email(type='email', name='username') 9 | label(for='password') Contraseña 10 | input.password(type='password', name='password') 11 | input.button.login(type='submit', value='Login') 12 | 13 | section.register 14 | a(href="/register") Registrate 15 | -------------------------------------------------------------------------------- /tema4/urlshort/views/register.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | section.login.container 5 | h1.section-title Registro de Usuario 6 | form.login-form(action="/register", method="POST") 7 | label(for='email') email 8 | input.email(type='email', name='username') 9 | label(for='password') contraseña 10 | input.password(type='password', name='password') 11 | label(for='password') confirmación 12 | input.password(type='password', name='passwordconfirm') 13 | input.button.login(type='submit', value='Enviar') 14 | 15 | section.register 16 | a(href="/login") ¿Ya tienes usuario? 17 | -------------------------------------------------------------------------------- /tema4/urlshort/views/url-form.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block buttons 4 | .newpost 5 | a(href='/urls/new') Nueva URL 6 | .logout 7 | a(href='/logout') Logout 8 | 9 | block nav 10 | nav.menu 11 | ul 12 | li 13 | a(href='/urls') Volver 14 | 15 | block content 16 | section.login 17 | .section-title 18 | h1= url.code? "Editar URL "+url.code : "Nueva URL" 19 | form.login-form(action=url.code? "/urls/#{url.code}" : "/urls", method="POST") 20 | input(type="text", name="original", placeholder="url", value=url.original, style="height:45px; margin-top:13px; width:480px") 21 | if url.code 22 | input(type="hidden", name="_method", value="put") 23 | input.button(type="submit") 24 | -------------------------------------------------------------------------------- /tema4/urlshort/views/url-index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block buttons 4 | .newpost 5 | a(href='/urls/new') Nueva URL 6 | .logout 7 | a(href='/logout') Logout 8 | 9 | block content 10 | section.url-list.container 11 | table 12 | thead 13 | th.long URL original 14 | th Creado 15 | th URL corta 16 | th Visitas 17 | th Detalles 18 | each url in urls 19 | tr 20 | td: a(href=url.original)= url.original 21 | if url.date 22 | - var d = new Date(url.date) 23 | td #{d.getDate()}/#{d.getMonth()}/#{d.getFullYear()} 24 | else 25 | td -- 26 | td: a(href="/#{url.code}") http://#{host}/#{url.code} 27 | td= url.visits 28 | td: a(href="/urls/#{url.code}") Detalles 29 | -------------------------------------------------------------------------------- /tema4/urlshort/views/url-show.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block buttons 4 | .newpost 5 | a(href='/urls/new') Nueva URL 6 | .logout 7 | a(href='/logout') Logout 8 | 9 | block nav 10 | nav.menu 11 | ul 12 | li 13 | a(href='/urls') Volver 14 | li 15 | a(href='/urls/#{url.code}/edit') Editar 16 | li 17 | form(action="/urls/#{url.code}",method="POST",id="form-delete") 18 | input(type="hidden",name="_method",value="delete") 19 | a(href='#',onclick="document.getElementById('form-delete').submit()") Eliminar 20 | 21 | block content 22 | section.login 23 | .section-title 24 | h1 http://#{host}/#{url.code} 25 | h4= url.original 26 | p Visitas: #{url.visits} 27 | -------------------------------------------------------------------------------- /tema5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema5.pdf -------------------------------------------------------------------------------- /tema5/digg_clone/app.js: -------------------------------------------------------------------------------- 1 | /* Modules */ 2 | 3 | var express = require('express'); 4 | var path = require('path'); 5 | var logger = require('morgan'); 6 | var cookieParser = require('cookie-parser'); 7 | var cookieSession = require('cookie-session'); 8 | var bodyParser = require('body-parser'); 9 | var methodOverride = require('method-override'); 10 | var Q = require('q'); 11 | var auth = require('./simpleauth'); 12 | var MongoClient = require('mongodb').MongoClient; 13 | var ObjectID = require('mongodb').ObjectID; 14 | var models = require('./models'); 15 | 16 | var app = express(); 17 | 18 | /* Config */ 19 | 20 | var client = Q.ninvoke(MongoClient, 21 | 'connect', 22 | 'mongodb://127.0.0.1:27017/diggclone'); 23 | 24 | models.setClient(client); 25 | 26 | client.fail(function(e) { 27 | console.log('ERROR conectando a Mongo: ', e); 28 | }); 29 | 30 | function extend() { 31 | var args = [].slice.call(arguments); 32 | return args.reduce(function(acc, el) { 33 | for (var k in el) { acc[k] = el[k]; } 34 | return acc; 35 | }); 36 | } 37 | 38 | Q.longStackSupport = true; 39 | 40 | app.set('views', path.join(__dirname, 'views')); 41 | app.set('view engine', 'jade'); 42 | 43 | app.use(logger('dev')); 44 | app.use(bodyParser.json()); 45 | app.use(methodOverride()); 46 | app.use(bodyParser.urlencoded()); 47 | app.use(cookieParser()); 48 | app.use(cookieSession({secret: 'asdf'})); 49 | app.use(express.static(path.join(__dirname, 'public'))); 50 | 51 | /* Auth */ 52 | 53 | auth.setStrategy({ 54 | serializeUser: function(user) { 55 | }, 56 | deserializeUser: function(userToken, cb) { 57 | }, 58 | checkCredentials: function(username, pass, cb) { 59 | // models.user("findOne") 60 | } 61 | }); 62 | 63 | /* Routing */ 64 | 65 | app.use('/', require('./routes/users')); 66 | app.use('/posts', require('./routes/posts')); 67 | app.use('/comments', require('./routes/comments')); 68 | 69 | /* Errors */ 70 | 71 | app.use(function(req, res, next) { 72 | res.send(404); 73 | }); 74 | 75 | app.use(function(err, req, res, next) { 76 | res.send(500); 77 | }); 78 | 79 | module.exports = app; 80 | -------------------------------------------------------------------------------- /tema5/digg_clone/bin/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var app = require('../app'); 3 | var port = process.env.PORT || 3000; 4 | 5 | var server = app.listen(port, function() { 6 | console.log('Express server listening on port ' + port); 7 | }); 8 | -------------------------------------------------------------------------------- /tema5/digg_clone/models/comment.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema5/digg_clone/models/comment.js -------------------------------------------------------------------------------- /tema5/digg_clone/models/index.js: -------------------------------------------------------------------------------- 1 | module.exports = exports = Object.create(require('./utils')); 2 | 3 | exports.user = require('./user'); 4 | exports.post = require('./post'); 5 | exports.comment = require('./comment'); 6 | -------------------------------------------------------------------------------- /tema5/digg_clone/models/post.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema5/digg_clone/models/post.js -------------------------------------------------------------------------------- /tema5/digg_clone/models/user.js: -------------------------------------------------------------------------------- 1 | var op = require('./utils').op; 2 | var user = op.bind({}, "users"); 3 | 4 | // ejemplo 5 | user.checkCredentials = function(email, password) { 6 | return user("findOne", {email: email, password: password}); 7 | }; 8 | 9 | 10 | module.exports = user; 11 | -------------------------------------------------------------------------------- /tema5/digg_clone/models/utils.js: -------------------------------------------------------------------------------- 1 | var Q = require("q"); 2 | 3 | var client = null; 4 | 5 | exports.setClient = function(mongoClient) { 6 | client = mongoClient; 7 | }; 8 | 9 | exports.op = function op(colname) { 10 | var args = [].slice.call(arguments, 1); 11 | return client 12 | .then(function(db) { 13 | // 1) primero necesito el objeto db 14 | // 2) db.collection(colname) => el "puntero" a la coleccion 15 | // 3) args = algo como: ["findOne", {a: 1}] 16 | // 4) Al final, la llamada es equivalente a hacer: 17 | // Q.ninvoke(col, "findOne", {a: 1}) 18 | return Q.ninvoke.apply(Q, [db.collection(colname)].concat(args)); 19 | }) 20 | .fail(function(err) { 21 | console.log("[MongoDB]", err); 22 | throw err; 23 | }); 24 | }; 25 | 26 | exports.makeOp = function(col) { 27 | var args = [].slice.call(arguments, 1); 28 | return function () { return col.apply({}, args); }; 29 | }; 30 | -------------------------------------------------------------------------------- /tema5/digg_clone/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-digg", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/start" 7 | }, 8 | "dependencies": { 9 | "express": "~4.0.0", 10 | "static-favicon": "~1.0.0", 11 | "morgan": "~1.0.0", 12 | "cookie-parser": "~1.0.1", 13 | "body-parser": "~1.0.0", 14 | "debug": "~0.7.4", 15 | "jade": "~1.3.0", 16 | "q": "~1.0.1", 17 | "method-override": "~1.0.0", 18 | "cookie-session": "~1.0.1", 19 | "mongodb": "~1.4.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tema5/digg_clone/public/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | 3 | $('.add > a').on('click', function(){ 4 | $(this).parent('.add').toggleClass('active'); 5 | }); 6 | 7 | 8 | 9 | 10 | }); 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tema5/digg_clone/public/assets/stylesheets/mixins.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema5/digg_clone/public/assets/stylesheets/mixins.css -------------------------------------------------------------------------------- /tema5/digg_clone/public/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema5/digg_clone/public/img/loading.gif -------------------------------------------------------------------------------- /tema5/digg_clone/routes/comments.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var resources = require('./resources'); 3 | var auth = require('../simpleauth'); 4 | 5 | var commentsController = { 6 | index: function(req, res) { 7 | }, 8 | show: function(req, res) { 9 | }, 10 | create: function(req, res) { 11 | }, 12 | update: function(req, res) { 13 | }, 14 | "delete": function(req, res) { 15 | }, 16 | vote: function(req, res) { 17 | }, 18 | param: function(req, res, next, postId) { 19 | } 20 | }; 21 | 22 | var router = express.Router(); 23 | router.use(auth.requiresToken); 24 | resources(router, 'comments', commentsController); 25 | router.post('/:commentsid/vote/:vote', commentsController.vote); 26 | 27 | module.exports = router; 28 | -------------------------------------------------------------------------------- /tema5/digg_clone/routes/posts.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var resources = require('./resources'); 3 | var auth = require('../simpleauth'); 4 | 5 | var postsController = { 6 | index: function(req, res) { 7 | }, 8 | show: function(req, res) { 9 | }, 10 | create: function(req, res) { 11 | }, 12 | update: function(req, res) { 13 | }, 14 | "delete": function(req, res) { 15 | }, 16 | vote: function(req, res) { 17 | }, 18 | param: function(req, res, next, postId) { 19 | } 20 | }; 21 | 22 | var router = express.Router(); 23 | router.use(auth.requiresToken); 24 | resources(router, 'posts', postsController); 25 | router.post('/:postsid/vote/:vote', postsController.vote); 26 | 27 | module.exports = router; 28 | -------------------------------------------------------------------------------- /tema5/digg_clone/routes/resources.js: -------------------------------------------------------------------------------- 1 | module.exports = function (router, name, controller) { 2 | if (controller.index) router.get("/", controller.index); 3 | if (controller["new"]) router.get("/new", controller["new"]); 4 | if (controller.create) router.post("/", controller.create); 5 | if (controller.show) router.get("/:"+name+"id", controller.show); 6 | if (controller.edit) router.get("/:"+name+"id/edit", controller.edit); 7 | if (controller.update) router.put("/:"+name+"id", controller.update); 8 | if (controller["delete"]) router["delete"]("/:"+name+"id", controller["delete"]); 9 | if (controller.param) router.param(name + "id", controller.param); 10 | }; 11 | -------------------------------------------------------------------------------- /tema5/digg_clone/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var resources = require('./resources'); 3 | var auth = require('../simpleauth'); 4 | 5 | var usersController = { 6 | create: function(req, res) { 7 | }, 8 | me: function(req, res) { 9 | }, 10 | login: function(req, res) { 11 | } 12 | }; 13 | 14 | var router = express.Router(); 15 | router.post('/session', auth.createSession(), usersController.login); 16 | router.post('/users', usersController.create); 17 | router.get('/me', auth.requiresToken, usersController.me); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /tema5/digg_clone/simpleauth.js: -------------------------------------------------------------------------------- 1 | function extend() { 2 | var args = [].slice.call(arguments) 3 | return args.reduce(function(acc, el) { 4 | for (var k in el) { acc[k] = el[k] } 5 | return acc; 6 | }) 7 | } 8 | 9 | strategy = { 10 | serializeUser: function(user) { 11 | }, 12 | deserializeUser: function(userId, cb) { 13 | }, 14 | checkCredentials: function(username, pass, done) { 15 | } 16 | } 17 | 18 | exports.setStrategy = function(customStrategy) { 19 | strategy = extend({}, strategy, customStrategy) 20 | } 21 | 22 | exports.createSession = function(options) { 23 | var config = { 24 | username: "username", 25 | password: "password", 26 | } 27 | config = extend({}, config, options) 28 | return function(req, res, next) { 29 | var username = req.body[config.username], 30 | pass = req.body[config.password] 31 | strategy.checkCredentials(username, pass, function(err, user) { 32 | if (!err && user) { 33 | req.user = user 34 | next() 35 | /* res.redirect(config.redirect) */ 36 | } else { 37 | console.log("Credenciales incorrectas") 38 | res.send(401, {error: "Username o contraseña incorrectos"}) 39 | } 40 | }) 41 | } 42 | } 43 | 44 | exports.requiresToken = function(req, res, next) { 45 | var token = req.param("token") 46 | if (token !== undefined) { 47 | strategy.deserializeUser(token, function(user) { 48 | if (!user) { 49 | console.log("El usuario no existe!") 50 | res.send(401, {error: "No autorizado"}) 51 | } else { 52 | req.user = user 53 | next() 54 | } 55 | }) 56 | } else { 57 | console.log("No existe token...") 58 | res.send(401, {error: "No autorizado"}) 59 | } 60 | } 61 | 62 | exports.withToken = function(app, cb) { 63 | function createAuthRouting(verb) { 64 | return function() { 65 | var route = arguments[0], 66 | args = [].slice.call(arguments, 1) 67 | return app[verb].apply(app, [route, exports.requiresToken].concat(args)) 68 | } 69 | } 70 | var routeVerbs = Object.create(app); 71 | ["get", "post", "put", "delete"].forEach(function(v) { 72 | routeVerbs[v] = createAuthRouting(v) 73 | }); 74 | cb(routeVerbs) 75 | } 76 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/bin/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var app = require('../app'); 3 | var port = process.env.PORT || 3000; 4 | 5 | var server = app.listen(port, function() { 6 | console.log('Express server listening on port ' + port); 7 | }); 8 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/data/db/.gitinclude: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema5/digg_clone_bluebird/data/db/.gitinclude -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/models/comment.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils'); 2 | var ObjectID = require('mongodb').ObjectID; 3 | 4 | var Comment = { 5 | getByPostId: function(postId){ 6 | var collection = utils.collection('comments'); 7 | //TODO: devolver los comentarios que tengan ese postId 8 | }, 9 | getById: function(commentId){ 10 | var collection = utils.collection('comments'); 11 | //TODO: Devolver un único comentario a partir de su id 12 | }, 13 | save: function(comment){ 14 | //TODO: guardar un comentario 15 | } 16 | } 17 | 18 | module.exports = Comment; -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/models/index.js: -------------------------------------------------------------------------------- 1 | //Indice de Modelos 2 | 3 | module.exports = exports = Object.create(require('./utils')); 4 | exports.user = require('./user'); 5 | exports.post = require('./post'); 6 | exports.comment = require('./comment'); 7 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/models/post.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils'); 2 | var ObjectID = require('mongodb').ObjectID; 3 | 4 | var COLNAME = 'posts'; 5 | var PAGE_SIZE = 10; 6 | 7 | var Post = { 8 | getPostsBySection: function(section, page){ 9 | var page = page || 0; 10 | var collection = utils.collection(COLNAME); 11 | // TODO: devolver los Posts correspondientes a la página y ordenados según la sección 12 | // limit(PAGE_SIZE).skip(PAGE_SIZE*page) 13 | }, 14 | getById: function(id){ 15 | var collection = utils.collection(COLNAME); 16 | //devolver un Post por su ID 17 | return collection.findOneAsync({ _id: ObjectID(id)}); 18 | }, 19 | save: function(post){ 20 | //TODO: guardar un post 21 | }, 22 | } 23 | 24 | 25 | module.exports = Post; 26 | 27 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/models/user.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils'); 2 | 3 | var User = { 4 | checkCredentials: function(email, password) { 5 | var collection = utils.collection('users'); 6 | //TODO: encontrar un usuario con el email y password y devolver la promesa 7 | }, 8 | getUserByToken: function(token){ 9 | var collection = utils.collection('users'); 10 | // TODO: encontrar un usuario a partir del token 11 | }, 12 | save: function(userdata){ 13 | var collection = utils.collection('users'); 14 | userdata.token = Date.now().toString(16); 15 | return collection.saveAsync(userdata); 16 | } 17 | } 18 | 19 | 20 | module.exports = User; 21 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/models/utils.js: -------------------------------------------------------------------------------- 1 | //Utilidades para Modelos 2 | 3 | //referencia al cliente MongoDB 4 | var client = null; 5 | 6 | exports.setClient = function(mongoClient) { 7 | client = mongoClient; 8 | }; 9 | 10 | exports.getClient = function(){ 11 | return client; 12 | } 13 | 14 | //Devuelve una colección del cliente MongoDB 15 | exports.collection = function(name){ 16 | return client.collection(name); 17 | } 18 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "redradix-nodejs-digg", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/start" 7 | }, 8 | "dependencies": { 9 | "bluebird": "^2.10.2", 10 | "body-parser": "~1.0.0", 11 | "cookie-parser": "~1.0.1", 12 | "cookie-session": "~1.0.1", 13 | "debug": "~0.7.4", 14 | "express": "~4.0.0", 15 | "jade": "~1.3.0", 16 | "method-override": "~1.0.0", 17 | "mongodb": "~1.4.2", 18 | "morgan": "~1.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/public/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | 3 | $('.add > a').on('click', function(){ 4 | $(this).parent('.add').toggleClass('active'); 5 | }); 6 | 7 | 8 | 9 | 10 | }); 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/public/assets/stylesheets/mixins.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema5/digg_clone_bluebird/public/assets/stylesheets/mixins.css -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/public/img/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema5/digg_clone_bluebird/public/img/loading.gif -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/routes/comments.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var auth = require('../simpleauth'); 3 | 4 | var Comment = require('../models/comment'); 5 | var Post = require('../models/post'); 6 | 7 | var commentsController = { 8 | // GET /?post_id=xxxxxx 9 | index: function(req, res) { 10 | // TODO: traer comentarios para un Post concreto 11 | res.send([]); 12 | }, 13 | // Guarda un nuevo comentario en la colección 14 | // y debería sumar un comentario al Post en cuestión 15 | create: function(req, res) { 16 | console.log('Create comment', req.body); 17 | // TODO: cargar el post primero para ver si existe 18 | // y si es así, creamos el comentario y actualizamos el Post 19 | }, 20 | // Suma 1 al número de votos de un comentario 21 | vote: function(req, res) { 22 | // TODO: actualizar votos y guardar comentario 23 | }, 24 | // Lee de BBDD un comentario a partir de su id 25 | // y lo almacena en req.comment para el resto de middlewares 26 | param: function(req, res, next, commentsId) { 27 | // TODO: cargar un comentario a partir de su id 28 | // si no existe, devolver un 404 not found - res.status(404).end() 29 | } 30 | }; 31 | 32 | var router = express.Router(); 33 | router.use(auth.requiresToken); 34 | router.get('/', commentsController.index); 35 | router.post('/', commentsController.create); 36 | router.post('/:commentsid/vote/:vote', commentsController.vote); 37 | router.param('commentsid', commentsController.param); 38 | 39 | module.exports = router; 40 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/routes/posts.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var auth = require('../simpleauth'); 3 | 4 | var Post = require('../models').post; 5 | 6 | var postsController = { 7 | // GET /?s=hottest|recent[&page=n] 8 | // Devuelve la lista de posts ordenada según la sección y paginada 9 | index: function(req, res) { 10 | // TODO 11 | }, 12 | // GET /xxxxxx 13 | // Devuelve los datos de un post concreto 14 | show: function(req, res) { 15 | // TODO 16 | }, 17 | // POST / 18 | // guarda un nuevo post 19 | create: function(req, res) { 20 | var postData = req.body; 21 | // TODO: 22 | // guardar el usuario que lo crea como documento incrustado user 23 | // generar la fecha actual 24 | // guardar el Post y devolverlo como respuesta 25 | }, 26 | // Actualizar un post (no se usa) 27 | update: function(req, res) { 28 | }, 29 | // Borrar un post (no se usa) 30 | "delete": function(req, res) { 31 | }, 32 | // Añadir un voto positivo o negativo a un post 33 | vote: function(req, res) { 34 | // TODO: decidir si sumamos o restamos voto y guardar el post 35 | }, 36 | // Lee de BBDD un Post a partir del postId 37 | param: function(req, res, next, postId) { 38 | // TODO: leer el Post y guardarlo en req.post 39 | // o devolver un 404 si no existe 40 | } 41 | }; 42 | 43 | var router = express.Router(); 44 | router.use(auth.requiresToken); 45 | 46 | router.param('postId', postsController.param); 47 | router.get('/', postsController.index); 48 | router.post('/', postsController.create); 49 | router.get('/:postId', postsController.show); 50 | router.put('/:postId', postsController.update); 51 | router.delete('/:postId', postsController.delete); 52 | router.post('/:postId/vote/:vote', postsController.vote); 53 | 54 | 55 | module.exports = router; 56 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var auth = require('../simpleauth'); 3 | 4 | var User = require('../models/user'); 5 | 6 | var usersController = { 7 | //Crea un nuevo usuario (registro) 8 | create: function(req, res) { 9 | console.log('Register user', req.body); 10 | if(req.body.password !== req.body.passwordconfirm){ 11 | res.status(400).send('Passwords no coinciden'); 12 | } 13 | else { 14 | User.save({ 15 | email: req.body.username, 16 | name: req.body.name, 17 | date: Date.now(), 18 | password: req.body.password 19 | }).then(function(user){ 20 | delete user.password; 21 | res.status(200).send(user); 22 | }) 23 | } 24 | }, 25 | //Devuelve la información del usuario 26 | //req.user está ya en request (por simpleAuth) 27 | me: function(req, res) { 28 | res.status(200).send(req.user); 29 | }, 30 | //Devuelve la información del usuario 31 | login: function(req, res) { 32 | res.status(200).send(req.user); 33 | } 34 | }; 35 | 36 | var router = express.Router(); 37 | router.post('/session', auth.createSession(), usersController.login); 38 | router.post('/users', usersController.create); 39 | router.get('/me', auth.requiresToken, usersController.me); 40 | 41 | module.exports = router; 42 | -------------------------------------------------------------------------------- /tema5/digg_clone_bluebird/simpleauth.js: -------------------------------------------------------------------------------- 1 | function extend() { 2 | var args = [].slice.call(arguments) 3 | return args.reduce(function(acc, el) { 4 | for (var k in el) { acc[k] = el[k] } 5 | return acc; 6 | }) 7 | } 8 | 9 | var strategy = { 10 | serializeUser: function(user) { 11 | }, 12 | deserializeUser: function(userId, cb) { 13 | }, 14 | checkCredentials: function(username, pass, done) { 15 | } 16 | } 17 | 18 | exports.setStrategy = function(customStrategy) { 19 | strategy = extend({}, strategy, customStrategy) 20 | } 21 | 22 | exports.createSession = function(options) { 23 | var config = { 24 | username: "username", 25 | password: "password", 26 | } 27 | config = extend({}, config, options) 28 | return function(req, res, next) { 29 | var username = req.body[config.username], 30 | pass = req.body[config.password] 31 | strategy.checkCredentials(username, pass, function(err, user) { 32 | if (!err && user) { 33 | req.user = user 34 | next() 35 | /* res.redirect(config.redirect) */ 36 | } else { 37 | console.log("Credenciales incorrectas") 38 | res.send(401, {error: "Username o contraseña incorrectos"}) 39 | } 40 | }) 41 | } 42 | } 43 | 44 | exports.requiresToken = function(req, res, next) { 45 | var token = req.param("token") 46 | if (token !== undefined) { 47 | strategy.deserializeUser(token, function(user) { 48 | if (!user) { 49 | console.log("El usuario no existe!") 50 | res.send(401, {error: "No autorizado"}) 51 | } else { 52 | req.user = user 53 | next() 54 | } 55 | }) 56 | } else { 57 | console.log("No existe token...") 58 | res.send(401, {error: "No autorizado"}) 59 | } 60 | } 61 | 62 | exports.withToken = function(app, cb) { 63 | function createAuthRouting(verb) { 64 | return function() { 65 | var route = arguments[0], 66 | args = [].slice.call(arguments, 1) 67 | return app[verb].apply(app, [route, exports.requiresToken].concat(args)) 68 | } 69 | } 70 | var routeVerbs = Object.create(app); 71 | ["get", "post", "put", "delete"].forEach(function(v) { 72 | routeVerbs[v] = createAuthRouting(v) 73 | }); 74 | cb(routeVerbs) 75 | } 76 | -------------------------------------------------------------------------------- /tema6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema6.pdf -------------------------------------------------------------------------------- /tema6/chat/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('static-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var cookieSession = require('cookie-session'); 7 | var bodyParser = require('body-parser'); 8 | var crypto = require('crypto'); 9 | 10 | var app = express(); 11 | var server = require('http').createServer(app); 12 | var io = require('socket.io').listen(server); 13 | 14 | // setup 15 | 16 | app.set('views', path.join(__dirname, 'views')); 17 | app.set('view engine', 'jade'); 18 | 19 | app.use(favicon()); 20 | app.use(logger('dev')); 21 | app.use(bodyParser.json()); 22 | app.use(bodyParser.urlencoded()); 23 | app.use(cookieParser()); 24 | app.use(cookieSession({secret: 'asdf'})); 25 | app.use(express.static(path.join(__dirname, 'public'))); 26 | 27 | // utilidades 28 | 29 | function gravatar(email, s) { 30 | var baseUrl = "http://www.gravatar.com/avatar/", 31 | parEmail = email.toLowerCase().trim(), 32 | hash = crypto.createHash("md5").update(parEmail).digest("hex"); 33 | return baseUrl + hash + (s? "s="+s : ""); 34 | } 35 | 36 | // rutas 37 | 38 | app.post('/session', function(req, res) { 39 | req.session.nick = req.body.nick; 40 | req.session.avatar = gravatar(req.body.gravatar, 50); 41 | res.redirect('/chat.html'); 42 | }); 43 | 44 | app.get('/me', function(req, res) { 45 | res.send({name: req.session.nick, avatar: req.session.avatar}); 46 | }); 47 | 48 | app.use(function(req, res) { 49 | res.redirect('/login.html'); 50 | }); 51 | 52 | // sockets 53 | 54 | // ---8<--- El servidor del chat aqui! ---8<--- 55 | 56 | 57 | // exports 58 | 59 | module.exports = server; 60 | -------------------------------------------------------------------------------- /tema6/chat/bin/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var server = require('../app'); 4 | server.listen(process.env.PORT || 3000); 5 | -------------------------------------------------------------------------------- /tema6/chat/npm-debug.log: -------------------------------------------------------------------------------- 1 | 0 info it worked if it ends with ok 2 | 1 verbose cli [ 'node', '/usr/local/bin/npm', 'start' ] 3 | 2 info using npm@1.4.3 4 | 3 info using node@v0.10.26 5 | 4 verbose run-script [ 'prestart', 'start', 'poststart' ] 6 | 5 info prestart application-name@0.0.1 7 | 6 info start application-name@0.0.1 8 | 7 verbose unsafe-perm in lifecycle true 9 | 8 info application-name@0.0.1 Failed to exec start script 10 | 9 error application-name@0.0.1 start: `node ./bin/www` 11 | 9 error Exit status 8 12 | 10 error Failed at the application-name@0.0.1 start script. 13 | 10 error This is most likely a problem with the application-name package, 14 | 10 error not with npm itself. 15 | 10 error Tell the author that this fails on your system: 16 | 10 error node ./bin/www 17 | 10 error You can get their info via: 18 | 10 error npm owner ls application-name 19 | 10 error There is likely additional logging output above. 20 | 11 error System Darwin 13.1.0 21 | 12 error command "node" "/usr/local/bin/npm" "start" 22 | 13 error cwd /Users/werelax/courses/material-nodejs/tema7/chat 23 | 14 error node -v v0.10.26 24 | 15 error npm -v 1.4.3 25 | 16 error code ELIFECYCLE 26 | 17 verbose exit [ 1, true ] 27 | -------------------------------------------------------------------------------- /tema6/chat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "application-name", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/start" 7 | }, 8 | "dependencies": { 9 | "body-parser": "^1.0.2", 10 | "cookie-parser": "^1.0.1", 11 | "cookie-session": "^1.0.2", 12 | "debug": "^0.7.4", 13 | "express": "^4.0.0", 14 | "jade": "^1.3.1", 15 | "morgan": "^1.0.1", 16 | "request": "^2.64.0", 17 | "socket.io": "^1.3.7", 18 | "static-favicon": "~1.0.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tema6/chat/public/assets/images/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redradix-school/curso-node-js/94e2a47d54b64769f9a99973f5a1895e7fb6107d/tema6/chat/public/assets/images/avatar.jpg -------------------------------------------------------------------------------- /tema6/chat/public/assets/javascripts/script.js: -------------------------------------------------------------------------------- 1 | $(function(){ 2 | $('.new').on('click', function(){ 3 | $(this).parents('.actions').toggleClass('active'); 4 | }); 5 | }); 6 | 7 | var Chat = { 8 | newMessage: function(msg) { 9 | if (this.handler) this.handler(msg); 10 | }, 11 | registerHandler: function(fn) { 12 | this.handler = fn; 13 | }, 14 | postMsg: function(from, msg) { 15 | var template = $("#other-message").html(); 16 | var code = template 17 | .replace("%avatar%", from.avatar) 18 | .replace("%name%", from.name) 19 | .replace("%content%", msg.text) 20 | .replace("%time%", new Date(msg.date).toLocaleTimeString()); 21 | var $messages = $(".messages").append(code); 22 | $("body").stop().animate({ scrollTop: $messages.height() }, 400); 23 | }, 24 | showMyMsg: function(from, msg) { 25 | var template = $("#my-message").html(); 26 | var code = template 27 | .replace("%avatar%", from.avatar) 28 | .replace("%name%", from.name) 29 | .replace("%content%", msg.text) 30 | .replace("%time%", new Date(msg.date).toLocaleTimeString()); 31 | var $messages = $(".messages").append(code); 32 | $("body").stop().animate({ scrollTop: $messages.height() }, 400); 33 | } 34 | }; 35 | 36 | //handles sending messages with key 37 | $("textarea.js-input").keyup(function(e){ 38 | if(e.keyCode === 13 && !e.shiftKey){ 39 | e.preventDefault(); 40 | $("form.new-message").submit(); 41 | } 42 | }); 43 | 44 | 45 | $("form.new-message").submit(function(e) { 46 | e.preventDefault(); 47 | var textarea = $(this).find("textarea"); 48 | Chat.newMessage(textarea.val()); 49 | textarea.val(""); 50 | }); -------------------------------------------------------------------------------- /tema6/chat/public/chat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Sala 12 | 13 | 14 | 15 | 16 | 17 | 29 | 30 | 42 | 43 | 44 | 45 | 46 |
47 |
48 |

Chat

49 |
50 |
51 |
52 | 53 | 54 | 55 | 56 |
57 |
58 |
59 |
60 | 61 | 62 |
63 |
64 |
65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /tema6/chat/public/code.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // ---8<--- El cliente del chat aqui! ---8<--- 4 | 5 | /* 6 | 7 | Para obtener los datos que hemos introducido en login, podemos 8 | hacer un GET a /me: 9 | $.get('/me').then(function(userData){ 10 | .... 11 | }) 12 | 13 | Tenemos disponible de forma global el objeto Chat 14 | 15 | Chat.registerHandler(cb) 16 | Registra un callback que será llamado con el texto del mensaje 17 | introducido por el usuario 18 | 19 | Chat.postMsg(fromObj, messageObj) 20 | Añade a la lista de mensajes un mensaje de otro usuario 21 | fromObj = { name, avatar } 22 | messageObj = { message, date (timestamp)} 23 | 24 | Chat.showMyMsg(fromObj, messageObj) 25 | Añade a la lista de mensajes un mensaje propio 26 | */ 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /tema6/chat/public/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Login 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |

Login

21 | 22 | 23 | 24 | 25 | 28 |
29 |
30 | 31 | 32 | 33 | 34 | --------------------------------------------------------------------------------