├── .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 |

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 |

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 |

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 |

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 |
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 |
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 |
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 |
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 |
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 |
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 |
51 |
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 |
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 |
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 |

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 |

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 |

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 |

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 |
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 |
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 |
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 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
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 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------