diff --git a/.gitignore b/.gitignore
index f4e3dcc..fb280fe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@ lib-cov
*.pid
*.gz
+db
pids
logs
results
diff --git a/config.js b/config.js
new file mode 100644
index 0000000..662be52
--- /dev/null
+++ b/config.js
@@ -0,0 +1,16 @@
+var join = require('path').join
+ , name = 'squatconf'
+ , cwd = process.cwd()
+
+module.exports = require('rc')(name, {
+ db_opts: { valueEncoding: 'json' }
+ , db_path: join(cwd, 'db', name)
+ , port: 8000
+ , host: "squatconf.eu"
+ , email: {
+ from : "no-reply@squatconf.eu"
+ , subject : "Hello, everyone is welcome at SquatConf.."
+ , bodyText : "Please verify that you wish to signup by following this link\n%link%\nYou can ignore this message if you DID NOT request to signup at our website\nhttp://squatconf.eu\n\nThe next event is in Paris, we hope to see you there !!\n\nKind regards from the team,\nSquatConf Paris 2014"
+ }
+})
+
diff --git a/config.json b/config.json
deleted file mode 100644
index 5f8ced6..0000000
--- a/config.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "db": {
- "path": ""
- },
-
- "email": {
- "from" : "no-reply@squatconf.eu"
- , "subject" : "Hello, everyone is welcome at SquatConf.."
- , "bodyText": "Please verify that you wish to signup by following this link\n%link%\nYou can ignore this message if you DID NOT request to signup at our website\nhttp://squatconf.eu\n\nThe next event is in Paris, we hope to see you there !!\n\nKind regards from the team,\nSquatConf Paris 2014"
-
- }
-}
-
diff --git a/html/verified.html b/html/verified.html
new file mode 100644
index 0000000..1af7948
--- /dev/null
+++ b/html/verified.html
@@ -0,0 +1,77 @@
+
+
+
+
+ SquatConf.386
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
You're verified
+
+
Thanks for completing our signup process
+
+
Go back
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
index aee6ee8..2aee1ff 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,11 @@
{
"name": "squatconf-web",
- "version": "0.3.0",
+ "version": "0.4.0",
"description": "website for the squatConf conference",
"main": "server.js",
"scripts": {
"start": "echo -n 'building.. '; npm run build && node server.js",
- "build": "browserify src/email.js -o html/assets/js/email.js",
+ "build": "browserify src/email-client.js -o html/assets/js/email.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
@@ -25,7 +25,13 @@
"dependencies": {
"browserify": "^5.11.2",
"domready": "^1.0.7",
+ "level": "^0.18.0",
+ "ecstatic": "^0.5.4",
"nodemailer": "^1.3.0",
- "valid-email": "0.0.1"
+ "rc": "^0.5.1",
+ "stack": "^0.1.0",
+ "tiny-route": "^2.1.1",
+ "valid-email": "0.0.1",
+ "xss-escape": "0.0.5"
}
}
diff --git a/server.js b/server.js
index b20f6dd..425747a 100644
--- a/server.js
+++ b/server.js
@@ -1,72 +1,37 @@
#!/usr/bin/env node
-var nodemailer = require('nodemailer')
- , transporter = nodemailer.createTransport()
- , server = require('http').createServer(handler)
- , email = require('./config.json').email
- , rn = require('./src/rng')
- , fs = require('fs')
- , re = new RegExp('\.js$', 'i')
- , port = process.env.PORT || /*80*/ 8000
-
-function handler(req, res) {
-
- // process incoming requests.
- if (req.url == '/') req.url = '/index.html'
- else if (re.test(req.url))
- res.setHeader('Content-Type', 'application/javascript')
-
- if (/^\/confirm\?/.test(req.url)) {
-
- // @TODO
- // compare submitted token with the token stored in our database.
-
- res.statusCode = 302
- res.setHeader('Location', '/')
- return res.end()
- }
-
- if (/^\/email\?/.test(req.url)) {
- var params = require('url').parse(req.url, true)
- if (params && params.query.email) {
-
- /*
- var to_addr = params.query.email // @NOTE:
- // Q: do we trust the user input ?
- // A: FUCK NO !!
- , url = 'http://squatconf.eu/confirm'
- , link = url +'?email='+ to_addr +'&token='+ rn() +'\n\n'
-
- var opts = {
- from : email.from
- , to : to_addr
- , subject: email.subject
- , text : email.bodyText.replace(/\%link\%/, link)
- }
-
- transporter.sendMail(opts, function(err, data) {
- if (err) return console.error('email problem !', err)
- console.log('email sent', data)
- })
- */
-
- console.log(' got email:', params.query)
- }
- res.statusCode = 302
- res.setHeader('Location', '/')
- return res.end()
- }
-
- // serve static assets
- var rs = fs.createReadStream(__dirname +'/html'+ req.url)
- rs.pipe(res)
-}
+var fs = require('fs')
+ , http = require('http')
+ , stack = require('stack')
+ , route = require('tiny-route')
+ , assets = require('ecstatic')
+ , join = require('path').join
+ , config = require('./config')
+ , db = require('level')(config.db_path, config.db_opts)
+ , port = process.env.PORT || config.port
+
+// create the level db folder if it does not exists
+if(!fs.existsSync('./db/squatconf')){
+ fs.mkdirSync('./db/squatconf', 0766, function(err){
+ if(err){
+ console.log(err);
+ }
+ });
+ }
+
+var app = stack(
+ route('/email', require('./src/email-submit')(db))
+ , route('/confirm', require('./src/email-confirm')(db))
+ , assets(join(__dirname, 'html'))
+)
process.on('uncaughtException', function (err) {
console.error('Error at:', new Date)
console.error(err.stack)
})
-server.listen(port)
-console.error('['+ process.pid +'] server started on port '+ port)
-console.error('(use ctrl+c to stop server)')
+http.createServer(app).listen(port, function() {
+ console.log('['+ process.pid +'] server started on port '+ port)
+ console.log('(use Ctrl+c to stop the server)')
+})
+
diff --git a/src/email.js b/src/email-client.js
similarity index 100%
rename from src/email.js
rename to src/email-client.js
diff --git a/src/email-confirm.js b/src/email-confirm.js
new file mode 100644
index 0000000..a2e5df9
--- /dev/null
+++ b/src/email-confirm.js
@@ -0,0 +1,39 @@
+var sanitize = require('xss-escape')
+ , ip = require('./ip-trace')
+
+module.exports = function(db) {
+ return function (req, res, next) {
+ req.resume()
+
+ var params = require('url').parse(req.url, true)
+
+ if (params && params.query.email && params.query.token) {
+ //console.log('got token:', params.query)
+
+ var email = sanitize(params.query.email)
+ , token = sanitize(params.query.token)
+
+ db.get(email, function(err, obj) {
+ if (err) next(err)
+
+ // db read OK..
+ if (obj && obj.token === token) {
+ obj.verified = true
+ obj.trace = obj.trace.concat(ip(req))
+
+ db.put(email, obj, function(err) {
+ if (err) next(err)
+
+ // db write OK..
+ res.statusCode = 302
+ res.setHeader('Location', '/verified.html')
+ return res.end()
+ })
+ }
+ })
+
+ if (next) return next()
+ }
+ }
+}
+
diff --git a/src/email-submit.js b/src/email-submit.js
new file mode 100644
index 0000000..4b45b69
--- /dev/null
+++ b/src/email-submit.js
@@ -0,0 +1,54 @@
+var sanitize = require('xss-escape')
+ , rn = require('./rng')
+ , ip = require('./ip-trace')
+ , config = require('../config')
+
+module.exports = function(db) {
+ return function (req, res, next) {
+ req.resume()
+
+ var params = require('url').parse(req.url, true)
+
+ if (params && params.query.email) {
+ console.log('got email:', params.query)
+
+ var obj = {}
+ , email = sanitize(params.query.email)
+
+ obj.token = rn()
+ obj.verified = false
+ obj.events = { paris: params.query.paris ? true : false }
+ obj.trace = ip(req)
+
+ db.put(email, obj, function(err) {
+ if (err) next(err)
+
+ // db write OK..
+ var nodemailer = require('nodemailer')
+ , transporter = nodemailer.createTransport()
+ , url = 'http://squatconf.eu/confirm'
+ , link = url +'?email='+ email +'&token='+ obj.token +'\n\n'
+
+ var opts = {
+ from : config.email.from
+ , to : email
+ , subject: config.email.subject
+ , text : config.email.bodyText.replace(/\%link\%/, link)
+ }
+
+ transporter.sendMail(opts, function(err, data) {
+ if (err) throw err
+ // validation email sent
+ console.log('email sent..', data)
+ })
+
+ res.statusCode = 302
+ res.setHeader('Location', '/')
+ return res.end()
+ })
+ }
+
+ if (next) return next()
+ }
+}
+
diff --git a/src/ip-trace.js b/src/ip-trace.js
new file mode 100644
index 0000000..f34bbe0
--- /dev/null
+++ b/src/ip-trace.js
@@ -0,0 +1,8 @@
+module.exports = function(req) {
+ if (req.headers['x-forwarded-for']) {
+ return req.headers['x-forwarded-for'].split(',')
+ } else {
+ return [ req.connection.remoteAddress ]
+ }
+}
+