Skip to content
Browse files

Add express storage functionality

  • Loading branch information...
1 parent 4081548 commit 1773f275b4759d7d163099006676fc09561c7abb Sebastian Kippe committed Feb 21, 2012
Showing with 294 additions and 5 deletions.
  1. +7 −0 config.js
  2. +143 −4 lib/express-storage.js
  3. +34 −0 lib/webfinger.js
  4. +82 −1 server.js
  5. +28 −0 views/oauth.jade
View
7 config.js
@@ -0,0 +1,7 @@
+exports.config = {
+ redisPort: 6379,
+ redisHost: 'localhost',
+ redisPwd: '',
+ origin: 'http://localhost',
+ port: 80
+};
View
147 lib/express-storage.js
@@ -2,10 +2,149 @@
* express-storage
* https://github.com/5apps/express-storage
*
- * Copyright (c) 2012 Sebastian Kippe, Garret Alfert
+ * Copyright (c) 2012 Michiel De Jong, Sebastian Kippe, Garret Alfert
* Licensed under the MIT license.
*/
-exports.awesome = function() {
- return 'awesome';
-};
+exports.storage = (function() {
+ var config = require('../config').config;
+ var redis = require('redis');
+ var redisClient;
+
+ function initRedis(callback) {
+ redisClient = redis.createClient(config.redisPort, config.redisHost);
+ redisClient.on("error", function (err) {
+ console.log("error event - " + redisClient.host + ":" + redisClient.port + " - " + err);
+ });
+ if (config.redisPwd == "") {
+ callback();
+ }
+ else {
+ redisClient.auth(config.redisPwd, function() {
+ callback();
+ });
+ }
+ }
+
+ function checkToken(userId, token, category, method, callback) {
+ if (category == 'public' && method == 'GET') {
+ console.log('public GET access ok');
+ callback(true);
+ } else {
+ console.log('looking for "'+category+'" in key "token:'+userId+':'+token+'"');
+
+ redisClient.get('token:'+userId+':'+token, function(err, categoriesStr) {
+ var categories;
+ try {
+ categories = JSON.parse(categoriesStr);
+ } catch(e) {
+ console.log('5-0');
+ callback(false);
+ return;
+ }
+
+ console.log('For user "'+userId+'", token "'+token+'", wanting "'+category+'", found categories: '+JSON.stringify(categories));
+
+ var i;
+ for(i in categories) {
+ console.log('considering '+categories[i]);
+ if(categories[i] == category) {
+ callback(true);
+ return;
+ }
+ }
+
+ console.log('sorry');
+ callback(false);
+ });
+ }
+ }
+
+ function doReq(reqObj, callback) {
+ initRedis(function(){
+ checkToken(reqObj.userId, reqObj.token, reqObj.category, reqObj.method, function(result) {
+ if (result) {
+ if (reqObj.method=='GET') {
+ console.log('it\'s a GET');
+ redisClient.get('value:'+reqObj.userId+':'+reqObj.category+':'+reqObj.key, function(err, value) {
+ console.log('redis says:');console.log(err);console.log(value);
+ redisClient.quit();
+ callback(200, value);
+ });
+ } else if (reqObj.method=='PUT') {
+ console.log('it\'s a PUT');
+ redisClient.set('value:'+reqObj.userId+':'+reqObj.category+':'+reqObj.key, reqObj.value, function(err, data) {
+ console.log('redis says:');console.log(err);console.log(data);
+ redisClient.quit();
+ callback(200);
+ });
+ } else if (reqObj.method=='DELETE') {
+ console.log('it\'s a DELETE');
+ redisClient.del('value:'+reqObj.userId+':'+reqObj.category+':'+reqObj.key, function(err, data) {
+ console.log('redis says:');console.log(err);console.log(data);
+ redisClient.quit();
+ callback(200);
+ });
+ }
+ } else {
+ redisClient.quit();
+ callback(403);
+ }
+ });
+ });
+ }
+
+ function addToken(userId, token, categories, callback) {
+ initRedis(function(){
+ console.log('created token "'+token+'" for user "'+userId+'", categories: '+JSON.stringify(categories));
+ redisClient.set('token:'+userId+':'+token, JSON.stringify(categories), function(err, data) {
+ redisClient.quit();
+ callback();
+ });
+ });
+ }
+
+ function removeToken(userId, token, callback) {
+ initRedis(function(){
+ console.log('removed token "'+token+'" for user "'+userId+'", categories: '+JSON.stringify(categories));
+ redisClient.del('token:'+userId+':'+token, function(err, data) {
+ redisClient.quit();
+ callback();
+ });
+ });
+ }
+
+ function addUser(userId, password, callback) {
+ initRedis(function(){
+ redisClient.set('user:'+userId, password, function(err, data) {
+ redisClient.quit();
+ callback();
+ });
+ });
+ }
+
+ function createToken(userId, password, token, categories, callback) {
+ console.log(userId+' - '+password+' - '+token+' - '+JSON.stringify(categories));
+ initRedis(function(){
+ redisClient.get('user:'+userId, function(err, data) {
+ if(data == password) {
+ console.log('creating token "'+token+'" for user "'+userId+'", categories: '+JSON.stringify(categories));
+ redisClient.set('token:'+userId+':'+token, JSON.stringify(categories), function(err, data) {
+ redisClient.quit();
+ callback(true);
+ });
+ } else {
+ redisClient.quit();
+ callback(false);
+ }
+ });
+ });
+ }
+
+ return {
+ addToken: addToken,
+ removeToken: removeToken,
+ addUser: addUser,
+ createToken: createToken
+ };
+})();
View
34 lib/webfinger.js
@@ -0,0 +1,34 @@
+exports.webfinger = (function() {
+
+ function genHostMeta(baseUrl) {
+ return '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n'
+ +'<XRD xmlns=\'http://docs.oasis-open.org/ns/xri/xrd-1.0\'\n'
+ +' xmlns:hm=\'http://host-meta.net/xrd/1.0\'>\n'
+ +' <hm:Host></hm:Host>\n'
+ +' <Link rel=\'lrdd\'\n'
+ +' template=\''+baseUrl+'/webfinger/{uri}\'>\n'
+ +' <Title>Resource Descriptor</Title>\n'
+ +' </Link>\n'
+ +'</XRD>\n';
+ }
+
+ function genWebfinger(api, authUrl, template) {
+ return '<?xml version=\'1.0\' encoding=\'UTF-8\'?>\n'
+ +'<XRD xmlns=\'http://docs.oasis-open.org/ns/xri/xrd-1.0\'\n'
+ +' xmlns:hm=\'http://host-meta.net/xrd/1.0\'>\n'
+ +' <hm:Host></hm:Host>\n'
+ +' <Link rel=\'remoteStorage\'\n'
+ +' api=\''+api+'\'\n'
+ +' auth=\''+authUrl+'\'\n'
+ +' template=\''+template+'\'>\n'
+ +' <Title>Resource Descriptor</Title>\n'
+ +' </Link>\n'
+ +'</XRD>\n';
+ }
+
+ return {
+ genHostMeta: genHostMeta,
+ genWebfinger: genWebfinger
+ };
+
+})();
View
83 server.js
@@ -1,8 +1,11 @@
// Module dependencies
var express = require('express');
-var sys = require('sys');
+var util = require('util');
var _ = require('./lib/vendor/underscore.js')._;
+var config = require('./config.js').config;
+var webfinger = require('./lib/webfinger.js').webfinger;
+var storage = require('./lib/express-storage.js').storage;
var app = module.exports = express.createServer();
@@ -35,7 +38,85 @@ app.get('/', function(req, res){
});
});
+app.get('/.well-known', function(req, res){
+ res.header('Access-Control-Allow-Origin', '*')
+ res.header('Content-Type', 'application/xrd+xml');
+ res.send(webfinger.genHostMeta(config.origin));
+});
+
+app.get(/^\/webfinger\/acct:(?:(.+))/, function(req, res){
+ var userId = req.params[0];
+ config.api = 'simple';
+ config.authUrl = config.origin+'/_oauth/'+userId;
+ config.template = config.origin+'/'+userId+'/{category}/';
+
+ res.header('Access-Control-Allow-Origin', '*')
+ res.header('Content-Type', 'application/xrd+xml');
+ res.send(webfinger.genWebfinger(config.api, config.authUrl, config.template));
+});
+
+app.get('/_oauth/:user', function(req, res){
+ var userId = req.params.user;
+
+ res.render('oauth', {
+ userId: userId,
+ redirectUri: req.param('redirect_uri'),
+ scope: req.param('scope', 'public')
+ });
+});
+
+app.post(/^\/_oauth\/(?:(.+))/, function(req, res){
+ var token = "yo-ho"; //TODO generate proper token
+
+ storage.createToken(req.param('userId'), req.param('password'), token, req.param('categories'), function(result) {
+ if(result) {
+ res.redirect(redirectUri+'#access_token='+token);
+ } else {
+ res.send("No, bro.", 401);
+ }
+ });
+});
+
+app.options('*', function(req, res){
+ res.header('Access-Control-Allow-Origin', req.headers.origin);
+ res.header('Access-Control-Allow-Methods', 'GET, PUT, DELETE');
+ res.header('Access-Control-Allow-Headers', 'Origin, Content-Type, Authorization');
+ res.end();
+});
+
+app.all('/:user/:category/:key', function(req, res){
+ res.header('Access-Control-Allow-Origin', req.headers.origin);
+ res.header('Access-Control-Allow-Methods', 'GET, PUT, DELETE');
+ res.header('Access-Control-Allow-Headers', 'Origin, Content-Type, Authorization');
+
+ try {
+ auth_header = req.header('authorization', 'Bearer ');
+
+ reqObj = {
+ method: req.method,
+ token: auth_header.substring('Bearer '.length),
+ userId: req.params.user,
+ category: req.params.category,
+ key: req.params.key,
+ value: req.body
+ };
+ console.log(reqObj);
+
+ doReq(reqObj, function(status_code, data) {
+ res.send(data, status_code);
+ });
+ }
+ catch (e) {
+ res.send(e, 500);
+ console.log(e);
+ }
+});
+
if (!module.parent) {
app.listen(4000);
console.log("Express server listening on port %d", app.address().port);
+
+ storage.addUser('jimmy@surf.unhosted.org', '12345678', function() {
+ console.log('created user jimmy@surf.unhosted.org with password 12345678');
+ });
}
View
28 views/oauth.jade
@@ -0,0 +1,28 @@
+!!! 5
+html(lang="en")
+ head
+ title OAuth
+ // link(href="/stylesheets/screen.css", media="screen, projection", rel="stylesheet", type="text/css")
+ body
+ #container
+ header
+ h1 Express Storage
+ h2 OAuth
+ #content
+
+ - if (redirectUri != undefined)
+ form(method="POST")
+ p
+ | UserId:
+ br
+ input(type="text", name="userId", value="#{userId}")
+ p
+ | Password:
+ br
+ input(type="password", name="password", value="")
+ input(type="hidden", name="redirectUri", value="#{redirectUri}")
+ input(type="hidden", name="scope", value="#{scope}")
+ input(type="submit", value="Allow")
+ - else
+ p
+ Please add ?redirect_uri=http://localhost/bla to the address

0 comments on commit 1773f27

Please sign in to comment.
Something went wrong with that request. Please try again.