├── .gitignore ├── README.md ├── package.json ├── routes ├── index.js ├── user.js └── words.js ├── server.js ├── utils └── jwtChecker.js └── words ├── words.js └── words.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular 2 demo + JWT (Backend) 2 | 3 | This is the companion backend of the [Angular 2 Demo + JWT](https://github.com/angular-tips/GermanWords-frontend-angular-2) 4 | 5 | Please read the article written at [Angular-Tips](http://angular-tips.com/blog/2015/05/an-introduction-to-angular-2) 6 | 7 | If you just want to try it, download the Frontend and run this project (If you're using node, you need to use the `--harmony` flag): 8 | 9 | ``` 10 | $ npm install 11 | $ node server.js 12 | ``` 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "german-words", 3 | "version": "1.0.0", 4 | "description": "A Koa backend for an Angular 2 demo", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/angular-tips/GermanWords-backend-koa.git" 12 | }, 13 | "keywords": [ 14 | "angular2", 15 | "koa", 16 | "demo" 17 | ], 18 | "author": "Jesus Rodriguez", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/angular-tips/GermanWords-backend-koa/issues" 22 | }, 23 | "homepage": "https://github.com/angular-tips/GermanWords-backend-koa#readme", 24 | "dependencies": { 25 | "koa": "^0.20.0", 26 | "koa-bodyparser": "^1.6.0", 27 | "koa-cors": "0.0.14", 28 | "koa-jwt": "^1.0.0", 29 | "koa-router": "^4.3.2", 30 | "lodash": "^3.8.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | user: require('./user'), 3 | words: require('./words') 4 | }; -------------------------------------------------------------------------------- /routes/user.js: -------------------------------------------------------------------------------- 1 | var router = require('koa-router')(); 2 | var jwt = require('koa-jwt'); 3 | var _ = require('lodash'); 4 | 5 | // Insert real DB in here. 6 | var users = [{ 7 | id: 1, 8 | username: 'demo', 9 | password: '12345' 10 | }]; 11 | 12 | function createToken(user) { 13 | return jwt.sign(_.omit(user, 'password'), 'this is my secret', { expiresInMinutes: 60*5 }); 14 | } 15 | 16 | router.post('/sessions/create', function *(next) { 17 | if ( ! this.request.body.username || ! this.request.body.password) { 18 | this.throw(400, 'You must send the username and the password'); 19 | } 20 | 21 | var user = _.find(users, {username: this.request.body.username}); 22 | if ( ! user) { 23 | this.throw(401, 'The username or password don\'t match'); 24 | } 25 | 26 | if (user.password !== this.request.body.password) { 27 | this.throw(401, 'The username or password don\'t match'); 28 | } 29 | 30 | this.status = 201; 31 | this.body = { id_token: createToken(user) }; 32 | }); 33 | 34 | module.exports = router.routes(); -------------------------------------------------------------------------------- /routes/words.js: -------------------------------------------------------------------------------- 1 | var router = require('koa-router')(); 2 | var jwtChecker = require('../utils/jwtChecker'); 3 | var words = require('../words/words'); 4 | var _ = require('lodash'); 5 | 6 | router.get('/api/random-word', function* () { 7 | var user = yield jwtChecker(this.header); 8 | var word = words.getRandomWord(); 9 | if ( ! user) { 10 | word = _.omit(word, 'english'); 11 | } 12 | this.body = word; 13 | }); 14 | 15 | module.exports = router.routes(); -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | var koa = require('koa'); 2 | var bodyParser = require('koa-bodyparser'); 3 | var cors = require('koa-cors'); 4 | 5 | var routes = require('./routes'); 6 | 7 | var app = koa(); 8 | 9 | app.use(cors({ 10 | headers: ['Content-Type', 'Authorization', 'Accept'] 11 | })); 12 | 13 | app.use(bodyParser()); 14 | 15 | app.use(routes.user); 16 | app.use(routes.words); 17 | 18 | app.listen(3001, function() { 19 | console.log('Backend running at port 3001'); 20 | }); -------------------------------------------------------------------------------- /utils/jwtChecker.js: -------------------------------------------------------------------------------- 1 | var jwt = require('koa-jwt'); 2 | 3 | // Instead of using koa-jwt middleware directly, 4 | // I just want to extract the user if there is a token 5 | module.exports = function* (header) { 6 | var token, parts, scheme, credentials; 7 | 8 | if (header.authorization) { 9 | parts = header.authorization.split(' '); 10 | if (parts.length == 2) { 11 | scheme = parts[0]; 12 | credentials = parts[1]; 13 | 14 | if (/^Bearer$/i.test(scheme)) { 15 | token = credentials; 16 | } 17 | } else { 18 | return null; 19 | } 20 | } 21 | 22 | try { 23 | return yield jwt.verify(token, 'this is my secret'); 24 | } catch(e) { 25 | return null; 26 | } 27 | }; -------------------------------------------------------------------------------- /words/words.js: -------------------------------------------------------------------------------- 1 | var words = require('./words.json').words; 2 | 3 | exports.getRandomWord = function() { 4 | var totalWords = words.length - 1; 5 | var rand = Math.ceil(Math.random() * totalWords); 6 | return words[rand]; 7 | }; -------------------------------------------------------------------------------- /words/words.json: -------------------------------------------------------------------------------- 1 | { 2 | "words": [ 3 | { 4 | "german": "der Lappen", 5 | "english": "cloth" 6 | }, 7 | { 8 | "german": "die Bettdecke", 9 | "english": "blanket, duvet" 10 | }, 11 | { 12 | "german": "etwas vervollständigen", 13 | "english": "to complete something" 14 | }, 15 | { 16 | "german": "umbauen", 17 | "english": "to renovate" 18 | }, 19 | { 20 | "german": "ebenso", 21 | "english": "also, as well" 22 | }, 23 | { 24 | "german": "die Auseinandersetzung", 25 | "english": "argument, quarrel" 26 | }, 27 | { 28 | "german": "allerdings", 29 | "english": "indeed" 30 | }, 31 | { 32 | "german": "durchführbar", 33 | "english": "feasible" 34 | }, 35 | { 36 | "german": "einen Film drehen", 37 | "english": "to shoot a film" 38 | }, 39 | { 40 | "german": "der Zweck", 41 | "english": "purpose" 42 | } 43 | ] 44 | } --------------------------------------------------------------------------------