Repository: stormpath/express-stormpath
Pull request #356 (2016-02-26 06:42:00)

Update to latest config, remove website and api options
This commit brings the config.yaml up-to-date with the latest copy from the framework spec.

As such, several of the form parsing files needed modifications in order to find the field and filed order definitions in their new locations, under the `form` key.

With this commit I am also removing the `website` and `api` options, as intended for the 3.0 release.  The features that were enabled by these options are now enabled by default, so these options are no longer necessary.


Patch:
diff --git a/README.md b/README.md
index 412239f..24e5df0 100644
--- a/README.md
+++ b/README.md
@@ -68,14 +68,15 @@ Follow these steps to add Stormpath user authentication to your Express.js app.
 
   **If your app is a traditional website:**
 
-  Set `website` to `true`. This will setup default views for login, registration, etc.
+  Initialize the Stormpath module, and pass an empty set of options:
 
   ```javascript
-  app.use(stormpath.init(app, {
-    website: true
-  }));
+  app.use(stormpath.init(app, { }));
   ```
 
+  This will enable the default features, such as login and registration pages
+
+
   **If your app is a single page application (Angular, React)**
 
   You will need to tell our library where the root file is.  For example, if
@@ -83,7 +84,6 @@ Follow these steps to add Stormpath user authentication to your Express.js app.
 
   ```javascript
   app.use(stormpath.init(app, {
-    website: true,
     web: {
       spa: {
         enabled: true,
diff --git a/docs/configuration.rst b/docs/configuration.rst
index 250b153..9149f7d 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -64,7 +64,6 @@ initialize the Stormpath middleware:
     var app = express();
     app.use(stormpath.init(app, {
       // Optional configuration options.
-      website: true
     }));
 
     // Once Stormpath has initialized itself, start your web server!
@@ -86,27 +85,35 @@ don't need to specify your credentials or application at all -- these values
 will be automatically populated for you.
 
 
-Option Profiles
----------------
+Disabling Features
+------------------
 
-For most applications, you will want to enable the "website" option.  This will
-configure the library to serve it's default views for login, registration, and
-password reset.  This also configures the JSON API for those same features:
+We enable many features by default, but you might not want to use all of them.
+For example, if you wanted to disable all the default features, you would use
+this configuration:
 
  .. code-block:: javascript
 
     app.use(stormpath.init(app, {
-      website: true
+      web: {
+        login: {
+          enabled: false
+        },
+        logout: {
+          enabled: false
+        },
+        me: {
+          enabled: false
+        },
+        oauth2: {
+          enabled: false
+        }
+        register: {
+          enabled: false
+        }
+      }
     }));
 
-If you do not need these routes (for example, you have an API servce that does not
-serve traditional login and registration pages) you do not need the website profile.
-
-Full documentation of the option profiles will be coming soon.  In the meantime, please
-refer to this YAML configuration which shows you the default options:
-
-https://github.com/stormpath/express-stormpath/blob/master/lib/config.yml
-
 
 Logging
 -------
@@ -154,8 +161,7 @@ Stormpath Client::
   app.use(stormpath.init(app, {
     cacheOptions: {
       store: 'redis'
-    },
-    website: true
+    }
   }));
 
 For a full reference of options, please see the Node SDK client documentation:
@@ -256,7 +262,6 @@ wants to handle. You need this option if the following are true:
   .. code-block:: javascript
 
     app.use(stormpath.init(app, {
-      website: true,
       web: {
         login: {
           uri: '/api/login'
diff --git a/docs/login.rst b/docs/login.rst
index a09a85e..46863eb 100644
--- a/docs/login.rst
+++ b/docs/login.rst
@@ -4,14 +4,16 @@
 Login
 =====
 
-This library can serve a login page for your application, this will happen
-if you opt into the ``{ website: true }`` configuration.  By default the login page
-will be available at this URL:
+By default this library will serve an HTML login page at ``/login``.  You can
+change this URI with the ``web.login.uri`` option.  You can disable this feature
+entirely by setting ``web.login.enabled`` to ``false``.
+
+To view the default page in your example application, navigate to this URL:
 
 http://localhost:3000/login
 
-If the login attempt is successful, we will send the user to the Next URI
-and create the proper session cookies.
+If the login attempt is successful, we will send the user to the Next URI and
+create the proper session cookies.
 
 
 Next URI
diff --git a/docs/logout.rst b/docs/logout.rst
index 7cebcb9..a6a14f5 100644
--- a/docs/logout.rst
+++ b/docs/logout.rst
@@ -7,10 +7,9 @@ Logout
 If you are using browser-based sessions, you'll need a way for the user to
 logout and destroy their session cookies.
 
-If you've enabled ``{ website: true }`` this library will automatically provide a
-POST route at ``/logout``.  Simply make a request of this URL and the session
-cookies will be destroyed.
-
+By default this library will automatically provide a POST route at ``/logout``.
+Simply make a POST request of this URL and the session cookies will be
+destroyed.
 
 Configuration Options
 ---------------------
@@ -18,12 +17,11 @@ Configuration Options
 If you wish to change the logout URI or the redirect url, you can provide the
 following configuration::
 
-    {
-      web: {
-        logout: {
-          enabled: true,
-          uri: '/log-me-out',
-          nextUri: '/goodbye'
-        }
+    web: {
+      logout: {
+        enabled: true,
+        uri: '/log-me-out',
+        nextUri: '/goodbye'
       }
     }
+
diff --git a/docs/registration.rst b/docs/registration.rst
index 9e55954..08659ee 100644
--- a/docs/registration.rst
+++ b/docs/registration.rst
@@ -5,12 +5,13 @@ Registration
 ============
 
 The registration feature of this library allows you to use Stormpath to create
-new accounts in a Stormpath directory.  You can create traditional password-based accounts, or gather account data from other providers such as Facebook and
+new accounts in a Stormpath directory.  You can create traditional password-
+based accounts, or gather account data from other providers such as Facebook and
 Google.
 
-If you've opted into the ``{ website: true }`` option in your configuration, you
-will have registration enabled by default.  The registration page will then be
-available at this URL:
+By default this library will serve an HTML registration page at ``/register``.
+You can change this URI with the ``web.register.uri`` option.  You can disable
+this feature entirely by setting ``web.register.enabled`` to ``false``.
 
 http://localhost:3000/register
 
@@ -26,13 +27,15 @@ we will cover them in detail below:
     {
       web: {
         register: {
-          enabled: true,   // Explicit enable, if not using { website: true }
+          enabled: true,
           uri: '/signup',  // Use a different URL
           nextUri: '/',    // Where to send the user to, if auto login is enabled
-          fields: {
-            /* see next section for documentation */
-          },
-          fieldOrder: [ /* see next section */ ]
+          form: {
+            fields: {
+              /* see next section for documentation */
+            },
+            fieldOrder: [ /* see next section */ ]
+          }
         }
       }
     }
@@ -60,13 +63,17 @@ Configure First Name and Last Name as Optional
 If you would like to show the fields for first name and last name, but not
 require them, you can set required to false::
 
-    register: {
-      fields: {
-        givenName: {
-          required: false
-        },
-        surname: {
-          required: false
+    web: {
+      register: {
+        form: {
+          fields: {
+            givenName: {
+              required: false
+            },
+            surname: {
+              required: false
+            }
+          }
         }
       }
     }
@@ -80,13 +87,17 @@ Disabling First Name and Last Name
 
 If you want to remove these fields entirely, you can set enabled to false::
 
-    register: {
-      fields: {
-        givenName: {
-          enabled: false
-        },
-        surname: {
-          enabled: false
+    web: {
+      register: {
+        form: {
+          fields: {
+            givenName: {
+              enabled: false
+            },
+            surname: {
+              enabled: false
+            }
+          }
         }
       }
     }
@@ -104,15 +115,19 @@ automatically added to the user's custom data object when they register
 successfully.  You can define a custom field by defining a new field object,
 like this::
 
-    register: {
-      fields: {
-        favoriteColor: {
-          enabled: true,
-          label: 'Favorite Color',
-          name: 'favoriteColor',
-          placeholder: 'E.g. Red, Blue',
-          required: true,
-          type: 'text'
+    web: {
+      register: {
+        form: {
+          fields: {
+            favoriteColor: {
+              enabled: true,
+              label: 'Favorite Color',
+              name: 'favoriteColor',
+              placeholder: 'E.g. Red, Blue',
+              required: true,
+              type: 'text'
+            }
+          }
         }
       }
     }
@@ -143,8 +158,12 @@ Changing Field Order
 If you want to change the order of the fields, you can do so by specifying the
 ``fieldOrder`` array::
 
-    register: {
-      fieldOrder: [ "givenName", "surname", "email", "password" ],
+    web: {
+      register: {
+        form: {
+          fieldOrder: [ "givenName", "surname", "email", "password" ]
+        }
+      }
     }
 
 Password Strength Rules
@@ -194,7 +213,7 @@ Auto Login
 If you are *not* using email verificaion (not recommended) you may log users in
 automatically when they register.  This can be achieved with this config::
 
-    {
+    web: {
       register: {
         autoLogin: true,
         nextUri: '/'
diff --git a/docs/upgrading.rst b/docs/upgrading.rst
index 8491813..17d08ab 100644
--- a/docs/upgrading.rst
+++ b/docs/upgrading.rst
@@ -7,6 +7,28 @@ Upgrade Guide
 This page contains specific upgrading instructions to help you migrate between
 Express-Stormpath releases.
 
+Version 2.4.0 -> Version 3.0.0
+------------------------------
+
+**Major Release 3.0**
+
+Shortlist of changes, this document needs to be updated with verbose information
+before release:
+
+- ``website`` and ``api`` options are removed.  The following features are now
+  enabled by default:
+
+  - Registration
+  - Login
+  - Logout
+  - OAuth2 endpoint
+  - ``/me`` endpoint
+
+- ``web.regisgter.fields`` -> ``web.register.form.fields``
+
+- ``web.regisgter.fieldOrder`` -> ``web.register.form.fieldOrder``
+
+
 Version 2.3.7 -> Version 2.4.0
 ------------------------------
 
diff --git a/lib/client.js b/lib/client.js
index 4ca4d7c..9d08402 100644
--- a/lib/client.js
+++ b/lib/client.js
@@ -21,7 +21,6 @@ module.exports = function (config) {
   // Load our integration config.
   configLoader.prepend(new configStrategy.LoadFileConfigStrategy(path.join(__dirname, '/config.yml'), true));
   configLoader.add(new configStrategy.EnrichClientFromRemoteConfigStrategy(ClientFactory));
-  configLoader.add(new configStrategy.EnrichIntegrationConfigStrategy(config));
   configLoader.add(new configStrategy.EnrichIntegrationFromRemoteConfigStrategy(ClientFactory));
 
   return new stormpath.Client(configLoader);
diff --git a/lib/config.yml b/lib/config.yml
index 0383b11..e36c299 100644
--- a/lib/config.yml
+++ b/lib/config.yml
@@ -1,11 +1,7 @@
----
 web:
-  spa:
-    enabled: false
-    view: null
-  produces:
-    - text/html
-    - application/json
+
+  basePath: null
+
   oauth2:
     enabled: true
     uri: "/oauth/token"
@@ -16,124 +12,158 @@ web:
     password:
       enabled: true
       validationStrategy: "local"
+
   accessTokenCookie:
     name: "access_token"
     httpOnly: true
+
+    # See cookie-authentication.md for explanation of
+    # how `null` values behave for these properties.
     secure: null
-    path: "/"
+    path: null
     domain: null
+
   refreshTokenCookie:
     name: "refresh_token"
     httpOnly: true
+
+    # See cookie-authentication.md for explanation of
+    # how `null` values behave for these properties.
     secure: null
-    path: "/"
+    path: null
     domain: null
-  # The registration feature will be automatically enabled by the existence of
-  # a default account store for your application.
+
+  # By default the Stormpath integration should respond to JSON and HTML
+  # requests.  If either is removed from configuration, the integration should
+  # not try to handle the response for the given content type.
+
+  produces:
+    - application/json
+    - text/html
+
   register:
-    enabled: false
+    enabled: true
     uri: "/register"
     nextUri: "/"
+    # autoLogin is possible only if the email verification feature is disabled
+    # on the default account store of the defined Stormpath
+    # application.
     autoLogin: false
-    fields:
-      givenName:
-        enabled: true
-        label: "First Name"
-        name: "givenName"
-        placeholder: "First Name"
-        required: true
-        type: "text"
-      middleName:
-        enabled: false
-        label: "Middle Name"
-        name: "middleName"
-        placeholder: "Middle Name"
-        required: true
-        type: "text"
-      surname:
-        enabled: true
-        label: "Last Name"
-        name: "surname"
-        placeholder: "Last Name"
-        required: true
-        type: "text"
-      username:
-        enabled: false
-        label: "Username"
-        name: "username"
-        placeholder: "Username"
-        required: true
-        type: "text"
-      email:
-        enabled: true
-        label: "Email"
-        name: "email"
-        placeholder: "Email"
-        required: true
-        type: "email"
-      password:
-        enabled: true
-        label: "Password"
-        name: "password"
-        placeholder: "Password"
-        required: true
-        type: "password"
-    fieldOrder:
-      - "username"
-      - "givenName"
-      - "middleName"
-      - "surname"
-      - "email"
-      - "password"
+    form:
+      fields:
+        givenName:
+          enabled: true
+          label: "First Name"
+          placeholder: "First Name"
+          required: true
+          type: "text"
+        middleName:
+          enabled: false
+          label: "Middle Name"
+          placeholder: "Middle Name"
+          required: true
+          type: "text"
+        surname:
+          enabled: true
+          label: "Last Name"
+          placeholder: "Last Name"
+          required: true
+          type: "text"
+        username:
+          enabled: false
+          label: "Username"
+          placeholder: "Username"
+          required: true
+          type: "text"
+        email:
+          enabled: true
+          label: "Email"
+          placeholder: "Email"
+          required: true
+          type: "email"
+        password:
+          enabled: true
+          label: "Password"
+          placeholder: "Password"
+          required: true
+          type: "password"
+        confirmPassword:
+          enabled: false
+          label: "Confirm Password"
+          placeholder: "Confirm Password"
+          required: true
+          type: "password"
+      fieldOrder:
+        - "username"
+        - "givenName"
+        - "middleName"
+        - "surname"
+        - "email"
+        - "password"
+        - "confirmPassword"
     view: "register"
-  # The email verification feature will be automatically enabled if the
-  # default account store for your application has this workflow enabled.
+
+  # Unless verifyEmail.enabled is specifically set to false, the email
+  # verification feature must be automatically enabled if the default account
+  # store for the defined Stormpath application has the email verification
+  # workflow enabled.
   verifyEmail:
+    enabled: null
     uri: "/verify"
-    nextUri: "/"
+    nextUri: "/login"
     view: "verify"
+
   login:
-    enabled: false
+    enabled: true
     uri: "/login"
     nextUri: "/"
     view: "login"
-    fields:
-      login:
-        enabled: true
-        label: "Username or Email"
-        name: "login"
-        placeholder: "Username or Email"
-        required: true
-        type: "text"
-      password:
-        enabled: true
-        label: "Password"
-        name: "password"
-        placeholder: "Password"
-        required: true
-        type: "password"
-    fieldOrder:
-      - "login"
-      - "password"
+    form:
+      fields:
+        login:
+          enabled: true
+          label: "Username or Email"
+          placeholder: "Username or Email"
+          required: true
+          type: "text"
+        password:
+          enabled: true
+          label: "Password"
+          placeholder: "Password"
+          required: true
+          type: "password"
+      fieldOrder:
+        - "login"
+        - "password"
+
   logout:
-    enabled: false
+    enabled: true
     uri: "/logout"
     nextUri: "/"
-  # The forgot password and change password features will be automatically
-  # enabled if the default account store for your application has this workflow
-  # enabled.
+
+  # Unless forgotPassword.enabled is explicitly set to false, this feature
+  # will be automatically enabled if the default account store for the defined
+  # Stormpath application has the password reset workflow enabled.
   forgotPassword:
-    enabled: false
+    enabled: null
     uri: "/forgot"
     view: "forgot-password"
     nextUri: "/login?status=forgot"
+
+  # Unless changePassword.enabled is explicitly set to false, this feature
+  # will be automatically enabled if the default account store for the defined
+  # Stormpath application has the password reset workflow enabled.
   changePassword:
-    enabled: false
+    enabled: null
     autoLogin: false
     uri: "/change"
     nextUri: "/login?status=reset"
     view: "change-password"
     errorUri: "/forgot?status=invalid_sptoken"
+
+  # If idSite.enabled is true, the user should be redirected to ID site for
+  # login, registration, and password reset.  They should also be redirected
+  # through ID Site on logout.
   idSite:
     enabled: false
     uri: "/idSiteResult"
@@ -141,6 +171,8 @@ web:
     loginUri: ""
     forgotUri: "/#/forgot"
     registerUri: "/#/register"
+
+
   # Social login configuration.  This defines the callback URIs for OAuth
   # flows, and the scope that is requested of each provider.  Some providers
   # want space-separated scopes, some want comma-separated.  As such, these
@@ -148,6 +180,7 @@ web:
   #
   # These settings have no affect if the application does not have an account
   # store for the given provider.
+
   social:
     facebook:
       uri: "/callbacks/facebook"
@@ -161,6 +194,37 @@ web:
     linkedin:
       uri: "/callbacks/linkedin"
       scope: "r_basicprofile, r_emailaddress"
+
+  # The /me route is for front-end applications, it returns a JSON object with
+  # the current user object.  The developer can opt-in to expanding account
+  # resources on this enpdoint.
   me:
+    enabled: true
+    uri: "/me"
+    expand:
+      apiKeys: false
+      applications: false
+      customData: false
+      directory: false
+      groupMemberships: false
+      groups: false
+      providerData: false
+      tenant: false
+
+  # If the developer wants our integration to serve their Single Page
+  # Application (SPA) in response to HTML requests for our default routes,
+  # such as /login, then they will need to enable this feature and tell us
+  # where the root of their SPA is.  This is likely a file path on the
+  # filesystem.
+  #
+  # If the developer does not want our integration to handle their SPA, they
+  # will need to configure the framework themeslves and remove 'text/html'
+  # from `stormpath.web.produces`, so that we don not serve our default
+  # HTML views.
+  spa:
     enabled: false
-    uri: "/me"
\ No newline at end of file
+    view: null
+
+  unauthorized:
+    view: "unauthorized"
+
diff --git a/lib/controllers/register.js b/lib/controllers/register.js
index aaf6732..c2150d0 100644
--- a/lib/controllers/register.js
+++ b/lib/controllers/register.js
@@ -82,7 +82,7 @@ function defaultJsonResponse(req, res) {
  */
 
 function applyDefaultAccountFields(stormpathConfig, req) {
-  var registerFields = stormpathConfig.web.register.fields;
+  var registerFields = stormpathConfig.web.register.form.fields;
 
   if (!registerFields.givenName || !registerFields.givenName.required || !registerFields.givenName.enabled && !req.body.givenName) {
     req.body.givenName = 'UNKNOWN';
diff --git a/lib/helpers/get-form-model.js b/lib/helpers/get-form-model.js
index 393c4ef..b1a801c 100644
--- a/lib/helpers/get-form-model.js
+++ b/lib/helpers/get-form-model.js
@@ -13,22 +13,24 @@ var _ = require('lodash');
  * of field objects
  */
 function getFormModel(stormpathConfig) {
-  var definedFields = stormpathConfig.web.register.fields;
+  var definedFields = stormpathConfig.web.register.form.fields;
   // Something about the config parsing will create duplicates in this
   // array, if the developer specifies these fields.  Need to investigate.
-  var fieldOrder = _.uniq(stormpathConfig.web.register.fieldOrder || []);
+  var fieldOrder = _.uniq(stormpathConfig.web.register.form.fieldOrder || []);
   var orderedFields = [];
   // populate the ordered fields first
   fieldOrder.reduce(function (orderedFields, fieldName) {
     var definedField = definedFields[fieldName];
+    definedField.name = fieldName;
     if (definedField && definedField.enabled) {
       orderedFields.push(definedField);
     }
     return orderedFields;
   }, orderedFields);
-  // now add any other fields that were not decalred in the field order
+  // now add any other fields that were not declared in the field order
   Object.keys(definedFields).forEach(function (fieldName) {
     var definedField = definedFields[fieldName];
+    definedField.name = fieldName;
     if (orderedFields.indexOf(definedField) === -1 && definedField.enabled) {
       orderedFields.push(definedField);
     }
diff --git a/lib/helpers/get-form-view-model.js b/lib/helpers/get-form-view-model.js
index f1cb937..6142c0e 100644
--- a/lib/helpers/get-form-view-model.js
+++ b/lib/helpers/get-form-view-model.js
@@ -56,7 +56,9 @@ function setCachedModel(formName, model) {
 function getFormFields(form) {
   // Get fields by fieldOrder.
   var fields = form.fieldOrder.map(function (fieldName) {
-    return form.fields[fieldName];
+    var field = _.clone(form.fields[fieldName]);
+    field.name = fieldName;
+    return field;
   });
 
   // Filter out only the enabled fields.
@@ -197,7 +199,7 @@ function getFormViewModel(formName, config, callback) {
     });
   }
 
-  var form = config.web[formName];
+  var form = config.web[formName].form;
   var fields = getFormFields(form);
 
   var model = {
diff --git a/lib/helpers/get-required-registration-fields.js b/lib/helpers/get-required-registration-fields.js
index 84f15b8..d80fbcd 100644
--- a/lib/helpers/get-required-registration-fields.js
+++ b/lib/helpers/get-required-registration-fields.js
@@ -23,8 +23,9 @@ module.exports = function (config, callback) {
     return callback([]);
   }
 
-  async.forEachOf(config.web.register.fields || {}, function (field, fieldName, cb) {
+  async.forEachOf(config.web.register.form.fields || {}, function (field, fieldName, cb) {
     if (field && field.enabled && field.required) {
+      field.name = fieldName;
       fields.push(field);
     }
 
diff --git a/lib/helpers/prep-account-data.js b/lib/helpers/prep-account-data.js
index 2002af9..a9859ff 100644
--- a/lib/helpers/prep-account-data.js
+++ b/lib/helpers/prep-account-data.js
@@ -33,8 +33,8 @@ module.exports = function (formData, stormpathConfig, callback) {
     throw new Error('prepAccountData must be provided with a callback argument.');
   }
 
-  if (stormpathConfig.web && stormpathConfig.web.register && stormpathConfig.web.register.fields && stormpathConfig.web.register.fields.passwordConfirm && stormpathConfig.web.register.fields.passwordConfirm.name) {
-    passwordConfirmFieldName = stormpathConfig.web.register.fields.passwordConfirm.name;
+  if (stormpathConfig.web && stormpathConfig.web.register && stormpathConfig.web.register.form.fields && stormpathConfig.web.register.form.fields.passwordConfirm && stormpathConfig.web.register.form.fields.passwordConfirm.name) {
+    passwordConfirmFieldName = stormpathConfig.web.register.form.fields.passwordConfirm.name;
   }
 
   var coreFields = [
diff --git a/lib/helpers/sanitize-form-data.js b/lib/helpers/sanitize-form-data.js
index 51c156b..423944d 100644
--- a/lib/helpers/sanitize-form-data.js
+++ b/lib/helpers/sanitize-form-data.js
@@ -21,7 +21,7 @@ module.exports = function (formData, stormpathConfig) {
     throw new Error('sanitizeFormData must be provided with a stormpathConfig argument.');
   }
 
-  var registerFields = stormpathConfig.web.register.fields;
+  var registerFields = stormpathConfig.web.register.form.fields;
 
   delete formData[registerFields.password.name];
 
diff --git a/lib/helpers/validate-account.js b/lib/helpers/validate-account.js
index 89b9a57..505fe1a 100644
--- a/lib/helpers/validate-account.js
+++ b/lib/helpers/validate-account.js
@@ -27,12 +27,12 @@ module.exports = function (formData, stormpathConfig, callback) {
   getRequiredRegistrationFields(stormpathConfig, function (requiredFields) {
     async.each(requiredFields, function (field, cb) {
       if (accountFieldNames.indexOf(field.name) <= -1 || (accountFieldNames.indexOf(field.name) > -1 && !formData[field.name])) {
-        errors.push(new Error((field.label || field.name) + ' required.'));
+        errors.push(new Error((field.label || field.label) + ' required.'));
       }
 
       cb();
     }, function () {
-      var registerFields = stormpathConfig.web.register.fields;
+      var registerFields = stormpathConfig.web.register.form.fields;
       var configuredFieldNames = Object.keys(registerFields);
       if (registerFields.passwordConfirm && (registerFields.passwordConfirm.enabled || registerFields.passwordConfirm.required)) {
         var passwordFieldName = registerFields.password.name;
diff --git a/lib/views/login.jade b/lib/views/login.jade
index e027899..ec15aef 100644
--- a/lib/views/login.jade
+++ b/lib/views/login.jade
@@ -5,7 +5,7 @@ block vars
   - var description = 'Log into your account!'
   - var bodytag = 'login'
   - var socialProviders = stormpathConfig.web.social
-  - var registerFields = stormpathConfig.web.register.fields
+  - var registerFields = stormpathConfig.web.register.form.fields
 
 block body
 


Test patch:
diff --git a/test/controllers/test-register.js b/test/controllers/test-register.js
index 1a6a908..bcfb2e6 100644
--- a/test/controllers/test-register.js
+++ b/test/controllers/test-register.js
@@ -112,12 +112,14 @@ function NamesOptionalRegistrationFixture(stormpathApplication) {
     web: {
       register: {
         enabled: true,
-        fields: {
-          surname: {
-            required: false
-          },
-          givenName: {
-            required: false
+        form: {
+          fields: {
+            surname: {
+              required: false
+            },
+            givenName: {
+              required: false
+            }
           }
         }
       }
@@ -155,12 +157,14 @@ function NamesDisabledRegistrationFixture(stormpathApplication) {
     web: {
       register: {
         enabled: true,
-        fields: {
-          surname: {
-            enabled: false
-          },
-          givenName: {
-            enabled: false
+        form: {
+          fields: {
+            surname: {
+              enabled: false
+            },
+            givenName: {
+              enabled: false
+            }
           }
         }
       }
@@ -197,23 +201,25 @@ function CustomFieldRegistrationFixture(stormpathApplication) {
     web: {
       register: {
         enabled: true,
-        fields: {
-          color: {
-            enabled: true,
-            name: 'color',
-            placeholder: 'Favorite Color',
-            required: true,
-            type: 'text'
+        form: {
+          fields: {
+            color: {
+              enabled: true,
+              name: 'color',
+              placeholder: 'Favorite Color',
+              required: true,
+              type: 'text'
+            },
+            music: {
+              enabled: true,
+              name: 'music',
+              placeholder: 'Music Preference',
+              required: false,
+              type: 'text'
+            }
           },
-          music: {
-            enabled: true,
-            name: 'music',
-            placeholder: 'Music Preference',
-            required: false,
-            type: 'text'
-          }
-        },
-        fieldOrder: ['givenName', 'surname', 'color', 'music', 'email', 'password']
+          fieldOrder: ['givenName', 'surname', 'color', 'music', 'email', 'password']
+        }
       }
     }
   });
@@ -779,29 +785,29 @@ describe('register', function () {
             var emailField = $(formFields[4]);
             var passwordField = $(formFields[5]);
 
-            assert.equal(givenNameField.attr('placeholder'), config.web.register.fields.givenName.placeholder);
-            assert.equal(givenNameField.attr('required') === 'required', config.web.register.fields.givenName.required);
-            assert.equal(givenNameField.attr('type'), config.web.register.fields.givenName.type);
+            assert.equal(givenNameField.attr('placeholder'), config.web.register.form.fields.givenName.placeholder);
+            assert.equal(givenNameField.attr('required') === 'required', config.web.register.form.fields.givenName.required);
+            assert.equal(givenNameField.attr('type'), config.web.register.form.fields.givenName.type);
 
-            assert.equal(surnameField.attr('placeholder'), config.web.register.fields.surname.placeholder);
-            assert.equal(surnameField.attr('required') === 'required', config.web.register.fields.surname.required);
-            assert.equal(surnameField.attr('type'), config.web.register.fields.surname.type);
+            assert.equal(surnameField.attr('placeholder'), config.web.register.form.fields.surname.placeholder);
+            assert.equal(surnameField.attr('required') === 'required', config.web.register.form.fields.surname.required);
+            assert.equal(surnameField.attr('type'), config.web.register.form.fields.surname.type);
 
-            assert.equal(colorField.attr('placeholder'), config.web.register.fields.color.placeholder);
-            assert.equal(colorField.attr('required') === 'required', config.web.register.fields.color.required);
-            assert.equal(colorField.attr('type'), config.web.register.fields.color.type);
+            assert.equal(colorField.attr('placeholder'), config.web.register.form.fields.color.placeholder);
+            assert.equal(colorField.attr('required') === 'required', config.web.register.form.fields.color.required);
+            assert.equal(colorField.attr('type'), config.web.register.form.fields.color.type);
 
-            assert.equal(musicField.attr('placeholder'), config.web.register.fields.music.placeholder);
-            assert.equal(musicField.attr('required') === 'required', config.web.register.fields.music.required);
-            assert.equal(musicField.attr('type'), config.web.register.fields.music.type);
+            assert.equal(musicField.attr('placeholder'), config.web.register.form.fields.music.placeholder);
+            assert.equal(musicField.attr('required') === 'required', config.web.register.form.fields.music.required);
+            assert.equal(musicField.attr('type'), config.web.register.form.fields.music.type);
 
-            assert.equal(emailField.attr('placeholder'), config.web.register.fields.email.placeholder);
-            assert.equal(emailField.attr('required') === 'required', config.web.register.fields.email.required);
-            assert.equal(emailField.attr('type'), config.web.register.fields.email.type);
+            assert.equal(emailField.attr('placeholder'), config.web.register.form.fields.email.placeholder);
+            assert.equal(emailField.attr('required') === 'required', config.web.register.form.fields.email.required);
+            assert.equal(emailField.attr('type'), config.web.register.form.fields.email.type);
 
-            assert.equal(passwordField.attr('placeholder'), config.web.register.fields.password.placeholder);
-            assert.equal(passwordField.attr('required') === 'required', config.web.register.fields.password.required);
-            assert.equal(passwordField.attr('type'), config.web.register.fields.password.type);
+            assert.equal(passwordField.attr('placeholder'), config.web.register.form.fields.password.placeholder);
+            assert.equal(passwordField.attr('required') === 'required', config.web.register.form.fields.password.required);
+            assert.equal(passwordField.attr('type'), config.web.register.form.fields.password.type);
 
             done();
 
diff --git a/test/controllers/test-social-providers.js b/test/controllers/test-social-providers.js
index f33526d..ac2b238 100644
--- a/test/controllers/test-social-providers.js
+++ b/test/controllers/test-social-providers.js
@@ -24,8 +24,7 @@ describe('/spa-config', function () {
     app = helpers.createStormpathExpressApp({
       application: {
         href: stormpathApplication.href
-      },
-      website: true
+      }
     });
 
     done(null, app);
diff --git a/test/fixtures/produces-fixture.js b/test/fixtures/produces-fixture.js
index 19ae9e4..d55811a 100644
--- a/test/fixtures/produces-fixture.js
+++ b/test/fixtures/produces-fixture.js
@@ -22,7 +22,6 @@ var helpers = require('../helpers');
 function ProducesFixture(stormpathApplication, producesArray, readyFn) {
   this.expressApp = helpers.createStormpathExpressApp({
     application: stormpathApplication,
-    website: true,
     web: {
       produces: producesArray
     }
diff --git a/test/handlers/test-me.js b/test/handlers/test-me.js
index 744d6e2..0dafb39 100644
--- a/test/handlers/test-me.js
+++ b/test/handlers/test-me.js
@@ -10,7 +10,6 @@ function prepateMeTestFixture(stormpathApplication, cb) {
 
   var app = helpers.createStormpathExpressApp({
     application: stormpathApplication,
-    website: true,
     expand: {
       customData: true
     },
diff --git a/test/handlers/test-post-login-handler.js b/test/handlers/test-post-login-handler.js
index f2532bf..c7b0bfc 100644
--- a/test/handlers/test-post-login-handler.js
+++ b/test/handlers/test-post-login-handler.js
@@ -10,7 +10,6 @@ function preparePostLoginExpansionTestFixture(stormpathApplication, cb) {
 
   var app = helpers.createStormpathExpressApp({
     application: stormpathApplication,
-    website: true,
     expand: {
       customData: true
     },
@@ -40,7 +39,6 @@ function preparePostLoginPassThroughTestFixture(stormpathApplication, cb) {
 
   fixture.expressApp = helpers.createStormpathExpressApp({
     application: stormpathApplication,
-    website: true,
     postLoginHandler: function (account, req, res, next) {
       fixture.sideEffect = sideEffectData;
       next();
diff --git a/test/handlers/test-post-registration-handler.js b/test/handlers/test-post-registration-handler.js
index 3891f16..17479f1 100644
--- a/test/handlers/test-post-registration-handler.js
+++ b/test/handlers/test-post-registration-handler.js
@@ -12,18 +12,19 @@ function preparePostRegistrationExpansionTestFixture(stormpathApplication, cb) {
 
   var app = helpers.createStormpathExpressApp({
     application: stormpathApplication,
-    website: true,
     expand: {
       customData: true
     },
     web: {
       register: {
-        fields: {
-          favoriteColor: {
-            name: 'favoriteColor',
-            placeholder: 'favoriteColor',
-            required: false,
-            type: 'text'
+        form: {
+          fields: {
+            favoriteColor: {
+              name: 'favoriteColor',
+              placeholder: 'favoriteColor',
+              required: false,
+              type: 'text'
+            }
           }
         }
       }
@@ -54,7 +55,6 @@ function preparePostRegistrationPassThroughTestFixture(stormpathApplication, cb)
 
   fixture.expressApp = helpers.createStormpathExpressApp({
     application: stormpathApplication,
-    website: true,
     postRegistrationHandler: function (account, req, res, next) {
       fixture.sideEffect = fixture.sideEffectData;
       next();
diff --git a/test/helpers/test-get-required-registration-fields.js b/test/helpers/test-get-required-registration-fields.js
index 19276ff..dd10f63 100644
--- a/test/helpers/test-get-required-registration-fields.js
+++ b/test/helpers/test-get-required-registration-fields.js
@@ -16,7 +16,9 @@ describe('getRequiredRegistrationFields', function () {
     var config = {
       web: {
         register: {
-          fields: {}
+          form: {
+            fields: {}
+          }
         }
       }
     };
@@ -31,20 +33,22 @@ describe('getRequiredRegistrationFields', function () {
     var config = {
       web: {
         register: {
-          fields: {
-            givenName: {
-              enabled: true,
-              name: 'givenName',
-              required: true
-            },
-            surname: {
-              enabled: true,
-              name: 'surname',
-              required: true
-            },
-            email: {
-              name: 'email',
-              required: false
+          form: {
+            fields: {
+              givenName: {
+                enabled: true,
+                name: 'givenName',
+                required: true
+              },
+              surname: {
+                enabled: true,
+                name: 'surname',
+                required: true
+              },
+              email: {
+                name: 'email',
+                required: false
+              }
             }
           }
         }
diff --git a/test/helpers/test-get-user.js b/test/helpers/test-get-user.js
index 8f445f7..4151bb3 100644
--- a/test/helpers/test-get-user.js
+++ b/test/helpers/test-get-user.js
@@ -458,7 +458,6 @@ describe('getUser', function () {
 
     var app = helpers.createStormpathExpressApp({
       application: stormpathApplication,
-      website: true,
       web: {
         oauth2: {
           password: {
diff --git a/test/helpers/test-prep-account-data.js b/test/helpers/test-prep-account-data.js
index f3fa705..e267e7c 100644
--- a/test/helpers/test-prep-account-data.js
+++ b/test/helpers/test-prep-account-data.js
@@ -8,26 +8,28 @@ describe('prepAccountData', function () {
   var config = {
     web: {
       register: {
-        fields: {
-          givenName: {
-            name: 'givenName',
-            required: true
-          },
-          surname: {
-            name: 'surname',
-            required: true
-          },
-          email: {
-            name: 'email',
-            required: true
-          },
-          password: {
-            name: 'password',
-            required: true
-          },
-          passwordConfirm: {
-            name: 'passwordConfirmWoo',
-            required: true
+        form: {
+          fields: {
+            givenName: {
+              name: 'givenName',
+              required: true
+            },
+            surname: {
+              name: 'surname',
+              required: true
+            },
+            email: {
+              name: 'email',
+              required: true
+            },
+            password: {
+              name: 'password',
+              required: true
+            },
+            passwordConfirm: {
+              name: 'passwordConfirmWoo',
+              required: true
+            }
           }
         }
       }
diff --git a/test/helpers/test-sanitize-form-data.js b/test/helpers/test-sanitize-form-data.js
index b8a2700..2cb6a76 100644
--- a/test/helpers/test-sanitize-form-data.js
+++ b/test/helpers/test-sanitize-form-data.js
@@ -8,26 +8,28 @@ describe('sanitizeFormData', function () {
   var config = {
     web: {
       register: {
-        fields: {
-          givenName: {
-            name: 'givenName',
-            required: true
-          },
-          surname: {
-            name: 'surname',
-            required: true
-          },
-          email: {
-            name: 'email',
-            required: true
-          },
-          password: {
-            name: 'password',
-            required: true
-          },
-          passwordConfirm: {
-            name: 'passwordConfirmWoo',
-            required: true
+        form: {
+          fields: {
+            givenName: {
+              name: 'givenName',
+              required: true
+            },
+            surname: {
+              name: 'surname',
+              required: true
+            },
+            email: {
+              name: 'email',
+              required: true
+            },
+            password: {
+              name: 'password',
+              required: true
+            },
+            passwordConfirm: {
+              name: 'passwordConfirmWoo',
+              required: true
+            }
           }
         }
       }
diff --git a/test/helpers/test-validate-account.js b/test/helpers/test-validate-account.js
index 5dd4eea..f261854 100644
--- a/test/helpers/test-validate-account.js
+++ b/test/helpers/test-validate-account.js
@@ -8,31 +8,33 @@ describe('validateAccount', function () {
   var config = {
     web: {
       register: {
-        fields: {
-          givenName: {
-            enabled: true,
-            name: 'givenName',
-            required: true
-          },
-          surname: {
-            enabled: true,
-            name: 'surname',
-            required: true
-          },
-          email: {
-            enabled: true,
-            name: 'email',
-            required: true
-          },
-          password: {
-            enabled: true,
-            name: 'password',
-            required: true
-          },
-          passwordConfirm: {
-            enabled: true,
-            name: 'passwordConfirm',
-            required: true
+        form: {
+          fields: {
+            givenName: {
+              enabled: true,
+              name: 'givenName',
+              required: true
+            },
+            surname: {
+              enabled: true,
+              name: 'surname',
+              required: true
+            },
+            email: {
+              enabled: true,
+              name: 'email',
+              required: true
+            },
+            password: {
+              enabled: true,
+              name: 'password',
+              required: true
+            },
+            passwordConfirm: {
+              enabled: true,
+              name: 'passwordConfirm',
+              required: true
+            }
           }
         }
       }