Skip to content

Commit 230d51f

Browse files
committed
Stuffed a server into one file
0 parents  commit 230d51f

File tree

6 files changed

+295
-0
lines changed

6 files changed

+295
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

Makefile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
SHELL := bash
3+
4+
export PORT=1999
5+
export MONGODB=localhost/klouds
6+
export ASSETS=../client/dist
7+
export JWT_KEY=klouds_is_so_secure
8+
export STRIPE_SK=sk_test_Z34c2IRtyypD4EIQjdowKeLd
9+
10+
all: dev
11+
.PHONY: all
12+
13+
node_modules: package.json
14+
# Installing node modules
15+
@ npm install
16+
@ touch node_modules
17+
18+
dev:
19+
# Starting development server
20+
@iojs bootstrap.js
21+
22+
.PHONY: dev

bootstrap.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
require('babel/register')
2+
3+
/**
4+
* Environment Variables Validation
5+
*/
6+
var env = [ 'PORT', 'MONGODB', 'ASSETS', 'JWT_KEY', 'STRIPE_SK' ];
7+
env.map(function (v) {
8+
if (typeof process.env[v] === 'undefined') {
9+
throw "Missing Environment Variable: " + v
10+
}
11+
console.log(v, process.env[v])
12+
})
13+
14+
/**
15+
* Babelized Server Code
16+
*/
17+
var server = require('./server.js');

package.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "klouds-backend",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "ISC",
11+
"dependencies": {
12+
"assert": "^1.3.0",
13+
"babel": "^5.6.7",
14+
"co-monk": "^1.0.0",
15+
"joi": "^6.5.0",
16+
"koa": "^0.21.0",
17+
"koa-joi-router": "^1.3.1",
18+
"koa-json": "^1.1.1",
19+
"koa-json-body": "0.0.3",
20+
"koa-jwt": "^1.1.0",
21+
"koa-route": "^2.4.1",
22+
"koa-static": "^1.4.9",
23+
"lodash": "^3.9.3",
24+
"monk": "^1.0.1",
25+
"pswd": "^3.0.1",
26+
"stripe": "^3.5.0"
27+
}
28+
}

server.js

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
let { PORT, MONGODB, ASSETS, JWT_KEY, STRIPE_SK } = process.env;
2+
3+
import { join } from 'path'
4+
import koa from 'koa'
5+
import json from 'koa-json'
6+
import jsonBody from 'koa-json-body'
7+
import route from 'koa-route'
8+
import serve from 'koa-static'
9+
import jwt from 'koa-jwt'
10+
import Joi from 'joi';
11+
import monk from 'monk'
12+
import wrap from 'co-monk'
13+
import router from 'koa-joi-router'
14+
15+
let pswd = require('pswd')();
16+
let auth = jwt({ secret: process.env.JWT_KEY });
17+
let staticFiles = serve(join(__dirname, ASSETS), { defer: false })
18+
let stripe = require('stripe')(process.env.STRIPE_SK);
19+
20+
/**
21+
* Mongo DB Tables
22+
*/
23+
let db = monk(process.env.MONGODB);
24+
let appsDb = wrap(db.get('apps'));
25+
let usersDb = wrap(db.get('users'));
26+
let stripeDb = wrap(db.get('stripe'));
27+
28+
29+
/**
30+
* Koa Application & Middleware
31+
*/
32+
33+
function* errors(next) {
34+
try {
35+
yield next;
36+
} catch (err) {
37+
console.error(err);
38+
39+
this.status = err.status || 500;
40+
this.body = {
41+
error: err.message
42+
}
43+
this.app.emit('error', err, this);
44+
}
45+
}
46+
47+
48+
function authorize(user) {
49+
delete user.password;
50+
return {
51+
token: jwt.sign(user, process.env.JWT_KEY, { expiresInMinutes: 60 * 5 }),
52+
user: user,
53+
}
54+
}
55+
56+
57+
let loginRoute = {
58+
method: 'post',
59+
path: '/login',
60+
validate: {
61+
body: {
62+
email: Joi.string().lowercase().email(),
63+
password: Joi.string().max(100)
64+
},
65+
type: 'json'
66+
},
67+
handler: function* () {
68+
var email = this.request.body.email;
69+
var password = this.request.body.password;
70+
71+
var user = yield usersDb.findOne({ email: email });
72+
this.assert(user, 401, 'authentication failed');
73+
74+
var valid = yield pswd.compare(password, user.password);
75+
this.assert(valid, 401, 'authentication failed');
76+
77+
this.body = authorize(user);
78+
79+
}
80+
};
81+
82+
let registerRoute = {
83+
method: 'post',
84+
path: '/register',
85+
validate: {
86+
body: {
87+
email: Joi.string().lowercase().email(),
88+
password: Joi.string().max(100)
89+
},
90+
type: 'json'
91+
},
92+
handler: function* () {
93+
var email = this.request.body.email;
94+
var password = this.request.body.password;
95+
96+
var duplicate = yield usersDb.findOne({ email: email });
97+
this.assert(!duplicate, 400, 'Klouds ID already exists');
98+
99+
var hash = yield pswd.hash(password);
100+
this.assert(hash, 500, 'Failed to hash password');
101+
102+
var user = yield usersDb.insert({
103+
email: email,
104+
password: hash
105+
});
106+
this.assert(user, 500, 'Failed to insert new user');
107+
108+
this.body = authorize(user);
109+
}
110+
}
111+
112+
let appsRoute = {
113+
method: 'get',
114+
path: '/apps',
115+
handler: function*() {
116+
this.body = yield appsDb.find({ disabled: { "$exists" : false }});;
117+
}
118+
}
119+
120+
let disabledRoute = {
121+
method: 'get',
122+
path: '/disabled',
123+
handler: function*() {
124+
this.body = yield appsDb.find({ disabled: true });
125+
}
126+
}
127+
128+
let subscribeRoute = {
129+
method: 'post',
130+
path: '/subscribe',
131+
validate: { type: 'json' },
132+
handler: [
133+
auth,
134+
function*() {
135+
let createStripeCustomer = (customer) => function get_thunked_lol(cb) {
136+
return stripe.customers.create(customer, cb)
137+
}
138+
139+
var params = this.request.body;
140+
var app = params.app;
141+
var stripeToken = params.tok;
142+
var customer = yield createStripeCustomer({
143+
source: stripeToken,
144+
plan: "web_application",
145+
email: this.state.user.email
146+
});
147+
148+
console.log('Stripe Customer', stripeCustomer);
149+
150+
this.assert(customer, 500, 'Stripe api call failed');
151+
152+
this.body = { customer: customer.id };
153+
154+
var inserted = yield stripeDb.insert(customer);
155+
console.log(inserted);
156+
}
157+
]
158+
}
159+
160+
161+
162+
163+
let app = koa();
164+
165+
app.use(json());
166+
// app.use(jsonBody({ limit: '10kb' }));
167+
app.use(errors);
168+
app.use(staticFiles);
169+
170+
let noAuth = router();
171+
noAuth.route(loginRoute);
172+
noAuth.route(registerRoute);
173+
noAuth.route(appsRoute);
174+
noAuth.route(disabledRoute);
175+
app.use(noAuth.middleware());
176+
177+
let user = router();
178+
user.route(subscribeRoute);
179+
app.use(user.middleware());
180+
181+
/* You Shall Not Pass! */
182+
// AUTH AUTH AUTH AUTH AUTH |UTH AUTH AUTH AUT| AUTH AUTH AUTH AUTH AUTH
183+
// AUTH AUTH AUTH AUTH AUTH |UTH AUTH AUTH AUT| AUTH AUTH AUTH AUTH AUTH
184+
185+
app.use(auth);
186+
187+
console.log(`Listening on port ${PORT}`);
188+
app.listen(PORT);

test.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
3+
BASE=localhost:1999
4+
5+
6+
apps=`curl -s \
7+
-H "Content-Type: application/json" \
8+
localhost:1999/apps`
9+
echo 'Apps:'
10+
iojs -e "console.log($apps.map(function(v){ return v.name } ).join(', '))"
11+
echo
12+
13+
disabled=`curl -s \
14+
-H "Content-Type: application/json" \
15+
localhost:1999/disabled`
16+
echo 'Disabled Apps:'
17+
iojs -e "console.log($disabled.map(function(v){ return v.name } ).join(', '))"
18+
echo
19+
20+
curl -i \
21+
-H "Content-Type: application/json" \
22+
-d '{
23+
"email": "'$(date +%s)'@klouds.io",
24+
"password": "TEST123"
25+
}' \
26+
http://localhost:1999/register \
27+
http://localhost:1999/login
28+
29+
30+
# echo -n -e "\nPOST /login: \t--\t"
31+
# curl --silent -i localhost:1999/login \
32+
33+
# -d password=test \
34+
# --header "Content-Type:application/json"
35+
# # | head -1
36+
#
37+
# echo -n -e "\nGET /subscribe: \t--\t"
38+
# curl --silent -i localhost:1999/subscribe\
39+
# | head -1

0 commit comments

Comments
 (0)