Modularizes API.

Project: http://git-wip-us.apache.org/repos/asf/rave/repo
Commit: http://git-wip-us.apache.org/repos/asf/rave/commit/fa312487
Tree: http://git-wip-us.apache.org/repos/asf/rave/tree/fa312487
Diff: http://git-wip-us.apache.org/repos/asf/rave/diff/fa312487

Branch: refs/heads/angular
Commit: fa31248756c8b43dc796310404e27d6d331cbde5
Parents: 20b522c
Author: Jmeas <[email protected]>
Authored: Mon Aug 18 15:01:10 2014 -0400
Committer: Jmeas <[email protected]>
Committed: Mon Aug 18 15:18:25 2014 -0400

----------------------------------------------------------------------
 .jshintrc-mock-api                              |  1 -
 rave-portal-ng/mock-api/bootstrap.js            |  3 +-
 rave-portal-ng/mock-api/core.js                 | 37 ++++++++
 .../mock-api/modules/preferences/db.js          | 52 ++++++++++++
 .../mock-api/modules/preferences/endpoint.js    | 28 +++++++
 .../mock-api/modules/preferences/get.js         | 32 -------
 .../mock-api/modules/preferences/index.js       | 14 ++++
 .../mock-api/modules/preferences/put.js         | 56 -------------
 rave-portal-ng/mock-api/modules/user/db.js      | 54 ++++++++++++
 rave-portal-ng/mock-api/util/endpoint.js        | 88 ++++++++++++++++++++
 rave-portal-ng/mock-api/util/error-response.js  | 15 ++++
 rave-portal-ng/mock-api/util/params.js          | 37 ++++++++
 rave-portal-ng/mock-api/util/token-util.js      | 30 +++++++
 13 files changed, 356 insertions(+), 91 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/.jshintrc-mock-api
----------------------------------------------------------------------
diff --git a/.jshintrc-mock-api b/.jshintrc-mock-api
index 754b84c..499a280 100644
--- a/.jshintrc-mock-api
+++ b/.jshintrc-mock-api
@@ -29,7 +29,6 @@
   "unused"        : "vars",
   "strict"        : false,
   "trailing"      : true,
-  "maxparams"     : 4,
   "maxdepth"      : 2,
 
   "asi"           : false,

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/bootstrap.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/bootstrap.js 
b/rave-portal-ng/mock-api/bootstrap.js
index 71e344b..92db321 100644
--- a/rave-portal-ng/mock-api/bootstrap.js
+++ b/rave-portal-ng/mock-api/bootstrap.js
@@ -37,8 +37,7 @@ define(function(require) {
        require('./modules/category/delete.js');
 
        // preferences
-       require('./modules/preferences/get.js');
-       require('./modules/preferences/put.js');
+       require('./modules/preferences/index');
 
        // users
        require('./modules/users/get.js');

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/core.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/core.js b/rave-portal-ng/mock-api/core.js
index 780c32d..f782a7c 100644
--- a/rave-portal-ng/mock-api/core.js
+++ b/rave-portal-ng/mock-api/core.js
@@ -145,6 +145,42 @@ define(function(require) {
                return true;
        }
 
+       // Parse an endpoint for registration with the mock API. Eventually,
+       // this should be the only thing that's in the core.
+       function registerEndpoint(endpoint) {
+
+               // Get our callback and url from the endpoint
+               var callback = endpoint.callback;
+               var url = endpoint.url;
+
+               // The endpoint methods that we will register
+               var methods = ['get', 'put', 'post', 'delete'];
+
+               // Register each method
+               _.each(methods, function(method) {
+                       if (endpoint[method]) {
+                               registerEndpointCallback(endpoint, url, method, 
callback);
+                       }
+               });
+       }
+
+       // Once the endpoint has been parsed, we actually make the registration 
here
+       function registerEndpointCallback(endpoint, route, method, callback) {
+               if (!registeredApiMethods.hasOwnProperty(route)) {
+                       registeredApiMethods[route] = {
+                               pattern: convertRouteToRegex(baseApiUrl+route),
+                               methods: {}
+                       };
+               }
+
+               // Bind the callback to the endpoint
+               var moddedCallback = function(method, url, data, headers) {
+                       return callback.bind(endpoint)(method, url, data, 
headers);
+               };
+
+               registeredApiMethods[route].methods[method.toUpperCase()] = 
moddedCallback;
+       }
+
        function setSessionStorage(key, value) {
                try {
                        value = JSON.stringify(value);
@@ -171,6 +207,7 @@ define(function(require) {
        return {
                initialize: initializeApiModule,
                register: registerApiMethod,
+               registerEndpoint: registerEndpoint,
                db: database,
                session: {
                        set: setSessionStorage,

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/modules/preferences/db.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/preferences/db.js 
b/rave-portal-ng/mock-api/modules/preferences/db.js
new file mode 100644
index 0000000..9d26997
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/preferences/db.js
@@ -0,0 +1,52 @@
+/*
+ * db
+ * Methods for getting and setting preferences data. Anytime
+ * you need to hit the DB in reference to preferences it should
+ * go through this file.
+ *
+ */
+
+define(function(require) {
+  var api = require('../../core.js');
+
+  var prefsDb = {
+
+    // Retrieve all of your preferences from the database.
+    // Although they're stored in the DB an array of objects with two
+    // properties each, key and value, this method transforms that data into 
an object.
+    get: function() {
+      var results = api.db.query('preferences');
+      var preferences = {};
+
+      _.each(results, function(item) {
+        preferences[item.key] = item.value;
+      });
+
+      return preferences;
+    },
+
+    // Update the data in the database
+    put: function(data) {
+      var searchParams;
+
+      // Loop through each value, updating it in the database
+      _.each(data, function(value, key) {
+        searchParams = {
+          key: key
+        };
+        api.db.update('preferences', searchParams, function(row) {
+          row.value = value;
+          return row;
+        });
+      });
+
+      // Save our data
+      api.db.commit();
+
+      // Lastly, return the updated data
+      return prefsDb.get();
+    }
+  };
+
+  return prefsDb;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/modules/preferences/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/preferences/endpoint.js 
b/rave-portal-ng/mock-api/modules/preferences/endpoint.js
new file mode 100644
index 0000000..3696557
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/preferences/endpoint.js
@@ -0,0 +1,28 @@
+/*
+ * endpoint
+ * The actual endpoint for preferences
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../util/endpoint');
+  var prefsDb = require('./db');
+
+  var endpoint = new Endpoint({
+
+    url: '/preferences',
+
+    // Our get endpoint. All that it does is return our
+    // of preferences as a simple object.
+    get: function(url, data, headers, params, currentUser) {
+      return [200, prefsDb.get()];
+    },
+
+    // Puts our data into the database.
+    put: function(url, data, headers, params, currentUser) {
+      return [200, prefsDb.put(data)];
+    }
+  });
+
+  return endpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/modules/preferences/get.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/preferences/get.js 
b/rave-portal-ng/mock-api/modules/preferences/get.js
deleted file mode 100644
index 4928b37..0000000
--- a/rave-portal-ng/mock-api/modules/preferences/get.js
+++ /dev/null
@@ -1,32 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../core.js');
-       require('underscore/underscore');
-
-       function getPreferences() {
-               var results = api.db.query('preferences');
-               var preferences = {};
-
-               _.each(results, function(item) {
-                       preferences[item.key] = item.value;
-               });
-
-               return preferences;
-       }
-
-       function processRequest(method, url, data, headers) {
-               if (method !== 'GET') {
-                       return [405, 'Unknown request'];
-               } else if (!this.requestHasToken) {
-                       return [401, 'A valid token is required'];
-               } else if (!this.userIsAuthenticated) {
-                       return [401, 'Invalid token'];
-               }
-
-               return [200, getPreferences()];
-       }
-
-       api.register('/preferences', 'get', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/modules/preferences/index.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/preferences/index.js 
b/rave-portal-ng/mock-api/modules/preferences/index.js
new file mode 100644
index 0000000..58544ac
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/preferences/index.js
@@ -0,0 +1,14 @@
+/*
+ * preferences
+ * Sets up the preferences section of the API. This includes two things:
+ * the actual endpoints and methods for retrieving data
+ *
+ */
+
+define(function(require) {
+  var api = require('../../core.js');
+
+  // Register our endpoints
+  var endpoint = require('./endpoint');
+  api.registerEndpoint(endpoint);
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/modules/preferences/put.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/preferences/put.js 
b/rave-portal-ng/mock-api/modules/preferences/put.js
deleted file mode 100644
index 845a894..0000000
--- a/rave-portal-ng/mock-api/modules/preferences/put.js
+++ /dev/null
@@ -1,56 +0,0 @@
-define(function(require) {
-  'use strict';
-
-  var api = require('../../core.js');
-  require('underscore/underscore');
-
-  function updatePreferences(data) {
-    var searchParams;
-
-    // Loop through each data point, updating the corresponding preference
-    // in the database.
-    _.each(data, function(value, key) {
-      searchParams = {
-        key: key
-      };
-      api.db.update('preferences', searchParams, function(row) {
-        row.value = value;
-        return row;
-      });
-    });
-    api.db.commit();
-
-    // This is exactly what we do in the GET method. We might
-    // want to DRY this up, but it's a mock API so no big deal.
-    var results = api.db.query('preferences');
-    var preferences = {};
-
-    _.each(results, function(item) {
-      preferences[item.key] = item.value;
-    });
-
-    return preferences;
-  }
-
-  function processRequest(method, url, data, headers) {
-    if (method !== 'PUT') {
-      return [405, 'Unknown request'];
-    } else if (!this.requestHasToken) {
-      return [401, 'A valid token is required'];
-    } else if (!this.userIsAuthenticated) {
-      return [401, 'Invalid token'];
-    }
-
-    data = angular.fromJson(data);
-
-    var updatedPreferences = updatePreferences(data);
-    if (!updatedPreferences) {
-      return [500, 'An internal database error has occurred'];
-    }
-
-    return [200, updatedPreferences];
-  }
-  
-  api.register('/preferences', 'put', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/modules/user/db.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/user/db.js 
b/rave-portal-ng/mock-api/modules/user/db.js
new file mode 100644
index 0000000..3dd351f
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/user/db.js
@@ -0,0 +1,54 @@
+/*
+ * db
+ * Methods for getting and setting users.
+ *
+ */
+
+define(function(require) {
+  var api = require('../../core.js');
+
+  // The whitelisted keys that we send back with our request for the users
+  var userKeys = [
+    'ID',
+    'username',
+    'description',
+    'firstName',
+    'lastName',
+    'locked',
+    'enabled',
+    'expired',
+    'authorities',
+    'openIdUrl',
+    'email'
+  ];
+
+  var userDb = {
+
+    // Retrieve the user by an identifier
+    get: function(identifier, filter) {
+
+      // Whether or not we want to filter the user's data.
+      // Filtering removes data we wouldn't want to send back,
+      // like passwords and tokens. Filtering is true by default
+      if (typeof filter === 'undefined') {
+        filter = true;
+      }
+
+      var results = api.db.query('users', identifier);
+
+      var user = results[0];
+
+      // If we don't have a user, then we return false
+      if (!user || results.length > 1) {
+        return false;
+      }
+
+      // If we want to filter, then do it
+      user = filter ? _.pick(user, userKeys) : user;
+
+      return user;
+    }
+  };
+
+  return userDb;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/util/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/util/endpoint.js 
b/rave-portal-ng/mock-api/util/endpoint.js
new file mode 100644
index 0000000..9792164
--- /dev/null
+++ b/rave-portal-ng/mock-api/util/endpoint.js
@@ -0,0 +1,88 @@
+/*
+ * endpoint
+ * Defines a RESTful endpoint
+ *
+ */
+
+define(function(require) {
+  var _ = require('underscore');
+  var paramsFromUrl = require('./params');
+  var ErrorResponse = require('./error-response');
+  var tokenUtil = require('./token-util');
+  var userDb = require('../modules/user/db');
+
+  // These are the valid options that you can pass into
+  // a new endpoint
+  var endpointOptions = [
+    'url',
+    'authorize',
+    'get',
+    'post',
+    'delete',
+    'put'
+  ];
+
+  var Endpoint = function(options) {
+
+    // Merge valid options directly into the endpoint
+    _.extend(this, _.pick(options, endpointOptions));
+  };
+
+  _.extend(Endpoint.prototype, {
+
+    // By default, all requests are 
+    authorize: true,
+
+    // What is ultimately returned from the endpoint.
+    callback: function(method, url, data, headers) {
+
+      // Our current user, if there is one.
+      var currentUser;
+
+      // The first thing we need to check for every endpoint is if we want to 
authorize or not
+      if (this.authorize) {
+
+        // Attempt to get our token from the headers
+        var token = tokenUtil.tokenFromHeaders(headers);
+
+        // If it doesn't exist, then we throw an error
+        if (!token) {
+          return new ErrorResponse(401, 'A valid token is required.');
+        }
+
+        // Otherwise, we try to get the user from the token
+        var user = userDb.get({
+          sessionToken: token
+        });
+
+        // Again, throw an error if there's no user
+        if (!user) {
+          return new ErrorResponse(401, 'Invalid token.');
+        }
+
+        // Otherwise, we set our currentUser as the user.
+        currentUser = user;
+      }
+
+      // Get our query parameters from the url
+      var params = paramsFromUrl(url);
+
+      // Ensure that our method is lowercase
+      method = method.toLowerCase();
+
+      var callback = this[method];
+
+      // If we have the associated method, then we call it
+      if (_.isFunction(callback)) {
+        return callback(url, data, headers, params, currentUser);
+      }
+
+      // Otherwise, this is an unhandled request.
+      else {
+        return new ErrorResponse(405, 'Unknown request');
+      }
+    }
+  });
+
+  return Endpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/util/error-response.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/util/error-response.js 
b/rave-portal-ng/mock-api/util/error-response.js
new file mode 100644
index 0000000..be1407b
--- /dev/null
+++ b/rave-portal-ng/mock-api/util/error-response.js
@@ -0,0 +1,15 @@
+/*
+ * error
+ * A convenience class to generate a JSON error.
+ *
+ */
+
+define(function(require) {
+  var ErrorResponse = function(code, msg) {
+    return [code, {
+      message: msg
+    }];
+  };
+
+  return ErrorResponse;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/util/params.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/util/params.js 
b/rave-portal-ng/mock-api/util/params.js
new file mode 100644
index 0000000..2c0cbd9
--- /dev/null
+++ b/rave-portal-ng/mock-api/util/params.js
@@ -0,0 +1,37 @@
+/*
+ * params
+ * A function to generate the query parameters from a URL
+ *
+ */
+
+define(function(require) {
+
+  // Pass in the URL; get back your parameters.
+  return function(str) {
+    str = str.split('?')[1];
+    if(typeof str !== 'string' || str.length === 0) {
+      return {};
+    }
+    var s = str.split('&');
+    var sLength = s.length;
+    var bit, query = {}, first, second;
+    for (var i = 0; i < sLength; i++) {
+      bit = s[i].split('=');
+      first = decodeURIComponent(bit[0]);
+      if(first.length === 0) {
+        continue;
+      }
+      second = decodeURIComponent(bit[1]);
+      if(typeof query[first] === 'undefined') {
+        query[first] = second;
+      }
+      else if(query[first] instanceof Array) {
+        query[first].push(second);
+      }
+      else {
+        query[first] = [query[first], second];
+      }
+    }
+    return query;
+  };
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/fa312487/rave-portal-ng/mock-api/util/token-util.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/util/token-util.js 
b/rave-portal-ng/mock-api/util/token-util.js
new file mode 100644
index 0000000..12dcdbb
--- /dev/null
+++ b/rave-portal-ng/mock-api/util/token-util.js
@@ -0,0 +1,30 @@
+/*
+ * tokenUtil
+ * Utility methods for working with tokens.
+ * Eventually we will also generate tokens in here.
+ *
+ *
+ */
+
+define(function(require) {
+
+  var tokenUtil = {
+
+    // Get the token from the headers. If it doesn't
+    // exist, or is invalid, then a value of false is returned
+    tokenFromHeaders: function(headers) {
+      if (!headers.Authorization) {
+        return false;
+      }
+
+      var token = headers.Authorization.replace('Basic ', '');
+      if (token.length !== 32) {
+        return false;
+      }
+
+      return token;
+    }
+  };
+
+  return tokenUtil;
+});

Reply via email to