<commit_before>// Karma configuration
// Generated on Thu Mar 03 2016 19:57:50 GMT-0600 (CST)
var Set = require('collections/set');

module.exports = function (config) {
  // Set up default files to test against
  var karmaTest = 'karma-test.js';
  var successTest = 'success-test.js';
  var phantomJsTest = 'phantomjs-test.js';
  var eofCommentTest = 'eof-comment-test.js';
  var failureTest = 'failure-test.js';
  var sourceMapTest = 'source-map-test.js';
  var uncaughtExceptionTest = 'uncaught-exception-test.js';
  var mainRequireTest = 'main-require-test.js';
  var nodeCommonTest = 'node-common-test.js';
  var nodeRequireTest = 'node-require-test.js';
  var nodeScriptSrcTest = 'node-script-src-test.js';
  var customContextFileTest = 'custom-context-file-test.js';
  var filenameOverrideTest = 'filename-override-test.js';
  var testFiles = ['*-test.js'];
  var excludeFiles = new Set([
    customContextFileTest, failureTest, filenameOverrideTest, karmaTest,
    nodeRequireTest, phantomJsTest, sourceMapTest, uncaughtExceptionTest,
    mainRequireTest]);

  // If we are testing uncaught exceptions, then update our tests
  if (process.env.TEST_TYPE === 'UNCAUGHT_EXCEPTION') {
    testFiles = [uncaughtExceptionTest];
    excludeFiles.delete(uncaughtExceptionTest);
  } else if (process.env.TEST_TYPE === 'EOF_COMMENT') {
    testFiles = [eofCommentTest];
    excludeFiles.delete(eofCommentTest);
  } else if (process.env.TEST_TYPE === 'FAILURE') {
    testFiles = [failureTest];
    excludeFiles.delete(failureTest);
  } else if (process.env.TEST_TYPE === 'KARMA') {
    testFiles = [karmaTest];
    excludeFiles.delete(karmaTest);
  } else if (process.env.TEST_TYPE === 'PHANTOMJS') {
    testFiles = [successTest, phantomJsTest];
    excludeFiles = new Set();
  } else if (process.env.TEST_TYPE === 'SOURCE_MAP') {
    testFiles = [sourceMapTest];
    excludeFiles.delete(sourceMapTest);
  } else if (process.env.TEST_TYPE === 'CUSTOM_CONTEXT_FILE') {
    testFiles = [customContextFileTest];
    excludeFiles.delete(customContextFileTest);
  } else if (process.env.TEST_TYPE === 'FILENAME_OVERRIDE') {
    testFiles = [filenameOverrideTest];
    excludeFiles.delete(filenameOverrideTest);
  } else if (process.env.TEST_TYPE === 'MAIN_REQUIRE') {
    testFiles = [mainRequireTest];
    excludeFiles.delete(mainRequireTest);
  } else if (process.env.TEST_TYPE === 'NODE_REQUIRE') {
    testFiles = [nodeCommonTest, nodeRequireTest];
    excludeFiles.add(nodeScriptSrcTest);
    excludeFiles.delete(nodeRequireTest);
  } else if (process.env.TEST_TYPE) {
    throw new Error('Unrecognized test type "' + process.env.TEST_TYPE + '"');
  }

  // Define our config
  config.set({
    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // Custom context/debug files and launchers
    customContextFile: process.env.TEST_TYPE === 'CUSTOM_CONTEXT_FILE' ?
      __dirname + '/test-files/custom-context.html' : null,
    customDebugFile: process.env.TEST_TYPE === 'CUSTOM_CONTEXT_FILE' ?
      __dirname + '/test-files/custom-debug.html' : null,
    customLaunchers: {
      // TODO: Update some tests to not use `WithNodeIntegration`
      ElectronWithNodeIntegration: {
        base: 'Electron',
        browserWindowOptions: {
          webPreferences: {
            nodeIntegration: true
          }
        }
      },
      ElectronMainRequire: {
        base: 'ElectronWithNodeIntegration',
        require: __dirname + '/test-files/main-require.js'
      },
      VisibleElectron: {
        base: 'ElectronWithNodeIntegration',
        flags: ['--show']
      }
    },
    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha'],

    // list of files / patterns to load in the browser
    files: testFiles,

    // list of files to exclude
    exclude: excludeFiles.toArray(),

    browserNoActivityTimeout: 2000,
    client: {
      // DEV: We use `client` as these options affect the client side of `karma`
      //   Based on https://github.com/karma-runner/karma-mocha/tree/v1.1.1#configuration
      __filenameOverride: process.env.TEST_TYPE === 'FILENAME_OVERRIDE' ?
        __dirname + '/test-files/filename-override-context.html' : null,
      loadScriptsViaRequire: process.env.TEST_TYPE === 'NODE_REQUIRE',
      useIframe: false
    },

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      '*-test.js': ['electron']
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['ElectronWithNodeIntegration'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity,

    // Load in our module as a plugin
    // https://github.com/karma-runner/karma-chrome-launcher/blob/v0.2.2/examples/simple/karma.conf.js
    plugins: [
        require('../../'),
        'karma-mocha',
        'karma-phantomjs-launcher'
    ]
  });
};
<commit_msg>Added disable for security warnings<commit_after>// Karma configuration
// Generated on Thu Mar 03 2016 19:57:50 GMT-0600 (CST)
var Set = require('collections/set');

// Disable security warnings
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = '1';

module.exports = function (config) {
  // Set up default files to test against
  var karmaTest = 'karma-test.js';
  var successTest = 'success-test.js';
  var phantomJsTest = 'phantomjs-test.js';
  var eofCommentTest = 'eof-comment-test.js';
  var failureTest = 'failure-test.js';
  var sourceMapTest = 'source-map-test.js';
  var uncaughtExceptionTest = 'uncaught-exception-test.js';
  var mainRequireTest = 'main-require-test.js';
  var nodeCommonTest = 'node-common-test.js';
  var nodeRequireTest = 'node-require-test.js';
  var nodeScriptSrcTest = 'node-script-src-test.js';
  var customContextFileTest = 'custom-context-file-test.js';
  var filenameOverrideTest = 'filename-override-test.js';
  var testFiles = ['*-test.js'];
  var excludeFiles = new Set([
    customContextFileTest, failureTest, filenameOverrideTest, karmaTest,
    nodeRequireTest, phantomJsTest, sourceMapTest, uncaughtExceptionTest,
    mainRequireTest]);

  // If we are testing uncaught exceptions, then update our tests
  if (process.env.TEST_TYPE === 'UNCAUGHT_EXCEPTION') {
    testFiles = [uncaughtExceptionTest];
    excludeFiles.delete(uncaughtExceptionTest);
  } else if (process.env.TEST_TYPE === 'EOF_COMMENT') {
    testFiles = [eofCommentTest];
    excludeFiles.delete(eofCommentTest);
  } else if (process.env.TEST_TYPE === 'FAILURE') {
    testFiles = [failureTest];
    excludeFiles.delete(failureTest);
  } else if (process.env.TEST_TYPE === 'KARMA') {
    testFiles = [karmaTest];
    excludeFiles.delete(karmaTest);
  } else if (process.env.TEST_TYPE === 'PHANTOMJS') {
    testFiles = [successTest, phantomJsTest];
    excludeFiles = new Set();
  } else if (process.env.TEST_TYPE === 'SOURCE_MAP') {
    testFiles = [sourceMapTest];
    excludeFiles.delete(sourceMapTest);
  } else if (process.env.TEST_TYPE === 'CUSTOM_CONTEXT_FILE') {
    testFiles = [customContextFileTest];
    excludeFiles.delete(customContextFileTest);
  } else if (process.env.TEST_TYPE === 'FILENAME_OVERRIDE') {
    testFiles = [filenameOverrideTest];
    excludeFiles.delete(filenameOverrideTest);
  } else if (process.env.TEST_TYPE === 'MAIN_REQUIRE') {
    testFiles = [mainRequireTest];
    excludeFiles.delete(mainRequireTest);
  } else if (process.env.TEST_TYPE === 'NODE_REQUIRE') {
    testFiles = [nodeCommonTest, nodeRequireTest];
    excludeFiles.add(nodeScriptSrcTest);
    excludeFiles.delete(nodeRequireTest);
  } else if (process.env.TEST_TYPE) {
    throw new Error('Unrecognized test type "' + process.env.TEST_TYPE + '"');
  }

  // Define our config
  config.set({
    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',

    // Custom context/debug files and launchers
    customContextFile: process.env.TEST_TYPE === 'CUSTOM_CONTEXT_FILE' ?
      __dirname + '/test-files/custom-context.html' : null,
    customDebugFile: process.env.TEST_TYPE === 'CUSTOM_CONTEXT_FILE' ?
      __dirname + '/test-files/custom-debug.html' : null,
    customLaunchers: {
      // TODO: Update some tests to not use `WithNodeIntegration`
      ElectronWithNodeIntegration: {
        base: 'Electron',
        browserWindowOptions: {
          webPreferences: {
            nodeIntegration: true
          }
        }
      },
      ElectronMainRequire: {
        base: 'ElectronWithNodeIntegration',
        require: __dirname + '/test-files/main-require.js'
      },
      VisibleElectron: {
        base: 'ElectronWithNodeIntegration',
        flags: ['--show']
      }
    },
    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['mocha'],

    // list of files / patterns to load in the browser
    files: testFiles,

    // list of files to exclude
    exclude: excludeFiles.toArray(),

    browserNoActivityTimeout: 2000,
    client: {
      // DEV: We use `client` as these options affect the client side of `karma`
      //   Based on https://github.com/karma-runner/karma-mocha/tree/v1.1.1#configuration
      __filenameOverride: process.env.TEST_TYPE === 'FILENAME_OVERRIDE' ?
        __dirname + '/test-files/filename-override-context.html' : null,
      loadScriptsViaRequire: process.env.TEST_TYPE === 'NODE_REQUIRE',
      useIframe: false
    },

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      '*-test.js': ['electron']
    },

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['ElectronWithNodeIntegration'],

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity,

    // Load in our module as a plugin
    // https://github.com/karma-runner/karma-chrome-launcher/blob/v0.2.2/examples/simple/karma.conf.js
    plugins: [
        require('../../'),
        'karma-mocha',
        'karma-phantomjs-launcher'
    ]
  });
};
<|endoftext|>


<commit_before>module.exports = function(app, express) {
  const passport = require('passport');
  const bodyParser = require('body-parser');
  app.use(bodyParser.urlencoded({ extended: false }));
  app.use(bodyParser.json());

  app.get('/api/feed', (req,res) => {console.log("success server get req.param", req.param)});
  app.post('/api/signup', (req,res) => {console.log("success server post req.body", req.body)});
  app.post('/api/signin', passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: '/api/signin',
    failureFlash: 'true'
  }));
  app.get('/api/signout', () => {});
};
<commit_msg>Update routes.js<commit_after>module.exports = function(app, express) {
  app.get('/api/feed', (req,res) => {console.log("success server get req.param", req.param)});
  app.post('/api/signup', (req,res) => {console.log("success server post req.body", req.body)});
  app.post('/api/signin', passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: '/api/signin',
    failureFlash: 'true'
  }));
  app.get('/api/signout', () => {});
};
<|endoftext|>


<commit_before>const {createNewUser, createNewRoom, joinRoom, createNewNote, showAllNotes, showFilteredNotes} = require ('../database/db-helpers');
const passport = require('./passport');
const path = require('path');

module.exports = (app, express) => {
  // Facebook OAuth
  app.get('/auth/facebook',
    passport.authenticate('facebook', {
      scope: ['public_profile', 'email', 'user_about_me', 'user_friends']
    }));

  app.get('/auth/facebook/callback',
    passport.authenticate('facebook', { failureRedirect: '/login' }),
      (req, res) => {
        res.cookie('authenticate', req.session.passport);
        res.redirect('/');
      }
  );

  app.get('/logout', function(req, res) {
    req.logout();
    res.redirect('/');
  });

  // User Creation
  app.post('/api/users/', (req, res) => {
    createNewUser(req.body, (user, created) => {
      if (!created) {
        res.send('User already exists!'); // dummy response, can change this
      } else {
        res.send(user); // if new user, send back user data
      }
    });
  });

  // User Info Update
  app.route('/api/users/:userId')
    .get((req, res) => {
      res.send('Retrieve the info for user #' + req.params.userId);
    })
    .put((req, res) => {
      res.send('Update the info for user #' + req.params.userId);
    })
    .delete((req, res) => {
      res.send('Delete user #' + req.params.userId);
    });

  // Room Creation
  app.post('/api/rooms', (req, res) => {
    // create and return hash for room path Url
    // { topic, className, lecturer, hostId }
    /*** Example Data sent back to Client ***
    {
      "audioUrl": "audio url",
      "id": 10,
      "pathUrl": "65ad3",
      "topic": "Data Structures",
      "class": "Hack Reactor",
      "lecturer": "Fred",
      "hostId": 1,
      "updatedAt": "2016-09-24T22:58:19.623Z",
      "createdAt": "2016-09-24T22:58:19.623Z"
    }
    ******************************************/
    createNewRoom(req.body, (roomInfo) => res.send(roomInfo));
  });

  app.post('/api/rooms/:pathUrl', (req, res) => {
  // Have user join the room at 'pathUrl'
    joinRoom(req.body.userId, req.params.pathUrl, (currentRoom) => res.send(currentRoom));
  });

  // Note Creation
  app.post('/api/notes/create', (req, res) => {
    // pass the notes in cache (redis) to database (postgres)
    // {content, audioTimestamp, show, roomId, editingUserId, originalUserId}
    // res.send('End of lecture, and create all new notes for each user');
    createNewNote(req.body, (newNote) => res.send(newNote));
  });

  // Note Editing
  app.route('/api/notes/:userId/:roomId')
    .get((req, res) => {
      if (req.query.filter === 'show') {
        // res.send('Show filtered notes for user #' + req.params.userId + ' inside room #' + req.params.roomId);
        showFilteredNotes(req.params, (allNotes) => res.send(allNotes));
      } else {
        // res.send('Compare all notes for user #' + req.params.userId + ' inside room #' + req.params.roomId);
        showAllNotes(req.params, (allNotes) => res.send(allNotes));
      }
    })
    .put((req, res) => {
      // accepts in req.body an array of notes to update
      // [{id, show, content}]
      res.send('Edit existing notes (save button) for user #' + req.params.userId + ' inside room #' + req.params.roomId);
    })
    .post((req, res) => {
      // potentially instead of using this endpoint, reuse /api/notes/create?
      res.send('Add new notes (save button) for user #' + req.params.userId + ' inside room #' + req.params.roomId);
    });
  app.get('*', function (request, response) {
    response.sendFile(path.resolve(__dirname, '../../client', 'index.html'));
  });
};
<commit_msg>fixed routing on wildcard<commit_after>const {createNewUser, createNewRoom, joinRoom, createNewNote, showAllNotes, showFilteredNotes} = require ('../database/db-helpers');
const passport = require('./passport');
const path = require('path');

module.exports = (app, express) => {
  // Facebook OAuth
  app.get('/auth/facebook',
    passport.authenticate('facebook', {
      scope: ['public_profile', 'email', 'user_about_me', 'user_friends']
    }));

  app.get('/auth/facebook/callback',
    passport.authenticate('facebook', { failureRedirect: '/login' }),
      (req, res) => {
        res.cookie('authenticate', req.session.passport);
        res.redirect('/');
      }
  );

  app.get('/logout', function(req, res) {
    req.logout();
    res.redirect('/');
  });

  // User Creation
  app.post('/api/users/', (req, res) => {
    createNewUser(req.body, (user, created) => {
      if (!created) {
        res.send('User already exists!'); // dummy response, can change this
      } else {
        res.send(user); // if new user, send back user data
      }
    });
  });

  // User Info Update
  app.route('/api/users/:userId')
    .get((req, res) => {
      res.send('Retrieve the info for user #' + req.params.userId);
    })
    .put((req, res) => {
      res.send('Update the info for user #' + req.params.userId);
    })
    .delete((req, res) => {
      res.send('Delete user #' + req.params.userId);
    });

  // Room Creation
  app.post('/api/rooms', (req, res) => {
    // create and return hash for room path Url
    // { topic, className, lecturer, hostId }
    /*** Example Data sent back to Client ***
    {
      "audioUrl": "audio url",
      "id": 10,
      "pathUrl": "65ad3",
      "topic": "Data Structures",
      "class": "Hack Reactor",
      "lecturer": "Fred",
      "hostId": 1,
      "updatedAt": "2016-09-24T22:58:19.623Z",
      "createdAt": "2016-09-24T22:58:19.623Z"
    }
    ******************************************/
    createNewRoom(req.body, (roomInfo) => res.send(roomInfo));
  });

  app.post('/api/rooms/:pathUrl', (req, res) => {
  // Have user join the room at 'pathUrl'
    joinRoom(req.body.userId, req.params.pathUrl, (currentRoom) => res.send(currentRoom));
  });

  // Note Creation
  app.post('/api/notes/create', (req, res) => {
    // pass the notes in cache (redis) to database (postgres)
    // {content, audioTimestamp, show, roomId, editingUserId, originalUserId}
    // res.send('End of lecture, and create all new notes for each user');
    createNewNote(req.body, (newNote) => res.send(newNote));
  });

  // Note Editing
  app.route('/api/notes/:userId/:roomId')
    .get((req, res) => {
      if (req.query.filter === 'show') {
        // res.send('Show filtered notes for user #' + req.params.userId + ' inside room #' + req.params.roomId);
        showFilteredNotes(req.params, (allNotes) => res.send(allNotes));
      } else {
        // res.send('Compare all notes for user #' + req.params.userId + ' inside room #' + req.params.roomId);
        showAllNotes(req.params, (allNotes) => res.send(allNotes));
      }
    })
    .put((req, res) => {
      // accepts in req.body an array of notes to update
      // [{id, show, content}]
      res.send('Edit existing notes (save button) for user #' + req.params.userId + ' inside room #' + req.params.roomId);
    })
    .post((req, res) => {
      // potentially instead of using this endpoint, reuse /api/notes/create?
      res.send('Add new notes (save button) for user #' + req.params.userId + ' inside room #' + req.params.roomId);
    });
<<<<<<< HEAD
  app.get('*', function (request, response) {
=======

  app.get('*/index.bundle.js', function (request, response) {
    response.sendFile(path.resolve(__dirname, '../../client', 'dist/index.bundle.js'));
  });

  app.get('*/index.bundle.js.map', function(request, response) {
    response.sendFile(path.resolve(__dirname, '../../client', 'dist/index.bundle.js.map'));
  });

  app.get('*', function(request, response) {
>>>>>>> fixed routing on wildcard
    response.sendFile(path.resolve(__dirname, '../../client', 'index.html'));
  });
};
<|endoftext|>


<commit_before>module.exports = function(app){
	app.get("/albums/api/haha",function(req,res){
		var haha = [];
		var data = {};
		data.title = "Purple Lamborghini [Explicit]";
		data.artist = "Skrillex";
		data.url = "https://www.amazon.com/Purple-Lamborghini-Explicit/dp/B01IQ0H1DY/ref=sr_1_3?ie=UTF8&qid=1476948109&sr=8-3&keywords=skrillex+purple+lamborghini";
		data.image = "https://images-na.ssl-images-amazon.com/images/I/61QHnD41%2BOL._SS500.jpg";
		data.thumbnail = "https://images-na.ssl-images-amazon.com/images/I/61QHnD41%2BOL._SS500.jpg";
		haha.push(data);
		data = {};
		console.log("hahadata\n",haha);
		res.json(haha);
	});
	app.get("/haha",function(req,res){
		res.send("haha");
	});
	app.get("/qwer",function(req,res){
		res.send("qwer");
	});
};
<commit_msg>change json to send again<commit_after>module.exports = function(app){
	app.get("/albums/api/haha",function(req,res){
		var haha = [];
		var data = {};
		data.title = "Purple Lamborghini [Explicit]";
		data.artist = "Skrillex";
		data.url = "https://www.amazon.com/Purple-Lamborghini-Explicit/dp/B01IQ0H1DY/ref=sr_1_3?ie=UTF8&qid=1476948109&sr=8-3&keywords=skrillex+purple+lamborghini";
		data.image = "https://images-na.ssl-images-amazon.com/images/I/61QHnD41%2BOL._SS500.jpg";
		data.thumbnail = "https://images-na.ssl-images-amazon.com/images/I/61QHnD41%2BOL._SS500.jpg";
		haha.push(data);
		data = {};
		console.log("hahadata\n",haha);
		res.send(haha);
	});
	app.get("/haha",function(req,res){
		res.send("haha");
	});
	app.get("/qwer",function(req,res){
		res.send("qwer");
	});
};
<|endoftext|>


<commit_before>import path from 'path';
import uc from '../APIv1/users/userController.js';
import rc from '../APIv1/recipes/recipeController.js';
import sc from '../APIv1/search/searchController.js';
import { handleGoogleLogin, authenticateGoogleLogin, checkAuth } from './auth.js';
import lc from '../APIv1/likes/likesController.js';
import fp from '../keys/getFPKey.js';
import * as fc from '../APIv1/follows/followsController.js';

module.exports = (app, express) => {

  /**
  * Auth
  */
  app.get('/auth/google', handleGoogleLogin);

  app.get('/auth/google/callback', authenticateGoogleLogin,
    (req, res) => { res.redirect('/'); }
  );

  app.get('/auth/signout', (req, res) => {
    req.session.destroy(() => { res.redirect('/'); });
  });

  /**
   * Users
   */

  app.get('/api/v1/user/', uc.getLoggedInUser);

  app.post('/api/v1/users/', checkAuth, uc.createUser);
  app.get('/api/v1/users/:user_id', uc.getOneUser);

  // TODO: getAllUsers should be protected for only admins, eventually.
  // app.get('/api/v1/users/', uc.getAllUsers);

  // app.get('/api/v1/users/me', /* auth, */ getCurrentUser);
  // app.put('/api/v1/users/:user_id', /* auth, */ updateUser);
  // app.get('/api/v1/users/followers/:user_id', findFollowers);

  /**
   * Recipes
   */
  app.get('/api/v1/trending', rc.trendingRecipes);

  app.post('/api/v1/recipes/', checkAuth, rc.createRecipe);
  app.put('/api/v1/recipes/', rc.editRecipe);
  // app.post('/api/v1/recipes/:recipe_id', /* auth, */ forkRecipe);
  app.get('/api/v1/recipes/', rc.getMultipleRecipes);
  app.get('/api/v1/recipes/:recipe_id', rc.getOneRecipe);

  // app.put('/api/v1/recipes/:recipe', /* auth, */ updateRecipe);
  // app.get('/api/v1/recipes/:user', /* auth, */ getUsersRecipes);
  // app.get('/api/v1/recipes/me', /* auth, */ namedFn);
  // app.get('/api/v1/recipes/me', /* auth, */ namedFn);

  /**
   * Created
   */

  app.get('/api/v1/created/:user', rc.getAllCreatedRecipes);

  /**
   * Search
   */
  app.get('/api/v1/search/:q', sc.searchRecipes);

  /**
   * Likes
   */
  app.get('/api/v1/likes', lc.getLikeState);
  app.post('/api/v1/likes', checkAuth, lc.addOrDeleteRecipeLike);
  app.get('/api/v1/likes/:user', lc.getAllLikedRecipes);
  // app.get('/api/v1/favorites/:user/count', /* auth, */ getUserFavoritesCount);

   /**
   * FPKey
   */
  app.get('/api/v1/FPKey', fp.getFPKey);

  /**
   * Follows
   */
  app.get('/api/v1/follows/users', fc.getUserFollowState);
  app.post('/api/v1/follows/users/', /* checkAuth,*/ fc.addOrRemoveUserFollow);
  app.get('/api/v1/follows/users/:user', /* checkAuth,*/ fc.getAllFollowedUsers);

  app.get('/api/v1/follows/recipes', fc.getRecipeFollowState);
  app.post('/api/v1/follows/recipes/', /* checkAuth,*/ fc.addOrRemoveRecipeFollow);
  app.get('/api/v1/follows/users/:recipe', /* checkAuth,*/ fc.getAllFollowedRecipes);

  /**
   * Catch unspecified routes
   */
  app.get('*', (request, response) => {
    response.sendFile(path.resolve(__dirname, '../../client', 'index.html'));
  });
};
<commit_msg>Correct route formatting, routes<commit_after>import path from 'path';
import uc from '../APIv1/users/userController.js';
import rc from '../APIv1/recipes/recipeController.js';
import sc from '../APIv1/search/searchController.js';
import { handleGoogleLogin, authenticateGoogleLogin, checkAuth } from './auth.js';
import lc from '../APIv1/likes/likesController.js';
import fp from '../keys/getFPKey.js';
import * as fc from '../APIv1/follows/followsController.js';

module.exports = (app, express) => {

  /**
  * Auth
  */
  app.get('/auth/google', handleGoogleLogin);

  app.get('/auth/google/callback', authenticateGoogleLogin,
    (req, res) => { res.redirect('/'); }
  );

  app.get('/auth/signout', (req, res) => {
    req.session.destroy(() => { res.redirect('/'); });
  });

  /**
   * Users
   */

  app.get('/api/v1/user/', uc.getLoggedInUser);

  app.post('/api/v1/users/', checkAuth, uc.createUser);
  app.get('/api/v1/users/:user_id', uc.getOneUser);

  // TODO: getAllUsers should be protected for only admins, eventually.
  // app.get('/api/v1/users/', uc.getAllUsers);

  // app.get('/api/v1/users/me', /* auth, */ getCurrentUser);
  // app.put('/api/v1/users/:user_id', /* auth, */ updateUser);
  // app.get('/api/v1/users/followers/:user_id', findFollowers);

  /**
   * Recipes
   */
  app.get('/api/v1/trending', rc.trendingRecipes);

  app.post('/api/v1/recipes/', checkAuth, rc.createRecipe);
  app.put('/api/v1/recipes/', rc.editRecipe);
  // app.post('/api/v1/recipes/:recipe_id', /* auth, */ forkRecipe);
  app.get('/api/v1/recipes/', rc.getMultipleRecipes);
  app.get('/api/v1/recipes/:recipe_id', rc.getOneRecipe);

  // app.put('/api/v1/recipes/:recipe', /* auth, */ updateRecipe);
  // app.get('/api/v1/recipes/:user', /* auth, */ getUsersRecipes);
  // app.get('/api/v1/recipes/me', /* auth, */ namedFn);
  // app.get('/api/v1/recipes/me', /* auth, */ namedFn);

  /**
   * Created
   */

  app.get('/api/v1/created/:user', rc.getAllCreatedRecipes);

  /**
   * Search
   */
  app.get('/api/v1/search/:q', sc.searchRecipes);

  /**
   * Likes
   */
  app.get('/api/v1/likes', lc.getLikeState);
  app.post('/api/v1/likes', checkAuth, lc.addOrDeleteRecipeLike);
  app.get('/api/v1/likes/:user', lc.getAllLikedRecipes);
  // app.get('/api/v1/favorites/:user/count', /* auth, */ getUserFavoritesCount);

   /**
   * FPKey
   */
  app.get('/api/v1/FPKey', fp.getFPKey);

  /**
   * Follows
   */
  app.get('/api/v1/follows/users', fc.getUserFollowState);
  app.post('/api/v1/follows/users', /* checkAuth,*/ fc.addOrRemoveUserFollow);
  app.get('/api/v1/follows/users/:user', /* checkAuth,*/ fc.getAllFollowedUsers);

  app.get('/api/v1/follows/recipes', fc.getRecipeFollowState);
  app.post('/api/v1/follows/recipes', /* checkAuth,*/ fc.addOrRemoveRecipeFollow);
  app.get('/api/v1/follows/recipes/:user', /* checkAuth,*/ fc.getAllFollowedRecipes);

  /**
   * Catch unspecified routes
   */
  app.get('*', (request, response) => {
    response.sendFile(path.resolve(__dirname, '../../client', 'index.html'));
  });
};
<|endoftext|>


<commit_before>'use strict';

var cfApp = require('cfenv').getAppEnv();
var postgresqlProductionConfig = cfApp.getServices('postgresql');
console.log(JSON.stringify(postgresqlProductionConfig));
var productionDbCredentials;

if(postgresqlProductionConfig['postgresql-2v']) {
  console.log(JSON.stringify(postgresqlProductionConfig['postgresql-2v']));
  productionDbCredentials = postgresqlProductionConfig['postgresql-2v'].credentials;
}
console.log(JSON.stringify(postgresqlProductionConfig['postgresql-2v']));

// Database connection object
module.exports = {

  development: {
    client: 'pg',
    connection: {
      database: 'pwadb',
      host: 'localhost'
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      tableName: 'knex_migrations'
    },
    seeds: {
      directory: './seeds'
    },
    debug: true
  },

  production: {
    client: 'pg',
    connection: productionDbCredentials.uri
  }
};
<commit_msg>turning on debug for production<commit_after>'use strict';

var cfApp = require('cfenv').getAppEnv();
var postgresqlProductionConfig = cfApp.getServices('postgresql');
console.log(JSON.stringify(postgresqlProductionConfig));
var productionDbCredentials;

if(postgresqlProductionConfig['postgresql-2v']) {
  console.log(JSON.stringify(postgresqlProductionConfig['postgresql-2v']));
  productionDbCredentials = postgresqlProductionConfig['postgresql-2v'].credentials;
}
console.log(JSON.stringify(postgresqlProductionConfig['postgresql-2v']));

// Database connection object
module.exports = {

  development: {
    client: 'pg',
    connection: {
      database: 'pwadb',
      host: 'localhost'
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      tableName: 'knex_migrations'
    },
    seeds: {
      directory: './seeds'
    },
    debug: true
  },

  production: {
    client: 'pg',
    connection: productionDbCredentials.uri,
    debug: true
  }
};
<|endoftext|>


<commit_before>var arDrone = require('ar-drone'),
  client = arDrone.createClient(),
  drone_state = {};

client.config('control:altitude_max', 3000); // mm

client.on('navdata', function(info) {
  drone_state = info.demo;
});

module.exports = {

  command: function(obj) {
    var roll = obj.roll || 0;
    var pitch = obj.pitch || 0;
    var yaw = obj.yaw || 0;
    var up = obj.up || 0;
    var start = obj.start || false;
    var stop = obj.stop || false;

    console.log('flight got command:', roll, pitch, yaw, up);

    if (start === true) {
      if (drone_state.controlState == 'CTRL_LANDED') {
        console.log('starting drone');
        client.takeoff();
     }
    }

    if (stop === true) {
      client.stop();
      client.land();
    }

    if (drone_state.controlState == 'CTRL_FLYING') {
      if (up >= 0) {
        client.up(up);
      } else {
        client.down(Math.abs(up));
      }

      if (pitch >= 0) {
        client.front(pitch);
      } else {
        client.back(Math.abs(pitch));
      }

      if (roll >= 0) {
        client.right(roll);
      } else {
        client.left(Math.abs(roll));
      }
    }
  },

    // Returns current drone state
  dronestate: function() {
    return drone_state;
  }
};
<commit_msg>change controlState check<commit_after>var arDrone = require('ar-drone'),
  client = arDrone.createClient(),
  drone_state = {};

client.config('control:altitude_max', 3000); // mm

client.on('navdata', function(info) {
  drone_state = info.demo;
});

module.exports = {

  command: function(obj) {
    var roll = obj.roll || 0;
    var pitch = obj.pitch || 0;
    var yaw = obj.yaw || 0;
    var up = obj.up || 0;
    var start = obj.start || false;
    var stop = obj.stop || false;

    console.log('flight got command:', roll, pitch, yaw, up);

    if (start === true) {
      if (drone_state.controlState == 'CTRL_LANDED') {
        console.log('starting drone');
        client.takeoff();
     }
    }

    if (stop === true) {
      client.stop();
      client.land();
    }

    if (drone_state.controlState != 'CTRL_LANDED') {
      console.log('going up');
      if (up >= 0) {
        client.up(up);
      } else {
        client.down(Math.abs(up));
      }

      if (pitch >= 0) {
        client.front(pitch);
      } else {
        client.back(Math.abs(pitch));
      }

      if (roll >= 0) {
        client.right(roll);
      } else {
        client.left(Math.abs(roll));
      }
    }
  },

    // Returns current drone state
  dronestate: function() {
    return drone_state;
  }
};
<|endoftext|>


<commit_before>var util = require('util');
var moment = require('moment');
var mysql = require('mysql');
var Base = require('./base');
var type = require('../data_type');
var log = require('../log');

var MysqlDriver = Base.extend({
  init: function(connection) {
    this._super();
    this.connection = connection;
  },

  mapDataType: function(spec) {
    var len;
    switch(spec.type) {
      case type.TEXT:
        len = parseInt(spec.length, 10) || 1000;
        if(len > 16777216) {
          return 'LONGTEXT';
        }
        if(len > 65536) {
          return 'MEDIUMTEXT';
        }
        if(len > 256) {
          return 'TEXT';
        }
        return 'TINYTEXT';
      case type.DATE_TIME:
        return 'DATETIME';
      case type.BLOB:
        len = parseInt(spec.length, 10) || 1000;
        if(len > 16777216) {
          return 'LONGBLOB';
        }
        if(len > 65536) {
          return 'MEDIUMBLOB';
        }
        if(len > 256) {
          return 'BLOB';
        }
        return 'TINYBLOB';
      case type.BOOLEAN:
        return 'TINYINT(1)';
    }
    return this._super(spec.type);
  },

  createColumnDef: function(name, spec, options) {
    name = util.format('`%s`', name);
    var t = this.mapDataType(spec);
    var len;
    if(spec.type !== type.TEXT && spec.type !== type.BLOB) {
      len = spec.length ? util.format('(%s)', spec.length) : '';
      if (t === 'VARCHAR' && len === '') {
        len = '(255)';
      }
    }
    var constraint = this.createColumnConstraint(spec, options);
    return [name, t, len, constraint].join(' ');
  },

  createColumnConstraint: function(spec, options) {
    var constraint = [];
    if (spec.unsigned) {
      constraint.push('UNSIGNED');
    }

    if (spec.primaryKey && (!options || options.emitPrimaryKey)) {
      constraint.push('PRIMARY KEY');
      if (spec.autoIncrement) {
        constraint.push('AUTO_INCREMENT');
      }
    }

    if (spec.notNull) {
      constraint.push('NOT NULL');
    }

    if (spec.unique) {
      constraint.push('UNIQUE');
    }

    if (spec.null) {
      constraint.push('NULL');
    }

    if (spec.defaultValue !== undefined) {
      constraint.push('DEFAULT');

      if (typeof spec.defaultValue === 'string'){
        constraint.push("'" + spec.defaultValue + "'");
      } else {
        constraint.push(spec.defaultValue);
      }
    }

    return constraint.join(' ');
  },

  createTable: function(tableName, options, callback) {
    log.verbose('creating table:', tableName);
    var columnSpecs = options;
    var tableOptions = {};

    if (options.columns !== undefined) {
      columnSpecs = options.columns;
      delete options.columns;
      tableOptions = options;
    }

    var ifNotExistsSql = "";
    if(tableOptions.ifNotExists) {
      ifNotExistsSql = "IF NOT EXISTS";
    }

    var primaryKeyColumns = [];
    var columnDefOptions = {
      emitPrimaryKey: false
    };

    for (var columnName in columnSpecs) {
      var columnSpec = this.normalizeColumnSpec(columnSpecs[columnName]);
      columnSpecs[columnName] = columnSpec;
      if (columnSpec.primaryKey) {
        primaryKeyColumns.push(columnName);
      }
    }

    var pkSql = '';
    if (primaryKeyColumns.length > 1) {
      pkSql = util.format(', PRIMARY KEY (`%s`)', primaryKeyColumns.join('`, `'));
    } else {
      columnDefOptions.emitPrimaryKey = true;
    }

    var columnDefs = [];
    for (var columnName in columnSpecs) {
      var columnSpec = columnSpecs[columnName];
      columnDefs.push(this.createColumnDef(columnName, columnSpec, columnDefOptions));
    }

    var sql = util.format('CREATE TABLE %s `%s` (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql);
    this.runSql(sql, callback);
  },

  renameTable: function(tableName, newTableName, callback) {
    var sql = util.format('RENAME TABLE `%s` TO `%s`', tableName, newTableName);
    this.runSql(sql, callback);
  },

  addColumn: function(tableName, columnName, columnSpec, callback) {
    var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec));
    var sql = util.format('ALTER TABLE `%s` ADD COLUMN %s', tableName, def);
    this.runSql(sql, callback);
  },

  removeColumn: function(tableName, columnName, callback) {
    var sql = util.format('ALTER TABLE `%s` DROP COLUMN `%s`', tableName, columnName);
    this.runSql(sql, callback);
  },

  addIndex: function(tableName, indexName, columns, unique, callback) {
    if (typeof(unique) === 'function') {
      callback = unique;
      unique = false;
    }

    if (!Array.isArray(columns)) {
      columns = [columns];
    }
    var sql = util.format('ALTER TABLE `%s` ADD %s INDEX `%s` (`%s`)', tableName, (unique ? 'UNIQUE ' : ''), indexName, columns.join('`, `'));
    this.runSql(sql, callback);
  },

  insert: function(tableName, columnNameArray, valueArray, callback) {
    if (columnNameArray.length !== valueArray.length) {
      return callback(new Error('The number of columns does not match the number of values.'));
    }

    var sql = util.format('INSERT INTO `%s` ', tableName);
    var columnNames = '(';
    var values = 'VALUES (';

    for (var index in columnNameArray) {
      columnNames += '`' + columnNameArray[index] + '`';

      if (typeof(valueArray[index]) === 'string') {
        values += "'" + this.escape(valueArray[index]) + "'";
      } else {
        values += valueArray[index];
      }

      if (index != columnNameArray.length - 1) {
        columnNames += ",";
        values +=  ",";
      }
    }

    sql += columnNames + ') '+ values + ');';
    this.runSql(sql, callback);
  },

  removeIndex: function(tableName, indexName, callback) {
    // tableName is optional for other drivers, but required for mySql. So, check the args to ensure they are valid
    if (arguments.length === 2 && typeof(indexName) === 'function') {
      callback = indexName;
      process.nextTick(function () {
        callback(new Error('Illegal arguments, must provide "tableName" and "indexName"'));
      });

      return;
    }

    var sql = util.format('DROP INDEX `%s` ON `%s`', indexName, tableName);
    this.runSql(sql, callback);
  },

  renameColumn: function(tableName, oldColumnName, newColumnName, callback) {
    var self = this, columnTypeSql = util.format("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s' AND COLUMN_NAME = '%s'", tableName, oldColumnName);
    this.all(columnTypeSql, function(err, result) {
      var columnType = result[0].COLUMN_TYPE;
      var alterSql = util.format("ALTER TABLE `%s` CHANGE `%s` `%s` %s", tableName, oldColumnName, newColumnName, columnType);
      self.runSql(alterSql, callback);
    });
  },

  changeColumn: function(tableName, columnName, columnSpec, callback) {
    var constraint = this.createColumnDef(columnName, columnSpec);
    var sql = util.format('ALTER TABLE `%s` CHANGE COLUMN `%s` %s', tableName, columnName, constraint);
    this.runSql(sql, callback);
  },

  addMigrationRecord: function (name, callback) {
    var formattedDate = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
    this.runSql('INSERT INTO migrations (`name`, `run_on`) VALUES (?, ?)', [name, formattedDate], callback);
  },

  addForeignKey: function(tableName, referencedTableName, keyName, fieldMapping, rules, callback) {
    if(arguments.length === 5 && typeof(rules) === 'function') {
      callback = rules;
      rules = {};
    }
    var columns = Object.keys(fieldMapping);
    var referencedColumns = columns.map(function (key) { return fieldMapping[key]; });
    var sql = util.format('ALTER TABLE `%s` ADD CONSTRAINT `%s` FOREIGN KEY (`%s`) REFERENCES `%s` (%s) ON DELETE %s ON UPDATE %s',
      tableName, keyName, columns, referencedTableName, referencedColumns, rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION');
    this.runSql(sql, callback);
  },

  removeForeignKey: function(tableName, keyName, callback) {
    var sql = util.format('ALTER TABLE `%s` DROP FOREIGN KEY `%s`', tableName, keyName);
    this.runSql(sql, function () {
      sql = util.format('ALTER TABLE `%s` DROP INDEX `%s`', tableName, keyName);
      this.runSql(sql, function () {
        callback();
      });
    }.bind(this));
  },

  runSql: function() {
    var args = this._makeParamArgs(arguments);
    var callback = args[2];
    log.sql.apply(null, arguments);
    if(global.dryRun) {
      return callback();
    }
    return this.connection.query.apply(this.connection, args);
  },

  _makeParamArgs: function(args) {
    var params = Array.prototype.slice.call(args);
    var sql = params.shift();
    var callback = params.pop();

    if (params.length > 0 && Array.isArray(params[0])) {
      params = params[0];
    }

    return [sql, params, callback];
  },

  all: function() {
    var args = this._makeParamArgs(arguments);
    return this.connection.query.apply(this.connection, args);
  },

  close: function(callback) {
    this.connection.end(callback);
  }

});

exports.connect = function(config, callback) {
  var db;
  if (typeof(mysql.createConnection) === 'undefined') {
    db = config.db || new mysql.createClient(config);
  } else {
    db = config.db || new mysql.createConnection(config);
  }
  callback(null, new MysqlDriver(db));
};
<commit_msg>Fix merge conflict<commit_after>var util = require('util');
var moment = require('moment');
var mysql = require('mysql');
var Base = require('./base');
var type = require('../data_type');
var log = require('../log');

var MysqlDriver = Base.extend({
  init: function(connection) {
    this._super();
    this.connection = connection;
  },

  mapDataType: function(spec) {
    var len;
    switch(spec.type) {
      case type.TEXT:
        len = parseInt(spec.length, 10) || 1000;
        if(len > 16777216) {
          return 'LONGTEXT';
        }
        if(len > 65536) {
          return 'MEDIUMTEXT';
        }
        if(len > 256) {
          return 'TEXT';
        }
        return 'TINYTEXT';
      case type.DATE_TIME:
        return 'DATETIME';
      case type.BLOB:
        len = parseInt(spec.length, 10) || 1000;
        if(len > 16777216) {
          return 'LONGBLOB';
        }
        if(len > 65536) {
          return 'MEDIUMBLOB';
        }
        if(len > 256) {
          return 'BLOB';
        }
        return 'TINYBLOB';
      case type.BOOLEAN:
        return 'TINYINT(1)';
    }
    return this._super(spec.type);
  },

  createColumnDef: function(name, spec, options) {
    name = util.format('`%s`', name);
    var t = this.mapDataType(spec);
    var len;
    if(spec.type !== type.TEXT && spec.type !== type.BLOB) {
      len = spec.length ? util.format('(%s)', spec.length) : '';
      if (t === 'VARCHAR' && len === '') {
        len = '(255)';
      }
    }
    var constraint = this.createColumnConstraint(spec, options);
    return [name, t, len, constraint].join(' ');
  },

  createColumnConstraint: function(spec, options) {
    var constraint = [];
    if (spec.unsigned) {
      constraint.push('UNSIGNED');
    }

    if (spec.primaryKey) {
      if (!options || options.emitPrimaryKey) {
        constraint.push('PRIMARY KEY');
      }
      if (spec.autoIncrement) {
        constraint.push('AUTO_INCREMENT');
      }
    }

    if (spec.notNull) {
      constraint.push('NOT NULL');
    }

    if (spec.unique) {
      constraint.push('UNIQUE');
    }

    if (spec.null) {
      constraint.push('NULL');
    }

    if (spec.defaultValue !== undefined) {
      constraint.push('DEFAULT');

      if (typeof spec.defaultValue === 'string'){
        constraint.push("'" + spec.defaultValue + "'");
      } else {
        constraint.push(spec.defaultValue);
      }
    }

    return constraint.join(' ');
  },

  createTable: function(tableName, options, callback) {
    log.verbose('creating table:', tableName);
    var columnSpecs = options;
    var tableOptions = {};

    if (options.columns !== undefined) {
      columnSpecs = options.columns;
      delete options.columns;
      tableOptions = options;
    }

    var ifNotExistsSql = "";
    if(tableOptions.ifNotExists) {
      ifNotExistsSql = "IF NOT EXISTS";
    }

    var primaryKeyColumns = [];
    var columnDefOptions = {
      emitPrimaryKey: false
    };

    for (var columnName in columnSpecs) {
      var columnSpec = this.normalizeColumnSpec(columnSpecs[columnName]);
      columnSpecs[columnName] = columnSpec;
      if (columnSpec.primaryKey) {
        primaryKeyColumns.push(columnName);
      }
    }

    var pkSql = '';
    if (primaryKeyColumns.length > 1) {
      pkSql = util.format(', PRIMARY KEY (`%s`)', primaryKeyColumns.join('`, `'));
    } else {
      columnDefOptions.emitPrimaryKey = true;
    }

    var columnDefs = [];
    for (var columnName in columnSpecs) {
      var columnSpec = columnSpecs[columnName];
      columnDefs.push(this.createColumnDef(columnName, columnSpec, columnDefOptions));
    }

    var sql = util.format('CREATE TABLE %s `%s` (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql);
    this.runSql(sql, callback);
  },

  renameTable: function(tableName, newTableName, callback) {
    var sql = util.format('RENAME TABLE `%s` TO `%s`', tableName, newTableName);
    this.runSql(sql, callback);
  },

  addColumn: function(tableName, columnName, columnSpec, callback) {
    var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec));
    var sql = util.format('ALTER TABLE `%s` ADD COLUMN %s', tableName, def);
    this.runSql(sql, callback);
  },

  removeColumn: function(tableName, columnName, callback) {
    var sql = util.format('ALTER TABLE `%s` DROP COLUMN `%s`', tableName, columnName);
    this.runSql(sql, callback);
  },

  addIndex: function(tableName, indexName, columns, unique, callback) {
    if (typeof(unique) === 'function') {
      callback = unique;
      unique = false;
    }

    if (!Array.isArray(columns)) {
      columns = [columns];
    }
    var sql = util.format('ALTER TABLE `%s` ADD %s INDEX `%s` (`%s`)', tableName, (unique ? 'UNIQUE ' : ''), indexName, columns.join('`, `'));
    this.runSql(sql, callback);
  },

  insert: function(tableName, columnNameArray, valueArray, callback) {
    if (columnNameArray.length !== valueArray.length) {
      return callback(new Error('The number of columns does not match the number of values.'));
    }

    var sql = util.format('INSERT INTO `%s` ', tableName);
    var columnNames = '(';
    var values = 'VALUES (';

    for (var index in columnNameArray) {
      columnNames += '`' + columnNameArray[index] + '`';

      if (typeof(valueArray[index]) === 'string') {
        values += "'" + this.escape(valueArray[index]) + "'";
      } else {
        values += valueArray[index];
      }

      if (index != columnNameArray.length - 1) {
        columnNames += ",";
        values +=  ",";
      }
    }

    sql += columnNames + ') '+ values + ');';
    this.runSql(sql, callback);
  },

  removeIndex: function(tableName, indexName, callback) {
    // tableName is optional for other drivers, but required for mySql. So, check the args to ensure they are valid
    if (arguments.length === 2 && typeof(indexName) === 'function') {
      callback = indexName;
      process.nextTick(function () {
        callback(new Error('Illegal arguments, must provide "tableName" and "indexName"'));
      });

      return;
    }

    var sql = util.format('DROP INDEX `%s` ON `%s`', indexName, tableName);
    this.runSql(sql, callback);
  },

  renameColumn: function(tableName, oldColumnName, newColumnName, callback) {
    var self = this, columnTypeSql = util.format("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '%s' AND COLUMN_NAME = '%s'", tableName, oldColumnName);
    this.all(columnTypeSql, function(err, result) {
      var columnType = result[0].COLUMN_TYPE;
      var alterSql = util.format("ALTER TABLE `%s` CHANGE `%s` `%s` %s", tableName, oldColumnName, newColumnName, columnType);
      self.runSql(alterSql, callback);
    });
  },

  changeColumn: function(tableName, columnName, columnSpec, callback) {
    var constraint = this.createColumnDef(columnName, columnSpec);
    var sql = util.format('ALTER TABLE `%s` CHANGE COLUMN `%s` %s', tableName, columnName, constraint);
    this.runSql(sql, callback);
  },

  addMigrationRecord: function (name, callback) {
    var formattedDate = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
    this.runSql('INSERT INTO migrations (`name`, `run_on`) VALUES (?, ?)', [name, formattedDate], callback);
  },

  addForeignKey: function(tableName, referencedTableName, keyName, fieldMapping, rules, callback) {
    if(arguments.length === 5 && typeof(rules) === 'function') {
      callback = rules;
      rules = {};
    }
    var columns = Object.keys(fieldMapping);
    var referencedColumns = columns.map(function (key) { return fieldMapping[key]; });
    var sql = util.format('ALTER TABLE `%s` ADD CONSTRAINT `%s` FOREIGN KEY (`%s`) REFERENCES `%s` (%s) ON DELETE %s ON UPDATE %s',
      tableName, keyName, columns, referencedTableName, referencedColumns, rules.onDelete || 'NO ACTION', rules.onUpdate || 'NO ACTION');
    this.runSql(sql, callback);
  },

  removeForeignKey: function(tableName, keyName, callback) {
    var sql = util.format('ALTER TABLE `%s` DROP FOREIGN KEY `%s`', tableName, keyName);
    this.runSql(sql, function () {
      sql = util.format('ALTER TABLE `%s` DROP INDEX `%s`', tableName, keyName);
      this.runSql(sql, function () {
        callback();
      });
    }.bind(this));
  },

  runSql: function() {
    var args = this._makeParamArgs(arguments);
    var callback = args[2];
    log.sql.apply(null, arguments);
    if(global.dryRun) {
      return callback();
    }
    return this.connection.query.apply(this.connection, args);
  },

  _makeParamArgs: function(args) {
    var params = Array.prototype.slice.call(args);
    var sql = params.shift();
    var callback = params.pop();

    if (params.length > 0 && Array.isArray(params[0])) {
      params = params[0];
    }

    return [sql, params, callback];
  },

  all: function() {
    var args = this._makeParamArgs(arguments);
    return this.connection.query.apply(this.connection, args);
  },

  close: function(callback) {
    this.connection.end(callback);
  }

});

exports.connect = function(config, callback) {
  var db;
  if (typeof(mysql.createConnection) === 'undefined') {
    db = config.db || new mysql.createClient(config);
  } else {
    db = config.db || new mysql.createConnection(config);
  }
  callback(null, new MysqlDriver(db));
};
<|endoftext|>


<commit_before>'use strict'

const mongoose = require('mongoose')
const { diff: deepDiff, applyChange } = require('deep-diff')
const chalk = require('chalk')
const removeEmptyFields = require('./remove-empty-fields')
const { get, set } = require('lodash')

const EditLogSchema = new mongoose.Schema({
	model: {
		type: String,
		required: true
	},
	date: {
		type: Date,
		required: true
	},
	action: {
		type: String,
		enum: ['create', 'update', 'delete'],
		required: true
	},
	item: {
		type: mongoose.Schema.Types.ObjectId,
		required: true
	},
	data: {
		type: mongoose.Schema.Types.Mixed,
		required: false
	},
	diff: {
		type: mongoose.Schema.Types.Mixed,
		required: false
	},
	who: {
		type: String,
		required: false
	},
	whoID: {
		type: mongoose.Schema.Types.ObjectId,
		required: false
	}
})

EditLogSchema.static('applyChange', (source, change) => {
	const target = Object.assign({}, source)
	if (change.kind === 'A' && !get(target, change.path)) {
		set(target, change.path, [])
	}
	applyChange(target, source, change)
	return target
})

const EditLog = mongoose.model('EditLog', EditLogSchema)

const getWho = doc => {
	const modelName = doc.constructor.modelName
	const who = doc.latestChangeBy

	if (!who) {
		// TODO use proper logger
		const stack = Error().stack.split('\n').slice(2).join('\n')
		process.stderr.write(chalk.yellow(`[EditLog][${modelName}] Field 'latestChangeBy' not set, operation will be logged anonymously\n`))
		process.stderr.write(chalk.yellow(stack) + '\n\n')
	}

	return [ modelName, who ]
}

const middleware = schema => {

	schema.add({
		latestChangeBy: {
			type: String,
			required: true
		}
	})

	schema.post('init', function () {
		this._original = this.toObject()
	})

	schema.pre('save', function (next) {
		const [modelName, who] = getWho(this)
		const data = this.toObject()

		// Create a EditLog instance
		// Store for post-save
		// We need to create it in pre-save to have a working 'isNew' attr
		const editLog = {
			model: modelName,
			item: data._id,
			date: new Date(),
			action: this.isNew ? 'create' : 'update',
			whoID: who
		}

		if (this.isNew) {
			editLog.data = removeEmptyFields(cleanupData(data))
		}
		else {
			// If the model was updated, we only store a diff
			const changes = flattenDiff(deepDiff(cleanupData(this._original), cleanupData(data)))
			if (isEmptyDiff(changes)) {
				return next() // no edit log inserted for empty diff
			}
			editLog.diff = changes
		}

		this._elLogToBeSaved = new EditLog(editLog)

		next()
	})

	schema.post('save', doc => {
		// Save on post-save, to ensure it was actually saved
		if (doc._elLogToBeSaved) {
			doc._elLogToBeSaved.save()
		}
	})

	// TODO: this will be handled differently when we solve the delete conundrum
	schema.post('remove', doc => {
		const [modelName, who] = getWho(doc)

		// Create a EditLog instance
		const log = new EditLog({
			model: modelName,
			item: doc.id,
			date: new Date(),
			data: removeEmptyFields(cleanupData(doc.toObject())),
			action: 'delete',
			who
		})

		// Save it asynchronously
		log.save()
	})

}

const isEmptyDiff = changes =>
	// No change at all
	(changes.length === 0) ||
	// The only modified field is 'latestChangeBy', which is pretty meaningless
	(changes.length === 1 && changes[0].path.length === 1 && changes[0].path[0] === 'latestChangeBy')

const flattenDiff = diffs => diffs.map(diff => Array.isArray(diff) && diff.length === 1 ? diff[0] : diff)

const cleanupData = (data, subDoc = false, returnNullIfNotModified = false) => {
	if (!data) {
		return returnNullIfNotModified ? null : data
	}

	if (typeof data !== 'object') {
		return data
	}

	// Sub-document: if it has an id, the whole object should be replace with this value
	if (subDoc && data._id instanceof mongoose.mongo.ObjectID) {
		return getID(data)
	}

	// Standard case, just cleanup object
	let modified = false
	const newData = Object.keys(data).reduce((res, k) => {
		// Handle ObjectID
		if (data[k] instanceof mongoose.mongo.ObjectID) {
			res[k] = asID(data[k])
			modified = true
		}
		// Remove special fields
		else if (k !== '_id' && k[0] === '_') {
			// SKIP FIELD
			modified = true
		}
		// Replace populated data with id
		else if (typeof data[k] === 'object' && data[k]._id instanceof mongoose.mongo.ObjectID) {
			res[k] = getID(data[k])
			modified = true
		}
		// Collection
		else if (Array.isArray(data[k])) {
			res[k] = data[k].map(o => {
				if (returnNullIfNotModified) {
					const o2 = cleanupData(o, true, true)
					if (o2) {
						modified = true
						return o2
					} else {
						return o
					}
				} else {
					return cleanupData(o, true, false)
				}
			})
		}
		// Other cases: just inject field
		else {
			res[k] = data[k]
		}
		return res
	}, {})

	if (!modified && returnNullIfNotModified) {
		return null
	} else {
		return newData
	}
}

const getID = o => o && (asID(o._id) || asID(o.id))

const asID = id => id && (id.toHexString ? id.toHexString() : String(id))

module.exports = {
	EditLogSchema,
	EditLog,
	middleware,
	cleanupData,
	flattenDiff,
	isEmptyDiff,
}
<commit_msg>fix(logs): fixes wrong diffs for Array<FK> (fixes #462)<commit_after>'use strict'

const mongoose = require('mongoose')
const { diff: deepDiff, applyChange } = require('deep-diff')
const chalk = require('chalk')
const removeEmptyFields = require('./remove-empty-fields')
const { get, set } = require('lodash')

const EditLogSchema = new mongoose.Schema({
	model: {
		type: String,
		required: true
	},
	date: {
		type: Date,
		required: true
	},
	action: {
		type: String,
		enum: ['create', 'update', 'delete'],
		required: true
	},
	item: {
		type: mongoose.Schema.Types.ObjectId,
		required: true
	},
	data: {
		type: mongoose.Schema.Types.Mixed,
		required: false
	},
	diff: {
		type: mongoose.Schema.Types.Mixed,
		required: false
	},
	who: {
		type: String,
		required: false
	},
	whoID: {
		type: mongoose.Schema.Types.ObjectId,
		required: false
	}
})

EditLogSchema.static('applyChange', (source, change) => {
	const target = Object.assign({}, source)
	if (change.kind === 'A' && !get(target, change.path)) {
		set(target, change.path, [])
	}
	applyChange(target, source, change)
	return target
})

const EditLog = mongoose.model('EditLog', EditLogSchema)

const getWho = doc => {
	const modelName = doc.constructor.modelName
	const who = doc.latestChangeBy

	if (!who) {
		// TODO use proper logger
		const stack = Error().stack.split('\n').slice(2).join('\n')
		process.stderr.write(chalk.yellow(`[EditLog][${modelName}] Field 'latestChangeBy' not set, operation will be logged anonymously\n`))
		process.stderr.write(chalk.yellow(stack) + '\n\n')
	}

	return [ modelName, who ]
}

const middleware = schema => {

	schema.add({
		latestChangeBy: {
			type: String,
			required: true
		}
	})

	schema.post('init', function () {
		this._original = this.toObject()
	})

	schema.pre('save', function (next) {
		const [modelName, who] = getWho(this)
		const data = this.toObject()

		// Create a EditLog instance
		// Store for post-save
		// We need to create it in pre-save to have a working 'isNew' attr
		const editLog = {
			model: modelName,
			item: data._id,
			date: new Date(),
			action: this.isNew ? 'create' : 'update',
			whoID: who
		}

		if (this.isNew) {
			editLog.data = removeEmptyFields(cleanupData(data))
		}
		else {
			// If the model was updated, we only store a diff
			const changes = flattenDiff(deepDiff(cleanupData(this._original), cleanupData(data)))
			if (isEmptyDiff(changes)) {
				return next() // no edit log inserted for empty diff
			}
			editLog.diff = changes
		}

		this._elLogToBeSaved = new EditLog(editLog)

		next()
	})

	schema.post('save', doc => {
		// Save on post-save, to ensure it was actually saved
		if (doc._elLogToBeSaved) {
			doc._elLogToBeSaved.save()
		}
	})

	// TODO: this will be handled differently when we solve the delete conundrum
	schema.post('remove', doc => {
		const [modelName, who] = getWho(doc)

		// Create a EditLog instance
		const log = new EditLog({
			model: modelName,
			item: doc.id,
			date: new Date(),
			data: removeEmptyFields(cleanupData(doc.toObject())),
			action: 'delete',
			who
		})

		// Save it asynchronously
		log.save()
	})

}

const isEmptyDiff = changes =>
	// No change at all
	(changes.length === 0) ||
	// The only modified field is 'latestChangeBy', which is pretty meaningless
	(changes.length === 1 && changes[0].path.length === 1 && changes[0].path[0] === 'latestChangeBy')

const flattenDiff = diffs => diffs.map(diff => Array.isArray(diff) && diff.length === 1 ? diff[0] : diff)

const cleanupData = (data, inArray = false, returnNullIfNotModified = false) => {
	if (!data) {
		return returnNullIfNotModified ? null : data
	}

	if (typeof data !== 'object') {
		return data
	}

	// Handle Array<FK>
	if (inArray) {
		// Case 1: the FK is a mongo.ObjectID
		if (data instanceof mongoose.mongo.ObjectID) {
			return asID(data)
		}
		// Case 2: the FK has been populated
		else if (typeof data === 'object' && data._id instanceof mongoose.mongo.ObjectID) {
			return getID(data)
		}
		// Case 3: the FK is a string: use it as-is (should not happen, but if it does it's like it's been already cleaned up)
		// Other cases: there are not other forms for a FK
		// And if it's not a FK? It's a raw value, just handle it normally
	}

	// Standard case, just cleanup object
	let modified = false
	const newData = Object.keys(data).reduce((res, k) => {
		// Handle ObjectID
		if (data[k] instanceof mongoose.mongo.ObjectID) {
			res[k] = asID(data[k])
			modified = true
		}
		// Remove special fields
		else if (k !== '_id' && k[0] === '_') {
			// SKIP FIELD
			modified = true
		}
		// Replace populated data with id
		else if (typeof data[k] === 'object' && data[k]._id instanceof mongoose.mongo.ObjectID) {
			res[k] = getID(data[k])
			modified = true
		}
		// Collection
		else if (Array.isArray(data[k])) {
			res[k] = data[k].map(o => {
				if (returnNullIfNotModified) {
					const o2 = cleanupData(o, true, true)
					if (o2) {
						modified = true
						return o2
					} else {
						return o
					}
				} else {
					return cleanupData(o, true, false)
				}
			})
		}
		// Other cases: just inject field
		else {
			res[k] = data[k]
		}
		return res
	}, {})

	if (!modified && returnNullIfNotModified) {
		return null
	} else {
		return newData
	}
}

const getID = o => o && (asID(o._id) || asID(o.id))

const asID = id => id && (id.toHexString ? id.toHexString() : String(id))

module.exports = {
	EditLogSchema,
	EditLog,
	middleware,
	cleanupData,
	flattenDiff,
	isEmptyDiff,
}
<|endoftext|>


<commit_before>var _ = require('lodash')
var orm = require('orm')
var bitcore = require('bitcore-lib')
var util = require('util')
var async = require('async')

var messages = require('../messages')

var testnet = bitcore.Networks.testnet
var PrivateKey = bitcore.PrivateKey
var Address = bitcore.Address
var Hash = bitcore.crypto.Hash

var FakeChain = function(cb) {

  var height = 0

  this.height = function(){ return height }
  this.clearTransactions = function(cb) {
    height = 0
    this.Transaction.all().remove(cb)
  }

  this.incrementBlockHeight = function() {
    return ++height
  }

  var that = this
  var storage = orm.connect("sqlite://", function(err, db) {
    if (err) return cb(err)

    that.Transaction = db.define("transactions", {
      txid:         { type: 'serial', key: true },
      data:         { type: 'binary'},
      receiverAddr: { type: 'text', mapsTo: 'receiver_addr'},
      senderAddr:   { type: 'text', mapsTo: 'sender_addr'},
      tip:          { type: 'integer' },
      blockHeight:  { type: 'integer' }
    }, {
      methods: { toMessageParams: function () {
        return { data: this.data, receiverAddr: this.receiverAddr,
          senderAddr: this.senderAddr, tip: this.tip,
          txid: (this.txid) ? String(this.txid) : null}
      }
    }})

    db.sync(cb)
  })
}

FakeChain.prototype.isTesting = function () {
  return true
}

FakeChain.prototype.privkeyToAddr = function (wif) {
  // TODO: We probably need to handle mainnet here too
  return PrivateKey.fromWIF(wif).toAddress(testnet).toString()
}

FakeChain.prototype.hash160ToAddr = function (hash160, network) {
  return Address.fromPublicKeyHash(new Buffer(hash160, 'hex'),
    network || testnet).toString()
}

FakeChain.prototype.hash160FromAddr = function (addr, network) {
  return Address.fromString(addr, network || testnet).hashBuffer
}

FakeChain.prototype.isValidAddr = function (addr, network) {
  return Address.isValid(addr, network || testnet)
}

FakeChain.prototype.save = function (tx, privateKey, cb) {
  /*
   * We ignore the private key in this connection. We return the database id
   * in lieue of transaction id.
   */
  var blockchainState = {blockHeight: this.height(),
    senderAddr: this.privkeyToAddr(privateKey)}

  this.Transaction.create( _.merge(tx, blockchainState), function(err, record) {
    cb(err, (record) ? record.toMessageParams() : null)
  })
}

FakeChain.prototype.txById = function (id, cb) {
  this.Transaction.get(parseInt(id), function(err, record) {
    if (err && err.literalCode != 'NOT_FOUND')
      throw err

    cb(null, (record) ? record.toMessageParams() : null)
  })
}

/* NOTE:
 *  - This needs to return the messages in Descending order by block
 *   In the case that two transactions are in the same block, it goes by time
 * - This should return only 'valid' messages. Not all transactions
 */
FakeChain.prototype.messagesByAddr = function (addr, options, cb) {
  this._filterMessages(["sender_addr = ? OR receiver_addr = ?", addr, addr],
    options, cb)
}

FakeChain.prototype.messagesInBlock = function (height, options, cb) {
  this._filterMessages([{blockHeight: height}], options, cb)
}

FakeChain.prototype._filterMessages = function (baseWhere, options, cb) {
  query = this.Transaction.find({}, ['blockHeight', 'Z'], ['txid','Z'])
  query.where.call(baseWhere)

  if (options.startBlock)
    query.where({blockHeight: orm.gte(options.startBlock)})

  if (options.endBlock)
    query.where({blockHeight: orm.lte(options.endBlock)})

  connection = this

  async.waterfall([
    function(next){ query.all(next) },
    function(transactions, waterfallNext){
      async.filter(transactions.map(function(tx){
        return messages.fromTx(connection, tx.toMessageParams()) }),
        function(msg, next){
        if (!msg) next(false)

        msg.isValid(function(err, res) {
          if (err) throw err

          next((res) ? false : true)
        })
      }, function(messages) { waterfallNext(null, messages) } )
    }], function (err, messages) {
      if (err) throw err

      if (messages.length > 0) {
        if (options.type)
          messages = messages.filter(function(msg){
            return msg.messageType == options.type})
      }

/* TODO
    if options.has_key?(:between)
      ret = ret.find_all{|c|
        [c.receiver_addr, c.sender_addr].all?{|a| options[:between].include?(a) } }
    end
*/
    cb(null, messages)
  })
}

module.exports = {
  FakeBitcoinConnection: FakeChain
}
<commit_msg>Fixed jslint issues<commit_after>var _ = require('lodash')
var orm = require('orm')
var bitcore = require('bitcore-lib')
var async = require('async')

var messages = require('../messages')

var testnet = bitcore.Networks.testnet
var PrivateKey = bitcore.PrivateKey
var Address = bitcore.Address

var FakeChain = function (cb) {
  var height = 0

  this.height = function () { return height }
  this.clearTransactions = function (cb) {
    height = 0
    this.Transaction.all().remove(cb)
  }

  this.incrementBlockHeight = function () {
    return ++height
  }

  var that = this
  orm.connect('sqlite://', function (err, db) {
    if (err) return cb(err)

    that.Transaction = db.define('transactions', {
      txid: {type: 'serial', key: true},
      data: {type: 'binary'},
      receiverAddr: {type: 'text', mapsTo: 'receiver_addr'},
      senderAddr: {type: 'text', mapsTo: 'sender_addr'},
      tip: {type: 'integer'}, blockHeight: {type: 'integer'}
    }, {
      methods: { toMessageParams: function () {
        return { data: this.data, receiverAddr: this.receiverAddr,
          senderAddr: this.senderAddr, tip: this.tip,
          txid: (this.txid) ? String(this.txid) : null}
      }
    }})

    db.sync(cb)
  })
}

FakeChain.prototype.isTesting = function () {
  return true
}

FakeChain.prototype.privkeyToAddr = function (wif) {
  // TODO: We probably need to handle mainnet here too
  return PrivateKey.fromWIF(wif).toAddress(testnet).toString()
}

FakeChain.prototype.hash160ToAddr = function (hash160, network) {
  return Address.fromPublicKeyHash(new Buffer(hash160, 'hex'),
    network || testnet).toString()
}

FakeChain.prototype.hash160FromAddr = function (addr, network) {
  return Address.fromString(addr, network || testnet).hashBuffer
}

FakeChain.prototype.isValidAddr = function (addr, network) {
  return Address.isValid(addr, network || testnet)
}

FakeChain.prototype.save = function (tx, privateKey, cb) {
  /*
   * We ignore the private key in this connection. We return the database id
   * in lieue of transaction id.
   */
  var blockchainState = {blockHeight: this.height(),
    senderAddr: this.privkeyToAddr(privateKey)}

  this.Transaction.create(_.merge(tx, blockchainState),
    function (err, record) { cb(err, (record) ? record.toMessageParams() : null) })
}

FakeChain.prototype.txById = function (id, cb) {
  this.Transaction.get(parseInt(id, 10), function (err, record) {
    if (err && err.literalCode !== 'NOT_FOUND') { throw err }

    cb(null, (record) ? record.toMessageParams() : null)
  })
}

/* NOTE:
 *  - This needs to return the messages in Descending order by block
 *   In the case that two transactions are in the same block, it goes by time
 * - This should return only 'valid' messages. Not all transactions
 */
FakeChain.prototype.messagesByAddr = function (addr, options, cb) {
  this._filterMessages(['sender_addr = ? OR receiver_addr = ?', addr, addr],
    options, cb)
}

FakeChain.prototype.messagesInBlock = function (height, options, cb) {
  this._filterMessages([{blockHeight: height}], options, cb)
}

FakeChain.prototype._filterMessages = function (baseWhere, options, cb) {
  var query = this.Transaction.find({}, ['blockHeight', 'Z'], ['txid', 'Z'])
  query.where.call(baseWhere)

  if (options.startBlock) {
    query.where({blockHeight: orm.gte(options.startBlock)})
  }

  if (options.endBlock) {
    query.where({blockHeight: orm.lte(options.endBlock)})
  }

  var connection = this

  async.waterfall([
    function (next) { query.all(next) },
    function (transactions, waterfallNext) {
      async.filter(transactions.map(function (tx) {
        return messages.fromTx(connection, tx.toMessageParams())
      }), function (msg, next) {
        if (!msg) next(false)

        msg.isValid(function (err, res) {
          if (err) throw err

          next(!res)
        })
      }, function (messages) { waterfallNext(null, messages) })
    }], function (err, messages) {
    if (err) throw err

    if (messages.length > 0) {
      if (options.type) {
        messages = messages.filter(
          function (msg) { return msg.messageType === options.type })
      }
    }

/* TODO
    if options.has_key?(:between)
      ret = ret.find_all{|c|
        [c.receiver_addr, c.sender_addr].all?{|a| options[:between].include?(a) } }
    end
*/
    cb(null, messages)
  })
}

module.exports = {
  FakeBitcoinConnection: FakeChain
}
<|endoftext|>


<commit_before>//
//   Copyright 2009-2014 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

'use strict';

const _ = require('lodash');
const CronJob = require('cron').CronJob;
const redis = require('./redis').createClient();
const log = require('./log');
const mailer = require('./mailer');
const User = require('../models/user');
const UserGId = require('../models/userGId');

const jobs = [];

exports.init = function init() {
    // Once in 15 minutes
    jobs.push(new CronJob('0 */10 * * * *', deliverEmails, null, true));
};

exports.quit = function quit() {
    for (const job of jobs) {
        job.stop();
    }
};

// Sends email notifications to offline users
async function deliverEmails() {
    log.info('Running deliverEmails job');

    function groupNotifications(ntf) {
        return ntf.groupName ? `Group: ${ntf.groupName}` : `1-on-1: ${ntf.senderName}`;
    }

    const userGIdStrings = await redis.smembers('emailnotifications');

    for (const userGIdString of userGIdStrings) {
        const notificationIds = await redis.lrange(
            `emailnotificationslist:${userGIdString}`, 0, -1);
        let notifications = [];

        for (const notificationId of notificationIds) {
            const notification = await redis.hgetall(`emailnotification:${notificationId}`);

            if (notification) {
                notifications.push(notification);
            }
        }

        notifications = _.groupBy(notifications, groupNotifications);

        const userGId = UserGId.create(userGIdString);
        const user = await User.fetch(userGId.id);

        // TODO: Better would be to clear pending notifications during login
        if (!(await user.isOnline())) {
            mailer.send('emails/build/mentioned.hbs', {
                name: user.get('name'),
                notifications
            }, user.get('email'), 'You were just mentioned on MeetAndSpeak');
        }

        for (const notificationId of notificationIds) {
            await redis.del(`emailnotification:${notificationId}`);
        }

        await redis.del(`emailnotificationslist:${userGIdString}`);
        await redis.srem('emailnotifications', userGIdString);
    }
}
<commit_msg>Use arrow function<commit_after>//
//   Copyright 2009-2014 Ilkka Oksanen <iao@iki.fi>
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing,
//   software distributed under the License is distributed on an "AS
//   IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
//   express or implied.  See the License for the specific language
//   governing permissions and limitations under the License.
//

'use strict';

const _ = require('lodash');
const CronJob = require('cron').CronJob;
const redis = require('./redis').createClient();
const log = require('./log');
const mailer = require('./mailer');
const User = require('../models/user');
const UserGId = require('../models/userGId');

const jobs = [];

exports.init = function init() {
    // Once in 15 minutes
    jobs.push(new CronJob('0 */10 * * * *', deliverEmails, null, true));
};

exports.quit = function quit() {
    for (const job of jobs) {
        job.stop();
    }
};

// Sends email notifications to offline users
async function deliverEmails() {
    log.info('Running deliverEmails job');

    const userGIdStrings = await redis.smembers('emailnotifications');

    for (const userGIdString of userGIdStrings) {
        const notificationIds = await redis.lrange(
            `emailnotificationslist:${userGIdString}`, 0, -1);
        let notifications = [];

        for (const notificationId of notificationIds) {
            const notification = await redis.hgetall(`emailnotification:${notificationId}`);

            if (notification) {
                notifications.push(notification);
            }
        }

        notifications = _.groupBy(notifications,
            ntf => ntf.groupName ? `Group: ${ntf.groupName}` : `1-on-1: ${ntf.senderName}`);

        const userGId = UserGId.create(userGIdString);
        const user = await User.fetch(userGId.id);

        // TODO: Better would be to clear pending notifications during login
        if (!(await user.isOnline())) {
            mailer.send('emails/build/mentioned.hbs', {
                name: user.get('name'),
                notifications
            }, user.get('email'), 'You were just mentioned on MeetAndSpeak');
        }

        for (const notificationId of notificationIds) {
            await redis.del(`emailnotification:${notificationId}`);
        }

        await redis.del(`emailnotificationslist:${userGIdString}`);
        await redis.srem('emailnotifications', userGIdString);
    }
}
<|endoftext|>


<commit_before>/* global Assets */
import {Invitations} from '../../lib/collections';
import {Meteor} from 'meteor/meteor';
import {check} from 'meteor/check';
import {Random} from 'meteor/random';
import {SSR} from 'meteor/meteorhacks:ssr';
import {Email} from 'meteor/email';
import {Accounts} from 'meteor/accounts-base';
import {Roles} from 'meteor/alanning:roles';
import {LoginState} from 'meteor/brettle:accounts-login-state';

export default function () {
  Meteor.methods({
    'users.create'(email, password) {
      check(email,String);
      check(password, String);
      const createdAt = new Date();
      const role = 'student';
      const userId = Accounts.createUser({email, password, createdAt});
      if (userId) {
        Roles.setUserRoles(userId, role);
      }
    },
    'users.addDisplayName'() {
      const user = Meteor.user();
      if (user && !LoginState.signedUp(user) && !user.displayName) {
        Meteor.users.update(user._id, {
          $set: {displayName: `usuario ${Math.floor((Math.random() * 1000))}`}
        });
      }
    },
    'invitation.create'(_id, email) {
      check(_id, String);
      check(email, String);
      const createdAt = new Date();
      const token = Random.hexString(16);
      const role = 'teacher';
      Meteor._sleepForMs(5000);
      const invitation = {_id, email, createdAt, token, role};
      const userExits = Accounts.findUserByEmail(email);
      if (userExits) {
        throw new Meteor.Error('invitation.create.userexits',
        'User email already exits',
        'User email already exits. Try with other email');
      } else {
        Invitations.insert(invitation);

        SSR.compileTemplate('htmlEmail', Assets.getText('invitationEmail.html'));

        const emailData = {
          url: `http://localhost:3000/invite/${token}`,

        };
        // Let other method calls from the same client start running,
        // without waiting for the email sending to complete.
        this.unblock();
        Email.send({
          to: email,
          from: 'johngonzalez@mimentor.co',
          subject: 'Invitación',
          html: SSR.render('htmlEmail', emailData)
        });
      }
    },
    'invitation.accept'(email, password, token) {
      check(email, String);
      check(password, String);
      check(token, String);

      const invitation = Invitations.findOne({token});
      if (invitation) {
        const userId = Accounts.createUser({email, password});
        if (userId) {
          Roles.setUserRoles(userId, invitation.role);
          Invitations.remove({email});
        }
      }
    }
  });
}
<commit_msg>Added galaxy server and domain url<commit_after>/* global Assets */
import {Invitations} from '../../lib/collections';
import {Meteor} from 'meteor/meteor';
import {check} from 'meteor/check';
import {Random} from 'meteor/random';
import {SSR} from 'meteor/meteorhacks:ssr';
import {Email} from 'meteor/email';
import {Accounts} from 'meteor/accounts-base';
import {Roles} from 'meteor/alanning:roles';
import {LoginState} from 'meteor/brettle:accounts-login-state';

export default function () {
  Meteor.methods({
    'users.create'(email, password) {
      check(email,String);
      check(password, String);
      const createdAt = new Date();
      const role = 'student';
      const userId = Accounts.createUser({email, password, createdAt});
      if (userId) {
        Roles.setUserRoles(userId, role);
      }
    },
    'users.addDisplayName'() {
      const user = Meteor.user();
      if (user && !LoginState.signedUp(user) && !user.displayName) {
        Meteor.users.update(user._id, {
          $set: {displayName: `usuario ${Math.floor((Math.random() * 1000))}`}
        });
      }
    },
    'invitation.create'(_id, email) {
      check(_id, String);
      check(email, String);
      const createdAt = new Date();
      const token = Random.hexString(16);
      const role = 'teacher';
      Meteor._sleepForMs(5000);
      const invitation = {_id, email, createdAt, token, role};
      const userExits = Accounts.findUserByEmail(email);
      if (userExits) {
        throw new Meteor.Error('invitation.create.userexits',
        'User email already exits',
        'User email already exits. Try with other email');
      } else {
        Invitations.insert(invitation);

        SSR.compileTemplate('htmlEmail', Assets.getText('invitationEmail.html'));

        const domain = Meteor.isProduction ? Meteor.settings.DOMAIN_URL : 'localhost:3000';
        const emailData = {
          url: `http://${domain}/invite/${token}`,
        };
        // Let other method calls from the same client start running,
        // without waiting for the email sending to complete.
        this.unblock();
        Email.send({
          to: email,
          from: 'johngonzalez@mimentor.co',
          subject: 'Invitación',
          html: SSR.render('htmlEmail', emailData)
        });
      }
    },
    'invitation.accept'(email, password, token) {
      check(email, String);
      check(password, String);
      check(token, String);

      const invitation = Invitations.findOne({token});
      if (invitation) {
        const userId = Accounts.createUser({email, password});
        if (userId) {
          Roles.setUserRoles(userId, invitation.role);
          Invitations.remove({email});
        }
      }
    }
  });
}
<|endoftext|>


<commit_before>import React, {Fragment} from 'react';
import PropTypes from 'prop-types';
import {CompositeDisposable} from 'event-kit';

import RefHolder from '../models/ref-holder';
import {RefHolderPropType} from '../prop-types';
import {autobind, extractProps} from '../helpers';

const editorProps = {
  buffer: PropTypes.object, // FIXME make proptype more specific
  mini: PropTypes.bool,
  readOnly: PropTypes.bool,
  placeholderText: PropTypes.string,
  lineNumberGutterVisible: PropTypes.bool,
  autoHeight: PropTypes.bool,
  autoWidth: PropTypes.bool,
};

export const TextEditorContext = React.createContext();

export default class AtomTextEditor extends React.Component {
  static propTypes = {
    ...editorProps,

    workspace: PropTypes.object.isRequired, // FIXME make more specific

    didChangeCursorPosition: PropTypes.func,
    didAddSelection: PropTypes.func,
    didChangeSelectionRange: PropTypes.func,
    didDestroySelection: PropTypes.func,
    observeSelections: PropTypes.func,

    refModel: RefHolderPropType,

    children: PropTypes.node,
  }

  static defaultProps = {
    didChangeCursorPosition: () => {},
    didAddSelection: () => {},
    didChangeSelectionRange: () => {},
    didDestroySelection: () => {},
  }

  constructor(props) {
    super(props);
    autobind(this, 'observeSelections');

    this.subs = new CompositeDisposable();

    this.refParent = new RefHolder();
    this.refElement = new RefHolder();
    this.refModel = null;
  }

  render() {
    return (
      <Fragment>

        <TextEditorContext.Provider value={this.getRefModel()}>
          {this.props.children}
        </TextEditorContext.Provider>
      </Fragment>
    );
  }

  componentDidMount() {
    const modelProps = extractProps(this.props, editorProps);

    this.refParent.map(element => {
      const editor = this.props.workspace.buildTextEditor(modelProps);
      element.appendChild(editor.getElement());
      this.getRefModel().setter(editor);
      this.refElement.setter(editor.getElement());

      this.subs.add(
        editor.onDidChangeCursorPosition(this.props.didChangeCursorPosition),
        editor.observeSelections(this.observeSelections),
      );

      return null;
    });
  }

  componentDidUpdate(prevProps) {
    const modelProps = extractProps(this.props, editorProps);
    this.getRefModel().map(editor => editor.update(modelProps));
  }

  componentWillUnmount() {
    this.getRefModel().map(editor => editor.destroy());
    this.subs.dispose();
  }

  observeSelections(selection) {
    const selectionSubs = new CompositeDisposable(
      selection.onDidChangeRange(this.props.didChangeSelectionRange),
      selection.onDidDestroy(() => {
        selectionSubs.dispose();
        this.subs.remove(selectionSubs);
        this.props.didDestroySelection(selection);
      }),
    );
    this.subs.add(selectionSubs);
    this.props.didAddSelection(selection);
  }

  contains(element) {
    return this.refElement.map(e => e.contains(element)).getOr(false);
  }

  focus() {
    this.refElement.map(e => e.focus());
  }

  getRefModel() {
    if (this.props.refModel) {
      return this.props.refModel;
    }

    if (!this.refModel) {
      this.refModel = new RefHolder();
    }

    return this.refModel;
  }
}
<commit_msg>Separate update and creation props<commit_after>import React, {Fragment} from 'react';
import PropTypes from 'prop-types';
import {CompositeDisposable} from 'event-kit';

import RefHolder from '../models/ref-holder';
import {RefHolderPropType} from '../prop-types';
import {autobind, extractProps} from '../helpers';

const editorUpdateProps = {
  mini: PropTypes.bool,
  readOnly: PropTypes.bool,
  placeholderText: PropTypes.string,
  lineNumberGutterVisible: PropTypes.bool,
  autoHeight: PropTypes.bool,
  autoWidth: PropTypes.bool,
};

const editorCreationProps = {
  buffer: PropTypes.object, // FIXME make proptype more specific
  ...editorUpdateProps,
};

export const TextEditorContext = React.createContext();

export default class AtomTextEditor extends React.Component {
  static propTypes = {
    ...editorCreationProps,

    workspace: PropTypes.object.isRequired, // FIXME make more specific

    didChangeCursorPosition: PropTypes.func,
    didAddSelection: PropTypes.func,
    didChangeSelectionRange: PropTypes.func,
    didDestroySelection: PropTypes.func,
    observeSelections: PropTypes.func,

    refModel: RefHolderPropType,

    children: PropTypes.node,
  }

  static defaultProps = {
    didChangeCursorPosition: () => {},
    didAddSelection: () => {},
    didChangeSelectionRange: () => {},
    didDestroySelection: () => {},
  }

  constructor(props) {
    super(props);
    autobind(this, 'observeSelections');

    this.subs = new CompositeDisposable();

    this.refParent = new RefHolder();
    this.refElement = new RefHolder();
    this.refModel = null;
  }

  render() {
    return (
      <Fragment>

        <TextEditorContext.Provider value={this.getRefModel()}>
          {this.props.children}
        </TextEditorContext.Provider>
      </Fragment>
    );
  }

  componentDidMount() {
    const modelProps = extractProps(this.props, editorCreationProps);

    this.refParent.map(element => {
      const editor = this.props.workspace.buildTextEditor(modelProps);
      element.appendChild(editor.getElement());
      this.getRefModel().setter(editor);
      this.refElement.setter(editor.getElement());

      this.subs.add(
        editor.onDidChangeCursorPosition(this.props.didChangeCursorPosition),
        editor.observeSelections(this.observeSelections),
      );

      return null;
    });
  }

  componentDidUpdate(prevProps) {
    const modelProps = extractProps(this.props, editorUpdateProps);
    this.getRefModel().map(editor => editor.update(modelProps));
  }

  componentWillUnmount() {
    this.getRefModel().map(editor => editor.destroy());
    this.subs.dispose();
  }

  observeSelections(selection) {
    const selectionSubs = new CompositeDisposable(
      selection.onDidChangeRange(this.props.didChangeSelectionRange),
      selection.onDidDestroy(() => {
        selectionSubs.dispose();
        this.subs.remove(selectionSubs);
        this.props.didDestroySelection(selection);
      }),
    );
    this.subs.add(selectionSubs);
    this.props.didAddSelection(selection);
  }

  contains(element) {
    return this.refElement.map(e => e.contains(element)).getOr(false);
  }

  focus() {
    this.refElement.map(e => e.focus());
  }

  getRefModel() {
    if (this.props.refModel) {
      return this.props.refModel;
    }

    if (!this.refModel) {
      this.refModel = new RefHolder();
    }

    return this.refModel;
  }

  getModel() {
    return this.getRefModel().getOr(undefined);
  }
}
<|endoftext|>


<commit_before>// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
if ( !Function.prototype.bind ) {

  Function.prototype.bind = function( obj ) {
    var slice = [].slice,
        args = slice.call(arguments, 1),
        self = this,
        nop = function () {},
        bound = function () {
          return self.apply( this instanceof nop ? this : ( obj || {} ),
                              args.concat( slice.call(arguments) ) );
        };

    nop.prototype = self.prototype;

    bound.prototype = new nop();

    return bound;
  };
}
<commit_msg>Fix Function.bind in Safari in case the original function had an undefined prototype. Example: call = Function.prototype.call.bind(something)<commit_after>// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
if ( !Function.prototype.bind ) {

  Function.prototype.bind = function( obj ) {
    var slice = [].slice,
        args = slice.call(arguments, 1),
        self = this,
        nop = function () {},
        bound = function () {
          return self.apply( nop.prototype && this instanceof nop ? this : ( obj || {} ),
                              args.concat( slice.call(arguments) ) );
        };

    nop.prototype = self.prototype;

    bound.prototype = new nop();

    return bound;
  };
}
<|endoftext|>