From f2049d59393f23ebabd133ecb34f91c2bdc0b844 Mon Sep 17 00:00:00 2001
From: Lloyd Hilaiel <lloyd@hilaiel.com>
Date: Wed, 28 Mar 2012 21:43:16 -0600
Subject: [PATCH] implement and test the prolong_session wsapi - which extends
 the duration of an existing session from the ephemeral duration (an hour) to
 full authentication session length (2 weeks) - doesn not change the start
 time of the session, so is a noop when invoked multiple times.  to be added
 to frontend code once user acknoledges ownership of device.

---
 lib/wsapi/prolong_session.js  |  18 +++++
 lib/wsapi_client.js           |   9 +++
 tests/lib/wsapi.js            |   4 ++
 tests/session-prolong-test.js | 119 ++++++++++++++++++++++++++++++++++
 4 files changed, 150 insertions(+)
 create mode 100644 lib/wsapi/prolong_session.js
 create mode 100755 tests/session-prolong-test.js

diff --git a/lib/wsapi/prolong_session.js b/lib/wsapi/prolong_session.js
new file mode 100644
index 000000000..2c9d5c02e
--- /dev/null
+++ b/lib/wsapi/prolong_session.js
@@ -0,0 +1,18 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const
+config = require('../configuration.js'),
+wsapi = require('../wsapi.js');
+
+exports.method = 'post';
+exports.writes_db = false;
+exports.authed = 'assertion';
+exports.i18n = false;
+
+exports.process = function(req, res) {
+  wsapi.authenticateSession(req.session, req.session.userid, req.session.auth_level,
+                            config.get('authentication_duration_ms'));
+  res.send(200);
+};
diff --git a/lib/wsapi_client.js b/lib/wsapi_client.js
index a86095e8f..2bb82fb5d 100644
--- a/lib/wsapi_client.js
+++ b/lib/wsapi_client.js
@@ -42,6 +42,15 @@ exports.clearCookies = function(ctx) {
   if (ctx && ctx.session) delete ctx.session;
 };
 
+exports.getCookie = function(ctx, which) {
+  if (typeof which === 'string') which = new Regex('/^' + which + '$/');
+  var cookieNames = Object.keys(ctx.cookieJar);
+  for (var i = 0; i < cookieNames.length; i++) {
+    if (which.test(cookieNames[i])) return ctx.cookieJar[cookieNames[i]];
+  }
+  return null;
+};
+
 exports.injectCookies = injectCookies;
 
 exports.get = function(cfg, path, context, getArgs, cb) {
diff --git a/tests/lib/wsapi.js b/tests/lib/wsapi.js
index 0bfd9989c..868c86d02 100644
--- a/tests/lib/wsapi.js
+++ b/tests/lib/wsapi.js
@@ -21,6 +21,10 @@ exports.injectCookies = function(cookies) {
   wcli.injectCookies({cookieJar: cookies}, context);
 };
 
+exports.getCookie = function(which) {
+  return wcli.getCookie(context, which);
+};
+
 exports.get = function (path, getArgs) {
   return function () {
     wcli.get(configuration, path, context, getArgs, this.callback);
diff --git a/tests/session-prolong-test.js b/tests/session-prolong-test.js
new file mode 100755
index 000000000..79749fd79
--- /dev/null
+++ b/tests/session-prolong-test.js
@@ -0,0 +1,119 @@
+#!/usr/bin/env node
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+require('./lib/test_env.js');
+
+const assert =
+require('assert'),
+vows = require('vows'),
+start_stop = require('./lib/start-stop.js'),
+wsapi = require('./lib/wsapi.js'),
+db = require('../lib/db.js'),
+config = require('../lib/configuration.js'),
+bcrypt = require('bcrypt');
+
+var suite = vows.describe('password-length');
+
+// disable vows (often flakey?) async error behavior
+suite.options.error = false;
+
+start_stop.addStartupBatches(suite);
+
+const TEST_EMAIL = 'someuser@somedomain.com',
+      PASSWORD = 'thisismypassword';
+
+var token = undefined;
+
+// first stage the account
+suite.addBatch({
+  "account staging": {
+    topic: wsapi.post('/wsapi/stage_user', {
+      email: TEST_EMAIL,
+      site: 'fakesite.com'
+    }),
+    "works":     function(err, r) {
+      assert.equal(r.code, 200);
+    }
+  }
+});
+
+// wait for the token
+suite.addBatch({
+  "a token": {
+    topic: function() {
+      start_stop.waitForToken(this.callback);
+    },
+    "is obtained": function (t) {
+      assert.strictEqual(typeof t, 'string');
+      token = t;
+    }
+  }
+});
+
+// create a new account via the api with (first address)
+suite.addBatch({
+  "setting password": {
+    topic: function() {
+      wsapi.post('/wsapi/complete_user_creation', {
+        token: token,
+        pass: PASSWORD
+      }).call(this);
+    },
+    "works just fine": function(err, r) {
+      assert.equal(r.code, 200);
+    }
+  }
+});
+
+suite.addBatch({
+  "authenticating with the password": {
+    topic: wsapi.post('/wsapi/authenticate_user', {
+      email: TEST_EMAIL,
+      pass: PASSWORD,
+      ephemeral: true
+    }),
+    "works as expected": function(err, r) {
+      assert.strictEqual(JSON.parse(r.body).success, true);
+    }
+  }
+});
+
+suite.addBatch({
+  "session length": {
+    topic: function() {
+      this.callback(wsapi.getCookie(/^browserid_state/));
+    },
+    "is short (ephemeral)": function(cookie) {
+      assert.equal(cookie.split('.')[3], config.get('ephemeral_session_duration_ms'));
+    }
+  }
+});
+
+suite.addBatch({
+  "session prolonging": {
+    topic: wsapi.post('/wsapi/prolong_session', {}),
+    "returns 200": function(err, r) {
+      assert.strictEqual(r.code, 200);
+    }
+  }
+});
+
+suite.addBatch({
+  "session length": {
+    topic: function() {
+      this.callback(wsapi.getCookie(/^browserid_state/));
+    },
+    "becomes long": function(cookie) {
+      assert.equal(cookie.split('.')[3], config.get('authentication_duration_ms'));
+    }
+  }
+});
+
+start_stop.addShutdownBatches(suite);
+
+// run or export the suite.
+if (process.argv[1] === __filename) suite.run();
+else suite.export(module);
-- 
GitLab