Refactors API.

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

Branch: refs/heads/angular
Commit: 26240a1c3365a503f4cf05e288add85a563dca53
Parents: 6140f2d
Author: Jmeas <[email protected]>
Authored: Mon Aug 18 22:33:12 2014 -0400
Committer: Jmeas <[email protected]>
Committed: Wed Aug 20 08:30:42 2014 -0400

----------------------------------------------------------------------
 rave-portal-ng/mock-api/bootstrap-data.js       |   4 +-
 rave-portal-ng/mock-api/bootstrap.js            |  42 +++----
 rave-portal-ng/mock-api/core.js                 |  92 ---------------
 rave-portal-ng/mock-api/database/install.js     |   5 +-
 .../create-account/create-account-util.js       |  58 ++++++++++
 .../authentication/create-account/endpoint.js   |  56 +++++++++
 .../authentication/create-account/post.js       | 114 -------------------
 .../authentication/forgot-password/endpoint.js  |  37 ++++++
 .../authentication/forgot-password/post.js      |  36 ------
 .../authentication/forgot-username/endpoint.js  |  37 ++++++
 .../authentication/forgot-username/post.js      |  36 ------
 .../modules/authentication/login/endpoint.js    |  50 ++++++++
 .../modules/authentication/login/post.js        |  86 --------------
 .../modules/authentication/verify/endpoint.js   |  54 +++++++++
 .../modules/authentication/verify/post.js       |  60 ----------
 .../modules/categories/categories-util.js       |  44 +++++++
 .../mock-api/modules/categories/endpoint.js     |  47 ++++++++
 .../mock-api/modules/categories/get.js          |  21 ----
 .../mock-api/modules/categories/post.js         |  63 ----------
 .../mock-api/modules/category/category-util.js  |  53 +++++++++
 .../mock-api/modules/category/delete.js         |  50 --------
 .../mock-api/modules/category/endpoint.js       |  96 ++++++++++++++++
 rave-portal-ng/mock-api/modules/category/get.js |  44 -------
 rave-portal-ng/mock-api/modules/category/put.js |  77 -------------
 rave-portal-ng/mock-api/modules/pages/get.js    |  15 ---
 .../mock-api/modules/preferences/db.js          |  52 ---------
 .../mock-api/modules/preferences/endpoint.js    |   7 +-
 .../mock-api/modules/preferences/index.js       |  14 ---
 .../modules/preferences/preferences-util.js     |  63 ++++++++++
 .../mock-api/modules/status/endpoint.js         |  24 ++++
 rave-portal-ng/mock-api/modules/status/get.js   |  15 ---
 rave-portal-ng/mock-api/modules/user/db.js      |  54 ---------
 rave-portal-ng/mock-api/modules/user/delete.js  |  50 --------
 .../mock-api/modules/user/endpoint.js           |  96 ++++++++++++++++
 rave-portal-ng/mock-api/modules/user/get.js     |  59 ----------
 rave-portal-ng/mock-api/modules/user/put.js     |  93 ---------------
 .../mock-api/modules/user/user-util.js          |  91 +++++++++++++++
 .../mock-api/modules/users/endpoint.js          |  23 ++++
 rave-portal-ng/mock-api/modules/users/get.js    |  93 ---------------
 .../mock-api/modules/users/users-util.js        |  65 +++++++++++
 rave-portal-ng/mock-api/util/endpoint.js        |   9 +-
 rave-portal-ng/mock-api/util/token-util.js      |   9 ++
 rave-portal-ng/src/config/requirejs.js          |   3 +-
 .../admin/categories/controllers/category.js    |   4 +-
 .../admin/categories/controllers/create.js      |   2 +-
 .../subapps/admin/users/templates/users.html    |  12 +-
 .../controllers/create-account.js               |   2 +-
 47 files changed, 945 insertions(+), 1172 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/bootstrap-data.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/bootstrap-data.js 
b/rave-portal-ng/mock-api/bootstrap-data.js
index 6eafd9f..ec1ffb8 100644
--- a/rave-portal-ng/mock-api/bootstrap-data.js
+++ b/rave-portal-ng/mock-api/bootstrap-data.js
@@ -9,8 +9,8 @@
 
 define(function(require) {
 
-  var api = require('./core.js');
-  require('underscore/underscore');
+  var api = require('./core');
+  require('underscore');
 
   function getPreferences() {
     var results = api.db.query('preferences');

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/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 92db321..0c24cd8 100644
--- a/rave-portal-ng/mock-api/bootstrap.js
+++ b/rave-portal-ng/mock-api/bootstrap.js
@@ -6,50 +6,36 @@ define(function(require) {
 
        // setup the mocked database
        require('./database/install.js');
+       var api = require('./core');
 
-       // The core API
-       var api = require( './core.js');
-
-       // The decorator routes:
-       
        // auth/login
-       require('./modules/authentication/login/post.js');
+       
api.registerEndpoint(require('./modules/authentication/login/endpoint'));
 
        // auth/logout
-       require('./modules/authentication/verify/post.js');
+       
api.registerEndpoint(require('./modules/authentication/verify/endpoint'));
 
        // auth/forgot-password
-       require('./modules/authentication/forgot-password/post.js');
+       
api.registerEndpoint(require('./modules/authentication/forgot-password/endpoint'));
 
        // auth/forgot-username
-       require('./modules/authentication/forgot-username/post.js');
+       
api.registerEndpoint(require('./modules/authentication/forgot-username/endpoint'));
 
        // auth/create-account
-       require('./modules/authentication/create-account/post.js');
-
-       // categories
-       require('./modules/categories/get.js');
-       require('./modules/categories/post.js');
+       
api.registerEndpoint(require('./modules/authentication/create-account/endpoint'));
 
-       // category
-       require('./modules/category/get.js');
-       require('./modules/category/put.js');
-       require('./modules/category/delete.js');
+       // categories & category
+       api.registerEndpoint(require('./modules/categories/endpoint'));
+       api.registerEndpoint(require('./modules/category/endpoint'));
 
        // preferences
-       require('./modules/preferences/index');
-
-       // users
-       require('./modules/users/get.js');
-       require('./modules/user/get.js');
-       require('./modules/user/put.js');
-       require('./modules/user/delete.js');
+       api.registerEndpoint(require('./modules/preferences/endpoint'));
 
-       // pages
-       require('./modules/pages/get.js');
+       // users & user
+       api.registerEndpoint(require('./modules/users/endpoint'));
+       api.registerEndpoint(require('./modules/user/endpoint'));
 
        // status
-       require('./modules/status/get.js');
+       api.registerEndpoint(require('./modules/status/endpoint'));
 
        // bootstrap the API
        rave.run(api.initialize);

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/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 f782a7c..6826512 100644
--- a/rave-portal-ng/mock-api/core.js
+++ b/rave-portal-ng/mock-api/core.js
@@ -54,97 +54,6 @@ define(function(require) {
                $httpBackend.whenJSONP(matchAllRegex).passThrough();
        }
 
-       function parseQueryString(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;
-  }
-
-       function buildApiScope(method, url, data, headers) {
-
-               function requestHasToken() {
-                       if (!headers.Authorization) {
-                               return false;
-                       }
-
-                       var token = headers.Authorization.replace( 'Basic ', '' 
);
-                       if (token.length !== 32) {
-                               return false;
-                       }
-
-                       return true;
-               }
-
-               function getCurrentUserFromToken() {
-                       if (!requestHasToken(headers)) {
-                               return false;
-                       }
-
-                       var searchParams = {
-                               sessionToken: headers.Authorization.replace( 
'Basic ', '' )
-                       };
-                       var results = database.query('users', searchParams);
-                       if (results.length === 1) {
-                               return results[0];
-                       }
-
-                       return false;
-               }
-
-               return {
-                       requestHasToken: requestHasToken(),
-                       userIsAuthenticated: ((getCurrentUserFromToken() !== 
false) ? true : false),
-                       currentUser: getCurrentUserFromToken(),
-                       parseQueryString: parseQueryString
-               };
-       }
-
-       function registerApiMethod(route, method, callback) {
-               if 
(!(/^(get|delete|post|put|jsonp)$/.test(method.toLowerCase()))) {
-                       throw new Error('Invalid API method.');
-               } else if (typeof callback !== 'function') {
-                       throw new Error('Callback must be a valid function.');
-               }
-
-               if (!registeredApiMethods.hasOwnProperty(route)) {
-                       registeredApiMethods[route] = {
-                               pattern: convertRouteToRegex(baseApiUrl+route),
-                               methods: {}
-                       };
-               }
-
-               // this is a really convenient hack to ensure that every HTTP 
callback
-               // gets our utility methods for authentication
-               var moddedCallback = function(method, url, data, headers) {
-                       var scope = buildApiScope(method, url, data, headers);
-                       return callback.bind(scope)(method, url, data, headers);
-               };
-               registeredApiMethods[route].methods[method.toUpperCase()] = 
moddedCallback;
-               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) {
@@ -206,7 +115,6 @@ define(function(require) {
        // expose methods we want publicly available
        return {
                initialize: initializeApiModule,
-               register: registerApiMethod,
                registerEndpoint: registerEndpoint,
                db: database,
                session: {

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/database/install.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/database/install.js 
b/rave-portal-ng/mock-api/database/install.js
index a305a78..628770f 100644
--- a/rave-portal-ng/mock-api/database/install.js
+++ b/rave-portal-ng/mock-api/database/install.js
@@ -2,11 +2,12 @@ define(function(require) {
        'use strict';
 
        // dependencies
-       require('underscore/underscore');
+       var _ = require('underscore');
        var Storage = require('localStorageDB');
 
        // setup vars
        var database = new Storage('rave', localStorage);
+
        var dataImport = {
                users: require('./import-data/users.js'),
                categories: require( './import-data/categories.js' ),
@@ -25,4 +26,4 @@ define(function(require) {
                importTables();
        }
 
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/create-account/create-account-util.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/mock-api/modules/authentication/create-account/create-account-util.js
 
b/rave-portal-ng/mock-api/modules/authentication/create-account/create-account-util.js
new file mode 100644
index 0000000..ff574ea
--- /dev/null
+++ 
b/rave-portal-ng/mock-api/modules/authentication/create-account/create-account-util.js
@@ -0,0 +1,58 @@
+/*
+ * createAccountUtil
+ * Utility methods for the account creation endpoint
+ *
+ */
+
+define(function(require) {
+  var _ = require('underscore');
+  var api = require('../../../core');
+
+  var createAccountUtil = {
+
+    // The necessary fields to create a new account
+    requiredFields: [
+      'username',
+      'password',
+      'confirmPassword',
+      'email'
+    ],
+
+    // Returns true if data contains all of the requiredFields.
+    // false otherwise.
+    ensureFields: function(data) {
+      var keys = _.keys(data);
+      var intersect = _.intersection(keys, createAccountUtil.requiredFields);
+      return intersect.length === createAccountUtil.requiredFields.length;
+    },
+
+    // Returns true if the email is valid; false otherwise
+    validateEmail: function(email) {
+      var emailRegex = 
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+      return emailRegex.test(email);
+    },
+
+    createAccount: function(data) {
+      var newUserData = {
+        username: data.username,
+        password: data.password,
+        email: data.email,
+        openIdUrl: (data.hasOwnProperty('openIdUrl') ? data.openIdUrl : ''),
+        firstName: (data.hasOwnProperty('firstName') ? data.firstName : ''),
+        lastName: (data.hasOwnProperty('lastName') ? data.lastName : '' ),
+        nameSeenByOthers: (data.hasOwnProperty('nameSeenByOthers') ? 
data.nameSeenByOthers : ''),
+        relationshipStatus: (data.hasOwnProperty('relationshipStatus') ? 
data.relationshipStatus: ''),
+        description: (data.hasOwnProperty('description') ? data.description: 
''),
+        locked: false,
+        enabled: true,
+        expired: false,
+        authorities: ['ROLE_USER']
+      };
+
+      api.db.insert('users', newUserData);
+      api.db.commit();
+    }
+  };
+
+  return createAccountUtil;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/create-account/endpoint.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/mock-api/modules/authentication/create-account/endpoint.js 
b/rave-portal-ng/mock-api/modules/authentication/create-account/endpoint.js
new file mode 100644
index 0000000..d1968a1
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/authentication/create-account/endpoint.js
@@ -0,0 +1,56 @@
+/*
+ * createAccountEndpoint
+ * The endpoint for /auth/create-account
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../../util/endpoint');
+  var userUtil = require('../../user/user-util');
+  var createAccountUtil = require('./create-account-util');
+  var ErrorResponse = require('../../../util/error-response');
+
+  var createAccountEndpoint = new Endpoint({
+
+    url: '/auth/create-account',
+
+    authorize: false,
+
+    // Request for the new username
+    post: function(url, data, headers, params, currentUser) {
+
+      // validate that require fields exist
+      if (!createAccountUtil.ensureFields(data)) {
+        return new ErrorResponse(400, 'Missing required fields');
+      }
+
+      // now make sure this username doesn't exist
+      else if (userUtil.userExists({username: data.username})) {
+        return new ErrorResponse(422, 'Username is not available.');
+      }
+
+      // now make sure the email doesn't exist
+      else if (userUtil.userExists({username: data.username})) {
+        return new ErrorResponse(422, 'That email is already in use.');
+      }
+
+      // The password needs to be long enough, too
+      else if (data.password.length < 8) {
+        return new ErrorResponse(422, 'The password is not long enough.');
+      }
+
+      // And that the email is valid
+      else if (!createAccountUtil.validateEmail(data.email)) {
+        return new ErrorResponse(422, 'The email address is not valid.');
+      }
+
+      // Create the account
+      createAccountUtil.createAccount(data);
+
+      // Lastly, send the success
+      return [200, {message: 'Account created.'}];
+    }
+  });
+
+  return createAccountEndpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/create-account/post.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/mock-api/modules/authentication/create-account/post.js 
b/rave-portal-ng/mock-api/modules/authentication/create-account/post.js
deleted file mode 100644
index 464e3a4..0000000
--- a/rave-portal-ng/mock-api/modules/authentication/create-account/post.js
+++ /dev/null
@@ -1,114 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../../core.js');
-
-       function usernameAlreadyExists(username) {
-               var results = api.db.query('users', {
-                       username: username
-               });
-
-               if (results.length === 0) {
-                       return false;
-               }
-
-               return true;
-       }
-
-       function emailAlreadyExists(email) {
-               var results = api.db.query('users', {
-                       email: email
-               });
-
-               if (results.length === 0) {
-                       return false;
-               }
-
-               return true;
-       }
-
-       function requiredFieldIsMissing(data) {
-               var requiredFields = [
-                       'username',
-                       'password',
-                       'confirmPassword',
-                       'email'
-               ];
-               for (var i = 0, len = requiredFields.length; i < len; i++) {
-                       var requiredField = requiredFields[i];
-                       if (!data.hasOwnProperty(requiredField)) {
-                               return [400, 'Missing ' + requiredField + ' 
field'];
-                       }
-               }
-
-               return false;
-       }
-
-       function isValidEmail(email) {
-               var emailRegex = 
/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
-               return emailRegex.test(email);
-       }
-
-       function insertNewUser(data) {
-               var newUserData = {
-                       username: data.username,
-                       password: data.password,
-                       email: data.email,
-                       openIdUrl: (data.hasOwnProperty('openIdUrl') ? 
data.openIdUrl : ''),
-                       firstName: (data.hasOwnProperty('firstName') ? 
data.firstName : ''),
-                       lastName: (data.hasOwnProperty('lastName') ? 
data.lastName : '' ),
-                       nameSeenByOthers: 
(data.hasOwnProperty('nameSeenByOthers') ? data.nameSeenByOthers : ''),
-                       relationshipStatus: 
(data.hasOwnProperty('relationshipStatus') ? data.relationshipStatus: ''),
-                       description: (data.hasOwnProperty('description') ? 
data.description: ''),
-                       locked: false,
-                       enabled: true,
-                       expired: false,
-                       authorities: ['ROLE_USER']
-               };
-
-               api.db.insert('users', newUserData);
-               api.db.commit();
-       }
-
-       function processCreateAccount(method, url, data) {
-               if (method !== 'POST') {
-                       return [405, 'Unknown request'];
-               }
-
-               data = angular.fromJson(data);
-
-               // validate that require fields exist
-               var error = requiredFieldIsMissing(data);
-               if (error !== false) {
-                       return error;
-               }
-
-               // now make sure this username doesn't exist
-               if (usernameAlreadyExists(data.username)) {
-                       return [422, 'Username is not available'];
-               }
-
-               // now make sure this username doesn't exist
-               else if (emailAlreadyExists(data.email)) {
-                       return [422, 'Email is not available'];
-               }
-
-               // else...
-               else if (data.password.length < 8) {
-                       return [422, 'Password is not long enough'];
-               }
-
-               else if (!isValidEmail(data.email)) {
-                       return [422, 'Email address is not valid'];
-               }
-
-               // now build out the data that will be stored for this new user
-               insertNewUser(data);
-
-               // assume they need to click the verify email link to sign in 
(or something)
-               return [200, 'Email sent'];
-       }
-
-       api.register('/auth/create-account', 'post', processCreateAccount);
-
-});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/forgot-password/endpoint.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/mock-api/modules/authentication/forgot-password/endpoint.js 
b/rave-portal-ng/mock-api/modules/authentication/forgot-password/endpoint.js
new file mode 100644
index 0000000..5defe41
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/authentication/forgot-password/endpoint.js
@@ -0,0 +1,37 @@
+/*
+ * forgotPasswordEndpoint
+ * The endpoint for /auth/forgot-password
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../../util/endpoint');
+  var userUtil = require('../../user/user-util');
+  var ErrorResponse = require('../../../util/error-response');
+
+  var forgotPasswordEndpoint = new Endpoint({
+
+    url: '/auth/forgot-password',
+
+    authorize: false,
+
+    // Request your forgotten password
+    post: function(url, data, headers, params, currentUser) {
+
+      // An email is required
+      if (!data.email) {
+        return new ErrorResponse(400, 'Missing email address field.');
+      }
+
+      // Also, the user must exist
+      else if (!userUtil.userExists({email: data.email})) {
+        return new ErrorResponse(422, 'User with that email does not exist.');
+      }
+
+      // Otherwise, we return the retrieved category
+      return [200, {message: 'Email sent.'}];
+    }
+  });
+
+  return forgotPasswordEndpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/forgot-password/post.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/mock-api/modules/authentication/forgot-password/post.js 
b/rave-portal-ng/mock-api/modules/authentication/forgot-password/post.js
deleted file mode 100644
index 6b7ad01..0000000
--- a/rave-portal-ng/mock-api/modules/authentication/forgot-password/post.js
+++ /dev/null
@@ -1,36 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../../core.js');
-
-       function userExists(email) {
-               var results = api.db.query('users', {
-                       email: email
-               });
-
-               if (results.length === 1) {
-                       return true;
-               }
-
-               return false;
-       }
-
-       function processForgotPasswordRequest(method, url, data) {
-               if (method !== 'POST') {
-                       return [405, 'Unknown request'];
-               }
-
-               data = angular.fromJson(data);
-
-               if (!data.hasOwnProperty('email')) {
-                       return [400, 'Missing email address field'];
-               } else if (!userExists(data.email)) {
-                       return [422, 'User with that email does not exist'];
-               }
-
-               return [200, 'Email sent'];
-       }
-
-       api.register('/auth/forgot-password', 'post', 
processForgotPasswordRequest);
-
-});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/forgot-username/endpoint.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/mock-api/modules/authentication/forgot-username/endpoint.js 
b/rave-portal-ng/mock-api/modules/authentication/forgot-username/endpoint.js
new file mode 100644
index 0000000..3a0b6b1
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/authentication/forgot-username/endpoint.js
@@ -0,0 +1,37 @@
+/*
+ * forgotUsernameEndpoint
+ * The endpoint for /auth/forgot-username
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../../util/endpoint');
+  var userUtil = require('../../user/user-util');
+  var ErrorResponse = require('../../../util/error-response');
+
+  var forgetUsernameEndpoint = new Endpoint({
+
+    url: '/auth/forgot-username',
+
+    authorize: false,
+
+    // Request for the new username
+    post: function(url, data, headers, params, currentUser) {
+
+      // An email is required
+      if (!data.email) {
+        return new ErrorResponse(400, 'Missing email address field.');
+      }
+
+      // Also, the user must exist
+      else if (!userUtil.userExists({email: data.email})) {
+        return new ErrorResponse(422, 'User with that email does not exist.');
+      }
+
+      // Otherwise, we return the retrieved category
+      return [200, {message: 'Email sent.'}];
+    }
+  });
+
+  return forgetUsernameEndpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/forgot-username/post.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/mock-api/modules/authentication/forgot-username/post.js 
b/rave-portal-ng/mock-api/modules/authentication/forgot-username/post.js
deleted file mode 100644
index 59eef8c..0000000
--- a/rave-portal-ng/mock-api/modules/authentication/forgot-username/post.js
+++ /dev/null
@@ -1,36 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../../core.js');
-
-       function userExists(email) {
-               var results = api.db.query('users', {
-                       email: email
-               });
-
-               if (results.length === 1) {
-                       return true;
-               }
-
-               return false;
-       }
-
-       function processForgotUsernameRequest(method, url, data) {
-               if (method !== 'POST') {
-                       return [405, 'Unknown request'];
-               }
-
-               data = angular.fromJson(data);
-
-               if (!data.hasOwnProperty('email')) {
-                       return [400, 'Missing email address field'];
-               } else if (!userExists(data.email)) {
-                       return [422, 'User with that email does not exist'];
-               }
-
-               return [200, 'Email sent'];
-       }
-
-       api.register('/auth/forgot-username', 'post', 
processForgotUsernameRequest);
-
-});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/login/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/authentication/login/endpoint.js 
b/rave-portal-ng/mock-api/modules/authentication/login/endpoint.js
new file mode 100644
index 0000000..f809c17
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/authentication/login/endpoint.js
@@ -0,0 +1,50 @@
+/*
+ * loginEndpoint
+ * The endpoint for /auth/login
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../../util/endpoint');
+  var userUtil = require('../../user/user-util');
+  var ErrorResponse = require('../../../util/error-response');
+  var tokenUtil = require('../../../util/token-util');
+
+  var loginEndpoint = new Endpoint({
+
+    url: '/auth/login',
+
+    authorize: false,
+
+    // Request for the new username
+    post: function(url, data, headers, params, currentUser) {
+
+      // Throw an error if the username or password doesn't exist
+      if (!data.username || !data.password) {
+        return new ErrorResponse(401, 'Missing username and/or password 
field(s).');
+      }
+
+      var user = userUtil.get({username: data.username, password: 
data.password});
+
+      if (!user) {
+        return new ErrorResponse(401, 'Invalid login.');
+      }
+
+      // Filter out the unwanted properties from the object
+      user = _.pick(user, userUtil.publicKeys);
+
+      // Generate our token, then save it to the user
+      var token = tokenUtil.generateToken();
+      userUtil.updateUser({username: data.username}, {sessionToken: token});
+
+      // Lastly, send the success
+      return [200, {
+        authorized: true,
+        user: user,
+        token: token
+      }];
+    }
+  });
+
+  return loginEndpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/login/post.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/authentication/login/post.js 
b/rave-portal-ng/mock-api/modules/authentication/login/post.js
deleted file mode 100644
index ddab953..0000000
--- a/rave-portal-ng/mock-api/modules/authentication/login/post.js
+++ /dev/null
@@ -1,86 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../../core.js');
-
-       // The keys we want to send back when we're verified
-       var userKeys = [
-    'ID',
-    'username',
-    'description',
-    'firstName',
-    'lastName',
-    'locked',
-    'enabled',
-    'expired',
-    'authorities',
-    'openIdUrl',
-    'email'
-  ];
-
-       function retrieveUser(username, password) {
-               var results = api.db.query('users', {
-                       username: username,
-                       password: password
-               });
-
-               if (results.length === 1) {
-                       return results[0];
-               }
-
-               return false;
-       }
-
-       function generateSessionToken() {
-               var length = 32, token = '';
-               for (var i = 0; i < length; i++) {
-                       token += Math.random().toString(36).substr(2,1);
-               }
-               return token;
-       }
-
-       function updateUserSessionToken(username, token) {
-               var searchParams = {
-                       username: username
-               };
-               api.db.update('users', searchParams, function(row) {
-                       row.sessionToken = token;
-                       return row;
-               });
-               api.db.commit();
-       }
-
-       function processLoginRequest(method, url, data) {
-               if (method !== 'POST') {
-                       return [405, 'Unknown request'];
-               }
-
-               data = angular.fromJson(data);
-
-               // now attempt to login the user
-               if (!data.hasOwnProperty('username') || 
!data.hasOwnProperty('password')) {
-                       return [401, 'Missing username and/or password 
field(s)'];
-               }
-
-               var user = retrieveUser(data.username, data.password);
-               if (!user) {
-                       return [401, 'Invalid login.'];
-               }
-
-               user = _.pick(user, userKeys);
-
-               // update the user's token in the database
-               var token = generateSessionToken();
-               updateUserSessionToken(user.username, token);
-
-               // return a record for the user
-               return [200, {
-                       authorized: true,
-                       user: user,
-                       token: token
-               }];
-       }
-
-       api.register('/auth/login', 'post', processLoginRequest);
-
-});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/verify/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/authentication/verify/endpoint.js 
b/rave-portal-ng/mock-api/modules/authentication/verify/endpoint.js
new file mode 100644
index 0000000..a10c0b3
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/authentication/verify/endpoint.js
@@ -0,0 +1,54 @@
+/*
+ * verifyEndpoint
+ * The endpoint for /auth/verify
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../../util/endpoint');
+  var userUtil = require('../../user/user-util');
+  var ErrorResponse = require('../../../util/error-response');
+  var _ = require('underscore');
+
+  var verifyEndpoint = new Endpoint({
+
+    url: '/auth/verify',
+
+    authorize: false,
+
+    // Request for the new username
+    post: function(url, data, headers, params, currentUser) {
+
+      var token = data.token;
+
+      // Ensure that the token exists
+      if (!token) {
+        return new ErrorResponse(400, 'Missing token field.');
+      }
+
+      // Also that it has the right form
+      else if (!_.isString(token) || token.length !== 32) {
+        return new ErrorResponse(401, 'A valid token is required.');
+      }
+
+      // If so, get the token
+      var user = userUtil.get({sessionToken: token});
+
+      // Return an error if the user doesn't exist
+      if (!user) {
+        return new ErrorResponse(401, 'Invalid token.');
+      }
+
+      // Filter out the unwanted properties from the object
+      user = _.pick(user, userUtil.publicKeys);
+
+      // Lastly, send the success
+      return [200, {
+        authorized: true,
+        user: user
+      }];
+    }
+  });
+
+  return verifyEndpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/authentication/verify/post.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/authentication/verify/post.js 
b/rave-portal-ng/mock-api/modules/authentication/verify/post.js
deleted file mode 100644
index 6906445..0000000
--- a/rave-portal-ng/mock-api/modules/authentication/verify/post.js
+++ /dev/null
@@ -1,60 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       require('underscore/underscore');
-       var api = require('../../../core.js');
-
-       // The keys we want to send back when we're verified
-       var userKeys = [
-    'ID',
-    'username',
-    'description',
-    'firstName',
-    'lastName',
-    'locked',
-    'enabled',
-    'expired',
-    'authorities',
-    'openIdUrl',
-    'email'
-  ];
-
-       // All of these 'helper' methods should be abstracted into (a) separate 
module(s).
-       function retrieveUserByToken(token) {
-               var results = api.db.query('users', {
-                       sessionToken: token
-               });
-
-               return (results.length === 1) ? results[0] : false;
-       }
-
-       function verify(method, url, data) {
-               data = angular.fromJson(data);
-
-               if (method !== 'POST') {
-                       return [405, 'Unknown request'];
-               } else if (!data.hasOwnProperty('token')) {
-                       return [400, 'Missing token field'];
-               } else if (!data.token || !_.isString(data.token) || 
data.token.length !== 32) {
-                       return [401, 'A valid token is required'];
-               }
-
-               var clientToken = data.token;
-               var user = retrieveUserByToken(clientToken);
-
-               // now, compare the session tokens
-               if (!user) {
-                       return [401, 'Invalid token'];
-               }
-
-               user = _.pick(user, userKeys);
-
-               // return the user object
-               return [200, {
-                       authorized: true,
-                       user: user
-               }];
-       }
-
-       api.register('/auth/verify', 'post', verify);
-});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/categories/categories-util.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/categories/categories-util.js 
b/rave-portal-ng/mock-api/modules/categories/categories-util.js
new file mode 100644
index 0000000..cccd820
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/categories/categories-util.js
@@ -0,0 +1,44 @@
+/*
+ * categoriesUtil
+ * Convenience methods for working with the categories data
+ * stored in the database
+ *
+ */
+
+define(function(require) {
+  var api = require('../../core');
+  var categoryUtil = require('../category/category-util');
+  var moment = require('moment');
+
+  var categoriesUtil = {
+
+    // Retrieve all of the categories
+    getAllCategories: function() {
+      return api.db.query('categories');
+    },
+
+    // Create a new category in the database
+    createCategory: function(data, user) {
+
+      // Build the data for this category
+      var newData = {
+        text: data.text,
+        createdUserId: user.ID,
+        createdUserName: user.username,
+        createdDate: moment().format(),
+        lastModifiedUserId: user.ID,
+        lastModifiedUserName: user.username,
+        lastModifiedDate: moment().format()
+      };
+
+      // Insert and commit
+      api.db.insert('categories', newData);
+      api.db.commit();
+
+      // Return the newly-created category
+      return categoryUtil.getCategory({text: data.text});
+    }
+  };
+
+  return categoriesUtil;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/categories/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/categories/endpoint.js 
b/rave-portal-ng/mock-api/modules/categories/endpoint.js
new file mode 100644
index 0000000..170f3a8
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/categories/endpoint.js
@@ -0,0 +1,47 @@
+/*
+ * categories-endpoint
+ * The endpoint for /categories
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../util/endpoint');
+  var ErrorResponse = require('../../util/error-response');
+  var categoriesUtil = require('./categories-util');
+  var categoryUtil = require('../category/category-util');
+
+  var categoriesEndpoint = new Endpoint({
+
+    url: '/categories',
+
+    // Returns all of the categories
+    get: function(url, data, headers, params, currentUser) {
+      return [200, categoriesUtil.getAllCategories()];
+    },
+
+    // Creates a new category
+    post: function(url, data, headers, params, currentUser) {
+
+      var text = data.text;
+
+      // Error out if we don't have any text
+      if (!text) {
+        return new ErrorResponse(400, 'Missing text field.');
+      }
+
+      // Error out if the text isn't a string
+      else if (!_.isString(text)) {
+        return new ErrorResponse(422, 'Text must be a string.');
+      }
+
+      // Also error out if it already exists
+      else if (categoryUtil.categoryExists({text: text})) {
+        return new ErrorResponse(409, 'The category already exists.');
+      }
+
+      return [200, categoriesUtil.createCategory(data, currentUser)];
+    }
+  });
+
+  return categoriesEndpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/categories/get.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/categories/get.js 
b/rave-portal-ng/mock-api/modules/categories/get.js
deleted file mode 100644
index ddde58e..0000000
--- a/rave-portal-ng/mock-api/modules/categories/get.js
+++ /dev/null
@@ -1,21 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../core.js');
-       require('underscore/underscore');
-
-       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, api.db.query('categories')];
-       }
-
-       api.register('/categories', 'get', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/categories/post.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/categories/post.js 
b/rave-portal-ng/mock-api/modules/categories/post.js
deleted file mode 100644
index 64be46b..0000000
--- a/rave-portal-ng/mock-api/modules/categories/post.js
+++ /dev/null
@@ -1,63 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../core.js');
-       require('underscore/underscore');
-       require('moment/moment');
-
-       function categoryExists(text) {
-               var results = api.db.query('categories', {
-                       text: text
-               });
-
-               if (results.length >= 1) {
-                       return true;
-               }
-               return false;
-       }
-
-       function createCategory(text, user) {
-               var newData = {
-                       text: text,
-                       createdUserId: user.ID,
-                       createdUserName: user.username,
-                       createdDate: moment().format(),
-                       lastModifiedUserId: user.ID,
-                       lastModifiedUserName: user.username,
-                       lastModifiedDate: moment().format()
-               };
-               api.db.insert('categories', newData);
-               api.db.commit();
-               var result = api.db.query('categories', {
-                       text: text
-               });
-               return result[0];
-       }
-
-       function processRequest(method, url, data, headers) {
-               if (method !== 'POST') {
-                       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);
-
-               if (!data.text) {
-                       return [400, 'Missing text field'];
-               } else if (!_.isString(data.text)) {
-                       return [422, 'Text must be a string'];
-               }
-
-               if (categoryExists(data.text)) {
-                       return [409, 'This category already exists'];
-               }
-
-               return [200, createCategory(data.text, this.currentUser)];
-       }
-
-       api.register('/categories', 'post', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/category/category-util.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/category/category-util.js 
b/rave-portal-ng/mock-api/modules/category/category-util.js
new file mode 100644
index 0000000..953f5a1
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/category/category-util.js
@@ -0,0 +1,53 @@
+/*
+ * categoryUtil
+ * Convenience methods for working with single category resources
+ *
+ */
+
+define(function(require) {
+  var api = require('../../core');
+  var moment = require('moment');
+
+  var categoryUtil = {
+
+    // Pull out the ID from the endpoint
+    idFromEndpoint: function(url) {
+      return parseInt(url.replace('/api/v1/category/', ''), 10);
+    },
+
+    // Whether or not a category with the given text exists
+    categoryExists: function(identifier) {
+      return !!categoryUtil.getCategory(identifier);
+    },
+
+    // Get a category by an identifier object.
+    // It can either be text or an ID.
+    getCategory: function(identifier) {
+      var results = api.db.query('categories', identifier);
+
+      if (results.length === 1) {
+        return results[0];
+      }
+
+      return false;
+    },
+
+    updateCategory: function(userID, categoryID, text) {
+      var searchParams = {ID: categoryID};
+      api.db.update('categories', searchParams, function(row) {
+        row.text = text;
+        row.lastModifiedUserId = userID;
+        row.lastModifiedDate = moment().format();
+        return row;
+      });
+      api.db.commit();
+    },
+
+    deleteCategory: function(identifier) {
+      api.db.deleteRows('categories', identifier);
+      api.db.commit();
+    }
+  };
+
+  return categoryUtil;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/category/delete.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/category/delete.js 
b/rave-portal-ng/mock-api/modules/category/delete.js
deleted file mode 100644
index 48cb68c..0000000
--- a/rave-portal-ng/mock-api/modules/category/delete.js
+++ /dev/null
@@ -1,50 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../core.js');
-       require('underscore/underscore');
-
-       function categoryExists(id) {
-               var results = api.db.query('categories', {
-                       ID: id
-               });
-
-               if (results.length === 1) {
-                       return true;
-               }
-
-               return false;
-       }
-
-       function deleteCategory(id) {
-               api.db.deleteRows('categories', {
-                       ID: id
-               });
-               api.db.commit();
-       }
-
-       function processRequest(method, url, data, headers) {
-               if (method !== 'DELETE') {
-                       return [405, 'Unknown request'];
-               } else if (!this.requestHasToken) {
-                       return [401, 'A valid token is required'];
-               } else if (!this.userIsAuthenticated) {
-                       return [401, 'Invalid token'];
-               }
-
-               // attempt to parse the category ID
-               var categoryID = parseInt( url.replace( '/api/v1/category/', '' 
), 10 );
-               if (!_.isNumber(categoryID) || _.isNaN(categoryID)) {
-                       return [400, 'Invalid category ID'];
-               } else if (!categoryExists(categoryID)) {
-                       return [404, 'Category does not exist'];
-               }
-
-               deleteCategory(categoryID);
-
-               return [200, null];
-       }
-
-       api.register('/category/:id', 'delete', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/category/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/category/endpoint.js 
b/rave-portal-ng/mock-api/modules/category/endpoint.js
new file mode 100644
index 0000000..cadd991
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/category/endpoint.js
@@ -0,0 +1,96 @@
+/*
+ * category-endpoint
+ * The endpoint for /category
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../util/endpoint');
+  var categoryUtil = require('../category/category-util');
+  var ErrorResponse = require('../../util/error-response');
+  var _ = require('underscore');
+
+  var categoryEndpoint = new Endpoint({
+
+    url: '/category/:id',
+
+    // Get a single category by ID
+    get: function(url, data, headers, params, currentUser) {
+
+      // Attempt to parse the category ID
+      var categoryID = categoryUtil.idFromEndpoint(url);
+
+      // Return an error if the ID isn't valid
+      if (!_.isNumber(categoryID) || _.isNaN(categoryID)) {
+        return new ErrorResponse(400, 'Invalid category ID');
+      }
+
+      // Attempt to retrieve a category with that ID
+      var category = categoryUtil.getCategory({ID: categoryID});
+
+      // If it doesn't exist, then we throw an error
+      if (!category) {
+        return new ErrorResponse(404, 'Category does not exist.');
+      }
+
+      // Otherwise, we return the retrieved category
+      return [200, category];
+    },
+
+    // Update a category
+    put: function(url, data, headers, params, currentUser) {
+
+      // attempt to parse the category ID
+      var categoryID = categoryUtil.idFromEndpoint(url);
+
+      if (!_.isNumber(categoryID) || _.isNaN(categoryID)) {
+        return new ErrorResponse(400, 'Invalid category ID');
+      }
+
+      var text = data.text;
+
+      // Error out if we don't have any text
+      if (!text) {
+        return new ErrorResponse(400, 'Missing text field.');
+      }
+
+      // Error out if the text isn't a string
+      else if (!_.isString(text)) {
+        return new ErrorResponse(422, 'Text must be a string.');
+      }
+
+      // Also error out if it doesn't exist
+      else if (!categoryUtil.categoryExists({ID: categoryID})) {
+        return new ErrorResponse(409, 'The category does not exist.');
+      }
+      
+      // Update our category
+      categoryUtil.updateCategory(currentUser.ID, categoryID, text);
+
+      // Return the updated category
+      return [200, categoryUtil.getCategory({ID: categoryID})];
+    },
+
+    delete: function(url, data, headers, params, currentUser) {
+
+      // attempt to parse the category ID
+      var categoryID = categoryUtil.idFromEndpoint(url);
+
+      if (!_.isNumber(categoryID) || _.isNaN(categoryID)) {
+        return new ErrorResponse(400, 'Invalid category ID');
+      }
+
+      // Also error out if it doesn't exist
+      else if (!categoryUtil.categoryExists({ID: categoryID})) {
+        return new ErrorResponse(409, 'The category does not exist.');
+      }
+
+      // Otherwise, we delete the category and send back a success response
+      categoryUtil.deleteCategory(categoryID);
+
+      return [200, null];
+    }
+  });
+
+  return categoryEndpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/category/get.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/category/get.js 
b/rave-portal-ng/mock-api/modules/category/get.js
deleted file mode 100644
index c575ed3..0000000
--- a/rave-portal-ng/mock-api/modules/category/get.js
+++ /dev/null
@@ -1,44 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../core.js');
-       require('underscore/underscore');
-
-       function getCategory(id) {
-               var results = api.db.query('categories', {
-                       ID: id
-               });
-
-               if (results.length === 1) {
-                       return results[0];
-               }
-
-               return false;
-       }
-
-       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'];
-               }
-
-               // attempt to parse the category ID
-               var categoryID = parseInt(url.replace('/api/v1/category/', ''), 
10);
-               if (!_.isNumber(categoryID) || _.isNaN(categoryID)) {
-                       return [400, 'Invalid category ID'];
-               }
-
-               var category = getCategory(categoryID);
-               if (!category) {
-                       return [404, 'Category does not exist'];
-               }
-
-               return [200, category];
-       }
-
-       api.register('/category/:id', 'get', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/category/put.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/category/put.js 
b/rave-portal-ng/mock-api/modules/category/put.js
deleted file mode 100644
index 5819e92..0000000
--- a/rave-portal-ng/mock-api/modules/category/put.js
+++ /dev/null
@@ -1,77 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../core.js');
-       require('underscore/underscore');
-       require('moment/moment');
-
-       function categoryExists(id) {
-               var results = api.db.query('categories', {
-                       ID: id
-               });
-
-               if (results.length === 1) {
-                       return true;
-               }
-
-               return false;
-       }
-
-       function updateCategory(userID, categoryID, text) {
-               var searchParams = {
-                       ID: categoryID
-               };
-               api.db.update('categories', searchParams, function(row) {
-                       row.text = text;
-                       row.lastModifiedUserId = userID;
-                       row.lastModifiedDate = moment().format();
-                       return row;
-               });
-               api.db.commit();
-
-               var results = api.db.query('categories', searchParams);
-               if (results.length === 1) {
-                       return results[0];
-               }
-
-               return false;
-       }
-
-       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'];
-               }
-
-               // attempt to parse the category ID
-               var categoryID = parseInt( url.replace( '/api/v1/category/', '' 
), 10 );
-               if (!_.isNumber(categoryID) || _.isNaN(categoryID)) {
-                       return [400, 'Invalid category ID'];
-               }
-
-               data = angular.fromJson(data);
-
-               if (!data.text) {
-                       return [400, 'Missing text field'];
-               } else if (!_.isString(data.text)) {
-                       return [422, 'Text must be a string'];
-               }
-
-               if (!categoryExists(categoryID)) {
-                       return [404, 'Category does not exist'];
-               }
-
-               var updatedCategory = updateCategory(this.currentUser.ID, 
categoryID, data.text);
-               if (!updatedCategory) {
-                       return [500, 'An internal database error has occurred'];
-               }
-
-               return [200, updatedCategory];
-       }
-
-       api.register('/category/:id', 'put', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/pages/get.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/pages/get.js 
b/rave-portal-ng/mock-api/modules/pages/get.js
deleted file mode 100644
index 7ae04f3..0000000
--- a/rave-portal-ng/mock-api/modules/pages/get.js
+++ /dev/null
@@ -1,15 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../core.js');
-
-       function processPagesRequest(method, url, data) {
-               var responseData = {
-                       status: 'ok'
-               };
-               return [200, responseData];
-       }
-
-       api.register('/pages', 'get', processPagesRequest);
-
-});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/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
deleted file mode 100644
index 9d26997..0000000
--- a/rave-portal-ng/mock-api/modules/preferences/db.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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/26240a1c/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
index 3696557..8d79c39 100644
--- a/rave-portal-ng/mock-api/modules/preferences/endpoint.js
+++ b/rave-portal-ng/mock-api/modules/preferences/endpoint.js
@@ -6,7 +6,7 @@
 
 define(function(require) {
   var Endpoint = require('../../util/endpoint');
-  var prefsDb = require('./db');
+  var preferencesUtil = require('./preferences-util');
 
   var endpoint = new Endpoint({
 
@@ -15,12 +15,13 @@ define(function(require) {
     // 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()];
+      return [200, preferencesUtil.getAll()];
     },
 
     // Puts our data into the database.
     put: function(url, data, headers, params, currentUser) {
-      return [200, prefsDb.put(data)];
+      preferencesUtil.put(data);
+      return [200, preferencesUtil.getAll()];
     }
   });
 

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/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
deleted file mode 100644
index 58544ac..0000000
--- a/rave-portal-ng/mock-api/modules/preferences/index.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * 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/26240a1c/rave-portal-ng/mock-api/modules/preferences/preferences-util.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/preferences/preferences-util.js 
b/rave-portal-ng/mock-api/modules/preferences/preferences-util.js
new file mode 100644
index 0000000..946566e
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/preferences/preferences-util.js
@@ -0,0 +1,63 @@
+/*
+ * preferences-util
+ * 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');
+
+  var preferencesUtil = {
+
+    // 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.
+    getAll: function() {
+      var results = api.db.query('preferences');
+      var preferences = {};
+
+      _.each(results, function(item) {
+        preferences[item.key] = item.value;
+      });
+
+      return preferences;
+    },
+
+    // Get a specific preference by name.
+    // Returns null if it doesn't exist.
+    getPreference: function(preferenceName) {
+
+      // Get all of our preferences
+      var prefs = preferencesUtil.getAll();
+
+      // Find the one that matches the name
+      var preference = prefs[preferenceName];
+
+      // Return it if it exists; otherwise, null
+      return (typeof preference !== 'undefined') ? preference : null;
+    },
+
+    // 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();
+    }
+  };
+
+  return preferencesUtil;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/status/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/status/endpoint.js 
b/rave-portal-ng/mock-api/modules/status/endpoint.js
new file mode 100644
index 0000000..3ccdb8b
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/status/endpoint.js
@@ -0,0 +1,24 @@
+/*
+ * endpoint
+ * The endpoint for status
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../util/endpoint');
+
+  var endpoint = new Endpoint({
+
+    url: '/status',
+
+    // Returns that the API is a-okay
+    get: function(url, data, headers, params, currentUser) {
+      var responseData = {
+        status: 'ok'
+      };
+      return [200, responseData];
+    }
+  });
+
+  return endpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/status/get.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/status/get.js 
b/rave-portal-ng/mock-api/modules/status/get.js
deleted file mode 100644
index b44f2ae..0000000
--- a/rave-portal-ng/mock-api/modules/status/get.js
+++ /dev/null
@@ -1,15 +0,0 @@
-define(function(require) {
-       'use strict';
-
-       var api = require('../../core.js');
-
-       function processStatusRequest(method, url, data) {
-               var responseData = {
-                       status: 'ok'
-               };
-               return [200, responseData];
-       }
-
-       api.register('/status', 'get', processStatusRequest);
-
-} );
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/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
deleted file mode 100644
index 3dd351f..0000000
--- a/rave-portal-ng/mock-api/modules/user/db.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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/26240a1c/rave-portal-ng/mock-api/modules/user/delete.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/user/delete.js 
b/rave-portal-ng/mock-api/modules/user/delete.js
deleted file mode 100644
index c7bf92d..0000000
--- a/rave-portal-ng/mock-api/modules/user/delete.js
+++ /dev/null
@@ -1,50 +0,0 @@
-define(function(require) {
-  'use strict';
-
-  var api = require('../../core.js');
-  require('underscore/underscore');
-
-  function userExists(id) {
-    var results = api.db.query('users', {
-      ID: id
-    });
-
-    if (results.length === 1) {
-      return true;
-    }
-
-    return false;
-  }
-
-  function deleteUser(id) {
-    api.db.deleteRows('users', {
-      ID: id
-    });
-    api.db.commit();
-  }
-
-  function processRequest(method, url, data, headers) {
-    if (method !== 'DELETE') {
-      return [405, 'Unknown request'];
-    } else if (!this.requestHasToken) {
-      return [401, 'A valid token is required'];
-    } else if (!this.userIsAuthenticated) {
-      return [401, 'Invalid token'];
-    }
-
-    // attempt to parse the user ID
-    var userID = parseInt( url.replace( '/api/v1/user/', '' ), 10 );
-    if (!_.isNumber(userID) || _.isNaN(userID)) {
-      return [400, 'Invalid user ID'];
-    } else if (!userExists(userID)) {
-      return [404, 'User does not exist'];
-    }
-
-    deleteUser(userID);
-
-    return [200, null];
-  }
-
-  api.register('/user/:id', 'delete', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/user/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/user/endpoint.js 
b/rave-portal-ng/mock-api/modules/user/endpoint.js
new file mode 100644
index 0000000..6770454
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/user/endpoint.js
@@ -0,0 +1,96 @@
+/*
+ * endpoint
+ * The /user endpoint
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../util/endpoint');
+  var ErrorResponse = require('../../util/error-response');
+  var userUtil = require('./user-util');
+
+  var endpoint = new Endpoint({
+
+    url: '/user/:id',
+
+    // Return our paginated data
+    get: function(url, data, headers, params, currentUser) {
+
+      // Get the user's ID from the url
+      var userId = userUtil.idFromUrl(url);
+
+      // If the ID is invalid, throw an error
+      if (!_.isNumber(userId) || _.isNaN(userId)) {
+        return new ErrorResponse(400, 'Invalid user ID');
+      }
+
+      // Retrieve the user from the database
+      var user = userUtil.get({ID:userId});
+
+      // If there's no user then we return the 404
+      if (!user) {
+        return new ErrorResponse(404, 'User does not exist.');
+      }
+
+      // Return the user
+      return [200, user];
+    },
+
+    put: function(url, data, headers, params, currentUser) {
+
+      // Get the user's ID from the url
+      var userId = userUtil.idFromUrl(url);
+
+      // If the ID is invalid, throw an error
+      if (!_.isNumber(userId) || _.isNaN(userId)) {
+        return new ErrorResponse(400, 'Invalid user ID.');
+      }
+
+      // Return a 404 if the user doesn't exist
+      if (!userUtil.userExists({ID:userId})) {
+        return new ErrorResponse(404, 'User does not exist.');
+      }
+
+      // Filter out the data
+      data = _.pick(data, userUtil.updateKeys);
+
+      // Actually make the update
+      userUtil.updateUser({ID: userId}, data);
+
+      // We want to return the user, so wetrieve them from the database
+      var user = userUtil.get({ID:userId});
+
+      // If there's no user then we return the 404
+      if (!user) {
+        return new ErrorResponse(404, 'User does not exist.');
+      }
+
+      // Make the return
+      return [200, user];
+    },
+
+    delete: function(url, data, headers, params, currentUser) {
+      
+      // Get the user's ID from the url
+      var userId = userUtil.idFromUrl(url);
+
+      // If the ID is invalid, throw an error
+      if (!_.isNumber(userId) || _.isNaN(userId)) {
+        return new ErrorResponse(400, 'Invalid user ID.');
+      }
+
+      // Return a 404 if the user doesn't exist
+      if (!userUtil.userExists({ID:userId})) {
+        return new ErrorResponse(404, 'User does not exist.');
+      }
+
+      // Actually delete the user
+      userUtil.deleteUser({ID:userId});
+
+      // Share that the user was deleted
+      return [200, null];
+    }
+  });
+
+  return endpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/user/get.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/user/get.js 
b/rave-portal-ng/mock-api/modules/user/get.js
deleted file mode 100644
index 9c712a5..0000000
--- a/rave-portal-ng/mock-api/modules/user/get.js
+++ /dev/null
@@ -1,59 +0,0 @@
-define(function(require) {
-  'use strict';
-
-  var api = require('../../core.js');
-  require('underscore/underscore');
-
-  // 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'
-  ];
-
-  function getUser(id) {
-    var results = api.db.query('users', {
-      ID: id
-    });
-
-    if (results.length === 1) {
-      return _.pick(results[0], userKeys);
-    }
-
-    return false;
-  }
-
-  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'];
-    }
-
-    // attempt to parse the user ID
-    var userID = parseInt(url.replace('/api/v1/user/', ''), 10);
-    if (!_.isNumber(userID) || _.isNaN(userID)) {
-      return [400, 'Invalid user ID'];
-    }
-
-    var user = getUser(userID);
-    if (!user) {
-      return [404, 'User does not exist'];
-    }
-
-    return [200, user];
-  }
-
-  api.register('/user/:id', 'get', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/user/put.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/user/put.js 
b/rave-portal-ng/mock-api/modules/user/put.js
deleted file mode 100644
index dfd794a..0000000
--- a/rave-portal-ng/mock-api/modules/user/put.js
+++ /dev/null
@@ -1,93 +0,0 @@
-define(function(require) {
-  'use strict';
-
-  var api = require('../../core.js');
-  require('underscore/underscore');
-
-  // The keys that a user is allowed to update through the client
-  var updateKeys = [
-    'email',
-    'openIdUrl',
-    'enabled',
-    'expired',
-    'locked',
-    'authorities'
-  ];
-
-  // 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'
-  ];
-
-  function userExists(id) {
-    var results = api.db.query('users', {
-      ID: id
-    });
-
-    if (results.length === 1) {
-      return results[0];
-    }
-
-    return false;
-  }
-
-  function updateUser(userID, data) {
-    var searchParams = {
-      ID: userID
-    };
-    api.db.update('users', searchParams, function(row) {
-      _.extend(row, _.pick(data, updateKeys));
-      return row;
-    });
-    api.db.commit();
-
-    var results = api.db.query('users', searchParams);
-    if (results.length === 1) {
-      return _.pick(results[0], userKeys);
-    }
-
-    return false;
-  }
-
-  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'];
-    }
-
-    // attempt to parse the user ID
-    var userID = parseInt( url.replace( '/api/v1/user/', '' ), 10 );
-    if (!_.isNumber(userID) || _.isNaN(userID)) {
-      return [400, 'Invalid user ID'];
-    }
-
-    data = angular.fromJson(data);
-
-    if (!userExists(userID)) {
-      return [404, 'User does not exist'];
-    }
-
-    var updatedUser = updateUser(userID, data);
-    if (!updatedUser) {
-      return [500, 'An internal database error has occurred'];
-    }
-
-    return [200, updatedUser];
-  }
-
-  api.register('/user/:id', 'put', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/user/user-util.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/user/user-util.js 
b/rave-portal-ng/mock-api/modules/user/user-util.js
new file mode 100644
index 0000000..18dc503
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/user/user-util.js
@@ -0,0 +1,91 @@
+/*
+ * user-util
+ * Utilities for user data
+ *
+ */
+
+define(function(require) {
+  var api = require('../../core');
+
+  var userUtil = {
+
+    // Safe keys to return back from the API
+    publicKeys: [
+      'ID',
+      'username',
+      'description',
+      'firstName',
+      'lastName',
+      'locked',
+      'enabled',
+      'expired',
+      'authorities',
+      'openIdUrl',
+      'email'
+    ],
+
+    // The valid keys for updating
+    updateKeys: [
+      'email',
+      'openIdUrl',
+      'enabled',
+      'expired',
+      'locked',
+      'authorities'
+    ],
+
+    // Retrieve from the user's ID from the URL
+    idFromUrl: function(url) {
+      return parseInt(url.replace('/api/v1/user/', ''), 10);
+    },
+
+    // Whether a particular user exists or not
+    userExists: function(identifier) {
+      return !!userUtil.get(identifier);
+    },
+
+    // Retrieve the user by an identifier. Optionally filter
+    // to remove secure properties.
+    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, userUtil.publicKeys) : user;
+
+      return user;
+    },
+
+    // Update the user's information in the database
+    updateUser: function(identifier, data) {
+
+      api.db.update('users', identifier, function(row) {
+        _.extend(row, data);
+        return row;
+      });
+      api.db.commit();
+    },
+
+    // Delete a user by identifier
+    deleteUser: function(identifier) {
+      api.db.deleteRows('users', identifier);
+      api.db.commit();
+    }
+  };
+
+  return userUtil;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/users/endpoint.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/users/endpoint.js 
b/rave-portal-ng/mock-api/modules/users/endpoint.js
new file mode 100644
index 0000000..0ef4a20
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/users/endpoint.js
@@ -0,0 +1,23 @@
+/*
+ * endpoint
+ * The /users endpoint
+ *
+ */
+
+define(function(require) {
+  var Endpoint = require('../../util/endpoint');
+  var usersUtil = require('./users-util');
+
+  var endpoint = new Endpoint({
+
+    url: '/users',
+
+    // Return our paginated data
+    get: function(url, data, headers, params, currentUser) {
+      var currentPage = params.page || 1;
+      return [200, usersUtil.getPage(currentPage)];
+    }
+  });
+
+  return endpoint;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/users/get.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/users/get.js 
b/rave-portal-ng/mock-api/modules/users/get.js
deleted file mode 100644
index 4bc65bb..0000000
--- a/rave-portal-ng/mock-api/modules/users/get.js
+++ /dev/null
@@ -1,93 +0,0 @@
-define(function(require) {
-  'use strict';
-
-  var api = require('../../core.js');
-  require('underscore/underscore');
-
-  // 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'
-  ];
-
-  function getPageSize() {
-    var prefs = api.db.query('preferences');
-    // return prefs;
-    var pageSize = _.findWhere(prefs, {key: 'pageSize'});
-    return pageSize.value;
-  }
-
-  function getUsers(params) {
-
-    var rawUsers = api.db.query('users');
-    var filteredUsers = [];
-
-    _.each(rawUsers, function(rawUser) {
-      filteredUsers.push(_.pick(rawUser, userKeys));
-    });
-
-    var page = params.page || 1;
-    var pageSize = getPageSize();
-
-    // The first index to start from
-    var startIndex = (page - 1) * pageSize;
-
-    // The naive end index. We may have overshot this.
-    var endIndex = page * pageSize;
-
-    // Truncate our end index if it's too long. Slice only goes UP TO
-    // this index, which is why we don't use (length - 1)
-    if (endIndex > filteredUsers.length) {
-      endIndex = filteredUsers.length;
-    }
-
-    var results = filteredUsers.slice(startIndex, endIndex);
-
-    var returnObj = {};
-
-    returnObj.data = results;
-    returnObj.metadata = {
-      pageSize: pageSize,
-      page: page,
-      start: startIndex+1,
-      end: endIndex,
-      pageCount: Math.ceil(filteredUsers.length / pageSize),
-      totalUsers: filteredUsers.length
-    };
-
-    return returnObj;
-  }
-
-  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'];
-    }
-
-    var params = this.parseQueryString(url);
-
-    var usersData = getUsers(params);
-
-    var object = {
-      data: usersData.data,
-      metadata: usersData.metadata
-    };
-
-    return [200, object];
-  }
-
-  api.register('/users', 'get', processRequest);
-
-} );

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/mock-api/modules/users/users-util.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/mock-api/modules/users/users-util.js 
b/rave-portal-ng/mock-api/modules/users/users-util.js
new file mode 100644
index 0000000..5f866b0
--- /dev/null
+++ b/rave-portal-ng/mock-api/modules/users/users-util.js
@@ -0,0 +1,65 @@
+/*
+ * usersUtil
+ * Methods for interacting with the users data
+ *
+ */
+
+define(function(require) {
+  var api = require('../../core');
+  var preferencesUtil = require('../preferences/preferences-util');
+  var userUtil = require('../user/user-util');
+
+  var usersUtil = {
+
+    // Get every single user from the database.
+    getAll: function() {
+      return api.db.query('users');
+    },
+
+    // Get the list of all users
+    getPage: function(currentPage) {
+
+      // Get the page size from the database
+      var pageSize = preferencesUtil.getPreference('pageSize');
+
+      var allUsers = usersUtil.getAll();
+
+      // Get a naive list of users from the DB
+      var filteredUsers = [];
+
+      _.each(allUsers, function(rawUser) {
+        filteredUsers.push(_.pick(rawUser, userUtil.publicKeys));
+      });
+
+      // The first index to start from
+      var startIndex = (currentPage - 1) * pageSize;
+
+      // The naive end index. We may have overshot this.
+      var endIndex = currentPage * pageSize;
+
+      // Truncate our end index if it's too long. Slice only goes UP TO
+      // this index, which is why we don't use (length - 1)
+      if (endIndex > filteredUsers.length) {
+        endIndex = filteredUsers.length;
+      }
+
+      var results = filteredUsers.slice(startIndex, endIndex);
+
+      var returnObj = {};
+
+      returnObj.data = results;
+      returnObj.metadata = {
+        pageSize: pageSize,
+        currentPage: currentPage,
+        start: startIndex+1,
+        end: endIndex,
+        pageCount: Math.ceil(filteredUsers.length / pageSize),
+        totalUsers: filteredUsers.length
+      };
+
+      return returnObj;
+    }
+  };
+
+  return usersUtil;
+});

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/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
index 9792164..2473c05 100644
--- a/rave-portal-ng/mock-api/util/endpoint.js
+++ b/rave-portal-ng/mock-api/util/endpoint.js
@@ -6,10 +6,11 @@
 
 define(function(require) {
   var _ = require('underscore');
+  var ng = require('angular');
   var paramsFromUrl = require('./params');
   var ErrorResponse = require('./error-response');
   var tokenUtil = require('./token-util');
-  var userDb = require('../modules/user/db');
+  var userUtil = require('../modules/user/user-util');
 
   // These are the valid options that you can pass into
   // a new endpoint
@@ -36,6 +37,10 @@ define(function(require) {
     // What is ultimately returned from the endpoint.
     callback: function(method, url, data, headers) {
 
+      // This is a JSON endpoint, so let's convert our
+      // data to JSON
+      data = ng.fromJson(data);
+
       // Our current user, if there is one.
       var currentUser;
 
@@ -51,7 +56,7 @@ define(function(require) {
         }
 
         // Otherwise, we try to get the user from the token
-        var user = userDb.get({
+        var user = userUtil.get({
           sessionToken: token
         });
 

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/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
index 12dcdbb..7473f26 100644
--- a/rave-portal-ng/mock-api/util/token-util.js
+++ b/rave-portal-ng/mock-api/util/token-util.js
@@ -10,6 +10,15 @@ define(function(require) {
 
   var tokenUtil = {
 
+    // Create a token
+    generateToken: function() {
+      var length = 32, token = '';
+      for (var i = 0; i < length; i++) {
+        token += Math.random().toString(36).substr(2,1);
+      }
+      return token;
+    },
+
     // Get the token from the headers. If it doesn't
     // exist, or is invalid, then a value of false is returned
     tokenFromHeaders: function(headers) {

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/src/config/requirejs.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/src/config/requirejs.js 
b/rave-portal-ng/src/config/requirejs.js
index 99f7b64..254cb4f 100644
--- a/rave-portal-ng/src/config/requirejs.js
+++ b/rave-portal-ng/src/config/requirejs.js
@@ -5,6 +5,7 @@ require.config({
   paths: {
     rave: 'rave',
     jquery: 'jquery/dist/jquery',
+    underscore: 'underscore/underscore',
     angular: 'angular/angular',
     angularMocks: 'angular-mocks/angular-mocks',
     uiRouter: 'angular-ui-router/release/angular-ui-router',
@@ -13,7 +14,7 @@ require.config({
     angularResource: 'angular-resource/angular-resource',
     angularCookie: 'angular-cookie/angular-cookie',
     angularSanitize: 'angular-sanitize/angular-sanitize',
-    moment: 'moment'
+    moment: 'moment/moment'
   },
 
   // load non-amd dependencies

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/src/subapps/admin/categories/controllers/category.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/src/subapps/admin/categories/controllers/category.js 
b/rave-portal-ng/src/subapps/admin/categories/controllers/category.js
index 12e6b85..3254ba9 100644
--- a/rave-portal-ng/src/subapps/admin/categories/controllers/category.js
+++ b/rave-portal-ng/src/subapps/admin/categories/controllers/category.js
@@ -55,7 +55,7 @@ define(function(require) {
           $state.transitionTo('portal.admin.categories');
         })
         .catch(function(err) {
-          categoriesMessages.errorMessage(err.data);
+          categoriesMessages.errorMessage(err.data.message);
         });
     };
 
@@ -72,7 +72,7 @@ define(function(require) {
           $state.transitionTo('portal.admin.categories');
         })
         .catch(function(err) {
-          categoriesMessages.errorMessage(err.data);
+          categoriesMessages.errorMessage(err.data.message);
         });
     };
   }];

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/src/subapps/admin/categories/controllers/create.js
----------------------------------------------------------------------
diff --git a/rave-portal-ng/src/subapps/admin/categories/controllers/create.js 
b/rave-portal-ng/src/subapps/admin/categories/controllers/create.js
index c9a298a..a0fe61e 100644
--- a/rave-portal-ng/src/subapps/admin/categories/controllers/create.js
+++ b/rave-portal-ng/src/subapps/admin/categories/controllers/create.js
@@ -19,7 +19,7 @@ define(function(require) {
           $scope.categories.push(newResource);
         })
         .catch(function(err) {
-          categoriesMessages.errorMessage(err.data);
+          categoriesMessages.errorMessage(err.data.message);
         });
     };
   }];

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/src/subapps/admin/users/templates/users.html
----------------------------------------------------------------------
diff --git a/rave-portal-ng/src/subapps/admin/users/templates/users.html 
b/rave-portal-ng/src/subapps/admin/users/templates/users.html
index cc88cc3..f53f36a 100644
--- a/rave-portal-ng/src/subapps/admin/users/templates/users.html
+++ b/rave-portal-ng/src/subapps/admin/users/templates/users.html
@@ -7,14 +7,14 @@
     <ul>
       <li ng-switch on="prevPageDisabled()" ng-class="prevPageDisabled()">
         <a ng-switch-when="disabled">&lt;</a>
-        <a ng-switch-default 
ui-sref="portal.admin.users({page:usersMeta.page-1})">&lt;</a>
+        <a ng-switch-default 
ui-sref="portal.admin.users({page:usersMeta.currentPage-1})">&lt;</a>
       </li>
-      <li ng-repeat="n in paginationPages(usersMeta.page, 
usersMeta.pageCount)" ng-class="{ active: n == usersMeta.page }">
+      <li ng-repeat="n in paginationPages(usersMeta.currentPage, 
usersMeta.pageCount)" ng-class="{ active: n == usersMeta.currentPage }">
         <a ui-sref="portal.admin.users({page:n})">{{ n }}</a>
       </li>
       <li ng-switch on="nextPageDisabled()" ng-class="nextPageDisabled()">
         <a ng-switch-when="disabled">&gt;</a>
-        <a ng-switch-default 
ui-sref="portal.admin.users({page:usersMeta.page+1})">&gt;</a>
+        <a ng-switch-default 
ui-sref="portal.admin.users({page:usersMeta.currentPage+1})">&gt;</a>
       </li>
     </ul>
   </div>
@@ -51,14 +51,14 @@
   <ul>
     <li ng-switch on="prevPageDisabled()" ng-class="prevPageDisabled()">
       <a ng-switch-when="disabled">&lt;</a>
-      <a ng-switch-default 
ui-sref="portal.admin.users({page:usersMeta.page-1})">&lt;</a>
+      <a ng-switch-default 
ui-sref="portal.admin.users({page:usersMeta.currentPage-1})">&lt;</a>
     </li>
-    <li ng-repeat="n in paginationPages(usersMeta.page, usersMeta.pageCount)" 
ng-class="{ active: n == usersMeta.page }">
+    <li ng-repeat="n in paginationPages(usersMeta.currentPage, 
usersMeta.pageCount)" ng-class="{ active: n == usersMeta.currentPage }">
       <a ui-sref="portal.admin.users({page:n})">{{ n }}</a>
     </li>
     <li ng-switch on="nextPageDisabled()" ng-class="nextPageDisabled()">
       <a ng-switch-when="disabled">&gt;</a>
-      <a ng-switch-default 
ui-sref="portal.admin.users({page:usersMeta.page+1})">&gt;</a>
+      <a ng-switch-default 
ui-sref="portal.admin.users({page:usersMeta.currentPage+1})">&gt;</a>
     </li>
   </ul>
 </article>

http://git-wip-us.apache.org/repos/asf/rave/blob/26240a1c/rave-portal-ng/src/subapps/auth/create-account/controllers/create-account.js
----------------------------------------------------------------------
diff --git 
a/rave-portal-ng/src/subapps/auth/create-account/controllers/create-account.js 
b/rave-portal-ng/src/subapps/auth/create-account/controllers/create-account.js
index 5cbbd8a..4f0eb4d 100644
--- 
a/rave-portal-ng/src/subapps/auth/create-account/controllers/create-account.js
+++ 
b/rave-portal-ng/src/subapps/auth/create-account/controllers/create-account.js
@@ -22,7 +22,7 @@ define(function(require) {
 
           .catch(function(res) {
             $scope.invalid = true;
-            $scope.error = res.data;
+            $scope.error = res.data.message;
           });
       };
     }

Reply via email to