<commit_before>// dependencies
var _ = require('lomath')
var graphlib = require("graphlib")
var Graph = graphlib.Graph;
var gio = require(__dirname + '/gio.js')
var parser = require(__dirname + '/parser.js')

var g = gio.importG(__dirname + '/data/g1.json')

// var E = g.edges()
// console.log(g.nodes())
// console.log(E)

// g.removeNode('b')

// console.log(g.nodes())
// console.log(E)

// console.log(_.isEmpty(['']))

// Approx VC alg. Note this is not MVC, but is a 2-approx
// 1. init C to empty set
// 2. while E nonempty
// 	2.1 pick any edge {u,v} in E
// 	2.2 add the pair of nodes to C
// 	2.3 delete all incident edges of u,v
// 3. return C
function aVC(g) {
    var C = []
    while (!_.isEmpty(g.edges())) {
        var pair = g.edges().pop()
        _.map(pair, function(i) {
            C.push(i)
            g.removeNode(i)
        })
    }
    return C
}

// console.log(aVC(g))

// brute force MVC: takes a path to graph json, and param k
// deletes from a combset then check if edgeCount == 0. If true return
function bruteVC(jsonify, k) {
    // init import of graph for params
    var g = graphlib.json.read(jsonify)
    var m = 0,
        nodes = g.nodes(),
        order = nodes.length,
        found = false,
        res = []
    if (order < k) throw 'order is smaller than k'
        // try while not found and m <= k
        //
    while (!found && _.lte(++m, k)) {

        // generate combination
        _.each(_.combList(order, m), function(indArr) {
            // fresh functional graph for each new indArr
            g = graphlib.json.read(jsonify)
            _.each(indArr, function(ind) {
                    g.removeNode(nodes[ind])
                })
                // if is a VC, found while and quit each loop
            if (g.edgeCount() == 0) {
                res = _.pullAt(nodes, indArr)
                found = true
                return false
            }
        })
    }
    return {
        found: found,
        VC: res,
        size: m
    }
}

// next:
// √see how to nicely duplicate graphlib's graph. Like readjson whatever, yeah u can clone json
// implemented reducing, with folding and struction subroutines
// keep tuples
// run

// let v0 w/ neighbors v1 thru vp
// struction:
// 1. remove N[v0], add a new node vij for each antiedge {vi,vj} w/ 0 < i < j <= p
// 2. add an edge (vir,vjs) if i == j, r != s, and (vr, vs) is an edge in G
// 3. if i != j add an edge (vir, vjs)
// 4. for every u !\in N[v0] add edge (vij, u) if (vi, u) or (vj, u) is an edge in G

function struction(jsonify, n) {
    var g = graphlib.json.read(jsonify)
        // 1. Identify closed neighborhood of n
    var closedN = g.neighbors(n)
    closedN.push(n)
    var complement = _.difference(g.nodes, closedN)

    var pairs = _.combList(closedN.length, 2)
    var joinedNodes = []
        // for each subset pair indices
    _.map(pairs, function(pairInd) {
        var pair = _.at(closedN, pairInd)
            // if is antiedge, add node delim by ',', as 'i,j'
        if (g.edge(pair[0], pair[1]) == undefined) {
            joinedNodes.push(pair)
            g.setNode(pair.join(','))
        }
    })

    // 2. take the newly added ndoes with paired indices, enum pairs (in [i, j])
    var newPairs = _.combList(joinedNodes.length, 2)
    _.map(newPairs, function(pairInd) {
        // take pair of [i,r] and [j, s] as left and right
        var pair = _.at(joinedNodes, pairInd)
        var left = pair[0],
            right = pair[1],
            i = left[0],
            r = left[1],
            j = right[0],
            s = right[1]

        // if i = j, r != s, and r, s is an edge in G
        if (i == j && r != s && g.edge(r, s) != undefined) {
            // add an edge (ir, js)
            g.setEdge(left.join(','), right.join(','))
        }
        // 3. if i != j, add adge (ir, js)
        else if (i != j) {
            g.setEdge(left.join(','), right.join(','))
        }
    })

    // 4. for all u !\in closedN, add edge (ij, u) if (i,u) or (j,u) were an edge
    _.each(complement, function(u) {
        _.each(joinedNodes, function(ij) {
            if (g.edge(ij[0], u) != undefined || g.edge(ij[1], u) != undefined) {
                g.setEdge(ij.join(','), u)
            }
        })
    })

    // remove closedN from g
    _.each(closedN, function(n) {
        g.removeNode(n)
    })

    return g
}

var jsonify = require(__dirname + '/data/g1.json')
console.log(bruteVC(jsonify, 3))

console.log(struction(jsonify, 'a').nodes())

var res = _.combList(4, 2)

console.log(res)
<commit_msg>corrected open n closed<commit_after>// dependencies
var _ = require('lomath')
var graphlib = require("graphlib")
var Graph = graphlib.Graph;
var gio = require(__dirname + '/gio.js')
var parser = require(__dirname + '/parser.js')

var g = gio.importG(__dirname + '/data/g1.json')

// var E = g.edges()
// console.log(g.nodes())
// console.log(E)

// g.removeNode('b')

// console.log(g.nodes())
// console.log(E)

// console.log(_.isEmpty(['']))

// Approx VC alg. Note this is not MVC, but is a 2-approx
// 1. init C to empty set
// 2. while E nonempty
// 	2.1 pick any edge {u,v} in E
// 	2.2 add the pair of nodes to C
// 	2.3 delete all incident edges of u,v
// 3. return C
function aVC(g) {
    var C = []
    while (!_.isEmpty(g.edges())) {
        var pair = g.edges().pop()
        _.map(pair, function(i) {
            C.push(i)
            g.removeNode(i)
        })
    }
    return C
}

// console.log(aVC(g))

// brute force MVC: takes a path to graph json, and param k
// deletes from a combset then check if edgeCount == 0. If true return
function bruteVC(jsonify, k) {
    // init import of graph for params
    var g = graphlib.json.read(jsonify)
    var m = 0,
        nodes = g.nodes(),
        order = nodes.length,
        found = false,
        res = []
    if (order < k) throw 'order is smaller than k'
        // try while not found and m <= k
        //
    while (!found && _.lte(++m, k)) {

        // generate combination
        _.each(_.combList(order, m), function(indArr) {
            // fresh functional graph for each new indArr
            g = graphlib.json.read(jsonify)
            _.each(indArr, function(ind) {
                    g.removeNode(nodes[ind])
                })
                // if is a VC, found while and quit each loop
            if (g.edgeCount() == 0) {
                res = _.pullAt(nodes, indArr)
                found = true
                return false
            }
        })
    }
    return {
        found: found,
        VC: res,
        size: m
    }
}

// next:
// √see how to nicely duplicate graphlib's graph. Like readjson whatever, yeah u can clone json
// implemented reducing, with folding and struction subroutines
// keep tuples
// run

// let v0 w/ neighbors v1 thru vp
// struction:
// 1. remove N[v0], add a new node vij for each antiedge {vi,vj} w/ 0 < i < j <= p
// 2. add an edge (vir,vjs) if i == j, r != s, and (vr, vs) is an edge in G
// 3. if i != j add an edge (vir, vjs)
// 4. for every u !\in N[v0] add edge (vij, u) if (vi, u) or (vj, u) is an edge in G

function struction(jsonify, n) {
    var g = graphlib.json.read(jsonify)
        // 1. Identify closed neighborhood of n
    var openN = g.neighbors(n)
    var closedN = openN.push(n)
    var complement = _.difference(g.nodes, closedN)

    var pairs = _.combList(openN.length, 2)
    var joinedNodes = []
        // for each subset pair indices
    _.map(pairs, function(pairInd) {
        var pair = _.at(openN, pairInd)
            // if is antiedge, add node delim by ',', as 'i,j'
        if (g.edge(pair[0], pair[1]) == undefined) {
            joinedNodes.push(pair)
            g.setNode(pair.join(','))
        }
    })

    // 2. take the newly added ndoes with paired indices, enum pairs (in [i, j])
    var newPairs = _.combList(joinedNodes.length, 2)
    _.map(newPairs, function(pairInd) {
        // take pair of [i,r] and [j, s] as left and right
        var pair = _.at(joinedNodes, pairInd)
        var left = pair[0],
            right = pair[1],
            i = left[0],
            r = left[1],
            j = right[0],
            s = right[1]

        // if i = j, r != s, and r, s is an edge in G
        if (i == j && r != s && g.edge(r, s) != undefined) {
            // add an edge (ir, js)
            g.setEdge(left.join(','), right.join(','))
        }
        // 3. if i != j, add adge (ir, js)
        else if (i != j) {
            g.setEdge(left.join(','), right.join(','))
        }
    })

    // 4. for all u !\in closedN, add edge (ij, u) if (i,u) or (j,u) were an edge
    _.each(complement, function(u) {
        _.each(joinedNodes, function(ij) {
            if (g.edge(ij[0], u) != undefined || g.edge(ij[1], u) != undefined) {
                g.setEdge(ij.join(','), u)
            }
        })
    })

    // remove closedN from g
    _.each(closedN, function(n) {
        g.removeNode(n)
    })

    return g
}

// simple Folding from the Measure n Conquer paper
// 1. add a new node ij if (i,j) is an antiedge in N(v)
// 2.
function folding(jsonify, n) {

}

var jsonify = require(__dirname + '/data/g1.json')
console.log(bruteVC(jsonify, 3))

console.log(struction(jsonify, 'a').nodes())

var res = _.combList(4, 2)

console.log(res)
<|endoftext|>


<commit_before>import 'babel-polyfill'
import SourceMapSupport from 'source-map-support'
import './reporter'
import Promise from 'bluebird'
import bcrypt from 'bcryptjs'

SourceMapSupport.install()

Promise.config({
  longStackTraces: true,
  warnings: process.env.NODE_ENV === 'development'
})

process.on('unhandledRejection', function (reason) {
  console.error('Unhandled rejection:', reason.stack) // eslint-disable-line no-console
})

Promise.promisifyAll(bcrypt)
<commit_msg>Using Bluebird as the default Promise implementation<commit_after>import 'babel-polyfill'
import SourceMapSupport from 'source-map-support'
import './reporter'
import Bluebird from 'bluebird'
import bcrypt from 'bcryptjs'

require('babel-runtime/core-js/promise').default = Bluebird

SourceMapSupport.install()

Bluebird.config({
  longStackTraces: true,
  warnings: process.env.NODE_ENV === 'development'
})
Bluebird.promisifyAll(bcrypt)

process.on('unhandledRejection', function (reason) {
  console.error('Unhandled rejection:', reason.stack) // eslint-disable-line no-console
})

<|endoftext|>


<commit_before>'use strict';

/*!
 * Module dependancies
 */
var fs = require('fs');
var restify = require('restify');
var cp = require('child_process')
var es = require('event-stream');
var _ = require('underscore');
var async = require('async');
var moment = require('moment');

module.exports = function(ummon){
  var api = {};

  api.doesCollectionExist = function(req, res, next) {
    var collection = req.params.collection

    if (collection && collection in ummon.config.collections) {
      next();
    } else {
      return next(new restify.ResourceNotFoundError('No collection of name '+collection+' found'));
    }
  };

  api.doesTaskExist = function(req, res, next) {
    if (!(req.params.taskid in ummon.tasks)) {
      return next(new restify.ResourceNotFoundError('Task not found! Consider broadening your search to a collection'));
    } else {
      next();
    }
  };

  /**
   * Return the configuration object
   */
  api.getConfig = function(req, res, next) {
    res.json(200, ummon.config);
    next();
  };

  /**
   * Update the configuration
   *
   * Currently limited to only top level of config. So
   * changing log.path won't work just yet
   */
  api.setConfig = function(req, res, next) {
    _.each(req.query, function(value, key) {
      // Convert strings for true and false to boolean
      if (value == "true" || value == "false") {
        value = (value == "true") ? true : false;

      } else if (!isNaN(value)) {
        value = +value;
      }

      ummon.config[key] = value;
    })

    res.json(200, ummon.config);
    next();
  };

  /**
   * What tasks are running
   */
  api.ps = function(req, res, next){
    var pids = Object.keys(ummon.workers);

    res.json(200, {
      "count":pids.length,
      "pids": pids,
      "runs": _.pluck(ummon.workers, 'run')
    });
    next();
  };

  /**
   * Get basic system info, for example:
   *
   *   {
   *     "ok": true,
   *     "version": "0.1.0",
   *     "name": "ummon.server",
   *     "port": 8888
   *   }
   */
  api.getInfo = function(req, res, next) {
    var pkg = require('./package.json');
    res.json(200, {
      ok: true,
      version: pkg.version,
      name: ummon.config.name,
      port: ummon.config.port
    });
  };

  /**
   * Return a snapshot of what is going on
   *
   * returns an object like:
   *
   *   {
   *     "workers": [...],
   *     "queue": [...],
   *     "activeTimers": 1,
   *     "isPaused": falase,
   *     "maxWorkers": 10,
   *     "collections": 2,
   *     "totalTasks":
   *   }
   */
  api.getStatus = function(req, res, next){
    var pids = Object.keys(ummon.workers);

    var workers = (_.size(ummon.workers))
      ? _.map(ummon.workers, function(worker) {return worker.run.task.id})
      : [];

    res.json(200, {
      "workers": workers,
      "queue": ummon.queue.getPresentTaskIds(),
      "activeTimers": Object.keys(ummon.timers),
      "isPaused": ummon.config.pause,
      "maxWorkers": ummon.MAX_WORKERS,
      "collections": ummon.getCollections(),
      "totalTasks": _.size(ummon.tasks)
    });
    next();
  };

  api.getQueue = function(req, res, next) {
    res.json(200, {"queue": ummon.queue.getPresentTaskIds()});
  }

  api.clearQueue = function(req, res, next) {
    var task = req.params.task || false;
    ummon.queue.clear(task);
    res.json(200)
  }

  /**
   * Get a number of tasks. Could be for a specific colleciton
   * or all configured tasks
   *
   * Returns:
   *   {
   *     'collectionName': {
   *       'defaults': { ...defaults... },
   *       'tasks': { ...tasks... }
   *     }
   *   }
   *
   * @param  {[type]}   req
   * @param  {[type]}   res
   * @param  {Function} next The callback
   * @return {[type]}        Heavily structured object. See above
   */
  api.getTasks = function(req, res, next) {
    var filter = req.params.collection || req.params.taskid || false;

    ummon.getTasks(filter, function(err, collections){
      if (err) {
        if (err.message === "There is no tasks or collections that match the provided filter") {
          return next(new restify.ResourceNotFoundError(err.message));
        } else {
          return next(err);
        }
      }
      res.json(200, { 'collections': collections } );
      next();
    });
  };

  api.getCollection = function (req, res, next) {
    ummon.getTasks(req.params.collection, function (err, results) {
      if (err) return next(err);
      // Collection object should always be the only member of the results array
      var col = results[0];
      // Return a simplified config
      var config = {
        enabled: col.config.enabled,
        tasks: {}
      };
      if (ummon.defaults[req.params.collection]) {
        config.defaults = ummon.defaults[req.params.collection];
      }
      for (var task in col.tasks) {
        config.tasks[task] = {
          enabled: col.tasks[task].enabled,
          command: col.tasks[task].command,
          trigger: col.tasks[task].trigger
        };
      }
      res.json(200, config);
    });
  };

  api.setCollection = function(req, res, next) {
    var config = req.body;
    // Modify config for feeding to createCollectionAndTasks
    // TODO Simplify stored object
    config.collection = req.params.collection;
    if ('enabled' in config) {
      config.config = {enabled: config.enabled};
    }
    ummon.createCollectionAndTasks(config, function(err){
      if (err) return next(new restify.InvalidContentError(err.message));

      ummon.getTasks(req.params.collection, function(err, collection){
        res.json(200, { 'collections': collection } );
        next();
      })
    });
  };

  api.getTask = function(req, res, next){
    ummon.getTask(req.params.taskid, function(err, task){
      if (err) {
        return next(err);
      }
      res.json(200, { 'task': task } );
      next();
    });
  };

  /**
   * PUT a collection
   *
   * @param {[type]}   req  [description]
   * @param {[type]}   res  [description]
   * @param {Function} next [description]
   */
  api.setTasks = function(req, res, next) {
    ummon.createCollectionAndTasks(req.body, function(err){
      if (err) return next(new restify.InvalidContentError(err.message));

      ummon.getTasks(req.params.collection, function(err, collection){
        res.json(200, { 'collections': collection } );
        next();
      })
    });
  };

  /**
   * Create a task and add it to a collection
   *
   * Accepts:
   *
   *     {
   *        "name":"hello",
   *        "command": "echo Hello;",
   *        "trigger": {
   *          "time": "* * * * *"
   *        }
   *      }
   */
  api.createTask = function(req, res, next){
    var task = ummon.createTask(req.body, function(err, task){
      if (err) {
        // Assume it's a duplicate task id error
        return next(new restify.ConflictError(err.message));
      }

      res.json(200, {"message":"Task "+task.id+" successfully created", "task":task});
      next();
    });
  };

  api.updateTask = function(req, res, next){
    var task = ummon.updateTask(req.params.taskid, req.body, function(err, task){
      res.json(200, {"message":"Task "+task.id+" successfully updated", "task":task});
      next();
    });
  };

  api.deleteTask = function(req, res, next){
    var p = req.params;

    ummon.deleteTask(p.taskid, function(err){
      if (err) {
        return next(err);
      }

      res.json(200, {"message":"Task "+p.taskid+" successfully deleted"});
      next();
    });
  };

  api.enableTask = function(req, res, next) {
    var task = ummon.tasks[req.params.taskid];

    // Don't enable a task that is in a disabled collection
    if (ummon.config.collections[task.collection].enabled === false) {
      res.json(424, { "message":  "Cannot enabled task " + task.id + " because it's collection is disabled. Please enable collection "+task.collection} );
      return next();
    }

    task.enabled = true;
    ummon.setupTaskTriggers(task);

    ummon.emit('task.updated', task.id); // Task.updated because this effect existing tasks

    res.json(200, { "message": "Task " + task.id + " enabled" });
    next();
  }

  api.disableTask = function(req, res, next) {
    var taskid = req.params.taskid;

    ummon.tasks[taskid].enabled = false;
    ummon.removeTaskTriggers(taskid);

    ummon.emit('task.updated', taskid); // Task.updated because this effect existing tasks

    res.json(200, { "message": "Task " + taskid + " disabled" });
    next();
  }

  // Run a task or one-off command
  api.run = function(req, res, next) {
    var task = req.body.task;

    ummon.runTask(task, function (err, run) {
      res.json(200, { message: 'Added "' + task + '" to the queue' });
    });
  };

  api.getCollectionDefaults = function(req, res, next) {
    var collection = req.params.collection;
    res.json(200, { "collection":  collection, "defaults": ummon.defaults[collection]} );
    next();
  }

  api.setCollectionDefaults = function(req, res, next) {
    var collection = req.params.collection;

    var message = (ummon.defaults[collection])
          ? 'Collection '+collection+' defaults successfully set'
          : 'Collection '+collection+' created and defaults set'

    ummon.defaults[collection] = req.body;

    ummon.emit('task.updated', collection); // Task.updated because this effect existing tasks

    res.json(200, { 'message': message, "collection":  collection, "defaults": ummon.defaults[collection]} );
    next();
  }

  api.enableCollection = function(req, res, next) {
    var collection = req.params.collection;
    var tasksEnabled = [];

    if (ummon.config.collections[collection].enabled === true) {
      res.json(304)
      return next();
    }

    ummon.config.collections[collection].enabled = true;
    for (var task in ummon.tasks) {
      if (ummon.tasks[task].collection === collection) {
        ummon.setupTaskTriggers(ummon.tasks[task]);
        tasksEnabled.push(task);
      }
    }

    ummon.emit('task.updated', collection); // Task.updated because this effect existing tasks

    res.json(200, { "message":  "Collection " + collection + " successfully enabled", "tasksEnabled": tasksEnabled} );
    next();
  }

  api.disableCollection = function(req, res, next) {
    var collection = req.params.collection;
    var tasksDisabled = [];

    if (ummon.config.collections[collection].enabled === false) {
      res.json(304)
      return next();
    }

    ummon.config.collections[collection].enabled = false;
    for (var task in ummon.tasks) {
      if (ummon.tasks[task].collection === collection) {
        ummon.removeTaskTriggers(task);
        tasksDisabled.push(task);
      }
    }

    ummon.emit('task.updated', collection); // Task.updated because this effect existing tasks

    res.json(200, { "message":  "Collection " + collection + " successfully disabled", "tasksDisabled": tasksDisabled} );
    next();
  }

  api.deleteCollection = function(req, res, next) {
    var collection = req.params.collection;

    delete ummon.config.collections[collection];
    delete ummon.defaults[collection];

    var collectionDbPath = ummon.config.tasksPath + '/' + collection + '.tasks.json';
    if (fs.existsSync(collectionDbPath)) {
      fs.unlinkSync(collectionDbPath)
    }

    var taskIds = ummon.getTaskIds(collection+'*');

    async.each(taskIds, ummon.deleteTask.bind(ummon), function(err){
      ummon.emit('task.deleted', collection); // Task.updated because this effect existing tasks

      res.json(200, { "message":  "Collection " + collection + " successfully deleted" } );
      next();
    });
  }

  api.showLog = function(req, res, next){
    delete req.params.lines; // Not sure why this is here but deleting it simplifies the code below

    var filter = req.query.filter || false;
    var from = req.query.from || false;
    var to = req.query.to || false;
    var runsOnly = (req.query.runsOnly) ? true : false;
    var follow = (req.query.follow) ? true : false;

    // Figure out the filter
    if (filter) {
      var runid = false, collection = false, taskid = false;
      if (/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/.test(filter)) {
        runid = filter;
      } else if (filter.indexOf('.') !== -1) {
        taskid = filter;
      } else {
        collection = filter;
      }
    }

    var d = require('domain').create();

    d.on('error', function(er) {
      console.log(er.stack)
    })

    d.run(function() {
      es.pipeline(
        fs.createReadStream(ummon.config.log.path, {encoding: 'utf8'}),
        es.split(), // Split on new lines
        es.parse(), // JSON.parse()

        // Start by filtering by date
        es.map(function (data, callback) {
          if ((!from || data.time >= from) && (!to || data.time <= to)) {
            return callback(null, data)
          }
          callback()
        }),

        // Filter on content
        es.map(function (data, callback) {
          if (runid || taskid || collection) {
            if ((runid && runid === data.runid) ||
              (taskid && taskid === data.taskid) ||
              (collection && collection === data.collection)) {
                return callback(null, data)
            }

            return callback()
          }

          callback(null, data);
        }),

        // filter on runs only
        es.map(function (data, callback) {
          if (runsOnly) {
            if (("run" in data)) {
              return callback(null, data)
            } else {
              return callback();
            }
          }
          callback(null, data)
        }),
        es.stringify(), // JSON.stringify()
        res
      )
    })

    return next();
  };

  // api.run = function(req, res, next){

  // };
  // api.kill = function(req, res, next){};

  return api;
};
<commit_msg>Correctly report cwd for individual tasks, and add a few missing callbacks (these caused the API request to not get logged<commit_after>'use strict';

/*!
 * Module dependancies
 */
var fs = require('fs');
var restify = require('restify');
var cp = require('child_process')
var es = require('event-stream');
var _ = require('underscore');
var async = require('async');
var moment = require('moment');

module.exports = function(ummon){
  var api = {};

  api.doesCollectionExist = function(req, res, next) {
    var collection = req.params.collection

    if (collection && collection in ummon.config.collections) {
      next();
    } else {
      return next(new restify.ResourceNotFoundError('No collection of name '+collection+' found'));
    }
  };

  api.doesTaskExist = function(req, res, next) {
    if (!(req.params.taskid in ummon.tasks)) {
      return next(new restify.ResourceNotFoundError('Task not found! Consider broadening your search to a collection'));
    } else {
      next();
    }
  };

  /**
   * Return the configuration object
   */
  api.getConfig = function(req, res, next) {
    res.json(200, ummon.config);
    next();
  };

  /**
   * Update the configuration
   *
   * Currently limited to only top level of config. So
   * changing log.path won't work just yet
   */
  api.setConfig = function(req, res, next) {
    _.each(req.query, function(value, key) {
      // Convert strings for true and false to boolean
      if (value == "true" || value == "false") {
        value = (value == "true") ? true : false;

      } else if (!isNaN(value)) {
        value = +value;
      }

      ummon.config[key] = value;
    })

    res.json(200, ummon.config);
    next();
  };

  /**
   * What tasks are running
   */
  api.ps = function(req, res, next){
    var pids = Object.keys(ummon.workers);

    res.json(200, {
      "count":pids.length,
      "pids": pids,
      "runs": _.pluck(ummon.workers, 'run')
    });
    next();
  };

  /**
   * Get basic system info, for example:
   *
   *   {
   *     "ok": true,
   *     "version": "0.1.0",
   *     "name": "ummon.server",
   *     "port": 8888
   *   }
   */
  api.getInfo = function(req, res, next) {
    var pkg = require('./package.json');
    res.json(200, {
      ok: true,
      version: pkg.version,
      name: ummon.config.name,
      port: ummon.config.port
    });
  };

  /**
   * Return a snapshot of what is going on
   *
   * returns an object like:
   *
   *   {
   *     "workers": [...],
   *     "queue": [...],
   *     "activeTimers": 1,
   *     "isPaused": falase,
   *     "maxWorkers": 10,
   *     "collections": 2,
   *     "totalTasks":
   *   }
   */
  api.getStatus = function(req, res, next){
    var pids = Object.keys(ummon.workers);

    var workers = (_.size(ummon.workers))
      ? _.map(ummon.workers, function(worker) {return worker.run.task.id})
      : [];

    res.json(200, {
      "workers": workers,
      "queue": ummon.queue.getPresentTaskIds(),
      "activeTimers": Object.keys(ummon.timers),
      "isPaused": ummon.config.pause,
      "maxWorkers": ummon.MAX_WORKERS,
      "collections": ummon.getCollections(),
      "totalTasks": _.size(ummon.tasks)
    });
    next();
  };

  api.getQueue = function(req, res, next) {
    res.json(200, {"queue": ummon.queue.getPresentTaskIds()});
  }

  api.clearQueue = function(req, res, next) {
    var task = req.params.task || false;
    ummon.queue.clear(task);
    res.json(200)
  }

  /**
   * Get a number of tasks. Could be for a specific colleciton
   * or all configured tasks
   *
   * Returns:
   *   {
   *     'collectionName': {
   *       'defaults': { ...defaults... },
   *       'tasks': { ...tasks... }
   *     }
   *   }
   *
   * @param  {[type]}   req
   * @param  {[type]}   res
   * @param  {Function} next The callback
   * @return {[type]}        Heavily structured object. See above
   */
  api.getTasks = function(req, res, next) {
    var filter = req.params.collection || req.params.taskid || false;

    ummon.getTasks(filter, function(err, collections){
      if (err) {
        if (err.message === "There is no tasks or collections that match the provided filter") {
          return next(new restify.ResourceNotFoundError(err.message));
        } else {
          return next(err);
        }
      }
      res.json(200, { 'collections': collections } );
      next();
    });
  };

  api.getCollection = function (req, res, next) {
    ummon.getTasks(req.params.collection, function (err, results) {
      if (err) return next(err);
      // Collection object should always be the only member of the results array
      var col = results[0];
      // Return a simplified config
      var config = {
        enabled: col.config.enabled,
        tasks: {}
      };
      if (ummon.defaults[req.params.collection]) {
        config.defaults = ummon.defaults[req.params.collection];
      }
      for (var task in col.tasks) {
        config.tasks[task] = {
          enabled: col.tasks[task].enabled,
          command: col.tasks[task].command,
          trigger: col.tasks[task].trigger
        };
        if (col.tasks[task].hasOwnProperty('cwd')) {
          config.tasks[task].cwd = col.tasks[task].cwd;
        }
      }
      res.json(200, config);
      next();
    });
  };

  api.setCollection = function(req, res, next) {
    var config = req.body;
    // Modify config for feeding to createCollectionAndTasks
    // TODO Simplify stored object
    config.collection = req.params.collection;
    if ('enabled' in config) {
      config.config = {enabled: config.enabled};
    }
    ummon.createCollectionAndTasks(config, function(err){
      if (err) return next(new restify.InvalidContentError(err.message));

      ummon.getTasks(req.params.collection, function(err, collection){
        res.json(200, { 'collections': collection } );
        next();
      })
    });
  };

  api.getTask = function(req, res, next){
    ummon.getTask(req.params.taskid, function(err, task){
      if (err) {
        return next(err);
      }
      res.json(200, { 'task': task } );
      next();
    });
  };

  /**
   * PUT a collection
   *
   * @param {[type]}   req  [description]
   * @param {[type]}   res  [description]
   * @param {Function} next [description]
   */
  api.setTasks = function(req, res, next) {
    ummon.createCollectionAndTasks(req.body, function(err){
      if (err) return next(new restify.InvalidContentError(err.message));

      ummon.getTasks(req.params.collection, function(err, collection){
        res.json(200, { 'collections': collection } );
        next();
      })
    });
  };

  /**
   * Create a task and add it to a collection
   *
   * Accepts:
   *
   *     {
   *        "name":"hello",
   *        "command": "echo Hello;",
   *        "trigger": {
   *          "time": "* * * * *"
   *        }
   *      }
   */
  api.createTask = function(req, res, next){
    var task = ummon.createTask(req.body, function(err, task){
      if (err) {
        // Assume it's a duplicate task id error
        return next(new restify.ConflictError(err.message));
      }

      res.json(200, {"message":"Task "+task.id+" successfully created", "task":task});
      next();
    });
  };

  api.updateTask = function(req, res, next){
    var task = ummon.updateTask(req.params.taskid, req.body, function(err, task){
      res.json(200, {"message":"Task "+task.id+" successfully updated", "task":task});
      next();
    });
  };

  api.deleteTask = function(req, res, next){
    var p = req.params;

    ummon.deleteTask(p.taskid, function(err){
      if (err) {
        return next(err);
      }

      res.json(200, {"message":"Task "+p.taskid+" successfully deleted"});
      next();
    });
  };

  api.enableTask = function(req, res, next) {
    var task = ummon.tasks[req.params.taskid];

    // Don't enable a task that is in a disabled collection
    if (ummon.config.collections[task.collection].enabled === false) {
      res.json(424, { "message":  "Cannot enabled task " + task.id + " because it's collection is disabled. Please enable collection "+task.collection} );
      return next();
    }

    task.enabled = true;
    ummon.setupTaskTriggers(task);

    ummon.emit('task.updated', task.id); // Task.updated because this effect existing tasks

    res.json(200, { "message": "Task " + task.id + " enabled" });
    next();
  }

  api.disableTask = function(req, res, next) {
    var taskid = req.params.taskid;

    ummon.tasks[taskid].enabled = false;
    ummon.removeTaskTriggers(taskid);

    ummon.emit('task.updated', taskid); // Task.updated because this effect existing tasks

    res.json(200, { "message": "Task " + taskid + " disabled" });
    next();
  }

  // Run a task or one-off command
  api.run = function(req, res, next) {
    var task = req.body.task;

    ummon.runTask(task, function (err, run) {
      res.json(200, { message: 'Added "' + task + '" to the queue' });
      next();
    });
  };

  api.getCollectionDefaults = function(req, res, next) {
    var collection = req.params.collection;
    res.json(200, { "collection":  collection, "defaults": ummon.defaults[collection]} );
    next();
  }

  api.setCollectionDefaults = function(req, res, next) {
    var collection = req.params.collection;

    var message = (ummon.defaults[collection])
          ? 'Collection '+collection+' defaults successfully set'
          : 'Collection '+collection+' created and defaults set'

    ummon.defaults[collection] = req.body;

    ummon.emit('task.updated', collection); // Task.updated because this effect existing tasks

    res.json(200, { 'message': message, "collection":  collection, "defaults": ummon.defaults[collection]} );
    next();
  }

  api.enableCollection = function(req, res, next) {
    var collection = req.params.collection;
    var tasksEnabled = [];

    if (ummon.config.collections[collection].enabled === true) {
      res.json(304)
      return next();
    }

    ummon.config.collections[collection].enabled = true;
    for (var task in ummon.tasks) {
      if (ummon.tasks[task].collection === collection) {
        ummon.setupTaskTriggers(ummon.tasks[task]);
        tasksEnabled.push(task);
      }
    }

    ummon.emit('task.updated', collection); // Task.updated because this effect existing tasks

    res.json(200, { "message":  "Collection " + collection + " successfully enabled", "tasksEnabled": tasksEnabled} );
    next();
  }

  api.disableCollection = function(req, res, next) {
    var collection = req.params.collection;
    var tasksDisabled = [];

    if (ummon.config.collections[collection].enabled === false) {
      res.json(304)
      return next();
    }

    ummon.config.collections[collection].enabled = false;
    for (var task in ummon.tasks) {
      if (ummon.tasks[task].collection === collection) {
        ummon.removeTaskTriggers(task);
        tasksDisabled.push(task);
      }
    }

    ummon.emit('task.updated', collection); // Task.updated because this effect existing tasks

    res.json(200, { "message":  "Collection " + collection + " successfully disabled", "tasksDisabled": tasksDisabled} );
    next();
  }

  api.deleteCollection = function(req, res, next) {
    var collection = req.params.collection;

    delete ummon.config.collections[collection];
    delete ummon.defaults[collection];

    var collectionDbPath = ummon.config.tasksPath + '/' + collection + '.tasks.json';
    if (fs.existsSync(collectionDbPath)) {
      fs.unlinkSync(collectionDbPath)
    }

    var taskIds = ummon.getTaskIds(collection+'*');

    async.each(taskIds, ummon.deleteTask.bind(ummon), function(err){
      ummon.emit('task.deleted', collection); // Task.updated because this effect existing tasks

      res.json(200, { "message":  "Collection " + collection + " successfully deleted" } );
      next();
    });
  }

  api.showLog = function(req, res, next){
    delete req.params.lines; // Not sure why this is here but deleting it simplifies the code below

    var filter = req.query.filter || false;
    var from = req.query.from || false;
    var to = req.query.to || false;
    var runsOnly = (req.query.runsOnly) ? true : false;
    var follow = (req.query.follow) ? true : false;

    // Figure out the filter
    if (filter) {
      var runid = false, collection = false, taskid = false;
      if (/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/.test(filter)) {
        runid = filter;
      } else if (filter.indexOf('.') !== -1) {
        taskid = filter;
      } else {
        collection = filter;
      }
    }

    var d = require('domain').create();

    d.on('error', function(er) {
      console.log(er.stack)
    })

    d.run(function() {
      es.pipeline(
        fs.createReadStream(ummon.config.log.path, {encoding: 'utf8'}),
        es.split(), // Split on new lines
        es.parse(), // JSON.parse()

        // Start by filtering by date
        es.map(function (data, callback) {
          if ((!from || data.time >= from) && (!to || data.time <= to)) {
            return callback(null, data)
          }
          callback()
        }),

        // Filter on content
        es.map(function (data, callback) {
          if (runid || taskid || collection) {
            if ((runid && runid === data.runid) ||
              (taskid && taskid === data.taskid) ||
              (collection && collection === data.collection)) {
                return callback(null, data)
            }

            return callback()
          }

          callback(null, data);
        }),

        // filter on runs only
        es.map(function (data, callback) {
          if (runsOnly) {
            if (("run" in data)) {
              return callback(null, data)
            } else {
              return callback();
            }
          }
          callback(null, data)
        }),
        es.stringify(), // JSON.stringify()
        res
      )
    })

    return next();
  };

  // api.run = function(req, res, next){

  // };
  // api.kill = function(req, res, next){};

  return api;
};
<|endoftext|>


<commit_before>var debug   = require('debug')('api:ctrlLocal'),
    models  = require('../models'),
    AWS     = require('aws-sdk'),
    uuid    = require('node-uuid'),
    s3      = new AWS.S3(),
    sharp   = require('sharp');

var AWS_PATH_PREFIX = 'https://s3.amazonaws.com/bikedeboa/';

var handleNotFound = function(data) {
  if(!data) {
    var err = new Error('Not Found');
    err.status = 404;
    throw err;
  }
  return data;
};

function LocalController(LocalModel) {
  this.model = LocalModel;
}

// ---------------- private functions ---------------- //

function promiseContTags(local) {
  return new Promise(function(resolve, reject) {
    models.sequelize.query('SELECT t.name, COUNT(*) FROM "Tag" t inner join "Review_Tags" rt on T.id = rt.tag_id inner join "Review" r on r.id = rt.review_id inner join "Local" l on r.local_id = l.id WHERE l.id = '+local.id+' GROUP BY t.id')
      .then(function(result, metatag) {
        local.dataValues.tags = result[0];
        resolve(local);
      });
  });
}

function getLocalsAndTags(locals) {
  return new Promise(function(resolve, reject) {
    var promises = [];

    locals.map(function(local){
      promises.push(promiseContTags(local));
    });

    Promise.all(promises).then(function(resp){
      resolve(resp);
    })
  });
}

function getTags(arrTagsId) {
  return new Promise(function(resolve, reject) {
    var promises = [];

    arrTagsId.map(function(tag) {
      promises.push(models.Tag.find({where: {id: tag.id}}));
    });

    Promise.all(promises).then(function(tags) {
      resolve(tags);
    });
  });
}

function saveFullImage(photo, id) {
  return new Promise(function(resolve, reject) {
    // valid photo exists
    if (!photo) resolve('');

    // get base64 and type image for save
    var type = photo.split(',')[0] === 'data:image/png;base64' ? '.png' : photo.split(',')[0] === 'data:image/jpeg;base64' ? '.jpeg' : '',
    base64Data  = type === '.png' ? photo.replace(/^data:image\/png;base64,/, "") : photo.replace(/^data:image\/jpeg;base64,/, "");
    base64Data += base64Data.replace('+', ' ');
    binaryData  = new Buffer(base64Data, 'base64');

    // path image
    var path = "images/";
    var imageName = path + id + type;

    // type invalid return
    if (!type) {
        reject(photo);
    }

    // Send image blob to Amazon S3
    s3.putObject(
      {
        Key: imageName,
        Body: binaryData,
        Bucket: 'bikedeboa',
        ACL: 'public-read'
      }, function(err, data){
        if (err) {
          debug('Error uploading image ', imageName);
          reject(err);
        } else {
          debug('Succesfully uploaded the image', imageName);
          resolve(AWS_PATH_PREFIX + imageName);
        }
      });
  });
}

function saveThumbImage(photo, id) {
  return new Promise(function(resolve, reject) {
    // valid photo exists
    if (!photo) resolve('');

    // get base64 and type image for save
    var type = photo.split(',')[0] === 'data:image/png;base64' ? '.png' : photo.split(',')[0] === 'data:image/jpeg;base64' ? '.jpeg' : '',
    base64Data  = type === '.png' ? photo.replace(/^data:image\/png;base64,/, "") : photo.replace(/^data:image\/jpeg;base64,/, "");
    base64Data += base64Data.replace('+', ' ');
    binaryData  = new Buffer(base64Data, 'base64');

    // path image
    var path = "images/thumbs/";
    var imageName = path + id + type;

    // type invalid return
    if (!type) {
      reject(photo);
    }

    sharp(binaryData)
      .resize(100, 100)
      .max()
      .on('error', function(err) {
        reject(err);
      })
      .toBuffer()
      .then(function (data) {
        // Send image blob to Amazon S3
        s3.putObject(
          {
            Key: imageName,
            Body: data,
            Bucket: 'bikedeboa',
            ACL: 'public-read'
          }, function(err, data){
            if (err) {
              debug('Error uploading image ', imageName);
              reject(err);
            } else {
              debug('Succesfully uploaded the image', imageName);
              resolve(AWS_PATH_PREFIX + imageName);
            }
          });
      });
  });
}

function deleteImage(id) {
  return new Promise(function(resolve, reject) {
    // path image
    var path = "images/";
    var pathThumb = "images/thumbs/";

    var imageName = path + id;
    var imageNameTumb = pathThumb + id;

    // params delete images
    var params = {
      Bucket: 'bikedeboa',
      Delete: {
        Objects: [
          {
            Key: imageName + '.jpeg'
          },
          {
            Key: imageName + '.png'
          },
          {
            Key: imageNameTumb + '.jpeg'
          },
          {
            Key: imageNameTumb + '.png'
          }
        ]
      }
    };
    // delete imagens in s3
    s3.deleteObjects(params, function(err, data) {
      if (err){
        debug(err, err.stack);
        reject(err);
      } else {
        debug(data);
        resolve(data);
      }
    });
  });
}

// ---------------- private functions ---------------- //

LocalController.prototype.getAll = function(request, response, next) {
    var query = {
        attributes: ['id', 'lat', 'lng', 'lat', 'structureType', 'isPublic', 'text', 'description', 'address', 'photo', 'updatedAt', 'createdAt'].concat([
            [
                models.sequelize.literal('(SELECT COUNT(*) FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'reviews'
            ],
            [
                models.sequelize.literal('(SELECT AVG("rating") FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'average'
            ],
            [
                models.sequelize.literal('(SELECT COUNT(*) FROM "Checkin" WHERE "Checkin"."local_id" = "Local"."id")'),
                'checkins'
            ]
        ])
    };

    this.model.findAll(query)
        .then(function(locals) {
            response.json(locals);
        })
        .catch(next);
};

LocalController.prototype.getAllLight = function(request, response, next) {
    var query = {
        attributes: ['id', 'lat', 'lng'].concat([
            [
                models.sequelize.literal('(SELECT AVG("rating") FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'average'
            ],
        ])
    };

    this.model.findAll(query)
        .then(function(data) {
            response.json(data);
        })
        .catch(next);
};

LocalController.prototype.getById = function(request, response, next) {
    var query = {
      attributes: ['id', 'lat', 'lng', 'lat', 'structureType', 'isPublic', 'text', 'photo', 'description', 'address', 'createdAt'].concat([
          [
              models.sequelize.literal('(SELECT COUNT(*) FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
              'reviews'
          ],
          [
              models.sequelize.literal('(SELECT COUNT(*) FROM "Checkin" WHERE "Checkin"."local_id" = "Local"."id")'),
              'checkins'
          ]
      ]),
      where: {id : request.params._id}
    }

  	this.model.find(query)
        .then(handleNotFound)
        .then(function(local){
            return promiseContTags(local)
              .then(function(resp){
                response.json(resp);
              });
        })
    .catch(next);
};

LocalController.prototype.create = function(request, response, next) {
  	var body = request.body;

    var _tags  = body.tags || [];
    var params = {
      lat: body.lat,
      lng: body.lng,
      structureType: body.structureType,
      isPublic: body.isPublic && (body.isPublic === 'true' ? 1 : 0),
      text: body.text,
      photo: '',
      description: body.description,
      address: body.address,
      authorIP: body.authorIP
    };

    if (body.idLocal) { params.id = body.idLocal; }

    // create local
    this.model.create(params).then(handleGetTags).catch(next);

    // get tags informed
    function handleGetTags(local) {
        return getTags(_tags).then(handleSetTags.bind(null, local)).catch(next);
    }

    // set tags local
    function handleSetTags(local, tags) {
        return local.setTags(tags).then(handleSaveThumbImage.bind(null, local)).catch(next);
    }

    // save thumb image local
    function handleSaveThumbImage(local) {
        return saveThumbImage(body.photo, local.id).then(handleSaveImage.bind(null, local)).catch(next);
    }

    // save image local
    function handleSaveImage(local) {
        return saveFullImage(body.photo, local.id).then(handleUpdateUrlLocal.bind(null, local)).catch(next);
    }

    // update local new image url
    function handleUpdateUrlLocal(local, url) {
        return local.update({photo: url}).then(handleResponse).catch(next);
    }

    // return response
    function handleResponse(local) {
      response.json(local);
    }
};

LocalController.prototype.update = function(request, response, next) {
    var _id  = request.params._id,
        body = request.body,
        self = this;

    var _local = {};

    if (body.lat) _local.lat = body.lat;
    if (body.lng) _local.lng = body.lng;
    if (body.description) _local.description = body.description;

    if (body.structureType) _local.structureType = body.structureType;
    if (body.isPublic) _local.isPublic = body.isPublic && (body.isPublic === 'true' ? 1 : 0);
    if (body.text) _local.text = body.text;
    if (body.address) _local.address = body.address;
    if (body.photoUrl) _local.photo = body.photoUrl;

  	var query = {
      where: {id : _id}
    };

    this.model.find(query)
      .then(handleNotFound)
      .then(handleUpdateLocal)
      .catch(next);

    // update data local
    function handleUpdateLocal(local) {
      return local.update(_local).then(handleDeleteImage.bind(null, local)).catch(next);
    }

    // delete image local exists
    function handleDeleteImage(local) {
      if(body.photo){
        return deleteImage(_id).then(handleSaveThumbImage.bind(null, local)).catch(next);
      } else {
        handleSaveThumbImage(local);
      }
    }

    // save thumb image local
    function handleSaveThumbImage(local) {
      if (body.photo) {
        return saveThumbImage(body.photo, local.id).then(handleSaveImage.bind(null, local)).catch(next);
      } else {
        handleUpdateUrlLocal(local);
      }
    }

    // save image local
    function handleSaveImage(local) {
      return saveFullImage(body.photo, _id).then(handleUpdateUrlLocal.bind(null, local)).catch(next);
    }

    // update local new image url
    function handleUpdateUrlLocal(local, url) {
      if (url) {
        return local.update({photo: url}).then(handleResponse.bind(null, local)).catch(next);
      } else {
        handleResponse(local);
      }
    }

    // return response
    function handleResponse(local) {
      response.json(local);
    }
};

LocalController.prototype.remove = function(request, response, next) {
    var _id  = request.params._id;

    var query = {
        where: {id : _id}
    };

    this.model.destroy(query)
      .then(handleNotFound)
      .then(handleDeleteImage.bind(null, _id))
      .catch(next);

    function handleDeleteImage(id, data) {
        return deleteImage(id).then(handleResponse.bind(null, data)).catch(next);
    }

    function handleResponse(rowDeleted) {
      if(rowDeleted){
          response.json({
              message: 'Deleted successfully'
          });
      }
    }
};

// Temporarily disabled until we fix ACL for this guy
// LocalController.prototype.removeAll = function(request, response, next) {
//     var _id  = request.params._id;

//     var query = {where: {}};

//     this.model.destroy(query)
//         .then(handleNotFound)
//         .then(function(rowDeleted){
//             response.json({
//                 message: 'Deleted successfully'
//             });
//         })
//         .catch(next);
// };

module.exports = function(LocalModel) {
  	return new LocalController(LocalModel);
};
<commit_msg>delete comments<commit_after>var debug   = require('debug')('api:ctrlLocal'),
    models  = require('../models'),
    AWS     = require('aws-sdk'),
    uuid    = require('node-uuid'),
    s3      = new AWS.S3(),
    sharp   = require('sharp');

var AWS_PATH_PREFIX = 'https://s3.amazonaws.com/bikedeboa/';

var handleNotFound = function(data) {
  if(!data) {
    var err = new Error('Not Found');
    err.status = 404;
    throw err;
  }
  return data;
};

function LocalController(LocalModel) {
  this.model = LocalModel;
}

// ---------------- private functions ---------------- //

function promiseContTags(local) {
  return new Promise(function(resolve, reject) {
    models.sequelize.query('SELECT t.name, COUNT(*) FROM "Tag" t inner join "Review_Tags" rt on T.id = rt.tag_id inner join "Review" r on r.id = rt.review_id inner join "Local" l on r.local_id = l.id WHERE l.id = '+local.id+' GROUP BY t.id')
      .then(function(result, metatag) {
        local.dataValues.tags = result[0];
        resolve(local);
      });
  });
}

function getLocalsAndTags(locals) {
  return new Promise(function(resolve, reject) {
    var promises = [];

    locals.map(function(local){
      promises.push(promiseContTags(local));
    });

    Promise.all(promises).then(function(resp){
      resolve(resp);
    })
  });
}

function getTags(arrTagsId) {
  return new Promise(function(resolve, reject) {
    var promises = [];

    arrTagsId.map(function(tag) {
      promises.push(models.Tag.find({where: {id: tag.id}}));
    });

    Promise.all(promises).then(function(tags) {
      resolve(tags);
    });
  });
}

function saveFullImage(photo, id) {
  return new Promise(function(resolve, reject) {
    // valid photo exists
    if (!photo) resolve('');

    // get base64 and type image for save
    var type = photo.split(',')[0] === 'data:image/png;base64' ? '.png' : photo.split(',')[0] === 'data:image/jpeg;base64' ? '.jpeg' : '',
    base64Data  = type === '.png' ? photo.replace(/^data:image\/png;base64,/, "") : photo.replace(/^data:image\/jpeg;base64,/, "");
    base64Data += base64Data.replace('+', ' ');
    binaryData  = new Buffer(base64Data, 'base64');

    // path image
    var path = "images/";
    var imageName = path + id + type;

    // type invalid return
    if (!type) {
        reject(photo);
    }

    // Send image blob to Amazon S3
    s3.putObject(
      {
        Key: imageName,
        Body: binaryData,
        Bucket: 'bikedeboa',
        ACL: 'public-read'
      }, function(err, data){
        if (err) {
          debug('Error uploading image ', imageName);
          reject(err);
        } else {
          debug('Succesfully uploaded the image', imageName);
          resolve(AWS_PATH_PREFIX + imageName);
        }
      });
  });
}

function saveThumbImage(photo, id) {
  return new Promise(function(resolve, reject) {
    // valid photo exists
    if (!photo) resolve('');

    // get base64 and type image for save
    var type = photo.split(',')[0] === 'data:image/png;base64' ? '.png' : photo.split(',')[0] === 'data:image/jpeg;base64' ? '.jpeg' : '',
    base64Data  = type === '.png' ? photo.replace(/^data:image\/png;base64,/, "") : photo.replace(/^data:image\/jpeg;base64,/, "");
    base64Data += base64Data.replace('+', ' ');
    binaryData  = new Buffer(base64Data, 'base64');

    // path image
    var path = "images/thumbs/";
    var imageName = path + id + type;

    // type invalid return
    if (!type) {
      reject(photo);
    }

    sharp(binaryData)
      .resize(100, 100)
      .max()
      .on('error', function(err) {
        reject(err);
      })
      .toBuffer()
      .then(function (data) {
        // Send image blob to Amazon S3
        s3.putObject(
          {
            Key: imageName,
            Body: data,
            Bucket: 'bikedeboa',
            ACL: 'public-read'
          }, function(err, data){
            if (err) {
              debug('Error uploading image ', imageName);
              reject(err);
            } else {
              debug('Succesfully uploaded the image', imageName);
              resolve(AWS_PATH_PREFIX + imageName);
            }
          });
      });
  });
}

function deleteImage(id) {
  return new Promise(function(resolve, reject) {
    // path image
    var path = "images/";
    var pathThumb = "images/thumbs/";

    var imageName = path + id;
    var imageNameTumb = pathThumb + id;

    // params delete images
    var params = {
      Bucket: 'bikedeboa',
      Delete: {
        Objects: [
          {
            Key: imageName + '.jpeg'
          },
          {
            Key: imageName + '.png'
          },
          {
            Key: imageNameTumb + '.jpeg'
          },
          {
            Key: imageNameTumb + '.png'
          }
        ]
      }
    };
    // delete imagens in s3
    s3.deleteObjects(params, function(err, data) {
      if (err){
        debug(err, err.stack);
        reject(err);
      } else {
        debug(data);
        resolve(data);
      }
    });
  });
}

// ---------------- private functions ---------------- //

LocalController.prototype.getAll = function(request, response, next) {
    var query = {
        attributes: ['id', 'lat', 'lng', 'lat', 'structureType', 'isPublic', 'text', 'description', 'address', 'photo', 'updatedAt', 'createdAt'].concat([
            [
                models.sequelize.literal('(SELECT COUNT(*) FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'reviews'
            ],
            [
                models.sequelize.literal('(SELECT AVG("rating") FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'average'
            ],
            [
                models.sequelize.literal('(SELECT COUNT(*) FROM "Checkin" WHERE "Checkin"."local_id" = "Local"."id")'),
                'checkins'
            ]
        ])
    };

    this.model.findAll(query)
        .then(function(locals) {
            response.json(locals);
        })
        .catch(next);
};

LocalController.prototype.getAllLight = function(request, response, next) {
    var query = {
        attributes: ['id', 'lat', 'lng'].concat([
            [
                models.sequelize.literal('(SELECT AVG("rating") FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'average'
            ],
        ])
    };

    this.model.findAll(query)
        .then(function(data) {
            response.json(data);
        })
        .catch(next);
};

LocalController.prototype.getById = function(request, response, next) {
    var query = {
      attributes: ['id', 'lat', 'lng', 'lat', 'structureType', 'isPublic', 'text', 'photo', 'description', 'address', 'createdAt'].concat([
          [
              models.sequelize.literal('(SELECT COUNT(*) FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
              'reviews'
          ],
          [
              models.sequelize.literal('(SELECT COUNT(*) FROM "Checkin" WHERE "Checkin"."local_id" = "Local"."id")'),
              'checkins'
          ]
      ]),
      where: {id : request.params._id}
    }

  	this.model.find(query)
        .then(handleNotFound)
        .then(function(local){
            return promiseContTags(local)
              .then(function(resp){
                response.json(resp);
              });
        })
    .catch(next);
};

LocalController.prototype.create = function(request, response, next) {
  	var body = request.body;

    var _tags  = body.tags || [];
    var params = {
      lat: body.lat,
      lng: body.lng,
      structureType: body.structureType,
      isPublic: body.isPublic && (body.isPublic === 'true' ? 1 : 0),
      text: body.text,
      photo: '',
      description: body.description,
      address: body.address,
      authorIP: body.authorIP
    };

    if (body.idLocal) { params.id = body.idLocal; }

    // create local
    this.model.create(params).then(handleGetTags).catch(next);

    // get tags informed
    function handleGetTags(local) {
        return getTags(_tags).then(handleSetTags.bind(null, local)).catch(next);
    }

    // set tags local
    function handleSetTags(local, tags) {
        return local.setTags(tags).then(handleSaveThumbImage.bind(null, local)).catch(next);
    }

    // save thumb image local
    function handleSaveThumbImage(local) {
        return saveThumbImage(body.photo, local.id).then(handleSaveImage.bind(null, local)).catch(next);
    }

    // save image local
    function handleSaveImage(local) {
        return saveFullImage(body.photo, local.id).then(handleUpdateUrlLocal.bind(null, local)).catch(next);
    }

    // update local new image url
    function handleUpdateUrlLocal(local, url) {
        return local.update({photo: url}).then(handleResponse).catch(next);
    }

    // return response
    function handleResponse(local) {
      response.json(local);
    }
};

LocalController.prototype.update = function(request, response, next) {
    var _id  = request.params._id,
        body = request.body,
        self = this;

    var _local = {};

    if (body.lat) _local.lat = body.lat;
    if (body.lng) _local.lng = body.lng;
    if (body.description) _local.description = body.description;

    if (body.structureType) _local.structureType = body.structureType;
    if (body.isPublic) _local.isPublic = body.isPublic && (body.isPublic === 'true' ? 1 : 0);
    if (body.text) _local.text = body.text;
    if (body.address) _local.address = body.address;
    if (body.photoUrl) _local.photo = body.photoUrl;

  	var query = {
      where: {id : _id}
    };

    this.model.find(query)
      .then(handleNotFound)
      .then(handleUpdateLocal)
      .catch(next);

    // update data local
    function handleUpdateLocal(local) {
      return local.update(_local).then(handleDeleteImage.bind(null, local)).catch(next);
    }

    // delete image local exists
    function handleDeleteImage(local) {
      if(body.photo){
        return deleteImage(_id).then(handleSaveThumbImage.bind(null, local)).catch(next);
      } else {
        handleSaveThumbImage(local);
      }
    }

    // save thumb image local
    function handleSaveThumbImage(local) {
      if (body.photo) {
        return saveThumbImage(body.photo, local.id).then(handleSaveImage.bind(null, local)).catch(next);
      } else {
        handleUpdateUrlLocal(local);
      }
    }

    // save image local
    function handleSaveImage(local) {
      return saveFullImage(body.photo, _id).then(handleUpdateUrlLocal.bind(null, local)).catch(next);
    }

    // update local new image url
    function handleUpdateUrlLocal(local, url) {
      if (url) {
        return local.update({photo: url}).then(handleResponse.bind(null, local)).catch(next);
      } else {
        handleResponse(local);
      }
    }

    // return response
    function handleResponse(local) {
      response.json(local);
    }
};

LocalController.prototype.remove = function(request, response, next) {
    var _id  = request.params._id;

    var query = {
        where: {id : _id}
    };

    this.model.destroy(query)
      .then(handleNotFound)
      .then(handleDeleteImage.bind(null, _id))
      .catch(next);

    function handleDeleteImage(id, data) {
        return deleteImage(id).then(handleResponse.bind(null, data)).catch(next);
    }

    function handleResponse(rowDeleted) {
      if(rowDeleted){
          response.json({
              message: 'Deleted successfully'
          });
      }
    }
};

module.exports = function(LocalModel) {
  	return new LocalController(LocalModel);
};
<|endoftext|>


<commit_before>var debug   = require('debug')('api:ctrlLocal'),
    models  = require('../models'),
    AWS     = require('aws-sdk'),
    uuid    = require('node-uuid'),
    s3      = new AWS.S3(),
    sharp   = require('sharp');

var AWS_PATH_PREFIX = 'https://s3.amazonaws.com/bikedeboa/';

var handleNotFound = function(data) {
  if(!data) {
    var err = new Error('Not Found');
    err.status = 404;
    throw err;
  }
  return data;
};

function LocalController(LocalModel) {
  this.model = LocalModel;
}

// ---------------- private functions ---------------- //

function promiseContTags(local) {
  return new Promise(function(resolve, reject) {
    models.sequelize.query('SELECT t.name, COUNT(*) FROM "Tag" t inner join "Review_Tags" rt on T.id = rt.tag_id inner join "Review" r on r.id = rt.review_id inner join "Local" l on r.local_id = l.id WHERE l.id = '+local.id+' GROUP BY t.id')
      .then(function(result, metatag) {
        local.dataValues.tags = result[0];
        resolve(local);
      });
  });
}

function getLocalsAndTags(locals) {
  return new Promise(function(resolve, reject) {
    var promises = [];

    locals.map(function(local){
      promises.push(promiseContTags(local));
    });

    Promise.all(promises).then(function(resp){
      resolve(resp);
    })
  });
}

function getTags(arrTagsId) {
  return new Promise(function(resolve, reject) {
    var promises = [];

    arrTagsId.map(function(tag) {
      promises.push(models.Tag.find({where: {id: tag.id}}));
    });

    Promise.all(promises).then(function(tags) {
      resolve(tags);
    });
  });
}

function saveFullImage(photo, id) {
  return new Promise(function(resolve, reject) {
    // valid photo exists
    if (!photo) resolve('');

    // get base64 and type image for save
    var type = photo.split(',')[0] === 'data:image/png;base64' ? '.png' : photo.split(',')[0] === 'data:image/jpeg;base64' ? '.jpeg' : '',
    base64Data  = type === '.png' ? photo.replace(/^data:image\/png;base64,/, "") : photo.replace(/^data:image\/jpeg;base64,/, "");
    base64Data += base64Data.replace('+', ' ');
    binaryData  = new Buffer(base64Data, 'base64');

    // path image
    var path = "images/";
    var imageName = path + id + type;

    // type invalid return
    if (!type) {
        reject(photo);
    }

    // Send image blob to Amazon S3
    s3.putObject(
      {
        Key: imageName,
        Body: binaryData,
        Bucket: 'bikedeboa',
        ACL: 'public-read'
      }, function(err, data){
        if (err) {
          debug('Error uploading image ', imageName);
          reject(err);
        } else {
          debug('Succesfully uploaded the image', imageName);
          resolve(AWS_PATH_PREFIX + imageName);
        }
      });
  });
}

function saveThumbImage(photo, id) {
  return new Promise(function(resolve, reject) {
    // valid photo exists
    if (!photo) resolve('');

    // get base64 and type image for save
    var type = photo.split(',')[0] === 'data:image/png;base64' ? '.png' : photo.split(',')[0] === 'data:image/jpeg;base64' ? '.jpeg' : '',
    base64Data  = type === '.png' ? photo.replace(/^data:image\/png;base64,/, "") : photo.replace(/^data:image\/jpeg;base64,/, "");
    base64Data += base64Data.replace('+', ' ');
    binaryData  = new Buffer(base64Data, 'base64');

    // path image
    var path = "images/thumbs/";
    var imageName = path + id + type;

    // type invalid return
    if (!type) {
      reject(photo);
    }

    sharp(binaryData)
      .resize(100, 100)
      .max()
      .on('error', function(err) {
        reject(err);
      })
      .toBuffer()
      .then(function (data) {
        // Send image blob to Amazon S3
        s3.putObject(
          {
            Key: imageName,
            Body: data,
            Bucket: 'bikedeboa',
            ACL: 'public-read'
          }, function(err, data){
            if (err) {
              debug('Error uploading image ', imageName);
              reject(err);
            } else {
              debug('Succesfully uploaded the image', imageName);
              resolve(AWS_PATH_PREFIX + imageName);
            }
          });
      });
  });
}

function deleteImage(id) {
  return new Promise(function(resolve, reject) {
    // path image
    var path = "images/";
    var pathThumb = "images/thumbs/";

    var imageName = path + id;
    var imageNameTumb = pathThumb + id;

    // params delete images
    var params = {
      Bucket: 'bikedeboa',
      Delete: {
        Objects: [
          {
            Key: imageName + '.jpeg'
          },
          {
            Key: imageName + '.png'
          },
          {
            Key: imageNameTumb + '.jpeg'
          },
          {
            Key: imageNameTumb + '.png'
          }
        ]
      }
    };
    // delete imagens in s3
    s3.deleteObjects(params, function(err, data) {
      if (err){
        debug(err, err.stack);
        reject(err);
      } else {
        debug(data);
        resolve(data);
      }
    });
  });
}

// ---------------- private functions ---------------- //

LocalController.prototype.getAll = function(request, response, next) {
    var query = {
        attributes: ['id', 'lat', 'lng', 'lat', 'structureType', 'isPublic', 'text', 'description', 'address', 'photo', 'updatedAt'].concat([
            [
                models.sequelize.literal('(SELECT COUNT(*) FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'reviews'
            ],
            [
                models.sequelize.literal('(SELECT AVG("rating") FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'average'
            ],
            [
                models.sequelize.literal('(SELECT COUNT(*) FROM "Checkin" WHERE "Checkin"."local_id" = "Local"."id")'),
                'checkins'
            ]
        ])
    };

    this.model.findAll(query)
        .then(function(locals) {
            response.json(locals);
        })
        .catch(next);
};

LocalController.prototype.getAllLight = function(request, response, next) {
    var query = {
        attributes: ['id', 'lat', 'lng'].concat([
            [
                models.sequelize.literal('(SELECT AVG("rating") FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'average'
            ],
        ])
    };

    this.model.findAll(query)
        .then(function(data) {
            response.json(data);
        })
        .catch(next);
};

LocalController.prototype.getById = function(request, response, next) {
    var query = {
      attributes: ['id', 'lat', 'lng', 'lat', 'structureType', 'isPublic', 'text', 'photo', 'description', 'address', 'updatedAt'].concat([
          [
              models.sequelize.literal('(SELECT COUNT(*) FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
              'reviews'
          ],
          [
              models.sequelize.literal('(SELECT COUNT(*) FROM "Checkin" WHERE "Checkin"."local_id" = "Local"."id")'),
              'checkins'
          ]
      ]),
      where: {id : request.params._id}
    }

  	this.model.find(query)
        .then(handleNotFound)
        .then(function(local){
            return promiseContTags(local)
              .then(function(resp){
                response.json(resp);
              });
        })
    .catch(next);
};

LocalController.prototype.create = function(request, response, next) {
  	var body = request.body;

    var _tags  = body.tags || [];
    var params = {
      lat: body.lat,
      lng: body.lng,
      structureType: body.structureType,
      isPublic: body.isPublic && (body.isPublic === 'true' ? 1 : 0),
      text: body.text,
      photo: '',
      description: body.description,
      address: body.address,
      authorIP: body.authorIP
    };

    // create local
    this.model.create(params).then(handleGetTags).catch(next);

    // get tags informed
    function handleGetTags(local) {
        return getTags(_tags).then(handleSetTags.bind(null, local)).catch(next);
    }

    // set tags local
    function handleSetTags(local, tags) {
        return local.setTags(tags).then(handleSaveThumbImage.bind(null, local)).catch(next);
    }

    // save thumb image local
    function handleSaveThumbImage(local) {
        return saveThumbImage(body.photo, local.id).then(handleSaveImage.bind(null, local)).catch(next);
    }

    // save image local
    function handleSaveImage(local) {
        return saveFullImage(body.photo, local.id).then(handleUpdateUrlLocal.bind(null, local)).catch(next);
    }

    // update local new image url
    function handleUpdateUrlLocal(local, url) {
        return local.update({photo: url}).then(handleResponse).catch(next);
    }

    // return response
    function handleResponse(local) {
      response.json(local);
    }
};

LocalController.prototype.update = function(request, response, next) {
    var _id  = request.params._id,
        body = request.body,
        self = this;

    var _local = {};

    if (body.lat) _local.lat = body.lat;
    if (body.lng) _local.lng = body.lng;
    if (body.description) _local.description = body.description;

    if (body.structureType) _local.structureType = body.structureType;
    if (body.isPublic) _local.isPublic = body.isPublic && (body.isPublic === 'true' ? 1 : 0);
    if (body.text) _local.text = body.text;
    if (body.address) _local.address = body.address;

  	var query = {
      where: {id : _id}
    };

    this.model.find(query)
      .then(handleNotFound)
      .then(handleUpdateLocal)
      .catch(next);

    // update data local
    function handleUpdateLocal(local) {
      return local.update(_local).then(handleDeleteImage.bind(null, local)).catch(next);
    }

    // delete image local exists
    function handleDeleteImage(local) {
      if(body.photo){
        return deleteImage(_id).then(handleSaveThumbImage.bind(null, local)).catch(next);
      } else {
        handleSaveThumbImage(local);
      }
    }

    // save thumb image local
    function handleSaveThumbImage(local) {
      if (body.photo) {
        return saveThumbImage(body.photo, local.id).then(handleSaveImage.bind(null, local)).catch(next);
      } else {
        handleUpdateUrlLocal(local);
      }
    }

    // save image local
    function handleSaveImage(local) {
      return saveFullImage(body.photo, _id).then(handleUpdateUrlLocal.bind(null, local)).catch(next);
    }

    // update local new image url
    function handleUpdateUrlLocal(local, url) {
      if (url) {
        return local.update({photo: url}).then(handleResponse.bind(null, local)).catch(next);
      } else {
        handleResponse(local);
      }
    }

    // return response
    function handleResponse(local) {
      response.json(local);
    }
};

LocalController.prototype.remove = function(request, response, next) {
    var _id  = request.params._id;

    var query = {
        where: {id : _id}
    };

    this.model.destroy(query)
      .then(handleNotFound)
      .then(handleDeleteImage.bind(null, _id))
      .catch(next);

    function handleDeleteImage(id, data) {
        return deleteImage(id).then(handleResponse.bind(null, data)).catch(next);
    }

    function handleResponse(rowDeleted) {
      if(rowDeleted){
          response.json({
              message: 'Deleted successfully'
          });
      }
    }
};

LocalController.prototype.removeAll = function(request, response, next) {
    var _id  = request.params._id;

    var query = {where: {}};

    this.model.destroy(query)
        .then(handleNotFound)
        .then(function(rowDeleted){
            response.json({
                message: 'Deleted successfully'
            });
        })
        .catch(next);
};

module.exports = function(LocalModel) {
  	return new LocalController(LocalModel);
};
<commit_msg>adds createAt field to Local getters<commit_after>var debug   = require('debug')('api:ctrlLocal'),
    models  = require('../models'),
    AWS     = require('aws-sdk'),
    uuid    = require('node-uuid'),
    s3      = new AWS.S3(),
    sharp   = require('sharp');

var AWS_PATH_PREFIX = 'https://s3.amazonaws.com/bikedeboa/';

var handleNotFound = function(data) {
  if(!data) {
    var err = new Error('Not Found');
    err.status = 404;
    throw err;
  }
  return data;
};

function LocalController(LocalModel) {
  this.model = LocalModel;
}

// ---------------- private functions ---------------- //

function promiseContTags(local) {
  return new Promise(function(resolve, reject) {
    models.sequelize.query('SELECT t.name, COUNT(*) FROM "Tag" t inner join "Review_Tags" rt on T.id = rt.tag_id inner join "Review" r on r.id = rt.review_id inner join "Local" l on r.local_id = l.id WHERE l.id = '+local.id+' GROUP BY t.id')
      .then(function(result, metatag) {
        local.dataValues.tags = result[0];
        resolve(local);
      });
  });
}

function getLocalsAndTags(locals) {
  return new Promise(function(resolve, reject) {
    var promises = [];

    locals.map(function(local){
      promises.push(promiseContTags(local));
    });

    Promise.all(promises).then(function(resp){
      resolve(resp);
    })
  });
}

function getTags(arrTagsId) {
  return new Promise(function(resolve, reject) {
    var promises = [];

    arrTagsId.map(function(tag) {
      promises.push(models.Tag.find({where: {id: tag.id}}));
    });

    Promise.all(promises).then(function(tags) {
      resolve(tags);
    });
  });
}

function saveFullImage(photo, id) {
  return new Promise(function(resolve, reject) {
    // valid photo exists
    if (!photo) resolve('');

    // get base64 and type image for save
    var type = photo.split(',')[0] === 'data:image/png;base64' ? '.png' : photo.split(',')[0] === 'data:image/jpeg;base64' ? '.jpeg' : '',
    base64Data  = type === '.png' ? photo.replace(/^data:image\/png;base64,/, "") : photo.replace(/^data:image\/jpeg;base64,/, "");
    base64Data += base64Data.replace('+', ' ');
    binaryData  = new Buffer(base64Data, 'base64');

    // path image
    var path = "images/";
    var imageName = path + id + type;

    // type invalid return
    if (!type) {
        reject(photo);
    }

    // Send image blob to Amazon S3
    s3.putObject(
      {
        Key: imageName,
        Body: binaryData,
        Bucket: 'bikedeboa',
        ACL: 'public-read'
      }, function(err, data){
        if (err) {
          debug('Error uploading image ', imageName);
          reject(err);
        } else {
          debug('Succesfully uploaded the image', imageName);
          resolve(AWS_PATH_PREFIX + imageName);
        }
      });
  });
}

function saveThumbImage(photo, id) {
  return new Promise(function(resolve, reject) {
    // valid photo exists
    if (!photo) resolve('');

    // get base64 and type image for save
    var type = photo.split(',')[0] === 'data:image/png;base64' ? '.png' : photo.split(',')[0] === 'data:image/jpeg;base64' ? '.jpeg' : '',
    base64Data  = type === '.png' ? photo.replace(/^data:image\/png;base64,/, "") : photo.replace(/^data:image\/jpeg;base64,/, "");
    base64Data += base64Data.replace('+', ' ');
    binaryData  = new Buffer(base64Data, 'base64');

    // path image
    var path = "images/thumbs/";
    var imageName = path + id + type;

    // type invalid return
    if (!type) {
      reject(photo);
    }

    sharp(binaryData)
      .resize(100, 100)
      .max()
      .on('error', function(err) {
        reject(err);
      })
      .toBuffer()
      .then(function (data) {
        // Send image blob to Amazon S3
        s3.putObject(
          {
            Key: imageName,
            Body: data,
            Bucket: 'bikedeboa',
            ACL: 'public-read'
          }, function(err, data){
            if (err) {
              debug('Error uploading image ', imageName);
              reject(err);
            } else {
              debug('Succesfully uploaded the image', imageName);
              resolve(AWS_PATH_PREFIX + imageName);
            }
          });
      });
  });
}

function deleteImage(id) {
  return new Promise(function(resolve, reject) {
    // path image
    var path = "images/";
    var pathThumb = "images/thumbs/";

    var imageName = path + id;
    var imageNameTumb = pathThumb + id;

    // params delete images
    var params = {
      Bucket: 'bikedeboa',
      Delete: {
        Objects: [
          {
            Key: imageName + '.jpeg'
          },
          {
            Key: imageName + '.png'
          },
          {
            Key: imageNameTumb + '.jpeg'
          },
          {
            Key: imageNameTumb + '.png'
          }
        ]
      }
    };
    // delete imagens in s3
    s3.deleteObjects(params, function(err, data) {
      if (err){
        debug(err, err.stack);
        reject(err);
      } else {
        debug(data);
        resolve(data);
      }
    });
  });
}

// ---------------- private functions ---------------- //

LocalController.prototype.getAll = function(request, response, next) {
    var query = {
        attributes: ['id', 'lat', 'lng', 'lat', 'structureType', 'isPublic', 'text', 'description', 'address', 'photo', 'updatedAt', 'createdAt'].concat([
            [
                models.sequelize.literal('(SELECT COUNT(*) FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'reviews'
            ],
            [
                models.sequelize.literal('(SELECT AVG("rating") FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'average'
            ],
            [
                models.sequelize.literal('(SELECT COUNT(*) FROM "Checkin" WHERE "Checkin"."local_id" = "Local"."id")'),
                'checkins'
            ]
        ])
    };

    this.model.findAll(query)
        .then(function(locals) {
            response.json(locals);
        })
        .catch(next);
};

LocalController.prototype.getAllLight = function(request, response, next) {
    var query = {
        attributes: ['id', 'lat', 'lng'].concat([
            [
                models.sequelize.literal('(SELECT AVG("rating") FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
                'average'
            ],
        ])
    };

    this.model.findAll(query)
        .then(function(data) {
            response.json(data);
        })
        .catch(next);
};

LocalController.prototype.getById = function(request, response, next) {
    var query = {
      attributes: ['id', 'lat', 'lng', 'lat', 'structureType', 'isPublic', 'text', 'photo', 'description', 'address', 'createdAt'].concat([
          [
              models.sequelize.literal('(SELECT COUNT(*) FROM "Review" WHERE "Review"."local_id" = "Local"."id")'),
              'reviews'
          ],
          [
              models.sequelize.literal('(SELECT COUNT(*) FROM "Checkin" WHERE "Checkin"."local_id" = "Local"."id")'),
              'checkins'
          ]
      ]),
      where: {id : request.params._id}
    }

  	this.model.find(query)
        .then(handleNotFound)
        .then(function(local){
            return promiseContTags(local)
              .then(function(resp){
                response.json(resp);
              });
        })
    .catch(next);
};

LocalController.prototype.create = function(request, response, next) {
  	var body = request.body;

    var _tags  = body.tags || [];
    var params = {
      lat: body.lat,
      lng: body.lng,
      structureType: body.structureType,
      isPublic: body.isPublic && (body.isPublic === 'true' ? 1 : 0),
      text: body.text,
      photo: '',
      description: body.description,
      address: body.address,
      authorIP: body.authorIP
    };

    // create local
    this.model.create(params).then(handleGetTags).catch(next);

    // get tags informed
    function handleGetTags(local) {
        return getTags(_tags).then(handleSetTags.bind(null, local)).catch(next);
    }

    // set tags local
    function handleSetTags(local, tags) {
        return local.setTags(tags).then(handleSaveThumbImage.bind(null, local)).catch(next);
    }

    // save thumb image local
    function handleSaveThumbImage(local) {
        return saveThumbImage(body.photo, local.id).then(handleSaveImage.bind(null, local)).catch(next);
    }

    // save image local
    function handleSaveImage(local) {
        return saveFullImage(body.photo, local.id).then(handleUpdateUrlLocal.bind(null, local)).catch(next);
    }

    // update local new image url
    function handleUpdateUrlLocal(local, url) {
        return local.update({photo: url}).then(handleResponse).catch(next);
    }

    // return response
    function handleResponse(local) {
      response.json(local);
    }
};

LocalController.prototype.update = function(request, response, next) {
    var _id  = request.params._id,
        body = request.body,
        self = this;

    var _local = {};

    if (body.lat) _local.lat = body.lat;
    if (body.lng) _local.lng = body.lng;
    if (body.description) _local.description = body.description;

    if (body.structureType) _local.structureType = body.structureType;
    if (body.isPublic) _local.isPublic = body.isPublic && (body.isPublic === 'true' ? 1 : 0);
    if (body.text) _local.text = body.text;
    if (body.address) _local.address = body.address;

  	var query = {
      where: {id : _id}
    };

    this.model.find(query)
      .then(handleNotFound)
      .then(handleUpdateLocal)
      .catch(next);

    // update data local
    function handleUpdateLocal(local) {
      return local.update(_local).then(handleDeleteImage.bind(null, local)).catch(next);
    }

    // delete image local exists
    function handleDeleteImage(local) {
      if(body.photo){
        return deleteImage(_id).then(handleSaveThumbImage.bind(null, local)).catch(next);
      } else {
        handleSaveThumbImage(local);
      }
    }

    // save thumb image local
    function handleSaveThumbImage(local) {
      if (body.photo) {
        return saveThumbImage(body.photo, local.id).then(handleSaveImage.bind(null, local)).catch(next);
      } else {
        handleUpdateUrlLocal(local);
      }
    }

    // save image local
    function handleSaveImage(local) {
      return saveFullImage(body.photo, _id).then(handleUpdateUrlLocal.bind(null, local)).catch(next);
    }

    // update local new image url
    function handleUpdateUrlLocal(local, url) {
      if (url) {
        return local.update({photo: url}).then(handleResponse.bind(null, local)).catch(next);
      } else {
        handleResponse(local);
      }
    }

    // return response
    function handleResponse(local) {
      response.json(local);
    }
};

LocalController.prototype.remove = function(request, response, next) {
    var _id  = request.params._id;

    var query = {
        where: {id : _id}
    };

    this.model.destroy(query)
      .then(handleNotFound)
      .then(handleDeleteImage.bind(null, _id))
      .catch(next);

    function handleDeleteImage(id, data) {
        return deleteImage(id).then(handleResponse.bind(null, data)).catch(next);
    }

    function handleResponse(rowDeleted) {
      if(rowDeleted){
          response.json({
              message: 'Deleted successfully'
          });
      }
    }
};

LocalController.prototype.removeAll = function(request, response, next) {
    var _id  = request.params._id;

    var query = {where: {}};

    this.model.destroy(query)
        .then(handleNotFound)
        .then(function(rowDeleted){
            response.json({
                message: 'Deleted successfully'
            });
        })
        .catch(next);
};

module.exports = function(LocalModel) {
  	return new LocalController(LocalModel);
};
<|endoftext|>