<commit_before>Deepstreams._ensureIndex({
  shortId: 1
}, {
  unique: 1
});

Deepstreams._ensureIndex({
  onAir: 1,
  live: 1
});

ContextBlocks._ensureIndex({
  streamShortId: 1
});

ContextBlocks._ensureIndex({
  deleted: 1
});

SuggestedContextBlocks._ensureIndex({
  streamShortId: 1
});

SuggestedContextBlocks._ensureIndex({
  suggestionStatus: 1
});

Meteor.users._ensureIndex({
  username: 1
});

var deepstreamFields = {
  'deleted': 0,
  //'streams.fullDetails': 0,
  'streams.reference.description': 0,
  'streams.authorId': 0,
  'streams.searchQuery': 0,
  'analytics.shares': 0,
  'analytics.views.byConnection': 0,
  'analytics.views.byIP': 0,
  'analytics.views.byId': 0,
  'curatorSignupCodes': 0
};

var contextFields = {
  'fullDetails': 0,
  'authorId': 0,
  'savedAt': 0,
  'addedAt': 0,
  'searchQuery': 0
};

/* now defunct? delete soon
Meteor.publish("deepstreamsOnAir", function() {
  this.unblock();
  return Deepstreams.find({
    onAir: true
  }, {
    sort: { createdAt: -1 },
    fields: deepstreamFields,
    limit: PUB_SIZE
  });
});
*/

Meteor.publish("deepstreamsMostRecent", function() {
  this.unblock();
  return Deepstreams.find({
    onAir: true
  }, {
    sort: { createdAt: -1 },
    fields: deepstreamFields,
    limit: 8
  });
});

Meteor.publish("deepstreamsEditorsPick", function() {
  this.unblock();
  return Deepstreams.find({
    onAir: true,
    editorsPick: true
  }, {
    sort: { editorsPickAt: -1 },
    fields: deepstreamFields,
    limit: 8
  });
});

Meteor.publish('deepstreamsForAdmin', function( search, published ) {
  this.unblock();
  check(search, Match.OneOf( String, null, undefined ));
  let query      = {onAir: false},
      projection = {
                     limit: 10,
                     sort: { createdAt: -1 },
                     fields: deepstreamFields,
                   };
  if (search) {
    let regex = new RegExp( search, 'i' );
    query = {
      $or: [
        { title: regex },
        { description: regex },
        { curatorName: regex },
        { streamPathSegment: regex },
        { curatorUsername: regex }
      ]
    };
    projection.limit = 100;
  }
  if(published){
    query.onAir = true;
  } else {
    query.onAir = false;
  }
  return Deepstreams.find( query, projection );
});

Meteor.publish("bestStreams", function() {
  this.unblock();
  return Streams.find({ oneIfCurrent: 1 }, {
    sort: {
      currentViewers: -1
    },
    limit: 20
  });
});
Meteor.publish("mostRecentStreams", function() {
  this.unblock();
  return Streams.find({ oneIfCurrent: 1 }, {
    sort: {
      creationDate: -1
    },
    limit: 20
  });
});

Meteor.publish("singleDeepstreamOnAir", function(userPathSegment, shortId) {
  this.unblock();
  check(shortId, String);
    return Deepstreams.find({userPathSegment: userPathSegment, shortId: shortId, onAir: true},{
      fields: deepstreamFields
    });
});

Meteor.publish("singleDeepstream", function(userPathSegment, shortId) {
  this.unblock();
  check(shortId, String);
  if (this.userId) {
    return Deepstreams.find({userPathSegment: userPathSegment, shortId: shortId, $or: [{curatorIds: this.userId}, {onAir: true}]},{
      fields: deepstreamFields
    });
  } else {
    return Deepstreams.find({userPathSegment: userPathSegment, shortId: shortId, onAir: true},{
      fields: deepstreamFields
    });
  }
});

Meteor.publish("deepstreamContext", function(streamShortId) {
  this.unblock();
  check(streamShortId, String);
  return ContextBlocks.find({streamShortId: streamShortId, deleted: {$ne: true}},{
    fields: contextFields
  });
});

Meteor.publish("deepstreamSuggestedContext", function(streamShortId) {
  this.unblock();
  check(streamShortId, String);
  return SuggestedContextBlocks.find({streamShortId: streamShortId, suggestionStatus: 'pending'},{
    fields: contextFields
  });
});

Meteor.publish("deepstreamPreviewContext", function(streamShortId) {
  this.unblock();
  check(streamShortId, String);
  return ContextBlocks.find({streamShortId: streamShortId, deleted: {$ne: true}, type: {$in: HOMEPAGE_PREVIEW_CONTEXT_TYPES}},{
    fields: contextFields
  });
});

Meteor.publish("myDeepstreams", function() {
  this.unblock();
  return Deepstreams.find({curatorIds: this.userId, deleted: {$ne: true}}, {
    fields: deepstreamFields, sort: {createdAt :-1}
  });
});

Meteor.publish("minimalUsersPub", function(userIds) {
  this.unblock();
  if (!userIds || !userIds.length || userIds.length > 1000) {
    return this.ready();
  }
  return Meteor.users.find({_id: {
    $in: userIds
  }}, {
    fields: {
      "profile.name": 1,
      "username": 1
    }
  });
});

Meteor.publish("userData", function () {
  this.unblock();
  if (this.userId) {
    return Meteor.users.find({_id: this.userId},
      {fields: {
        'accessPriority': 1,
        "services.twitter.id": 1,
        "keenScopedKey": 1,
        "keenProjectId": 1,
        "admin": 1,
        "profile": 1
      }});
  } else {
    this.ready();
  }
});

Meteor.publish('usersForAdmin', function( search ) {
  check(search, Match.OneOf( String, null, undefined ));
  let query      = {},
      projection = {
                     limit: 100,
                     sort: { createdAt: -1 },
                     fields: {
                       'profile': 1,
                       'username': 1,
                       'createdAt': 1,
                       'services.twitter.id' : 1,
                       'emails.address' : 1
                     },
                   };
  if (search) {
    let regex = new RegExp( search, 'i' );
    query = {
      $or: [
        { "profile.name": regex },
        { emails: { $elemMatch: {address: regex}}},
        { username: regex },
        { "twitter.screename": regex }
      ]
    };
    projection.limit = 100;
  }
  return Meteor.users.find( query, projection );
});

// this publishes info on server facts (used on /stats page)
Facts.setUserIdFilter(function (userId) {
  var user = Meteor.users.findOne(userId);
  return user && user.admin;
});
<commit_msg>tidy publications<commit_after>Deepstreams._ensureIndex({
  shortId: 1
}, {
  unique: 1
});

Deepstreams._ensureIndex({
  onAir: 1,
  live: 1
});

ContextBlocks._ensureIndex({
  streamShortId: 1
});

ContextBlocks._ensureIndex({
  deleted: 1
});

SuggestedContextBlocks._ensureIndex({
  streamShortId: 1
});

SuggestedContextBlocks._ensureIndex({
  suggestionStatus: 1
});

Meteor.users._ensureIndex({
  username: 1
});

var deepstreamFields = {
  'deleted': 0,
  //'streams.fullDetails': 0,
  'streams.reference.description': 0,
  'streams.authorId': 0,
  'streams.searchQuery': 0,
  'analytics.shares': 0,
  'analytics.views.byConnection': 0,
  'analytics.views.byIP': 0,
  'analytics.views.byId': 0,
  'curatorSignupCodes': 0
};

var contextFields = {
  'fullDetails': 0,
  'authorId': 0,
  'savedAt': 0,
  'addedAt': 0,
  'searchQuery': 0
};

Meteor.publish("deepstreamsMostRecent", function() {
  this.unblock();
  return Deepstreams.find({
    onAir: true
  }, {
    sort: { createdAt: -1 },
    fields: deepstreamFields,
    limit: 8
  });
});

Meteor.publish("deepstreamsEditorsPick", function() {
  this.unblock();
  return Deepstreams.find({
    onAir: true,
    editorsPick: true
  }, {
    sort: { editorsPickAt: -1 },
    fields: deepstreamFields,
    limit: 8
  });
});

Meteor.publish('deepstreamsForAdmin', function( search, published ) {
  this.unblock();
  check(search, Match.OneOf( String, null, undefined ));
  let query      = {onAir: false},
      projection = {
                     limit: 10,
                     sort: { createdAt: -1 },
                     fields: deepstreamFields,
                   };
  if (search) {
    let regex = new RegExp( search, 'i' );
    query = {
      $or: [
        { title: regex },
        { description: regex },
        { curatorName: regex },
        { streamPathSegment: regex },
        { curatorUsername: regex }
      ]
    };
    projection.limit = 100;
  }
  if(published){
    query.onAir = true;
  } else {
    query.onAir = false;
  }
  return Deepstreams.find( query, projection );
});

Meteor.publish("bestStreams", function() {
  this.unblock();
  return Streams.find({ oneIfCurrent: 1 }, {
    sort: {
      currentViewers: -1
    },
    limit: 20
  });
});
Meteor.publish("mostRecentStreams", function() {
  this.unblock();
  return Streams.find({ oneIfCurrent: 1 }, {
    sort: {
      creationDate: -1
    },
    limit: 20
  });
});

Meteor.publish("singleDeepstreamOnAir", function(userPathSegment, shortId) {
  this.unblock();
  check(shortId, String);
    return Deepstreams.find({userPathSegment: userPathSegment, shortId: shortId, onAir: true},{
      fields: deepstreamFields
    });
});

Meteor.publish("singleDeepstream", function(userPathSegment, shortId) {
  this.unblock();
  check(shortId, String);
  if (this.userId) {
    return Deepstreams.find({userPathSegment: userPathSegment, shortId: shortId, $or: [{curatorIds: this.userId}, {onAir: true}]},{
      fields: deepstreamFields
    });
  } else {
    return Deepstreams.find({userPathSegment: userPathSegment, shortId: shortId, onAir: true},{
      fields: deepstreamFields
    });
  }
});

Meteor.publish("deepstreamContext", function(streamShortId) {
  this.unblock();
  check(streamShortId, String);
  return ContextBlocks.find({streamShortId: streamShortId, deleted: {$ne: true}},{
    fields: contextFields
  });
});

Meteor.publish("deepstreamSuggestedContext", function(streamShortId) {
  this.unblock();
  check(streamShortId, String);
  return SuggestedContextBlocks.find({streamShortId: streamShortId, suggestionStatus: 'pending'},{
    fields: contextFields
  });
});

Meteor.publish("deepstreamPreviewContext", function(streamShortId) {
  this.unblock();
  check(streamShortId, String);
  return ContextBlocks.find({streamShortId: streamShortId, deleted: {$ne: true}, type: {$in: HOMEPAGE_PREVIEW_CONTEXT_TYPES}},{
    fields: contextFields
  });
});

Meteor.publish("myDeepstreams", function() {
  this.unblock();
  return Deepstreams.find({curatorIds: this.userId, deleted: {$ne: true}}, {
    fields: deepstreamFields, sort: {createdAt :-1}
  });
});

Meteor.publish("minimalUsersPub", function(userIds) {
  this.unblock();
  if (!userIds || !userIds.length || userIds.length > 1000) {
    return this.ready();
  }
  return Meteor.users.find({_id: {
    $in: userIds
  }}, {
    fields: {
      "profile.name": 1,
      "username": 1
    }
  });
});

Meteor.publish("userData", function () {
  this.unblock();
  if (this.userId) {
    return Meteor.users.find({_id: this.userId},
      {fields: {
        'accessPriority': 1,
        "services.twitter.id": 1,
        "keenScopedKey": 1,
        "keenProjectId": 1,
        "admin": 1,
        "profile": 1
      }});
  } else {
    this.ready();
  }
});

Meteor.publish('usersForAdmin', function( search ) {
  check(search, Match.OneOf( String, null, undefined ));
  let query      = {},
      projection = {
                     limit: 100,
                     sort: { createdAt: -1 },
                     fields: {
                       'profile': 1,
                       'username': 1,
                       'createdAt': 1,
                       'services.twitter.id' : 1,
                       'emails.address' : 1
                     },
                   };
  if (search) {
    let regex = new RegExp( search, 'i' );
    query = {
      $or: [
        { "profile.name": regex },
        { emails: { $elemMatch: {address: regex}}},
        { username: regex },
        { "twitter.screename": regex }
      ]
    };
    projection.limit = 100;
  }
  return Meteor.users.find( query, projection );
});

// this publishes info on server facts (used on /stats page)
Facts.setUserIdFilter(function (userId) {
  var user = Meteor.users.findOne(userId);
  return user && user.admin;
});
<|endoftext|>


<commit_before>// --- CAR -----------------
var Car = function (image) {
  this.image = image;
}

// --- TRACK --------------------------
var Track = function (name, segments) {
  this.name = name;
  this.segments = segments;
}

// --- TRACK BUILDER ---------------
var TrackBuilder = function (name) {
  this.name = name;
  this.segments = [];
}

TrackBuilder.prototype.straight = function (length, width, color) {
  for (var i = 0; i < length; i++) {
    var index = this.segments.length;
    this.segments.push([index, 0, width, color]);
  }
}

TrackBuilder.prototype.create = function () {
  return new Track(this.name, this.segments);
}

// --- RACE -----------------------
var Race = function (track, cars) {
  this.track = track;
  this.cars = cars;
}

// --- CAMERA ------------
var Camera = function () {
  this.field_of_view = Math.tan(45);
}

// --- RENDER ------------------------------------------
var Render = function (config, assets, updateCallback) {
  var self = this;
  this.config = config;
  this.assets = assets;
  this.updateCallback = updateCallback;
  this.loader = new PIXI.AssetLoader(this.assets);
  this.loader.onComplete = function () { self.load() };
  this.loader.load();
}

Render.prototype.load = function () {
  this.stage = new PIXI.Stage(0xDDDDDD);
  this.renderer = new PIXI.autoDetectRenderer(
    this.config.width, this.config.height);
  document.body.appendChild(this.renderer.view);
  this.render();
}

Render.prototype.render = function () {
  var self = this;
  this.updateCallback();
  this.renderer.render(this.stage);
  requestAnimFrame(function () { self.render() });
};

// --- RENDER CONFIG ------------------
var DefaultRenderConfig = function () {
  this.scale = 0.5;
  this.width = 1920 * this.scale;
  this.height = 1080 * this.scale;
  this.halfWidth = this.width / 2;
  this.halfHeight = this.height / 2;
}

// --- RACE RENDER -----------------------
var RaceRender = function (race, config) {
  this.race = race;
  this.config = config || new DefaultRenderConfig();
  this.assets = this.getAssets();
  this.render = new Render(this.config, this.assets, this.update);
}

RaceRender.prototype.update = function () {
  // TODO: update race state here!
}

RaceRender.prototype.getAssets = function () {
  return _(this.race.cars).map(function (c) { return c.image });
}
<commit_msg>creating basic render structure<commit_after>// --- CAR -----------------
var Car = function (image) {
  this.image = image;
}

// --- TRACK --------------------------
var Track = function (name, segments) {
  this.name = name;
  this.segments = segments;
}

// --- TRACK BUILDER ---------------
var TrackBuilder = function (name) {
  this.name = name;
  this.segments = [];
}

TrackBuilder.prototype.straight = function (length, width, color) {
  // todo: use underscore here
  for (var i = 0; i < length; i++) {
    var index = this.segments.length;
    this.segments.push([index, 0, width, color]);
  }
}

TrackBuilder.prototype.create = function () {
  return new Track(this.name, this.segments);
}

// --- RACE -----------------------
var Race = function (track, cars) {
  this.track = track;
  this.cars = cars;
}

// --- CAMERA ------------
var Camera = function () {
  this.field_of_view = Math.tan(45);
}

// --- RENDER ------------------------------------------
var Render = function (config, assets, updateCallback) {
  var self = this;
  this.config = config;
  this.assets = assets;
  this.updateCallback = updateCallback;
  this.loader = new PIXI.AssetLoader(this.assets);
  this.loader.onComplete = function () { self.load() };
  this.loader.load();
}

Render.prototype.load = function () {
  this.stage = new PIXI.Stage(0xDDDDDD);
  this.renderer = new PIXI.autoDetectRenderer(
    this.config.width, this.config.height);
  document.body.appendChild(this.renderer.view);
  this.render();
}

Render.prototype.render = function () {
  var self = this;
  this.updateCallback();
  this.renderer.render(this.stage);
  requestAnimFrame(function () { self.render() });
}

// --- RENDER CONFIG ------------------
var DefaultRenderConfig = function () {
  this.scale = 0.5;
  this.width = 1920 * this.scale;
  this.height = 1080 * this.scale;
  this.halfWidth = this.width / 2;
  this.halfHeight = this.height / 2;
}

// --- CAR RENDER --------------
var CarRender = function (car) {
  this.car = car;
  this.assets = [car.image];
}

// --- RACE RENDER -----------------------
var RaceRender = function (race, config) {
  this.race = race;
  this.config = config || new DefaultRenderConfig();
  this.objects = this.getRaceObjects();
  this.assets = this.getAssets();
  this.render = new Render(this.config, this.assets, this.update);
}

RaceRender.prototype.update = function () { }

RaceRender.prototype.getRaceObjects = function () {
  return _(this.race.cars).map(function (c) { return new CarRender(c) });
}

RaceRender.prototype.getAssets = function () {
  return _.chain(this.objects).
    map(function (o) { return o.assets }).
    flatten().
    value();
}
<|endoftext|>


<commit_before>var camp = require('../lib/camp');
var fleau = require('fleau');
var http = require('http');
var mime = require('../lib/mime.json');
var Test = require('./test');
var t = new Test();

var get = function (path, callback) {
  http.get('http://localhost:' + portNumber + path, callback);
};
var post = function (path, postData, contentType, callback) {
  var options = {
    hostname: 'localhost',
    port: portNumber,
    path: path,
    method: 'POST'
  };
  var req = http.request(options, callback);
  if (contentType) req.setHeader('Content-Type', contentType);
  if (postData) req.write(postData);
  req.end();
};

var launchTests = function () {
  t.seq([
    function t0 (next) {
      get('', function (res) {
        t.eq(res.httpVersion, '1.1', "Server must be HTTP 1.1.");
        t.eq(res.headers['transfer-encoding'], 'chunked',
          "Connection should be chunked by default.");
        res.on('data', function (content) {
          t.eq('' + content, '404',
               "Did not receive content of index.html.");
          next();
        });
      });
    },

    function t1 (next) {
      // Using a streamed route.
      // Create a stream out of the following string.
      var template = '{{= text in plain}}\n{{for comment in comments{{\n- {{= comment in plain}}}} }}';

      server.route( /^\/blog$/, function (query, match, end) {
        end ({
          text: 'My, what a silly blog.',
          comments: ['first comment!', 'second comment…']
        }, {
          string: template,   // A stream.
          reader: fleau
        });
      });

      // Test that now.
      get('/blog', function (res) {
        var content = '';
        res.on('data', function (chunk) {
          content += '' + chunk;
        });
        res.on('end', function () {
          t.eq(content, 'My, what a silly blog.\n\n- first comment!\n- second comment…',
            "Routing a streamed template should work.");
          next();
        });
      });
    },

    function t2 (next) {
      // Using `sc.path` with/out named non-slash placeholders (i.e. ':foo').
      server.path('foo', function (req, res) {
        res.end('foo');
      });

      server.path('foo/:bar', function (req, res) {
        res.end('bar=' + req.data.bar);
      });

      server.path('foo/:bar/baz', function (req, res) {
        res.end('baz');
      });

      get('/foo', function (res) {
        res.on('data', function (body) {
          t.eq(String(body), 'foo',
            'Basic sc.path should work.');

          get('/foo/quux', function (res) {
            res.on('data', function (body) {
              t.eq(String(body), 'bar=quux',
                'Named sc.path placeholder should work.');

              get('/foo/quux/baz', function (res) {
                res.on('data', function (body) {
                  t.eq(String(body), 'baz',
                    'Named sc.path placeholder should not pre-empt sub-paths.');
                  next();
                });
              });
            });
          });
        });
      }); // Mmmh… I love spaghetti!
    },

    function t3 (next) {
      var data = { message: '☃' };

      server.path('json', function (req, res) {
        res.statusCode = 418; // I'm a teapot (see RFC 2324).
        res.json(data, null, 2);
      });

      get('/json', function (res) {
        t.eq(res.statusCode, 418,
          'Setting `res.statusCode` before `res.json(data)` should work.');
        t.eq(res.headers['content-type'], mime.json,
          'Served content type should always be "' + mime.json + '".');
        var body = '';
        res.on('data', function (chunk) {
          body += String(chunk);
        });
        res.on('end', function () {
          t.eq(String(body).trim(), JSON.stringify(data, null, 2),
            '`res.json(data, null, 2)` should return human-readable JSON.');
          next();
        });
      });
    },

    function t4 (next) {
      var data = { id: '☃' };
      var things = {};

      server.get('things/:thing', function (req, res) {
        var thing = things[req.query.thing];
        if (!thing) {
          res.statusCode = 404;
          res.end('Could not find the thing :(');
          return;
        }
        res.json(thing);
      });

      server.post('things/:thing', function (req, res) {
        t.eq(req.headers['content-type'], mime.json,
          'Request content type should be "' + mime.json + '".');
        var json = '';
        req.on('data', function (chunk) {
          json += String(chunk);
        });
        req.on('end', function () {
          var thing = JSON.parse(json);
          t.eq(data.id, thing.id,
            'Handling JSON post data should work.');
          things[req.query.thing] = thing;
          res.statusCode = 201; // Created.
          res.end('Created the thing! :)');
        });
      });

      post('/things/snowman', JSON.stringify(data), mime.json, function (res) {
        t.eq(res.statusCode, 201,
          'Response status should be 201, not ' + res.statusCode + '.');
        get('/things/snowman', function (res) {
          var json = '';
          res.on('data', function (chunk) {
            json += String(chunk);
          });
          res.on('end', function () {
            t.eq(data.id, JSON.parse(json).id,
              'Should receive the original data back.');
            next();
          });
        });
      });
    },

    function t5 (next) {
      var name = 'Robert\'); DROP TABLE Students;--';
      var data = encodeURI('Name="' + name + '"');
      var urlencoded = 'application\/x-www-form-urlencoded';

      server.path('/Students.php', function (req, res) {
        t.eq(req.query.Name, name, 'POST data should be processed.');
        if (server.saveRequestChunks) {
          t.eq(req.savedChunks && req.savedChunks.toString(), data,
            'Processed chunks should be saved in the request when required.');
        } else {
          t.eq(req.savedChunks, undefined,
            'Processed chunks should not be saved when it isn\'t required.');
        }

        res.statusCode = 500; // Internal Server Error (not really)
        res.end('mysql> Query OK, 1337 rows affected (0.03 sec)\n');
      });

      server.saveRequestChunks = false;
      post('/Students.php', data, urlencoded, function (res) {
        t.eq(res.statusCode, 500,
          'Response status should be 500, not ' + res.statusCode + '.');
        server.saveRequestChunks = true;
        post('/Students.php', data, urlencoded, function (res) {
          t.eq(res.statusCode, 500,
            'Response status should be 500, not ' + res.statusCode + '.');
          next();
        });
      });
    },

    function t6 (next) {
      server.path('/redirection', function (req, res) {
        res.redirect('/other/path');
      });
      get('/redirection', function(res) {
        t.eq(res.statusCode, 303, 'Redirection should be a 303');
        t.eq(res.headers['location'], '/other/path',
          'Redirection should send the right location header');
        next();
      });
    },
  ], function end () {
    t.tldr();
    process.exit(0);
  });
};

// FIXME: is there a good way to make a server get a port for testing?
var server;
var portNumber = 8000;
var startServer = function () {
  server = camp.start({port:portNumber, documentRoot:'./test/web'});
  server.on('listening', launchTests);
};
var serverStartDomain = require('domain').create();
serverStartDomain.on('error', function (err) {
  if (err.code === 'EADDRINUSE') {
    portNumber++;
    serverStartDomain.run(startServer);
  } else {
    throw err;
  }
});
serverStartDomain.run(startServer);

<commit_msg>Ensure test process returns non-zero exit code when tests fail.<commit_after>var camp = require('../lib/camp');
var fleau = require('fleau');
var http = require('http');
var mime = require('../lib/mime.json');
var Test = require('./test');
var t = new Test();

var get = function (path, callback) {
  http.get('http://localhost:' + portNumber + path, callback);
};
var post = function (path, postData, contentType, callback) {
  var options = {
    hostname: 'localhost',
    port: portNumber,
    path: path,
    method: 'POST'
  };
  var req = http.request(options, callback);
  if (contentType) req.setHeader('Content-Type', contentType);
  if (postData) req.write(postData);
  req.end();
};

var launchTests = function () {
  t.seq([
    function t0 (next) {
      get('', function (res) {
        t.eq(res.httpVersion, '1.1', "Server must be HTTP 1.1.");
        t.eq(res.headers['transfer-encoding'], 'chunked',
          "Connection should be chunked by default.");
        res.on('data', function (content) {
          t.eq('' + content, '404',
               "Did not receive content of index.html.");
          next();
        });
      });
    },

    function t1 (next) {
      // Using a streamed route.
      // Create a stream out of the following string.
      var template = '{{= text in plain}}\n{{for comment in comments{{\n- {{= comment in plain}}}} }}';

      server.route( /^\/blog$/, function (query, match, end) {
        end ({
          text: 'My, what a silly blog.',
          comments: ['first comment!', 'second comment…']
        }, {
          string: template,   // A stream.
          reader: fleau
        });
      });

      // Test that now.
      get('/blog', function (res) {
        var content = '';
        res.on('data', function (chunk) {
          content += '' + chunk;
        });
        res.on('end', function () {
          t.eq(content, 'My, what a silly blog.\n\n- first comment!\n- second comment…',
            "Routing a streamed template should work.");
          next();
        });
      });
    },

    function t2 (next) {
      // Using `sc.path` with/out named non-slash placeholders (i.e. ':foo').
      server.path('foo', function (req, res) {
        res.end('foo');
      });

      server.path('foo/:bar', function (req, res) {
        res.end('bar=' + req.data.bar);
      });

      server.path('foo/:bar/baz', function (req, res) {
        res.end('baz');
      });

      get('/foo', function (res) {
        res.on('data', function (body) {
          t.eq(String(body), 'foo',
            'Basic sc.path should work.');

          get('/foo/quux', function (res) {
            res.on('data', function (body) {
              t.eq(String(body), 'bar=quux',
                'Named sc.path placeholder should work.');

              get('/foo/quux/baz', function (res) {
                res.on('data', function (body) {
                  t.eq(String(body), 'baz',
                    'Named sc.path placeholder should not pre-empt sub-paths.');
                  next();
                });
              });
            });
          });
        });
      }); // Mmmh… I love spaghetti!
    },

    function t3 (next) {
      var data = { message: '☃' };

      server.path('json', function (req, res) {
        res.statusCode = 418; // I'm a teapot (see RFC 2324).
        res.json(data, null, 2);
      });

      get('/json', function (res) {
        t.eq(res.statusCode, 418,
          'Setting `res.statusCode` before `res.json(data)` should work.');
        t.eq(res.headers['content-type'], mime.json,
          'Served content type should always be "' + mime.json + '".');
        var body = '';
        res.on('data', function (chunk) {
          body += String(chunk);
        });
        res.on('end', function () {
          t.eq(String(body).trim(), JSON.stringify(data, null, 2),
            '`res.json(data, null, 2)` should return human-readable JSON.');
          next();
        });
      });
    },

    function t4 (next) {
      var data = { id: '☃' };
      var things = {};

      server.get('things/:thing', function (req, res) {
        var thing = things[req.query.thing];
        if (!thing) {
          res.statusCode = 404;
          res.end('Could not find the thing :(');
          return;
        }
        res.json(thing);
      });

      server.post('things/:thing', function (req, res) {
        t.eq(req.headers['content-type'], mime.json,
          'Request content type should be "' + mime.json + '".');
        var json = '';
        req.on('data', function (chunk) {
          json += String(chunk);
        });
        req.on('end', function () {
          var thing = JSON.parse(json);
          t.eq(data.id, thing.id,
            'Handling JSON post data should work.');
          things[req.query.thing] = thing;
          res.statusCode = 201; // Created.
          res.end('Created the thing! :)');
        });
      });

      post('/things/snowman', JSON.stringify(data), mime.json, function (res) {
        t.eq(res.statusCode, 201,
          'Response status should be 201, not ' + res.statusCode + '.');
        get('/things/snowman', function (res) {
          var json = '';
          res.on('data', function (chunk) {
            json += String(chunk);
          });
          res.on('end', function () {
            t.eq(data.id, JSON.parse(json).id,
              'Should receive the original data back.');
            next();
          });
        });
      });
    },

    function t5 (next) {
      var name = 'Robert\'); DROP TABLE Students;--';
      var data = encodeURI('Name="' + name + '"');
      var urlencoded = 'application\/x-www-form-urlencoded';

      server.path('/Students.php', function (req, res) {
        t.eq(req.query.Name, name, 'POST data should be processed.');
        if (server.saveRequestChunks) {
          t.eq(req.savedChunks && req.savedChunks.toString(), data,
            'Processed chunks should be saved in the request when required.');
        } else {
          t.eq(req.savedChunks, undefined,
            'Processed chunks should not be saved when it isn\'t required.');
        }

        res.statusCode = 500; // Internal Server Error (not really)
        res.end('mysql> Query OK, 1337 rows affected (0.03 sec)\n');
      });

      server.saveRequestChunks = false;
      post('/Students.php', data, urlencoded, function (res) {
        t.eq(res.statusCode, 500,
          'Response status should be 500, not ' + res.statusCode + '.');
        server.saveRequestChunks = true;
        post('/Students.php', data, urlencoded, function (res) {
          t.eq(res.statusCode, 500,
            'Response status should be 500, not ' + res.statusCode + '.');
          next();
        });
      });
    },

    function t6 (next) {
      server.path('/redirection', function (req, res) {
        res.redirect('/other/path');
      });
      get('/redirection', function(res) {
        t.eq(res.statusCode, 303, 'Redirection should be a 303');
        t.eq(res.headers['location'], '/other/path',
          'Redirection should send the right location header');
        next();
      });
    },
  ], function end () {
    t.tldr();
    t.exit();
  });
};

// FIXME: is there a good way to make a server get a port for testing?
var server;
var portNumber = 8000;
var startServer = function () {
  server = camp.start({port:portNumber, documentRoot:'./test/web'});
  server.on('listening', launchTests);
};
var serverStartDomain = require('domain').create();
serverStartDomain.on('error', function (err) {
  if (err.code === 'EADDRINUSE') {
    portNumber++;
    serverStartDomain.run(startServer);
  } else {
    throw err;
  }
});
serverStartDomain.run(startServer);

<|endoftext|>


<commit_before>// Copyright (c) Cognitect, Inc.
// All rights reserved.

"use strict";

var caching = require("./caching"),
    h       = require("./handlers"),
    t       = require("./types"),
    d       = require("./delimiters"),
    sb      = require("./stringbuilder");

var JSON_INT_MAX = Math.pow(2, 53);
var JSON_INT_MIN = -JSON_INT_MAX;

function escape(string) {
    if(string.length > 0) {
        var c = string[0];
        if(c === d.RES && string[1] === ESC) {
            return string.substring(1);
        } else if(c === d.ESC || c === d.SUB || c === d.RES) {
            return d.ESC+string;
        } else {
            return string;
        }
    }
    return null;
}

// STATES

var STATES = ["OBJECT", "ARRAY", "OBJECT_KEY", "OBJECT_VALUE",
              "OBJECT_FIRST_KEY", "ARRAY_FIRST_VALUE"];
/*
var OBJECT = 0,
    ARRAY = 1,
    OBJECT_KEY = 2,
    OBJECT_VALUE = 3,
    OBJECT_FIRST_KEY = 4,
    ARRAY_FIRST_VALUE = 5;
*/

function JSONMarshaller(stream, options) {
    this.buffer = (options && options.buffer) || sb.stringBuilder();
    this.state = t.queue();
    this.handlers = h.handlers();
    this._prefersStrings = options ? options.prefersString || false : true;
}

JSONMarshaller.prototype = {
    getState: function() {
        return this.state.peek();
    },

    pushState: function(newState) {
        var oldState = this.getState();
        this.state.push(newState);

        // ARRAY
        if(oldState === 1) {
            this.buffer.write(",");
        }

        switch(newState) {
        // ARRAY
        case 1:
            this.state.push(5); // ARRAY_FIRST_VALUE
            this.buffer.write("[");
            break;
        // OBJECT
        case 0:
            this.state.push(4); // OBJECT_FIRST_KEY
            this.buffer.write("{");
            break;
        default:
            var err = new Error("JSONMarshaller: Invalid pushState, " + STATES[newState]);
            err.data = {state: newState};
            throw err;
            break;
        }
    },

    popState: function() {
        var state = this.state.pop();

        // while !OBJECT && !ARRAY
        while(state !== 0 && state !== 1) {
            state = this.state.pop();
        }

        // if OBJECT_VALUE STATE, pop
        // and push OBJECT_KEY STATE
        if(this.state.peek() === 3) {
            this.state.pop();
            this.state.push(2);
        }

        switch(state) {
        // ARRAY
        case 1:
            this.buffer.write("]");
            return 1; // ARRAY
            break;
        // OBJECT
        case 0:
            this.buffer.write("}");
            return 0; // OBJECT
            break;
        default:
            var err = new Error("JSONMarshaller: Popped unknown state " + STATES[state]);
            err.data = {state: state};
            throw err;
            break;
        }
    },

    debugState: function() {
        var l   = this.state.list,
            ret = [];
        while(l) {
            ret.push(STATES[l.head]);
            l = l.tail;
        }
        return ret.reverse();
    },

    pushKey: function(obj) {
        var state = this.getState();
        switch(state) {
        // OBJECT_KEY
        case 2:
            this.buffer.write(",");
        // OBJECT_FIRST_KEY
        case 4:
            this.state.pop();
            this.state.push(3); // OBJECT_VALUE
            this.buffer.write(obj);
            break;
        default:
            var err = new Error("JSONMarshaller: Cannot pushKey in state " + STATES[state] + " " + obj);
            err.data = {state: state};
            throw err;
            break;
        }
        this.buffer.write(":");
    },

    pushValue: function(obj) {
        var state = this.getState();
        switch(state) {
        // ARRAY
        case 1:
            this.buffer.write(",");
            this.buffer.write(obj);
            break;
        // ARRAY_FIRST_VALUE
        case 5:
            this.state.pop();
            this.buffer.write(obj);
            break;
        // OBJECT_VALUE
        case 3:
            this.state.pop();
            this.buffer.write(obj);
            this.state.push(2);
            break;
        default:
            this.buffer.write(obj);
            break;
        }
    },

    handler: function(obj) {
        return this.handlers.get(h.constructor(obj));
    },

    registerHandler: function(ctor, handler) {
        this.handlers.set(ctor, handler);
    },

    writeObject: function(obj, asMapKey) {
        asMapKey = asMapKey || false;
        if(asMapKey) {
            this.pushKey(obj);
        } else {
            this.pushValue(obj);
        }
    },

    emitNil: function(asMapKey, cache) {
        if(asMapKey) {
            this.emitString(d.ESC, "_", "", asMapKey, cache);
        } else {
            this.writeObject("null", false);
        }
    },

    emitString: function(prefix, tag, s, asMapKey, cache) {
        var s = "\""+cache.write(prefix+tag+s, asMapKey)+"\"";
        this.writeObject(s, asMapKey);
    },

    emitBoolean: function(b, asMapKey, cache) {
        var s = b.toString();
        if(asMapKey) {
            this.emitString(d.ESC, "?", s[0], asMapKey, cache);
        } else {
            this.writeObject(s, false);
        }
    },

    emitInteger: function(i, asMapKey, cache) {
        if(asMapKey || (typeof i === "string") || (i > JSON_INT_MAX) || (i < JSON_INT_MIN)) {
            this.emitString(d.ESC, "i", i, asMapKey, cache);
        } else {
            this.writeObject(i);
        }
    },

    emitDouble: function(d, asMapKey, cache) {
        if(asMapKey) {
            this.emitString(d.ESC, "d", d, asMapKey, cache);
        } else {
            this.writeObject(s);
        }
    },

    emitBinary: function(b, asMapKey, cache) {
        this.emitBinary(d.ESC, "b", new Buffer(b).toString("base64"), asMapKey, cache);
    },

    emitArrayStart: function(size) {
        this.pushState(1); // ARRAY
    },

    emitArrayEnd: function() {
        var lastState = this.popState();
        if(lastState !== 1) { // ARRAY
            throw new Error("JSONMarshaller: Invalid array end");
        }
    },

    emitMapStart: function(size) {
        this.pushState(0);
    },

    emitMapEnd: function() {
        var lastState = this.popState();
        if(lastState !== 0) {
            throw new Error("JSONMarshaller: Invalid object end");
        }
    },

    emitQuoted: function(obj, cache) {
        this.emitMapStart();
        this.emitString(d.ESC, "'", "", true, cache);
        marshal(this, obj, false, cache);
        this.emitMapEnd();
    },

    flushBuffer: function(ignore) {
        this.state = t.queue();
        return this.buffer.flush();
    },

    prefersStrings: function() {
        return this._prefersStrings;
    }
};

function emitInts(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitInt(em, src[i], false, cache);
    }
}

function emitShorts(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitShort(em, src[i], false, cache);
    }
}

function emitLongs(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitLong(em, src[i], false, cache);
    }
}

function emitFloats(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitFloat(em, src[i], false, cache);
    }
}

function emitDouble(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitDouble(em, src[i], false, cache);
    }
}

function emitChars(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        marshal(em, src[i], false, cache);
    }
}

function emitBooleans(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitBoolean(em, src[i], false, cache);
    }
}

function emitObjects(em, iterable, cache) {
    if(Array.isArray(iterable)) {
        for(var i = 0; i < iterable.length; i++) {
            marshal(em, iterable[i], false, cache);
        }
    } else {
        iterable.forEach(function(v, i) {
            marshal(em, v, false, cache);
        });
    }
}

function emitArray(em, iterable, skip, cache) {
    em.emitArrayStart();
    if(iterable instanceof Int8Array) {
        emitChars(em, iterable, cache);
    } else if(iterable instanceof Int16Array) {
        emitShorts(em, iterable, cache);
    } else if(iterable instanceof Int32Array) {
        emitInts(em, iterable, cache);
    } else if(iterable instanceof Float32Array) {
        emitFloats(em, iterable, cache);
    } else if(iterable instanceof Float64Array) {
        emitDoubles(em, iterable, cache);
    } else {
        emitObjects(em, iterable, cache);
    }
    em.emitArrayEnd();
}

function emitMap(em, obj, skip, cache) {
    em.emitMapStart();
    var ks = Object.keys(obj);
    for(var i = 0; i < ks.length; i++) {
        marshal(em, ks[i], true, cache);
        marshal(em, obj[ks[i]], false, cache);
    }
    em.emitMapEnd();
}

function emitTaggedMap(em, tag, rep, skip, cache) {
    em.emitMapStart();
    em.emitString(d.ESC_TAG, tag, "", true, cache);
    marshal(em, rep, false, cache);
    em.emitMapEnd();
}

function emitEncoded(em, h, tag, obj, asMapKey, cache) {
    if(tag.length === 1) {
        var rep = h.rep(obj);
        if(typeof rep === "string") {
            em.emitString(d.ESC, tag, rep, asMapKey, cache);
        } else if((asMapKey === true) || em.prefersStrings()) {
            rep = h.stringRep(obj);
            if(typeof rep === "string") {
                em.emitString(d.ESC, tag, rep, asMapKey, cache);
            } else {
                var err = new Error("Cannot be encoded as string");
                err.data = {tag: tag, rep: rep, obj: obj};
                throw err;
            }
        } else {
            emitTaggedMap(em, tag, rep, asMapKey, cache);
        }
    } else if (asMapKey === true) {
        var err = new Error("Cannot be used as map key");
        err.data = {tag: tag, rep: rep, obj: obj};
        throw err;
    } else {
        emitTaggedMap(em, tag, h.rep(obj), asMapKey, cache);
    }
}

function marshal(em, obj, asMapKey, cache) {
    var h   = em.handler(obj),
        tag = h ? h.tag(obj) : null,
        rep = h ? h.rep(obj) : null;

    if(h != null && tag != null) {
        switch(tag) {
        case "_":
            em.emitNil(asMapKey, cache);
            break;
        case "s":
            em.emitString("", "", escape(rep), asMapKey, cache);
            break;
        case "?":
            em.emitBoolean(rep, asMapKey, cache);
            break;
        case "i":
            em.emitInteger(rep, asMapKey, cache);
            break;
        case "d":
            em.emitDouble(rep, asMapKey, cache);
            break;
        case "b":
            em.emitBinary(rep, asMapKey, cache);
            break;
        case "'":
            em.emitQuoted(rep, cache);
            break;
        case "array":
            emitArray(em, rep, asMapKey, cache);
            break;
        case "map":
            emitMap(em, rep, asMapKey, cache);
            break;
        default:
            emitEncoded(em, h, tag, obj, asMapKey, cache);
            break;
        }
    } else {
        var err = new Error("Not supported");
        err.data = {obj: obj, type: h.constructor(obj).name};
        throw err;
    }
}

function maybeQuoted(em, obj) {
    var h = em.handler(obj);

    if(h != null) {
        if(h.tag(obj).length === 1) {
            return t.quoted(obj);
        } else {
            return obj;
        }
    } else {
        var err = new Error("Not supported");
        err.data = {obj: obj, type: h.constructor(obj).name};
        throw err;
    }
}

function marshalTop(em, obj, cache) {
    marshal(em, maybeQuoted(em, obj), false, cache);
}

function Writer(marshaller, stream, options) {
    this.marshaller = marshaller;
    this.stream = stream;
    this.options = options || {};
    this.cache = this.options.cache ? this.options.cache : caching.writeCache();
}

Writer.prototype = {
    write: function(obj) {
        marshalTop(this.marshaller, obj, this.cache)
        this.stream.write(this.marshaller.flushBuffer());
        this.cache.clear();
    },

    register: function(type, handler) {
        this.marshaller.registerHandler(type, handler);
    }
};

function writer(out, type, opts) {
    if(type === "json") {
        var marshaller = new JSONMarshaller(opts);
        return new Writer(marshaller, out, opts);
    } else {
        var err = new Error("Type must be \"json\"");
        err.data = {type: type};
        throw err;
    }
}

module.exports = {
    writer: writer,
    marshal: marshal,
    marshalTop: marshalTop,
    emitTaggedMap: emitTaggedMap,
    JSONMarshaller: JSONMarshaller
};
<commit_msg>refactor state machine code, always pushValue after popState as this means and object or array was written<commit_after>// Copyright (c) Cognitect, Inc.
// All rights reserved.

"use strict";

var caching = require("./caching"),
    h       = require("./handlers"),
    t       = require("./types"),
    d       = require("./delimiters"),
    sb      = require("./stringbuilder");

var JSON_INT_MAX = Math.pow(2, 53);
var JSON_INT_MIN = -JSON_INT_MAX;

function escape(string) {
    if(string.length > 0) {
        var c = string[0];
        if(c === d.RES && string[1] === ESC) {
            return string.substring(1);
        } else if(c === d.ESC || c === d.SUB || c === d.RES) {
            return d.ESC+string;
        } else {
            return string;
        }
    }
    return null;
}

// STATES

var STATES = ["OBJECT", "ARRAY", "OBJECT_KEY", "OBJECT_VALUE",
              "OBJECT_FIRST_KEY", "ARRAY_FIRST_VALUE"];
/*
var OBJECT = 0,
    ARRAY = 1,
    OBJECT_KEY = 2,
    OBJECT_VALUE = 3,
    OBJECT_FIRST_KEY = 4,
    ARRAY_FIRST_VALUE = 5;
*/

function JSONMarshaller(stream, options) {
    this.buffer = (options && options.buffer) || sb.stringBuilder();
    this.state = t.queue();
    this.handlers = h.handlers();
    this._prefersStrings = options ? options.prefersString || false : true;
}

JSONMarshaller.prototype = {
    NO_WRITE: {},

    getState: function() {
        return this.state.peek();
    },

    pushState: function(newState) {
        var oldState = this.getState();
        this.state.push(newState);

        // ARRAY
        if(oldState === 1) {
            this.buffer.write(",");
        }

        switch(newState) {
        // ARRAY
        case 1:
            this.state.push(5); // ARRAY_FIRST_VALUE
            this.buffer.write("[");
            break;
        // OBJECT
        case 0:
            this.state.push(4); // OBJECT_FIRST_KEY
            this.buffer.write("{");
            break;
        default:
            var err = new Error("JSONMarshaller: Invalid pushState, " + STATES[newState]);
            err.data = {state: newState};
            throw err;
            break;
        }
    },

    popState: function() {
        var state = this.state.pop();

        // while !OBJECT && !ARRAY
        while(state !== 0 && state !== 1) {
            state = this.state.pop();
        }

        switch(state) {
        // ARRAY
        case 1:
            this.buffer.write("]");
            break;
        // OBJECT
        case 0:
            this.buffer.write("}");
            break;
        default:
            var err = new Error("JSONMarshaller: Popped unknown state " + STATES[state]);
            err.data = {state: state};
            throw err;
            break;
        }

        this.pushValue(this.NO_WRITE);

        return state;
    },

    debugState: function() {
        var l   = this.state.list,
            ret = [];
        while(l) {
            ret.push(STATES[l.head]);
            l = l.tail;
        }
        return ret.reverse();
    },

    pushKey: function(obj) {
        var state = this.getState();
        switch(state) {
        // OBJECT_KEY
        case 2:
            this.buffer.write(",");
        // OBJECT_FIRST_KEY
        case 4:
            this.state.pop();
            this.state.push(3); // OBJECT_VALUE
            this.buffer.write(obj);
            break;
        default:
            var err = new Error("JSONMarshaller: Cannot pushKey in state " + STATES[state] + " " + obj);
            err.data = {state: state};
            throw err;
            break;
        }
        this.buffer.write(":");
    },

    pushValue: function(obj) {
        var state = this.getState();
        switch(state) {
        // ARRAY
        case 1:
            if(obj !== this.NO_WRITE) {
                this.buffer.write(",");
                this.buffer.write(obj);
            }
            break;
        // ARRAY_FIRST_VALUE
        case 5:
            this.state.pop();
            if(obj !== this.NO_WRITE) {
                this.buffer.write(obj);
            }
            break;
        // OBJECT_VALUE
        case 3:
            this.state.pop();
            if(obj !== this.NO_WRITE) {
                this.buffer.write(obj);
            }
            this.state.push(2);
            break;
        default:
            if(obj !== this.NO_WRITE) {
                this.buffer.write(obj);
            }
            break;
        }
    },

    handler: function(obj) {
        return this.handlers.get(h.constructor(obj));
    },

    registerHandler: function(ctor, handler) {
        this.handlers.set(ctor, handler);
    },

    writeObject: function(obj, asMapKey) {
        asMapKey = asMapKey || false;
        if(asMapKey) {
            this.pushKey(obj);
        } else {
            this.pushValue(obj);
        }
    },

    emitNil: function(asMapKey, cache) {
        if(asMapKey) {
            this.emitString(d.ESC, "_", "", asMapKey, cache);
        } else {
            this.writeObject("null", false);
        }
    },

    emitString: function(prefix, tag, s, asMapKey, cache) {
        var s = "\""+cache.write(prefix+tag+s, asMapKey)+"\"";
        this.writeObject(s, asMapKey);
    },

    emitBoolean: function(b, asMapKey, cache) {
        var s = b.toString();
        if(asMapKey) {
            this.emitString(d.ESC, "?", s[0], asMapKey, cache);
        } else {
            this.writeObject(s, false);
        }
    },

    emitInteger: function(i, asMapKey, cache) {
        if(asMapKey || (typeof i === "string") || (i > JSON_INT_MAX) || (i < JSON_INT_MIN)) {
            this.emitString(d.ESC, "i", i, asMapKey, cache);
        } else {
            this.writeObject(i);
        }
    },

    emitDouble: function(d, asMapKey, cache) {
        if(asMapKey) {
            this.emitString(d.ESC, "d", d, asMapKey, cache);
        } else {
            this.writeObject(s);
        }
    },

    emitBinary: function(b, asMapKey, cache) {
        this.emitBinary(d.ESC, "b", new Buffer(b).toString("base64"), asMapKey, cache);
    },

    emitArrayStart: function(size) {
        this.pushState(1); // ARRAY
    },

    emitArrayEnd: function() {
        var lastState = this.popState();
        if(lastState !== 1) { // ARRAY
            throw new Error("JSONMarshaller: Invalid array end");
        }
    },

    emitMapStart: function(size) {
        this.pushState(0);
    },

    emitMapEnd: function() {
        var lastState = this.popState();
        if(lastState !== 0) {
            throw new Error("JSONMarshaller: Invalid object end");
        }
    },

    emitQuoted: function(obj, cache) {
        this.emitMapStart();
        this.emitString(d.ESC, "'", "", true, cache);
        marshal(this, obj, false, cache);
        this.emitMapEnd();
    },

    flushBuffer: function(ignore) {
        this.state = t.queue();
        return this.buffer.flush();
    },

    prefersStrings: function() {
        return this._prefersStrings;
    }
};

function emitInts(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitInt(em, src[i], false, cache);
    }
}

function emitShorts(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitShort(em, src[i], false, cache);
    }
}

function emitLongs(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitLong(em, src[i], false, cache);
    }
}

function emitFloats(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitFloat(em, src[i], false, cache);
    }
}

function emitDouble(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitDouble(em, src[i], false, cache);
    }
}

function emitChars(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        marshal(em, src[i], false, cache);
    }
}

function emitBooleans(em, src, cache) {
    for(var i = 0; i < src.length; i++) {
        em.emitBoolean(em, src[i], false, cache);
    }
}

function emitObjects(em, iterable, cache) {
    if(Array.isArray(iterable)) {
        for(var i = 0; i < iterable.length; i++) {
            marshal(em, iterable[i], false, cache);
        }
    } else {
        iterable.forEach(function(v, i) {
            marshal(em, v, false, cache);
        });
    }
}

function emitArray(em, iterable, skip, cache) {
    em.emitArrayStart();
    if(iterable instanceof Int8Array) {
        emitChars(em, iterable, cache);
    } else if(iterable instanceof Int16Array) {
        emitShorts(em, iterable, cache);
    } else if(iterable instanceof Int32Array) {
        emitInts(em, iterable, cache);
    } else if(iterable instanceof Float32Array) {
        emitFloats(em, iterable, cache);
    } else if(iterable instanceof Float64Array) {
        emitDoubles(em, iterable, cache);
    } else {
        emitObjects(em, iterable, cache);
    }
    em.emitArrayEnd();
}

function emitMap(em, obj, skip, cache) {
    em.emitMapStart();
    var ks = Object.keys(obj);
    for(var i = 0; i < ks.length; i++) {
        marshal(em, ks[i], true, cache);
        marshal(em, obj[ks[i]], false, cache);
    }
    em.emitMapEnd();
}

function emitTaggedMap(em, tag, rep, skip, cache) {
    em.emitMapStart();
    em.emitString(d.ESC_TAG, tag, "", true, cache);
    marshal(em, rep, false, cache);
    em.emitMapEnd();
}

function emitEncoded(em, h, tag, obj, asMapKey, cache) {
    if(tag.length === 1) {
        var rep = h.rep(obj);
        if(typeof rep === "string") {
            em.emitString(d.ESC, tag, rep, asMapKey, cache);
        } else if((asMapKey === true) || em.prefersStrings()) {
            rep = h.stringRep(obj);
            if(typeof rep === "string") {
                em.emitString(d.ESC, tag, rep, asMapKey, cache);
            } else {
                var err = new Error("Cannot be encoded as string");
                err.data = {tag: tag, rep: rep, obj: obj};
                throw err;
            }
        } else {
            emitTaggedMap(em, tag, rep, asMapKey, cache);
        }
    } else if (asMapKey === true) {
        var err = new Error("Cannot be used as map key");
        err.data = {tag: tag, rep: rep, obj: obj};
        throw err;
    } else {
        emitTaggedMap(em, tag, h.rep(obj), asMapKey, cache);
    }
}

function marshal(em, obj, asMapKey, cache) {
    var h   = em.handler(obj),
        tag = h ? h.tag(obj) : null,
        rep = h ? h.rep(obj) : null;

    if(h != null && tag != null) {
        switch(tag) {
        case "_":
            em.emitNil(asMapKey, cache);
            break;
        case "s":
            em.emitString("", "", escape(rep), asMapKey, cache);
            break;
        case "?":
            em.emitBoolean(rep, asMapKey, cache);
            break;
        case "i":
            em.emitInteger(rep, asMapKey, cache);
            break;
        case "d":
            em.emitDouble(rep, asMapKey, cache);
            break;
        case "b":
            em.emitBinary(rep, asMapKey, cache);
            break;
        case "'":
            em.emitQuoted(rep, cache);
            break;
        case "array":
            emitArray(em, rep, asMapKey, cache);
            break;
        case "map":
            emitMap(em, rep, asMapKey, cache);
            break;
        default:
            emitEncoded(em, h, tag, obj, asMapKey, cache);
            break;
        }
    } else {
        var err = new Error("Not supported");
        err.data = {obj: obj, type: h.constructor(obj).name};
        throw err;
    }
}

function maybeQuoted(em, obj) {
    var h = em.handler(obj);

    if(h != null) {
        if(h.tag(obj).length === 1) {
            return t.quoted(obj);
        } else {
            return obj;
        }
    } else {
        var err = new Error("Not supported");
        err.data = {obj: obj, type: h.constructor(obj).name};
        throw err;
    }
}

function marshalTop(em, obj, cache) {
    marshal(em, maybeQuoted(em, obj), false, cache);
}

function Writer(marshaller, stream, options) {
    this.marshaller = marshaller;
    this.stream = stream;
    this.options = options || {};
    this.cache = this.options.cache ? this.options.cache : caching.writeCache();
}

Writer.prototype = {
    write: function(obj) {
        marshalTop(this.marshaller, obj, this.cache)
        this.stream.write(this.marshaller.flushBuffer());
        this.cache.clear();
    },

    register: function(type, handler) {
        this.marshaller.registerHandler(type, handler);
    }
};

function writer(out, type, opts) {
    if(type === "json") {
        var marshaller = new JSONMarshaller(opts);
        return new Writer(marshaller, out, opts);
    } else {
        var err = new Error("Type must be \"json\"");
        err.data = {type: type};
        throw err;
    }
}

module.exports = {
    writer: writer,
    marshal: marshal,
    marshalTop: marshalTop,
    emitTaggedMap: emitTaggedMap,
    JSONMarshaller: JSONMarshaller
};
<|endoftext|>


<commit_before>const express = require('express')
const router = express.Router()
const passport = require('passport')

const {scriptUrl} = require('../services/server_helpers')
const {
  getCandidateById,
  getFullCandidatePromise,
  setCandidateMetadata,
} = require('../services/candidate')

router.get('/', isLoggedIn, (req, res) => {
  const initialState = {}
  res.render('index.jade', {
    initialState,
    scriptUrl: scriptUrl(),
    user: req.user,
  })
})

// Login
router.get('/login', (req, res) => {
  if (req.isAuthenticated()) {
    res.redirect('/admin')
  } else {
    res.render('admin/login.jade', { message: req.flash('loginMessage') })
  }
})

router.post('/login', passport.authenticate('local-login', {
  successRedirect : '/admin', // redirect to the secure profile section
  failureRedirect : '/login', // redirect back to the signup page if there is an error
  failureFlash : true, // allow flash messages
}))

// Signup
// router.get('/signup', isSuperAdmin, (req, res) => {
router.get('/signup', (req, res) => {
  res.render('admin/signup.jade', { message: req.flash('signupMessage') })
})

// router.post('/signup', isSuperAdmin, passport.authenticate('local-signup', {
router.post('/signup', passport.authenticate('local-signup', {
  successRedirect: '/admin', // redirect to the secure profile section
  failureRedirect: '/admin/signup', // redirect back to the signup page if there is an error
  failureFlash: true, // allow flash messages
}))

router.get('/logout', (req, res) => {
  req.logout()
  res.redirect('/')
})

router.get('/candidate/id/:id', isLoggedIn, (req, res) => {
  getCandidateById(req.params.id).then(candidate => {
    return res.redirect(`/admin/candidate/${candidate.Candidate_ID}`)
  })
})

router.get('/candidate/:candidateId', isLoggedIn, (req, res) => {
  const candidateId = req.params.candidateId
  console.log('candidateId', candidateId)

  const candidatePr = getFullCandidatePromise(candidateId)

  var result = candidatePr.then(data => {
    return {
      candidate: data,
    }
  },
  failure => {
    console.error('Unable to get candidates data')
    console.error(failure)
    return { candidate: {} }
  })

  result.then(data => {
    const initialState = {
      candidate: data.candidate,
      user: req.user,
    }

    res.render('index.jade', {
      initialState,
      scriptUrl: scriptUrl(),
      user: req.user,
    })
  })
})

router.put('/:candidateId', isLoggedIn, (req, res) => {
  const candidateId = req.params.candidateId

  const candidatePr = setCandidateMetadata(candidateId, req.body)

  var result = candidatePr.then(data => {
    return {
      candidate: data,
    }
  },
  failure => {
    console.error('Unable to set candidates data')
    console.error(failure)
    return { candidate: {} }
  })

  result.then(data => {
    const initialState = {
      candidate: data.candidate,
      user: req.user,
    }

    res.render('index.jade', {
      initialState,
      scriptUrl: scriptUrl(),
      user: req.user,
    })
  })
})

function isLoggedIn(req, res, next) {
  // if user is authenticated in the session, carry on
  if (req.isAuthenticated()) return next()

  // if they aren't redirect them to the home page
  res.redirect('/admin/login')
}

function isSuperAdmin(req, res, next) {
  if (req.isAuthenticated()) {
    if (req.user.attributes.role === 'admin') {
      return next()
    }
  }

  req.flash('loginMessage', 'Not authorized to signup')
  res.redirect('/admin/login')
}

module.exports = router
<commit_msg>fix another redirect<commit_after>const express = require('express')
const router = express.Router()
const passport = require('passport')

const {scriptUrl} = require('../services/server_helpers')
const {
  getCandidateById,
  getFullCandidatePromise,
  setCandidateMetadata,
} = require('../services/candidate')

router.get('/', isLoggedIn, (req, res) => {
  const initialState = {}
  res.render('index.jade', {
    initialState,
    scriptUrl: scriptUrl(),
    user: req.user,
  })
})

// Login
router.get('/login', (req, res) => {
  if (req.isAuthenticated()) {
    res.redirect('/admin')
  } else {
    res.render('admin/login.jade', { message: req.flash('loginMessage') })
  }
})

router.post('/login', passport.authenticate('local-login', {
  successRedirect : '/admin', // redirect to the secure profile section
  failureRedirect : '/admin/login', // redirect back to the signup page if there is an error
  failureFlash : true, // allow flash messages
}))

// Signup
// router.get('/signup', isSuperAdmin, (req, res) => {
router.get('/signup', (req, res) => {
  res.render('admin/signup.jade', { message: req.flash('signupMessage') })
})

// router.post('/signup', isSuperAdmin, passport.authenticate('local-signup', {
router.post('/signup', passport.authenticate('local-signup', {
  successRedirect: '/admin', // redirect to the secure profile section
  failureRedirect: '/admin/signup', // redirect back to the signup page if there is an error
  failureFlash: true, // allow flash messages
}))

router.get('/logout', (req, res) => {
  req.logout()
  res.redirect('/')
})

router.get('/candidate/id/:id', isLoggedIn, (req, res) => {
  getCandidateById(req.params.id).then(candidate => {
    return res.redirect(`/admin/candidate/${candidate.Candidate_ID}`)
  })
})

router.get('/candidate/:candidateId', isLoggedIn, (req, res) => {
  const candidateId = req.params.candidateId
  console.log('candidateId', candidateId)

  const candidatePr = getFullCandidatePromise(candidateId)

  var result = candidatePr.then(data => {
    return {
      candidate: data,
    }
  },
  failure => {
    console.error('Unable to get candidates data')
    console.error(failure)
    return { candidate: {} }
  })

  result.then(data => {
    const initialState = {
      candidate: data.candidate,
      user: req.user,
    }

    res.render('index.jade', {
      initialState,
      scriptUrl: scriptUrl(),
      user: req.user,
    })
  })
})

router.put('/:candidateId', isLoggedIn, (req, res) => {
  const candidateId = req.params.candidateId

  const candidatePr = setCandidateMetadata(candidateId, req.body)

  var result = candidatePr.then(data => {
    return {
      candidate: data,
    }
  },
  failure => {
    console.error('Unable to set candidates data')
    console.error(failure)
    return { candidate: {} }
  })

  result.then(data => {
    const initialState = {
      candidate: data.candidate,
      user: req.user,
    }

    res.render('index.jade', {
      initialState,
      scriptUrl: scriptUrl(),
      user: req.user,
    })
  })
})

function isLoggedIn(req, res, next) {
  // if user is authenticated in the session, carry on
  if (req.isAuthenticated()) return next()

  // if they aren't redirect them to the home page
  res.redirect('/admin/login')
}

function isSuperAdmin(req, res, next) {
  if (req.isAuthenticated()) {
    if (req.user.attributes.role === 'admin') {
      return next()
    }
  }

  req.flash('loginMessage', 'Not authorized to signup')
  res.redirect('/admin/login')
}

module.exports = router
<|endoftext|>


<commit_before>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2015  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import { API_HOST } from '../config'
import ApiClient from '../api/client'
import { getStore } from '../store';
import {
  addError, addMessage, removeAllMessages,
  addUser, addPost, addPostToRiver, setCurrentUser, removePost,
  setLikes, setFavourites, setPostsToLikesRiver,
  setUserTags, setSchools, addSchool, setSuggestedUsers
} from '../actions';

const client = new ApiClient(API_HOST);

export async function likePost(current_user_id, post_id) {
  try {
    let responseBody = await client.like(post_id);

    if (responseBody.success) {
      getStore().dispatch(setLikes(current_user_id, responseBody.likes, post_id, responseBody.likers));
      syncLikedPosts(current_user_id);
    } else {
      getStore().dispatch(addError('internal server error. please try later'));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function unlikePost(current_user_id, post_id) {
  try {
    let responseBody = await client.unlike(post_id);

    if (responseBody.success) {
      getStore().dispatch(setLikes(current_user_id, responseBody.likes, post_id, responseBody.likers));
      syncLikedPosts(current_user_id);
    } else {
      getStore().dispatch(addError('internal server error. please try later'));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function syncLikedPosts() {
  try {
    let likedPosts = client.userLikedPosts();
    getStore().dispatch(setPostsToLikesRiver(await likedPosts));
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function favPost(current_user_id, post_id) {
  try {
    let responseBody = await client.fav(post_id);

    if (responseBody.success) {
      getStore().dispatch(setFavourites(current_user_id, responseBody.favourites, post_id, responseBody.favourers));
    } else {
      getStore().dispatch(addError('internal server error. please try later'));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function unfavPost(current_user_id, post_id) {
  try {
    let responseBody = await client.unfav(post_id);

    if (responseBody.success) {
      getStore().dispatch(setFavourites(current_user_id, responseBody.favourites, post_id, responseBody.favourers));
    } else {
      getStore().dispatch(addError('internal server error. please try later'));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function createPost(type, data) {
  try {
    let result = await client.createPost(type, data);
    getStore().dispatch(addPostToRiver(result));

    let userTags = client.userTags();
    getStore().dispatch(setUserTags(await userTags));
  } catch (e) {
    console.log(e)
    console.log(e.stack)

    getStore().dispatch(addError(e.message));
  }
}

export async function updateUserInfo(user) {
  try {
    let res = await client.updateUser(user);

    if ('user' in res) {
      getStore().dispatch(addMessage('Saved successfully'));
      getStore().dispatch(addUser(res.user));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function changePassword(old_password, new_password1, new_password2)
{
  if (old_password.trim() == '' || new_password1.trim() == '' || new_password2.trim() == '') {
    getStore().dispatch(addError('some of the fields are empty'));
    return;
  }

  if (new_password1 !== new_password2) {
    getStore().dispatch(addError('passwords do not match'));
    return;
  }

  try {
    let res = await client.changePassword(old_password, new_password1);

    if ('success' in res && res.success === true) {
      getStore().dispatch(addMessage('Password is changed successfully'));
    }
  } catch (e) {
    if (('body' in e.response) && ('error' in e.response.body)) {
      getStore().dispatch(addError(e.response.body.error));
    } else {
      getStore().dispatch(addError(e.message));
    }
  }
}

export async function followUser(user) {
  try {
    let res = await client.follow(user.username);

    if ('user1' in res) {
      getStore().dispatch(addUser(res.user1));
      getStore().dispatch(addUser(res.user2));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function unfollowUser(user) {
  try {
    let res = await client.unfollow(user.username);

    if ('user1' in res) {
      getStore().dispatch(addUser(res.user1));
      getStore().dispatch(addUser(res.user2));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function login(username, password) {
  getStore().dispatch(removeAllMessages());

  try {
    let result = await client.login({username, password});

    if (result.success) {
      let user = result.user;
      getStore().dispatch(setCurrentUser(user));
      getStore().dispatch(setLikes(user.id, user.liked_posts.map(like => like.id)));
      getStore().dispatch(setFavourites(user.id, user.favourited_posts.map(fav => fav.id)));
    } else {
      getStore().dispatch(setCurrentUser(null));
      getStore().dispatch(addError('Invalid username or password'));
    }
  } catch (e) {
    getStore().dispatch(setCurrentUser(null));
    getStore().dispatch(addError('Invalid username or password'));
  }
}

export async function registerUser(username, password, email, firstName, lastName) {
  getStore().dispatch(removeAllMessages());

  // FIXME: disable form
  try {
    let result = await client.registerUser({username, password, email, firstName, lastName});

    if (result.success) {
      let user = result.user;

      getStore().dispatch(setCurrentUser(user));

      return user;
    } else {
      // FIXME: enable form again
      getStore().dispatch(addError(result.error));
    }
  } catch (e) {
    // FIXME: enable form again

    if (e.response && ('error' in e.response.body)) {
      // FIXME: enable form again
      getStore().dispatch(addError(e.response.body.error));
    } else {
      getStore().dispatch(addError('Server seems to have problems. Retry later, please'));
    }
  }
}

export async function deletePost(post_uuid) {
  await client.deletePost(post_uuid);
  getStore().dispatch(removePost(post_uuid));
}

export async function updatePost(post_uuid, post_fields) {
  try {
    let result = await client.updatePost(post_uuid, post_fields);
    getStore().dispatch(addPost(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function updateSchool(school_uuid, school_fields) {
  try {
    let result = await client.updateSchool(school_uuid, school_fields);
    getStore().dispatch(addSchool(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function loadSchools() {
  try {
    let result = await client.schools();
    getStore().dispatch(setSchools(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function loadInitialSuggestions() {
  try {
    let result = await client.initialSuggestions();

    getStore().dispatch(setSuggestedUsers(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}
<commit_msg>Add loadPostRiver trigger<commit_after>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2015  Loki Education (Social Enterprise)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
import { API_HOST } from '../config'
import ApiClient from '../api/client'
import { getStore } from '../store';
import {
  addError, addMessage, removeAllMessages,
  addUser, addPost, addPostToRiver, setCurrentUser, removePost,
  setLikes, setFavourites, setPostsToLikesRiver,
  setUserTags, setSchools, addSchool, setSuggestedUsers, setPostsToRiver
} from '../actions';

const client = new ApiClient(API_HOST);

export async function likePost(current_user_id, post_id) {
  try {
    let responseBody = await client.like(post_id);

    if (responseBody.success) {
      getStore().dispatch(setLikes(current_user_id, responseBody.likes, post_id, responseBody.likers));
      syncLikedPosts(current_user_id);
    } else {
      getStore().dispatch(addError('internal server error. please try later'));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function unlikePost(current_user_id, post_id) {
  try {
    let responseBody = await client.unlike(post_id);

    if (responseBody.success) {
      getStore().dispatch(setLikes(current_user_id, responseBody.likes, post_id, responseBody.likers));
      syncLikedPosts(current_user_id);
    } else {
      getStore().dispatch(addError('internal server error. please try later'));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function syncLikedPosts() {
  try {
    let likedPosts = client.userLikedPosts();
    getStore().dispatch(setPostsToLikesRiver(await likedPosts));
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function favPost(current_user_id, post_id) {
  try {
    let responseBody = await client.fav(post_id);

    if (responseBody.success) {
      getStore().dispatch(setFavourites(current_user_id, responseBody.favourites, post_id, responseBody.favourers));
    } else {
      getStore().dispatch(addError('internal server error. please try later'));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function unfavPost(current_user_id, post_id) {
  try {
    let responseBody = await client.unfav(post_id);

    if (responseBody.success) {
      getStore().dispatch(setFavourites(current_user_id, responseBody.favourites, post_id, responseBody.favourers));
    } else {
      getStore().dispatch(addError('internal server error. please try later'));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function createPost(type, data) {
  try {
    let result = await client.createPost(type, data);
    getStore().dispatch(addPostToRiver(result));

    let userTags = client.userTags();
    getStore().dispatch(setUserTags(await userTags));
  } catch (e) {
    console.log(e)
    console.log(e.stack)

    getStore().dispatch(addError(e.message));
  }
}

export async function updateUserInfo(user) {
  try {
    let res = await client.updateUser(user);

    if ('user' in res) {
      getStore().dispatch(addMessage('Saved successfully'));
      getStore().dispatch(addUser(res.user));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function changePassword(old_password, new_password1, new_password2)
{
  if (old_password.trim() == '' || new_password1.trim() == '' || new_password2.trim() == '') {
    getStore().dispatch(addError('some of the fields are empty'));
    return;
  }

  if (new_password1 !== new_password2) {
    getStore().dispatch(addError('passwords do not match'));
    return;
  }

  try {
    let res = await client.changePassword(old_password, new_password1);

    if ('success' in res && res.success === true) {
      getStore().dispatch(addMessage('Password is changed successfully'));
    }
  } catch (e) {
    if (('body' in e.response) && ('error' in e.response.body)) {
      getStore().dispatch(addError(e.response.body.error));
    } else {
      getStore().dispatch(addError(e.message));
    }
  }
}

export async function followUser(user) {
  try {
    let res = await client.follow(user.username);

    if ('user1' in res) {
      getStore().dispatch(addUser(res.user1));
      getStore().dispatch(addUser(res.user2));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function unfollowUser(user) {
  try {
    let res = await client.unfollow(user.username);

    if ('user1' in res) {
      getStore().dispatch(addUser(res.user1));
      getStore().dispatch(addUser(res.user2));
    }
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function login(username, password) {
  getStore().dispatch(removeAllMessages());

  try {
    let result = await client.login({username, password});

    if (result.success) {
      let user = result.user;
      getStore().dispatch(setCurrentUser(user));
      getStore().dispatch(setLikes(user.id, user.liked_posts.map(like => like.id)));
      getStore().dispatch(setFavourites(user.id, user.favourited_posts.map(fav => fav.id)));
    } else {
      getStore().dispatch(setCurrentUser(null));
      getStore().dispatch(addError('Invalid username or password'));
    }
  } catch (e) {
    getStore().dispatch(setCurrentUser(null));
    getStore().dispatch(addError('Invalid username or password'));
  }
}

export async function registerUser(username, password, email, firstName, lastName) {
  getStore().dispatch(removeAllMessages());

  // FIXME: disable form
  try {
    let result = await client.registerUser({username, password, email, firstName, lastName});

    if (result.success) {
      let user = result.user;

      getStore().dispatch(setCurrentUser(user));

      return user;
    } else {
      // FIXME: enable form again
      getStore().dispatch(addError(result.error));
    }
  } catch (e) {
    // FIXME: enable form again

    if (e.response && ('error' in e.response.body)) {
      // FIXME: enable form again
      getStore().dispatch(addError(e.response.body.error));
    } else {
      getStore().dispatch(addError('Server seems to have problems. Retry later, please'));
    }
  }
}

export async function deletePost(post_uuid) {
  await client.deletePost(post_uuid);
  getStore().dispatch(removePost(post_uuid));
}

export async function updatePost(post_uuid, post_fields) {
  try {
    let result = await client.updatePost(post_uuid, post_fields);
    getStore().dispatch(addPost(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function updateSchool(school_uuid, school_fields) {
  try {
    let result = await client.updateSchool(school_uuid, school_fields);
    getStore().dispatch(addSchool(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function loadSchools() {
  try {
    let result = await client.schools();
    getStore().dispatch(setSchools(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function loadInitialSuggestions() {
  try {
    let result = await client.initialSuggestions();

    getStore().dispatch(setSuggestedUsers(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}

export async function loadPostRiver() {
  try {
    let result = await client.subscriptions();
    getStore().dispatch(setPostsToRiver(result));

    return result;
  } catch (e) {
    getStore().dispatch(addError(e.message));
  }
}
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();

/* GET cards listing. */
router.get('/', function (req, res, next) {
    var allowedOrigins = ['http://locaohost', 'http://localhost:4200'];
    var origin = req.headers.origin;
    if (allowedOrigins.indexOf(origin) > -1) {
        res.set('Access-Control-Allow-Origin', origin);
    }
    global.db.collection("cards").find({name: "Crowd Favorite"}).toArray(function (err, result) { // 返回集合中所有数据
        if (err) throw err;
        console.log("成功连接cards");
        console.log(result);
        res.json(result);
    });
});

/* GET users listing. */
router.get('/1', function (req, res, next) {
    // res.send('respond with a resource');
    res.json({user: 1});
});

module.exports = router;
<commit_msg>Allowed getting cards with page & pageSize<commit_after>var express = require('express');
var router = express.Router();

/* GET cards listing. */
router.get('/', function (req, res, next) {
    var allowedOrigins = ['http://localhost', 'http://localhost:4200'];
    var origin = req.headers.origin;
    if (allowedOrigins.indexOf(origin) > -1) {
        res.set('Access-Control-Allow-Origin', origin);
    }
    var page = req.query.page ? req.query.page : 1;
    var pageSize = req.query.pageSize ? req.query.pageSize : 10;
    global.db.collection("cards").find().skip((page - 1) * pageSize).limit(pageSize).toArray(function (err, result) { // 返回集合中所有数据
        if (err) throw err;
        console.log("成功连接cards");
        console.log(result);
        res.json(result);
    });
});

/* GET users listing. */
router.get('/1', function (req, res, next) {
    // res.send('respond with a resource');
    res.json({user: 1});
});

module.exports = router;
<|endoftext|>


<commit_before>var
  assert = require('assert'),
  fft_lib = require('../lib/fft'),
  complex_array_lib = require('../lib/complex_array'),
  ComplexArray = complex_array_lib.ComplexArray,
  isComplexArray = complex_array_lib.isComplexArray,
  EPSILON = 1e-5,
  SQRT2 = Math.SQRT2,
  SQRT1_2 = Math.SQRT1_2,
  random = Math.random

function assertApproximatelyEqual(first, second, message) {
  var delta = Math.abs(first - second)
  assert.ok(delta < EPSILON, message)
}

function assertComplexArraysAlmostEqual(first, second) {
  var message = second + ' != ' + first

  assert.equal(first.length, second.length, message)

  first.forEach(function(value, i) {
    assertApproximatelyEqual(value.real, second.real[i], message)
    assertApproximatelyEqual(value.imag, second.imag[i], message)
  })
}

function assertFFTMatches(original, expected) {
  var transformed

  if (!isComplexArray(expected)) {
    throw TypeError('expected match should be a ComplexArray')
  }

  transformed = fft_lib.FFT(original)
  assertComplexArraysAlmostEqual(expected, transformed)
  assertComplexArraysAlmostEqual(
      new ComplexArray(original), fft_lib.InvFFT(transformed))
}

describe('fft', function() {
  describe('#FFT()', function() {
    describe('on N=2 Arrays', function() {
      it('should return a single frequency given a constant array', function() {
        assertFFTMatches([1, 1], new ComplexArray([SQRT2, 0]))
      })

      it('should return flat with a delta function input', function() {
        assertFFTMatches([1, 0], new ComplexArray([SQRT1_2, SQRT1_2]))
      })

      it('should return a single negative freq', function() {
        assertFFTMatches([-1, 1], new ComplexArray([0, -SQRT2]))
      })
    })

    describe('on N=3 Arrays', function() {
      it('should throw an error', function() {
        assert.throws(function(){fft_lib.FFT([1, 1, 1])}, Error)
      })
    })

    describe('on N=4 Arrays', function() {
      it('should return a single frequency given a constant array', function() {
        assertFFTMatches([1, 1, 1, 1], new ComplexArray([2, 0, 0, 0]))
      })

      it('should return flat with a delta function input', function() {
        assertFFTMatches([1, 0, 0, 0], new ComplexArray([0.5, 0.5, 0.5, 0.5]))
      })

      it('should return a single high freq', function() {
        assertFFTMatches([1, -1, 1, -1], new ComplexArray([0, 0, 2, 0]))
      })

      it('should return a single low freq', function() {
        assertFFTMatches([1, 0, -1, -0], new ComplexArray([0, 1, 0, 1]))
      })

      it('should return a high freq and DC', function() {
        assertFFTMatches([1, 0, 1, 0], new ComplexArray([1, 0, 1, 0]))
      })
    })

    describe('on N=8 Arrays', function() {
      it('should return a single frequency given a constant array', function() {
        assertFFTMatches([1, 1, 1, 1, 1, 1, 1, 1],
          new ComplexArray([2*SQRT2, 0, 0, 0, 0, 0, 0, 0]))
      })

      it('should return a single high freq', function() {
        assertFFTMatches([1, -1, 1, -1, 1, -1, 1, -1],
          new ComplexArray([0, 0, 0, 0, 2*SQRT2, 0, 0, 0]))
      })

      it('should return a single low freq', function() {
        var cos_pi_4 = Math.cos(Math.PI/4)

        assertFFTMatches(
          [1, cos_pi_4, 0, -cos_pi_4, -1, -cos_pi_4, 0, cos_pi_4],
          new ComplexArray([0, SQRT2, 0, 0, 0, 0, 0, SQRT2]))
      })
    })

    describe('on N=512 Arrays', function() {
      it('should return the same array after InvFFT.FFT', function() {
        var
          a = [],
          i

        for(i = 0; i < 512; i++) {
          a[i] = random()
        }

        assertComplexArraysAlmostEqual(
          new ComplexArray(a), fft_lib.InvFFT(fft_lib.FFT(a)))
      })
    })
  })

  describe('#Filter()', function() {
    it('should not modify the original', function() {
      var filtered = fft_lib.Filter([1, 2, 3, 4], function() {})

      assertComplexArraysAlmostEqual(new ComplexArray([1, 2, 3, 4]), filtered)
    })

    it('should halve the original', function() {
      var filtered = fft_lib.Filter([1, 2, 3, 4], function(value, i) {
        value.real /= 2
        value.imag /= 2
      })

      assertComplexArraysAlmostEqual(new ComplexArray([0.5, 1, 1.5, 2]), filtered)
    })

    it('should return zeroed ComplexArray', function() {
      var filtered = fft_lib.Filter([1, 2, 3, 4], function(value, i) {
        value.real = value.imag = 0
      })

      assertComplexArraysAlmostEqual(new ComplexArray([0, 0, 0, 0]), filtered)
    })

    it('should shift the original', function() {
      var filtered = fft_lib.Filter([1, 2, 3, 4], function(value, i) {
        var
          // Multiply by a phase to shift the original.
          real_multiplier = i % 2 ? 0 : (1 - i),
          imag_multiplier = i % 2 ? (2 - i) : 0,
          swap_real = value.real,
          swap_imag = value.imag

        value.real = real_multiplier * swap_real - imag_multiplier * swap_imag
        value.imag = real_multiplier * swap_imag + imag_multiplier * swap_real
      })

      assertComplexArraysAlmostEqual(new ComplexArray([4, 1, 2, 3]), filtered)
    })
  })
})

<commit_msg>Test to ensure fft matches dft for random array; removed other tests.<commit_after>var
  assert = require('assert'),
  fft_lib = require('../lib/fft'),
  complex_array_lib = require('../lib/complex_array'),
  ComplexArray = complex_array_lib.ComplexArray,
  isComplexArray = complex_array_lib.isComplexArray,
  PI = Math.PI,
  EPSILON = 1e-5,
  SQRT2 = Math.SQRT2,
  SQRT1_2 = Math.SQRT1_2,
  cos = Math.cos,
  sin = Math.sin,
  sqrt = Math.sqrt,
  random = Math.random

function DFT(input) {
  var
    n = input.length,
    amplitude = 1 / sqrt(n),
    output = new ComplexArray(input),
    phase = {real: 0, imag: 0},
    delta = {real: 0, imag: 0},
    _swap

  return output.map(function(out_value, i) {
    out_value.real = 0, out_value.imag = 0
    phase.real = 1, phase.imag = 0
    delta.real = cos(2*PI*i/n), delta.imag = sin(2*PI*i/n)

    input.forEach(function(in_value, j) {
      out_value.real += phase.real * in_value.real - phase.imag * in_value.imag
      out_value.imag += phase.real * in_value.imag + phase.imag * in_value.real
      _swap = phase.real
      phase.real = phase.real * delta.real - phase.imag * delta.imag
      phase.imag = _swap * delta.imag + phase.imag * delta.real
    })
    out_value.real *= amplitude
    out_value.imag *= amplitude
  })
}

function assertApproximatelyEqual(first, second, message) {
  var delta = Math.abs(first - second)
  assert.ok(delta < EPSILON, message)
}

function assertComplexArraysAlmostEqual(first, second) {
  var message = second + ' != ' + first

  assert.equal(first.length, second.length, message)

  first.forEach(function(value, i) {
    assertApproximatelyEqual(value.real, second.real[i], message)
    assertApproximatelyEqual(value.imag, second.imag[i], message)
  })
}

function assertFFTMatches(original, expected) {
  var transformed

  if (!isComplexArray(expected)) {
    throw TypeError('expected match should be a ComplexArray')
  }

  transformed = fft_lib.FFT(original)
  assertComplexArraysAlmostEqual(expected, transformed)
  assertComplexArraysAlmostEqual(
      new ComplexArray(original), fft_lib.InvFFT(transformed))
}

function assertFFTMatchesDFT(input) {
  input = new ComplexArray(input)

  assertComplexArraysAlmostEqual(DFT(input), fft_lib.FFT(input))
}

describe('fft', function() {
  describe('#FFT()', function() {
    describe('on N=3 Arrays', function() {
      it('should throw an error', function() {
        assert.throws(function(){fft_lib.FFT([1, 1, 1])}, Error)
      })
    })

    describe('on N=4 Arrays', function() {
      it('should return a single frequency given a constant array', function() {
        assertFFTMatches([1, 1, 1, 1], new ComplexArray([2, 0, 0, 0]))
      })

      it('should return flat with a delta function input', function() {
        assertFFTMatches([1, 0, 0, 0], new ComplexArray([0.5, 0.5, 0.5, 0.5]))
      })

      it('should return a single high freq', function() {
        assertFFTMatches([1, -1, 1, -1], new ComplexArray([0, 0, 2, 0]))
      })

      it('should return a single low freq', function() {
        assertFFTMatches([1, 0, -1, -0], new ComplexArray([0, 1, 0, 1]))
      })

      it('should return a high freq and DC', function() {
        assertFFTMatches([1, 0, 1, 0], new ComplexArray([1, 0, 1, 0]))
      })
    })

    describe('on N=512 Arrays', function() {
      it('should return the same array after InvFFT.FFT', function() {
        var a = new ComplexArray(512)

        a.map(function(value) {
          value.real = random()
          value.imag = random()
        })

        assertFFTMatchesDFT(a)
      })
    })
  })

  describe('#Filter()', function() {
    it('should not modify the original', function() {
      var filtered = fft_lib.Filter([1, 2, 3, 4], function() {})

      assertComplexArraysAlmostEqual(new ComplexArray([1, 2, 3, 4]), filtered)
    })

    it('should halve the original', function() {
      var filtered = fft_lib.Filter([1, 2, 3, 4], function(value, i) {
        value.real /= 2
        value.imag /= 2
      })

      assertComplexArraysAlmostEqual(new ComplexArray([0.5, 1, 1.5, 2]), filtered)
    })

    it('should return zeroed ComplexArray', function() {
      var filtered = fft_lib.Filter([1, 2, 3, 4], function(value, i) {
        value.real = value.imag = 0
      })

      assertComplexArraysAlmostEqual(new ComplexArray([0, 0, 0, 0]), filtered)
    })

    it('should shift the original', function() {
      var filtered = fft_lib.Filter([1, 2, 3, 4], function(value, i) {
        var
          // Multiply by a phase to shift the original.
          real_multiplier = i % 2 ? 0 : (1 - i),
          imag_multiplier = i % 2 ? (2 - i) : 0,
          swap_real = value.real,
          swap_imag = value.imag

        value.real = real_multiplier * swap_real - imag_multiplier * swap_imag
        value.imag = real_multiplier * swap_imag + imag_multiplier * swap_real
      })

      assertComplexArraysAlmostEqual(new ComplexArray([4, 1, 2, 3]), filtered)
    })
  })
})

<|endoftext|>


<commit_before>const express = require('express');

const webpackConfig = require('../../webpack.config');
const config = require('../config');
const { authenticationMiddleware } = require('../authentication');

const router = express.Router();

const renderData = {
  appinsightsKey: config.appinsightsKey,
};

if (config.dev) {
  // eslint-disable-next-line
  const webpack = require('webpack');
  // eslint-disable-next-line
  const webpackMiddleware = require('webpack-dev-middleware');
  // eslint-disable-next-line
  const webpackHotMiddleware = require('webpack-hot-middleware');

  const compiler = webpack(webpackConfig);
  const middleware = webpackMiddleware(compiler, {
    publicPath: webpackConfig.output.publicPath,
    contentBase: 'client',
    noInfo: true,
  });

  router.use(middleware);
  router.use(webpackHotMiddleware(compiler));
  router.get('*', authenticationMiddleware(), (req, res) => {
    res.render('index', { ...renderData, name: req.user.name });
  });
} else {
  router.get('*', authenticationMiddleware(), (req, res) => {
    res.render('index', { ...renderData, isLoggedIn: req.isAuthenticated(), name: req.user && `${req.user.forename} ${req.user.surname}` });
  });
}

module.exports = router;
<commit_msg>CSRA-680: Refactor the apps rendered data<commit_after>const express = require('express');

const webpackConfig = require('../../webpack.config');
const config = require('../config');
const { authenticationMiddleware } = require('../authentication');

const router = express.Router();

if (config.dev) {
  // eslint-disable-next-line
  const webpack = require('webpack');
  // eslint-disable-next-line
  const webpackMiddleware = require('webpack-dev-middleware');
  // eslint-disable-next-line
  const webpackHotMiddleware = require('webpack-hot-middleware');

  const compiler = webpack(webpackConfig);
  const middleware = webpackMiddleware(compiler, {
    publicPath: webpackConfig.output.publicPath,
    contentBase: 'client',
    noInfo: true,
  });

  router.use(middleware);
  router.use(webpackHotMiddleware(compiler));
}

router.get('*', authenticationMiddleware(), (req, res) => {
  res.render('index', { appinsightsKey: config.appinsightsKey, isLoggedIn: true, name: req.user && `${req.user.forename} ${req.user.surname}` });
});

module.exports = router;
<|endoftext|>