<commit_before>'use strict';

var chai = require('chai')
  , expect = chai.expect
  , Support = require(__dirname + '/../support')
  , DataTypes = require(__dirname + '/../../../lib/data-types');

chai.config.includeStack = true;

describe(Support.getTestDialectTeaser('Multiple Level Filters'), function() {
  it('can filter through belongsTo', function(done) {
    var User = this.sequelize.define('User', {username: DataTypes.STRING })
      , Task = this.sequelize.define('Task', {title: DataTypes.STRING })
      , Project = this.sequelize.define('Project', { title: DataTypes.STRING });

    Project.belongsTo(User);
    User.hasMany(Project);

    Task.belongsTo(Project);
    Project.hasMany(Task);

    this.sequelize.sync({ force: true }).success(function() {
      User.bulkCreate([{
        username: 'leia'
      }, {
        username: 'vader'
      }]).success(function() {
        Project.bulkCreate([{
          UserId: 1,
          title: 'republic'
        },{
          UserId: 2,
          title: 'empire'
        }]).success(function() {
          Task.bulkCreate([{
            ProjectId: 1,
            title: 'fight empire'
          },{
            ProjectId: 1,
            title: 'stablish republic'
          },{
            ProjectId: 2,
            title: 'destroy rebel alliance'
          },{
            ProjectId: 2,
            title: 'rule everything'
          }]).success(function() {
            Task.findAll({
              include: [
                {model: Project, include: [
                  {model: User, where: {username: 'leia'}}
                ]}
              ]
            }).done(function(err, tasks) {
              expect(err).not.to.be.ok;

              try {
                expect(tasks.length).to.be.equal(2);
                expect(tasks[0].title).to.be.equal('fight empire');
                expect(tasks[1].title).to.be.equal('stablish republic');
                done();
              }catch (e) {
                done(e);
              }
            });
          });
        });
      });
    });
  });

  it('avoids duplicated tables in query', function(done) {
    var User = this.sequelize.define('User', {username: DataTypes.STRING })
      , Task = this.sequelize.define('Task', {title: DataTypes.STRING })
      , Project = this.sequelize.define('Project', { title: DataTypes.STRING });

    Project.belongsTo(User);
    User.hasMany(Project);

    Task.belongsTo(Project);
    Project.hasMany(Task);

    this.sequelize.sync({ force: true }).success(function() {
      User.bulkCreate([{
        username: 'leia'
      }, {
        username: 'vader'
      }]).success(function() {
        Project.bulkCreate([{
          UserId: 1,
          title: 'republic'
        },{
          UserId: 2,
          title: 'empire'
        }]).success(function() {
          Task.bulkCreate([{
            ProjectId: 1,
            title: 'fight empire'
          },{
            ProjectId: 1,
            title: 'stablish republic'
          },{
            ProjectId: 2,
            title: 'destroy rebel alliance'
          },{
            ProjectId: 2,
            title: 'rule everything'
          }]).success(function() {
            Task.findAll({
              include: [
                {model: Project, include: [
                  {model: User, where: {
                    username: 'leia',
                    id: 1
                  }}
                ]}
              ]
            }).success(function(tasks) {
              try {
                expect(tasks.length).to.be.equal(2);
                expect(tasks[0].title).to.be.equal('fight empire');
                expect(tasks[1].title).to.be.equal('stablish republic');
                done();
              }catch (e) {
                done(e);
              }
            });
          });
        });
      });
    });
  });

  it('can filter through hasMany', function(done) {
    var User = this.sequelize.define('User', {username: DataTypes.STRING })
      , Task = this.sequelize.define('Task', {title: DataTypes.STRING })
      , Project = this.sequelize.define('Project', { title: DataTypes.STRING });

    Project.belongsTo(User);
    User.hasMany(Project);

    Task.belongsTo(Project);
    Project.hasMany(Task);

    this.sequelize.sync({ force: true }).success(function() {
      User.bulkCreate([{
        username: 'leia'
      }, {
        username: 'vader'
      }]).success(function() {
        Project.bulkCreate([{
          UserId: 1,
          title: 'republic'
        },{
          UserId: 2,
          title: 'empire'
        }]).success(function() {
          Task.bulkCreate([{
            ProjectId: 1,
            title: 'fight empire'
          },{
            ProjectId: 1,
            title: 'stablish republic'
          },{
            ProjectId: 2,
            title: 'destroy rebel alliance'
          },{
            ProjectId: 2,
            title: 'rule everything'
          }]).success(function() {
            User.findAll({
              include: [
                {model: Project, include: [
                  {model: Task, where: {title: 'fight empire'}}
                ]}
              ]
            }).done(function(err, users) {
              try {
                expect(users.length).to.be.equal(1);
                expect(users[0].username).to.be.equal('leia');
                done();
              }catch (e) {
                done(e);
              }
            });
          });
        });
      });
    });
  });

  it('can filter through hasMany connector', function(done) {
    var User = this.sequelize.define('User', {username: DataTypes.STRING })
      , Project = this.sequelize.define('Project', { title: DataTypes.STRING });

    Project.hasMany(User);
    User.hasMany(Project);

    this.sequelize.sync({ force: true }).success(function() {
      User.bulkCreate([{
        username: 'leia'
      }, {
        username: 'vader'
      }]).success(function() {
        Project.bulkCreate([{
          title: 'republic'
        },{
          title: 'empire'
        }]).success(function() {
          User.find(1).success(function(user) {
            Project.find(1).success(function(project) {
              user.setProjects([project]).success(function() {
                User.find(2).success(function(user) {
                  Project.find(2).success(function(project) {
                    user.setProjects([project]).success(function() {
                      User.findAll({
                        include: [
                          {model: Project, where: {title: 'republic'}}
                        ]
                      }).success(function(users) {
                        try {
                          expect(users.length).to.be.equal(1);
                          expect(users[0].username).to.be.equal('leia');
                          done();
                        }catch (e) {
                          done(e);
                        }
                      });
                    });
                  });
                });

              });
            });
          });
        });
      });
    });
  });
});
<commit_msg>conver tests to promises<commit_after>'use strict';

var chai = require('chai')
  , expect = chai.expect
  , Support = require(__dirname + '/../support')
  , DataTypes = require(__dirname + '/../../../lib/data-types');

chai.config.includeStack = true;

describe(Support.getTestDialectTeaser('Multiple Level Filters'), function() {
  it('can filter through belongsTo', function() {
    var User = this.sequelize.define('User', {username: DataTypes.STRING })
      , Task = this.sequelize.define('Task', {title: DataTypes.STRING })
      , Project = this.sequelize.define('Project', { title: DataTypes.STRING });

    Project.belongsTo(User);
    User.hasMany(Project);

    Task.belongsTo(Project);
    Project.hasMany(Task);

    return this.sequelize.sync({ force: true }).then(function() {
      return User.bulkCreate([{
        username: 'leia'
      }, {
        username: 'vader'
      }]).then(function() {
        return Project.bulkCreate([{
          UserId: 1,
          title: 'republic'
        },{
          UserId: 2,
          title: 'empire'
        }]).then(function() {
          return Task.bulkCreate([{
            ProjectId: 1,
            title: 'fight empire'
          },{
            ProjectId: 1,
            title: 'stablish republic'
          },{
            ProjectId: 2,
            title: 'destroy rebel alliance'
          },{
            ProjectId: 2,
            title: 'rule everything'
          }]).then(function() {
            return Task.findAll({
              include: [
                {model: Project, include: [
                  {model: User, where: {username: 'leia'}}
                ]}
              ]
            }).then(function(tasks) {
              expect(tasks.length).to.be.equal(2);
              expect(tasks[0].title).to.be.equal('fight empire');
              expect(tasks[1].title).to.be.equal('stablish republic');
            });
          });
        });
      });
    });
  });

  it('avoids duplicated tables in query', function() {
    var User = this.sequelize.define('User', {username: DataTypes.STRING })
      , Task = this.sequelize.define('Task', {title: DataTypes.STRING })
      , Project = this.sequelize.define('Project', { title: DataTypes.STRING });

    Project.belongsTo(User);
    User.hasMany(Project);

    Task.belongsTo(Project);
    Project.hasMany(Task);

    return this.sequelize.sync({ force: true }).then(function() {
      return User.bulkCreate([{
        username: 'leia'
      }, {
        username: 'vader'
      }]).then(function() {
        return Project.bulkCreate([{
          UserId: 1,
          title: 'republic'
        },{
          UserId: 2,
          title: 'empire'
        }]).then(function() {
          return Task.bulkCreate([{
            ProjectId: 1,
            title: 'fight empire'
          },{
            ProjectId: 1,
            title: 'stablish republic'
          },{
            ProjectId: 2,
            title: 'destroy rebel alliance'
          },{
            ProjectId: 2,
            title: 'rule everything'
          }]).then(function() {
            return Task.findAll({
              include: [
                {model: Project, include: [
                  {model: User, where: {
                    username: 'leia',
                    id: 1
                  }}
                ]}
              ]
            }).then(function(tasks) {
              expect(tasks.length).to.be.equal(2);
              expect(tasks[0].title).to.be.equal('fight empire');
              expect(tasks[1].title).to.be.equal('stablish republic');
            });
          });
        });
      });
    });
  });

  it('can filter through hasMany', function() {
    var User = this.sequelize.define('User', {username: DataTypes.STRING })
      , Task = this.sequelize.define('Task', {title: DataTypes.STRING })
      , Project = this.sequelize.define('Project', { title: DataTypes.STRING });

    Project.belongsTo(User);
    User.hasMany(Project);

    Task.belongsTo(Project);
    Project.hasMany(Task);

    return this.sequelize.sync({ force: true }).then(function() {
      return User.bulkCreate([{
        username: 'leia'
      }, {
        username: 'vader'
      }]).then(function() {
        return Project.bulkCreate([{
          UserId: 1,
          title: 'republic'
        },{
          UserId: 2,
          title: 'empire'
        }]).then(function() {
          return Task.bulkCreate([{
            ProjectId: 1,
            title: 'fight empire'
          },{
            ProjectId: 1,
            title: 'stablish republic'
          },{
            ProjectId: 2,
            title: 'destroy rebel alliance'
          },{
            ProjectId: 2,
            title: 'rule everything'
          }]).then(function() {
            return User.findAll({
              include: [
                {model: Project, include: [
                  {model: Task, where: {title: 'fight empire'}}
                ]}
              ]
            }).then(function(users) {
              expect(users.length).to.be.equal(1);
              expect(users[0].username).to.be.equal('leia');
            });
          });
        });
      });
    });
  });

  it('can filter through hasMany connector', function() {
    var User = this.sequelize.define('User', {username: DataTypes.STRING })
      , Project = this.sequelize.define('Project', { title: DataTypes.STRING });

    Project.hasMany(User);
    User.hasMany(Project);

    return this.sequelize.sync({ force: true }).then(function() {
      return User.bulkCreate([{
        username: 'leia'
      }, {
        username: 'vader'
      }]).then(function() {
        return Project.bulkCreate([{
          title: 'republic'
        },{
          title: 'empire'
        }]).then(function() {
          return User.find(1).then(function(user) {
            return Project.find(1).then(function(project) {
              return user.setProjects([project]).then(function() {
                return User.find(2).then(function(user) {
                  return Project.find(2).then(function(project) {
                    return user.setProjects([project]).then(function() {
                      return User.findAll({
                        include: [
                          {model: Project, where: {title: 'republic'}}
                        ]
                      }).then(function(users) {
                        expect(users.length).to.be.equal(1);
                        expect(users[0].username).to.be.equal('leia');
                      });
                    });
                  });
                });
              });
            });
          });
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>// article api

var
    async = require('async'),
    api = require('../api'),
    db = require('../db'),
    utils = require('./_utils'),
    images = require('./_images'),
    constants = require('../constants');

var
    commentApi = require('./commentApi'),
    attachmentApi = require('./attachmentApi'),
    checkAttachment = attachmentApi.checkAttachment,
    createAttachmentTaskInTx = attachmentApi.createAttachmentTaskInTx;

var
    User = db.user,
    Article = db.article,
    Category = db.category,
    Text = db.text,
    warp = db.warp,
    next_id = db.next_id;

function getRecentArticles(max, callback) {
    var now = Date.now();
    Article.findAll({
        where: 'publish_at<?',
        order: 'publish_at desc',
        params: [now],
        offset: 0,
        limit: max
    }, function(err, entities) {
        if (err) {
            return callback(err);
        }
        return callback(null, entities);
    });
}

function doGetArticles(page, countOptions, findOptions, callback) {
    Article.findNumber(countOptions, function(err, num) {
        if (err) {
            return callback(err);
        }
        page.totalItems = num;
        if (page.isEmpty) {
            return callback(null, { page: page, articles: [] });
        }
        findOptions.offset = page.offset;
        findOptions.limit = page.limit;
        Article.findAll(findOptions, function(err, entities) {
            if (err) {
                return callback(err);
            }
            return callback(null, {
                page: page,
                articles: entities
            });
        });
    });
}

function getAllArticles(page, callback) {
    var countOptions = 'count(*)';
    var findOptions = {
        order: 'publish_at desc'
    };
    doGetArticles(page, countOptions, findOptions, callback);
}

function getArticlesByCategory(page, categoryId, callback) {
    var now = Date.now();
    var countOptions = {
        select: 'count(*)',
        where: 'publish_at<? and category_id=?',
        params: [now, categoryId]
    };
    var findOptions = {
        order: 'publish_at desc',
        where: 'publish_at<? and category_id=?',
        params: [now, categoryId]
    };
    doGetArticles(page, countOptions, findOptions, callback);
}

function getArticles(page, callback) {
    var now = Date.now();
    var countOptions = {
        select: 'count(*)',
        where: 'publish_at<?',
        params: [now]
    };
    var findOptions = {
        where: 'publish_at<?',
        params: [now]
    };
    doGetArticles(page, countOptions, findOptions, callback);
}

function getArticle(id, tx, callback) {
    if (arguments.length===2) {
        callback = tx;
        tx = undefined;
    }
    Article.find(id, function(err, article) {
        if (err) {
            return callback(err);
        }
        if (article===null) {
            return callback(api.notFound('Article'));
        }
        Text.find(article.content_id, function(err, text) {
            if (err) {
                return callback(err);
            }
            if (text===null) {
                return callback(api.notFound('Text'));
            }
            article.content = text.value;
            callback(null, article);
        });
    });
}

var RE_TIMESTAMP = /^\-?[0-9]{1,13}$/;

exports = module.exports = {

    getRecentArticles: getRecentArticles,

    getArticlesByCategory: getArticlesByCategory,

    getAllArticles: getAllArticles,

    getArticles: getArticles,

    getArticle: getArticle,

    'GET /api/articles/:id': function(req, res, next) {
        getArticle(req.params.id, function(err, article) {
            if (err) {
                return next(err);
            }
            return res.send(article);
        });
    },

    'GET /api/articles': function(req, res, next) {
        var page = utils.getPage(req);
        getArticles(page, function(err, articles) {
            if (err) {
                return next(err);
            }
            return res.send(articles);
        });
    },

    'POST /api/articles': function(req, res, next) {
        /**
         * Create a new article.
         *
         * @return {object} The created article object.
         */
        if (utils.isForbidden(req, constants.ROLE_EDITOR)) {
            return next(api.notAllowed('Permission denied.'));
        }
        try {
            var name = utils.getRequiredParam('name', req),
                category_id = utils.getRequiredParam('category_id', req),
                content = utils.getRequiredParam('content', req);
        }
        catch (e) {
            return next(e);
        }
        var description = utils.getParam('description', '', req),
            tags = utils.formatTags(utils.getParam('tags', '', req)),
            publish_at = utils.getParam('publish_at', null, req);

        var file = req.files && req.files.file;

        if (publish_at!==null) {
            if ( ! RE_TIMESTAMP.test(publish_at)) {
                return next(api.invalidParam('publish_at'));
            }
            publish_at = parseInt(publish_at);
        }
        else {
            publish_at = Date.now();
        }

        var content_id = next_id();
        var article_id = next_id();

        var fnCreate = function(fileObject) {
            warp.transaction(function(err, tx) {
                if (err) {
                    return next(err);
                }
                async.waterfall([
                    // check category:
                    function(callback) {
                        Category.find(category_id, tx, callback);
                    },
                    // create text:
                    function(category, callback) {
                        if (category===null) {
                            return callback(api.invalidParam('category_id'));
                        }
                        Text.create({
                            id: content_id,
                            ref_id: article_id,
                            value: content
                        }, tx, callback);
                    },
                    // create attachment:
                    function(text, callback) {
                        if (fileObject) {
                            var fn = createAttachmentTaskInTx(fileObject, tx, req.user.id);
                            return fn(callback);
                        }
                        callback(null, null);
                    },
                    // create article:
                    function(atta, callback) {
                        Article.create({
                            id: article_id,
                            user_id: req.user.id,
                            user_name: req.user.name,
                            category_id: category_id,
                            cover_id: atta===null ? '' : atta.id,
                            content_id: content_id,
                            name: name,
                            tags: tags,
                            description: description,
                            publish_at: publish_at
                        }, tx, callback);
                    }
                ], function(err, result) {
                    tx.done(err, function(err) {
                        if (err) {
                            return next(err);
                        }
                        result.content = content;
                        return res.send(result);
                    });
                });
            });
        };

        if (file) {
            return checkAttachment(file, true, function(err, attachFileObject) {
                if (err) {
                    return next(err);
                }
                // override name:
                attachFileObject.name = name;
                fnCreate(attachFileObject);
            });
        }
        return fnCreate(null);
    },

    'POST /api/articles/:id': function(req, res, next) {
        /**
         * Update an article.
         *
         * @return {object} The updated article object.
         */
        if (utils.isForbidden(req, constants.ROLE_EDITOR)) {
            return next(api.notAllowed('Permission denied.'));
        }
        var name = utils.getParam('name', req),
            category_id = utils.getParam('category_id', req),
            description = utils.getParam('description', req),
            tags = utils.getParam('tags', req),
            publish_at = utils.getParam('publish_at', req),
            content = utils.getParam('content', req);

        if (name!==null && name==='') {
            return next(api.invalidParam('name'));
        }
        if (category_id!==null && category_id==='') {
            return next(api.invalidParam('category_id'));
        }
        if (content!==null && content==='') {
            return next(api.invalidParam('content'));
        }
        if (publish_at!==null) {
            if (! RE_TIMESTAMP.test(publish_at)) {
                return next(api.invalidParam('publish_at'));
            }
            publish_at = parseInt(publish_at);
        }
        if (tags!==null) {
            tags = utils.formatTags(tags);
        }

        var file = req.files && req.files.file;

        var fnUpdate = function(fileObject) {
            warp.transaction(function(err, tx) {
                if (err) {
                    return next(err);
                }
                async.waterfall([
                    // query article:
                    function(callback) {
                        Article.find(req.params.id, tx, callback);
                    },
                    // update category?
                    function(article, callback) {
                        if (article===null) {
                            return callback(api.notFound('Article'));
                        }
                        if (req.user.role!==constants.ROLE_ADMIN && req.user.id!==article.user_id) {
                            return next(api.notAllowed('Permission denied.'));
                        }
                        if (category_id===null || category_id===article.category_id) {
                            return callback(null, article);
                        }
                        Category.find(category_id, tx, function(err, category) {
                            if (err) {
                                return callback(err);
                            }
                            if (category===null) {
                                return callback(api.invalidParam('category_id'));
                            }
                            article.category_id = category_id;
                            callback(null, article);
                        });
                    },
                    // update text?
                    function(article, callback) {
                        if (content===null) {
                            return callback(null, article);
                        }
                        var content_id = next_id();
                        Text.create({
                            id: content_id,
                            ref_id: article.id,
                            value: content
                        }, tx, function(err, text) {
                            if (err) {
                                return callback(err);
                            }
                            article.content_id = content_id;
                            callback(null, article);
                        });
                    },
                    // update cover?
                    function(article, callback) {
                        if (fileObject) {
                            var fn = createAttachmentTaskInTx(fileObject, tx, req.user.id);
                            return fn(function(err, atta) {
                                if (err) {
                                    return callback(err);
                                }
                                article.cover_id = atta.id;
                                callback(null, article);
                            });
                        }
                        callback(null, article);
                    },
                    // update article:
                    function(article, callback) {
                        if (name!==null) {
                            article.name = name;
                        }
                        if (description!==null) {
                            article.description = description;
                        }
                        if (tags!==null) {
                            article.tags = tags;
                        }
                        if (publish_at!==null) {
                            article.publish_at = publish_at;
                        }
                        article.update(tx, callback);
                    }
                ], function(err, result) {
                    tx.done(err, function(err) {
                        if (err) {
                            return next(err);
                        }
                        if (content!==null) {
                            result.content = content;
                            return res.send(result);
                        }
                        Text.find(result.content_id, function(err, text) {
                            if (err) {
                                return next(err);
                            }
                            result.content = text.value;
                            return res.send(result);
                        });
                    });
                });
            });
        };

        if (file) {
            return checkAttachment(file, true, function(err, attachFileObject) {
                if (err) {
                    return next(err);
                }
                // override name:
                attachFileObject.name = name;
                fnUpdate(attachFileObject);
            });
        }
        return fnUpdate(null);
    },

    'POST /api/articles/:id/comments': function(req, res, next) {
        /**
         * Create a comment on an article.
         *
         * @return {object} The created comment object.
         */
        if (utils.isForbidden(req, constants.ROLE_SUBSCRIBER)) {
            return next(api.notAllowed('Permission denied.'));
        }
        try {
            var content = utils.getRequiredParam('content', req);
        }
        catch (e) {
            return next(e);
        }
        Article.find(req.params.id, function(err, article) {
            if (err) {
                return next(err);
            }
            commentApi.createComment('article', article.id, req.user, content, function(err, c) {
                if (err) {
                    return next(err);
                }
                return res.send(c);
            });
        });
    },

    'POST /api/articles/:id/delete': function(req, res, next) {
        /**
         * Delete an article by its id.
         *
         * @param {string} :id - The id of the article.
         * @return {object} Results contains deleted id. e.g. {"id": "12345"}
         */
        if (utils.isForbidden(req, constants.ROLE_EDITOR)) {
            return next(api.notAllowed('Permission denied.'));
        }
        warp.transaction(function(err, tx) {
            if (err) {
                return next(err);
            }
            async.waterfall([
                function(callback) {
                    Article.find(req.params.id, tx, callback);
                },
                function(article, callback) {
                    if (article===null) {
                        return callback(api.notFound('Article'));
                    }
                    if (req.user.role!==constants.ROLE_ADMIN && req.user.id!==article.user_id) {
                        return next(api.notAllowed('Permission denied.'));
                    }
                    article.destroy(tx, callback);
                },
                function(r, callback) {
                    // delete all texts:
                    warp.update('delete from texts where ref_id=?', [req.params.id], tx, callback);
                }
            ], function(err, result) {
                tx.done(err, function(err) {
                    if (err) {
                        return next(err);
                    }
                    res.send({ id: req.params.id });
                });
            });
        });
    }
}
<commit_msg>add api doc<commit_after>// article api

var
    async = require('async'),
    api = require('../api'),
    db = require('../db'),
    utils = require('./_utils'),
    images = require('./_images'),
    constants = require('../constants');

var
    commentApi = require('./commentApi'),
    attachmentApi = require('./attachmentApi'),
    checkAttachment = attachmentApi.checkAttachment,
    createAttachmentTaskInTx = attachmentApi.createAttachmentTaskInTx;

var
    User = db.user,
    Article = db.article,
    Category = db.category,
    Text = db.text,
    warp = db.warp,
    next_id = db.next_id;

function getRecentArticles(max, callback) {
    var now = Date.now();
    Article.findAll({
        where: 'publish_at<?',
        order: 'publish_at desc',
        params: [now],
        offset: 0,
        limit: max
    }, function(err, entities) {
        if (err) {
            return callback(err);
        }
        return callback(null, entities);
    });
}

function doGetArticles(page, countOptions, findOptions, callback) {
    Article.findNumber(countOptions, function(err, num) {
        if (err) {
            return callback(err);
        }
        page.totalItems = num;
        if (page.isEmpty) {
            return callback(null, { page: page, articles: [] });
        }
        findOptions.offset = page.offset;
        findOptions.limit = page.limit;
        Article.findAll(findOptions, function(err, entities) {
            if (err) {
                return callback(err);
            }
            return callback(null, {
                page: page,
                articles: entities
            });
        });
    });
}

function getAllArticles(page, callback) {
    var countOptions = 'count(*)';
    var findOptions = {
        order: 'publish_at desc'
    };
    doGetArticles(page, countOptions, findOptions, callback);
}

function getArticlesByCategory(page, categoryId, callback) {
    var now = Date.now();
    var countOptions = {
        select: 'count(*)',
        where: 'publish_at<? and category_id=?',
        params: [now, categoryId]
    };
    var findOptions = {
        order: 'publish_at desc',
        where: 'publish_at<? and category_id=?',
        params: [now, categoryId]
    };
    doGetArticles(page, countOptions, findOptions, callback);
}

function getArticles(page, callback) {
    var now = Date.now();
    var countOptions = {
        select: 'count(*)',
        where: 'publish_at<?',
        params: [now]
    };
    var findOptions = {
        where: 'publish_at<?',
        params: [now]
    };
    doGetArticles(page, countOptions, findOptions, callback);
}

function getArticle(id, tx, callback) {
    if (arguments.length===2) {
        callback = tx;
        tx = undefined;
    }
    Article.find(id, function(err, article) {
        if (err) {
            return callback(err);
        }
        if (article===null) {
            return callback(api.notFound('Article'));
        }
        Text.find(article.content_id, function(err, text) {
            if (err) {
                return callback(err);
            }
            if (text===null) {
                return callback(api.notFound('Text'));
            }
            article.content = text.value;
            callback(null, article);
        });
    });
}

var RE_TIMESTAMP = /^\-?[0-9]{1,13}$/;

exports = module.exports = {

    getRecentArticles: getRecentArticles,

    getArticlesByCategory: getArticlesByCategory,

    getAllArticles: getAllArticles,

    getArticles: getArticles,

    getArticle: getArticle,

    'GET /api/articles/:id': function(req, res, next) {
        /**
         * Get article.
         *
         * @name Get Article
         * @param {string} id: Id of the article.
         * @return {object} Article object.
         * @error {resource:notfound} Article not found by id.
         */
        getArticle(req.params.id, function(err, article) {
            if (err) {
                return next(err);
            }
            return res.send(article);
        });
    },

    'GET /api/articles': function(req, res, next) {
        /**
         * Get articles by page.
         *
         * @name Get Articles
         * @param {number} [page=1]: The page number, starts from 1.
         * @return {object} Article objects and page information.
         */
        var page = utils.getPage(req);
        getArticles(page, function(err, articles) {
            if (err) {
                return next(err);
            }
            return res.send(articles);
        });
    },

    'POST /api/articles': function(req, res, next) {
        /**
         * Create a new article.
         *
         * @name Create Article
         * @param {string} category_id: Id of the category that article belongs to.
         * @param {string} name: Name of the article.
         * @param {string} description: Description of the article.
         * @param {string} content: Content of the article.
         * @param {string} [tags]: Tags of the article, seperated by ','.
         * @param {string} [publish_at]: Publish time of the article with format 'yyyy-MM-dd HH:mm:ss', default to current time.
         * @return {object} The created article object.
         * @error {parameter:invalid} If some parameter is invalid.
         * @error {permission:denied} If current user has no permission.
         */
        if (utils.isForbidden(req, constants.ROLE_EDITOR)) {
            return next(api.notAllowed('Permission denied.'));
        }
        try {
            var
                name = utils.getRequiredParam('name', req),
                description = utils.getRequiredParam('description', req),
                category_id = utils.getRequiredParam('category_id', req),
                content = utils.getRequiredParam('content', req);
        }
        catch (e) {
            return next(e);
        }
        var
            tags = utils.formatTags(utils.getParam('tags', '', req)),
            publish_at = utils.getParam('publish_at', null, req);

        var file = req.files && req.files.file;

        if (publish_at!==null) {
            if ( ! RE_TIMESTAMP.test(publish_at)) {
                return next(api.invalidParam('publish_at'));
            }
            publish_at = parseInt(publish_at);
        }
        else {
            publish_at = Date.now();
        }

        var content_id = next_id();
        var article_id = next_id();

        var fnCreate = function(fileObject) {
            warp.transaction(function(err, tx) {
                if (err) {
                    return next(err);
                }
                async.waterfall([
                    // check category:
                    function(callback) {
                        Category.find(category_id, tx, callback);
                    },
                    // create text:
                    function(category, callback) {
                        if (category===null) {
                            return callback(api.invalidParam('category_id'));
                        }
                        Text.create({
                            id: content_id,
                            ref_id: article_id,
                            value: content
                        }, tx, callback);
                    },
                    // create attachment:
                    function(text, callback) {
                        if (fileObject) {
                            var fn = createAttachmentTaskInTx(fileObject, tx, req.user.id);
                            return fn(callback);
                        }
                        callback(null, null);
                    },
                    // create article:
                    function(atta, callback) {
                        Article.create({
                            id: article_id,
                            user_id: req.user.id,
                            user_name: req.user.name,
                            category_id: category_id,
                            cover_id: atta===null ? '' : atta.id,
                            content_id: content_id,
                            name: name,
                            tags: tags,
                            description: description,
                            publish_at: publish_at
                        }, tx, callback);
                    }
                ], function(err, result) {
                    tx.done(err, function(err) {
                        if (err) {
                            return next(err);
                        }
                        result.content = content;
                        return res.send(result);
                    });
                });
            });
        };

        if (file) {
            return checkAttachment(file, true, function(err, attachFileObject) {
                if (err) {
                    return next(err);
                }
                // override name:
                attachFileObject.name = name;
                fnCreate(attachFileObject);
            });
        }
        return fnCreate(null);
    },

    'POST /api/articles/:id': function(req, res, next) {
        /**
         * Update an exist article.
         *
         * @name Update Article
         * @param {string} id: Id of the article.
         * @param {string} [category_id]: Id of the category that article belongs to.
         * @param {string} [name]: Name of the article.
         * @param {string} [description]: Description of the article.
         * @param {string} [content]: Content of the article.
         * @param {string} [tags]: Tags of the article, seperated by ','.
         * @param {string} [publish_at]: Publish time of the article with format 'yyyy-MM-dd HH:mm:ss'.
         * @return {object} The updated article object.
         * @error {resource:notfound} Article not found by id.
         * @error {parameter:invalid} If some parameter is invalid.
         * @error {permission:denied} If current user has no permission.
         */
        if (utils.isForbidden(req, constants.ROLE_EDITOR)) {
            return next(api.notAllowed('Permission denied.'));
        }
        var name = utils.getParam('name', req),
            category_id = utils.getParam('category_id', req),
            description = utils.getParam('description', req),
            tags = utils.getParam('tags', req),
            publish_at = utils.getParam('publish_at', req),
            content = utils.getParam('content', req);

        if (name!==null && name==='') {
            return next(api.invalidParam('name'));
        }
        if (category_id!==null && category_id==='') {
            return next(api.invalidParam('category_id'));
        }
        if (content!==null && content==='') {
            return next(api.invalidParam('content'));
        }
        if (publish_at!==null) {
            if (! RE_TIMESTAMP.test(publish_at)) {
                return next(api.invalidParam('publish_at'));
            }
            publish_at = parseInt(publish_at);
        }
        if (tags!==null) {
            tags = utils.formatTags(tags);
        }

        var file = req.files && req.files.file;

        var fnUpdate = function(fileObject) {
            warp.transaction(function(err, tx) {
                if (err) {
                    return next(err);
                }
                async.waterfall([
                    // query article:
                    function(callback) {
                        Article.find(req.params.id, tx, callback);
                    },
                    // update category?
                    function(article, callback) {
                        if (article===null) {
                            return callback(api.notFound('Article'));
                        }
                        if (req.user.role!==constants.ROLE_ADMIN && req.user.id!==article.user_id) {
                            return next(api.notAllowed('Permission denied.'));
                        }
                        if (category_id===null || category_id===article.category_id) {
                            return callback(null, article);
                        }
                        Category.find(category_id, tx, function(err, category) {
                            if (err) {
                                return callback(err);
                            }
                            if (category===null) {
                                return callback(api.invalidParam('category_id'));
                            }
                            article.category_id = category_id;
                            callback(null, article);
                        });
                    },
                    // update text?
                    function(article, callback) {
                        if (content===null) {
                            return callback(null, article);
                        }
                        var content_id = next_id();
                        Text.create({
                            id: content_id,
                            ref_id: article.id,
                            value: content
                        }, tx, function(err, text) {
                            if (err) {
                                return callback(err);
                            }
                            article.content_id = content_id;
                            callback(null, article);
                        });
                    },
                    // update cover?
                    function(article, callback) {
                        if (fileObject) {
                            var fn = createAttachmentTaskInTx(fileObject, tx, req.user.id);
                            return fn(function(err, atta) {
                                if (err) {
                                    return callback(err);
                                }
                                article.cover_id = atta.id;
                                callback(null, article);
                            });
                        }
                        callback(null, article);
                    },
                    // update article:
                    function(article, callback) {
                        if (name!==null) {
                            article.name = name;
                        }
                        if (description!==null) {
                            article.description = description;
                        }
                        if (tags!==null) {
                            article.tags = tags;
                        }
                        if (publish_at!==null) {
                            article.publish_at = publish_at;
                        }
                        article.update(tx, callback);
                    }
                ], function(err, result) {
                    tx.done(err, function(err) {
                        if (err) {
                            return next(err);
                        }
                        if (content!==null) {
                            result.content = content;
                            return res.send(result);
                        }
                        Text.find(result.content_id, function(err, text) {
                            if (err) {
                                return next(err);
                            }
                            result.content = text.value;
                            return res.send(result);
                        });
                    });
                });
            });
        };

        if (file) {
            return checkAttachment(file, true, function(err, attachFileObject) {
                if (err) {
                    return next(err);
                }
                // override name:
                attachFileObject.name = name;
                fnUpdate(attachFileObject);
            });
        }
        return fnUpdate(null);
    },

    'POST /api/articles/:id/comments': function(req, res, next) {
        /**
         * Create a comment on an article.
         *
         * @name Comment Article
         * @param {string} id: Id of the article.
         * @param {string} [content]: Content of the comment.
         * @return {object} The comment object.
         * @error {resource:notfound} Article not found by id.
         * @error {parameter:invalid} If some parameter is invalid.
         * @error {permission:denied} If current user has no permission.
         */
        if (utils.isForbidden(req, constants.ROLE_SUBSCRIBER)) {
            return next(api.notAllowed('Permission denied.'));
        }
        try {
            var content = utils.getRequiredParam('content', req);
        }
        catch (e) {
            return next(e);
        }
        Article.find(req.params.id, function(err, article) {
            if (err) {
                return next(err);
            }
            commentApi.createComment('article', article.id, req.user, content, function(err, c) {
                if (err) {
                    return next(err);
                }
                return res.send(c);
            });
        });
    },

    'POST /api/articles/:id/delete': function(req, res, next) {
        /**
         * Delete an article.
         *
         * @name Delete Article
         * @param {string} id: Id of the article.
         * @return {object} Object contains deleted id.
         * @error {resource:notfound} Article not found by id.
         * @error {permission:denied} If current user has no permission.
         */
        if (utils.isForbidden(req, constants.ROLE_EDITOR)) {
            return next(api.notAllowed('Permission denied.'));
        }
        warp.transaction(function(err, tx) {
            if (err) {
                return next(err);
            }
            async.waterfall([
                function(callback) {
                    Article.find(req.params.id, tx, callback);
                },
                function(article, callback) {
                    if (article===null) {
                        return callback(api.notFound('Article'));
                    }
                    if (req.user.role!==constants.ROLE_ADMIN && req.user.id!==article.user_id) {
                        return next(api.notAllowed('Permission denied.'));
                    }
                    article.destroy(tx, callback);
                },
                function(r, callback) {
                    // delete all texts:
                    warp.update('delete from texts where ref_id=?', [req.params.id], tx, callback);
                }
            ], function(err, result) {
                tx.done(err, function(err) {
                    if (err) {
                        return next(err);
                    }
                    res.send({ id: req.params.id });
                });
            });
        });
    }
}
<|endoftext|>


<commit_before>/* global require */
'use strict';
var _ = require('lodash'),
	child_process = require('child_process'),
	gutil = require('gulp-util'),
	PluginError = gutil.PluginError,
	es = require('event-stream'),
	path = require('path'),
	temp = require('temp'),
	fs = require('fs'),
	teamcity = require('./lib/teamcity'),

	PLUGIN_NAME = 'gulp-nunit-runner',
	NUNIT_CONSOLE = 'nunit-console.exe',
	NUNIT_X86_CONSOLE = 'nunit-console-x86.exe',

	runner;

// Main entry point
runner = function gulpNunitRunner(opts) {
	var stream,
		files;
	opts = opts || {};

	files = [];

	stream = es.through(function write(file) {
		if (_.isUndefined(file)) {
			fail(this, 'File may not be null.');
		}

		files.push(file);
		this.emit('data', file);
	}, function end() {
		run(this, files, opts);
	});

	return stream;
};

runner.getExecutable = function (options) {
	var executable,
		consoleRunner;
	consoleRunner = options.platform === 'x86' ? NUNIT_X86_CONSOLE : NUNIT_CONSOLE;
	if (!options.executable) {
		return consoleRunner;
	}
	// trim any existing surrounding quotes and then wrap in ""
	executable = trim(options.executable, '\\s', '"', "'");
	return !path.extname(options.executable) ?
		path.join(executable, consoleRunner) : executable;
};

runner.getArguments = function (options, assemblies) {
	var args = [];

	if (options.options) {
		args = args.concat(parseSwitches(options.options));
	}
	args = args.concat(assemblies);

	return args;
};

function parseSwitches(options) {
	var filtered,
		switches,
		isWin = /^win/.test(process.platform),
	// when running under mono on linux/mac switches must be specified with a - not a /
		switchChar = isWin ? '/' : '-';

	switches = _.map(options, function (val, key) {
		var qualifier;
		if (typeof val === 'boolean') {
			if (val) {
				return (switchChar + key);
			}
			return undefined;
		}
		if (typeof val === 'string') {
			qualifier = val.trim().indexOf(' ') > -1 ? '"' : '';
			return (switchChar + key + ':' + qualifier + val + qualifier);
		}
		if (val instanceof Array) {
			return (switchChar + key + ':' + val.join(','));
		}
	});

	filtered = _.filter(switches, function (val) {
		return !_.isUndefined(val);
	});

	return filtered;
}

function fail(stream, msg) {
	stream.emit('error', new gutil.PluginError(PLUGIN_NAME, msg));
}

function end(stream) {
	stream.emit('end');
}

function run(stream, files, options) {

	var child,
		args,
		exe,
		opts,
		assemblies,
		cleanupTempFiles;

	options.options = options.options || {};

	if (!options.options.result && options.teamcity) {
		temp.track();
		options.options.result = temp.path({suffix: '.xml'});
		cleanupTempFiles = temp.cleanup;
	}

	assemblies = files.map(function (file) {
		return file.path;
	});

	if (assemblies.length === 0) {
		return fail(stream, 'Some assemblies required.'); //<-- See what I did there ;)
	}

	opts = {
		stdio: [process.stdin, process.stdout, process.stderr, 'pipe']
	};

	exe = runner.getExecutable(options);
	args = runner.getArguments(options, assemblies);

	child = child_process.spawn(exe, args, opts);

	child.on('error', function (e) {
		fail(stream, e.code === 'ENOENT' ? 'Unable to find \'' + exe + '\'.' : e.message);
	});

	child.on('close', function (code) {
		if (options.teamcity) {
			gutil.log.apply(null, teamcity(fs.readFileSync(options.options.result, 'utf8')));
		}
		if (cleanupTempFiles) {
			cleanupTempFiles();
		}
		if (code !== 0) {
			gutil.log(gutil.colors.red('NUnit tests failed.'));
			fail(stream, 'NUnit tests failed.');
		} else {
			gutil.log(gutil.colors.cyan('NUnit tests passed'));
		}
		return end(stream);
	});
}

function trim() {
	var args = Array.prototype.slice.call(arguments),
		source = args[0],
		replacements = args.slice(1).join(','),
		regex = new RegExp("^[" + replacements + "]+|[" + replacements + "]+$", "g");
	return source.replace(regex, '');
}

module.exports = runner;
<commit_msg>Set stdin option to null for child_process.spawn<commit_after>/* global require */
'use strict';
var _ = require('lodash'),
	child_process = require('child_process'),
	gutil = require('gulp-util'),
	PluginError = gutil.PluginError,
	es = require('event-stream'),
	path = require('path'),
	temp = require('temp'),
	fs = require('fs'),
	teamcity = require('./lib/teamcity'),

	PLUGIN_NAME = 'gulp-nunit-runner',
	NUNIT_CONSOLE = 'nunit-console.exe',
	NUNIT_X86_CONSOLE = 'nunit-console-x86.exe',

	runner;

// Main entry point
runner = function gulpNunitRunner(opts) {
	var stream,
		files;
	opts = opts || {};

	files = [];

	stream = es.through(function write(file) {
		if (_.isUndefined(file)) {
			fail(this, 'File may not be null.');
		}

		files.push(file);
		this.emit('data', file);
	}, function end() {
		run(this, files, opts);
	});

	return stream;
};

runner.getExecutable = function (options) {
	var executable,
		consoleRunner;
	consoleRunner = options.platform === 'x86' ? NUNIT_X86_CONSOLE : NUNIT_CONSOLE;
	if (!options.executable) {
		return consoleRunner;
	}
	// trim any existing surrounding quotes and then wrap in ""
	executable = trim(options.executable, '\\s', '"', "'");
	return !path.extname(options.executable) ?
		path.join(executable, consoleRunner) : executable;
};

runner.getArguments = function (options, assemblies) {
	var args = [];

	if (options.options) {
		args = args.concat(parseSwitches(options.options));
	}
	args = args.concat(assemblies);

	return args;
};

function parseSwitches(options) {
	var filtered,
		switches,
		isWin = /^win/.test(process.platform),
	// when running under mono on linux/mac switches must be specified with a - not a /
		switchChar = isWin ? '/' : '-';

	switches = _.map(options, function (val, key) {
		var qualifier;
		if (typeof val === 'boolean') {
			if (val) {
				return (switchChar + key);
			}
			return undefined;
		}
		if (typeof val === 'string') {
			qualifier = val.trim().indexOf(' ') > -1 ? '"' : '';
			return (switchChar + key + ':' + qualifier + val + qualifier);
		}
		if (val instanceof Array) {
			return (switchChar + key + ':' + val.join(','));
		}
	});

	filtered = _.filter(switches, function (val) {
		return !_.isUndefined(val);
	});

	return filtered;
}

function fail(stream, msg) {
	stream.emit('error', new gutil.PluginError(PLUGIN_NAME, msg));
}

function end(stream) {
	stream.emit('end');
}

function run(stream, files, options) {

	var child,
		args,
		exe,
		opts,
		assemblies,
		cleanupTempFiles;

	options.options = options.options || {};

	if (!options.options.result && options.teamcity) {
		temp.track();
		options.options.result = temp.path({suffix: '.xml'});
		cleanupTempFiles = temp.cleanup;
	}

	assemblies = files.map(function (file) {
		return file.path;
	});

	if (assemblies.length === 0) {
		return fail(stream, 'Some assemblies required.'); //<-- See what I did there ;)
	}

	opts = {
		stdio: [null, process.stdout, process.stderr, 'pipe']
	};

	exe = runner.getExecutable(options);
	args = runner.getArguments(options, assemblies);

	child = child_process.spawn(exe, args, opts);

	child.on('error', function (e) {
		fail(stream, e.code === 'ENOENT' ? 'Unable to find \'' + exe + '\'.' : e.message);
	});

	child.on('close', function (code) {
		if (options.teamcity) {
			gutil.log.apply(null, teamcity(fs.readFileSync(options.options.result, 'utf8')));
		}
		if (cleanupTempFiles) {
			cleanupTempFiles();
		}
		if (code !== 0) {
			gutil.log(gutil.colors.red('NUnit tests failed.'));
			fail(stream, 'NUnit tests failed.');
		} else {
			gutil.log(gutil.colors.cyan('NUnit tests passed'));
		}
		return end(stream);
	});
}

function trim() {
	var args = Array.prototype.slice.call(arguments),
		source = args[0],
		replacements = args.slice(1).join(','),
		regex = new RegExp("^[" + replacements + "]+|[" + replacements + "]+$", "g");
	return source.replace(regex, '');
}

module.exports = runner;
<|endoftext|>


<commit_before>var express    = require('express'),
    controller = express.Router(),
    mongoose   = require('mongoose'),
    Attendance = require('../models/Attendance'),
    path       = require('path');

controller.route('/new')
  .post(function(req, res, next) {
    console.log(req.body);
    var attendanceData = {
      type: req.body.type,
      date: Date.now(),
      user: req.body.user,
      location: req.body.location
    }

    var message;
    var beginningOfToday = new Date().setHours(0, 0, 0, 0);
    var endOfToday = new Date().setHours(23, 59, 59, 999);

    console.log('begin', beginningOfToday);
    console.log('end', endOfToday);

    Attendance.create(attendanceData)
      .then(function(err, attendance) {
        return Attendance.find({ "date" : { "$gte": beginningOfToday, "$lt": endOfToday },
                                 "type" : req.body.type,
                                 "location" : req.body.location,
                                 "user" : req.body.user });
      })
      .then(function(dates) {
        console.log(dates);
        message = 'Success!  New attendance created.';
        res.json({
          message: message,
          attendance: dates
        });
      });
  })

controller.route('/all')
  .get(function(req, res, next) {
    Attendance.find(function(err, attends) {
      if (err) console.log(err);
      else res.json(attends);
    })
  })

controller.route('/reports')
  .get(function(req, res, next) {
    // console.log(path.dirname() + '../');
    res.sendFile(path.join(__dirname, '../views/reports.html'));
  })

controller.route('/buttons')
  .get(function(req, res, next) {
    res.sendFile(path.join(__dirname, '../views/buttons.html'));
  })

module.exports = controller;
<commit_msg>Set up email sender.<commit_after>var express    = require('express'),
    controller = express.Router(),
    mongoose   = require('mongoose'),
    Attendance = require('../models/Attendance'),
    path       = require('path'),
    nodemailer = require('nodemailer');

controller.route('/new')
  .post(function(req, res, next) {
    console.log(req.body);
    var attendanceData = {
      type: req.body.type,
      date: Date.now(),
      user: req.body.user,
      location: req.body.location
    }

    var message;
    var beginningOfToday = new Date().setHours(0, 0, 0, 0);
    var endOfToday = new Date().setHours(23, 59, 59, 999);

    console.log('begin', beginningOfToday);
    console.log('end', endOfToday);

    Attendance.create(attendanceData)
      .then(function(err, attendance) {
        return Attendance.find({ "date" : { "$gte": beginningOfToday, "$lt": endOfToday },
                                 "type" : req.body.type,
                                 "location" : req.body.location,
                                 "user" : req.body.user });
      })
      .then(function(dates) {
        console.log(dates);
        message = 'Success!  New attendance created.';
        res.json({
          message: message,
          attendance: dates
        });
      });
  })

controller.route('/all')
  .get(function(req, res, next) {
    var smtpConfig = {
      host: 'smtp.gmail.com',
      port: 465,
      secure: true, // use SSL
      auth: {
          user: 'user@gmail.com',
          pass: 'pass'
      }
    };
    var transporter = nodemailer.createTransport('smtps://' + process.env.EMAIL + '%40gmail.com:' + process.env.EMAILPWD + '@smtp.gmail.com');
    var mailOptions = {
      from: 'Art Museum Attendance',
      to: 'dmtopp@gmail.com',
      subject: 'Test mail',
      text: 'Attached is the art musuem attendance for the last week.  Cheers!'
    }

    transporter.sendMail(mailOptions, function(error, info) {
      if (error) console.log(error);
      else console.log(info);
    });

    Attendance.find(function(err, attends) {
      if (err) console.log(err);
      else res.json(attends);
    })
  })

controller.route('/reports')
  .get(function(req, res, next) {
    res.sendFile(path.join(__dirname, '../views/reports.html'));
  })

controller.route('/buttons')
  .get(function(req, res, next) {
    res.sendFile(path.join(__dirname, '../views/buttons.html'));
  })

module.exports = controller;
<|endoftext|>


<commit_before>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow strict-local
 */

import React from 'react';
import type {Node} from 'react';
import {
  SafeAreaView,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  useColorScheme,
  View,
} from 'react-native';

import {
  Colors,
  DebugInstructions,
  Header,
  LearnMoreLinks,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';

const Section = ({children, title}): Node => {
  const isDarkMode = useColorScheme() === 'dark';
  return (
    <View style={styles.sectionContainer}>
      <Text
        style={[
          styles.sectionTitle,
          {
            color: isDarkMode ? Colors.white : Colors.black,
          },
        ]}>
        {title}
      </Text>
      <Text
        style={[
          styles.sectionDescription,
          {
            color: isDarkMode ? Colors.light : Colors.dark,
          },
        ]}>
        {children}
      </Text>
    </View>
  );
};

const App: () => Node = () => {
  const isDarkMode = useColorScheme() === 'dark';

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };

  return (
    <SafeAreaView style={backgroundStyle}>
      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
      <ScrollView
        contentInsetAdjustmentBehavior="automatic"
        style={backgroundStyle}>

        <View
          style={{
            backgroundColor: isDarkMode ? Colors.black : Colors.white,
          }}>

            Edit <Text style={styles.highlight}>App.js</Text> to change this
            screen and then come back to see your edits.

            <ReloadInstructions />

            <DebugInstructions />

            Read the docs to discover what to do next:

          <LearnMoreLinks />
        </View>
      </ScrollView>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  sectionContainer: {
    marginTop: 32,
    paddingHorizontal: 24,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: '600',
  },
  sectionDescription: {
    marginTop: 8,
    fontSize: 18,
    fontWeight: '400',
  },
  highlight: {
    fontWeight: '700',
  },
});

export default App;
<commit_msg>Copy App.js from existing fixture<commit_after>import React from 'react';
import Bugsnag from "@bugsnag/react-native";
import {
  SafeAreaView,
  StyleSheet,
  ScrollView,
  View,
  Text,
  StatusBar,
  Button, NativeModules
} from 'react-native';

import {
  Colors
} from 'react-native/Libraries/NewAppScreen';

function jsNotify() {
  try { // execute crashy code
    iMadeThisUp();
  } catch (error) {
    console.log('Bugsnag.notify JS error')
    Bugsnag.notify(error);
  }
}

function nativeNotify() {
  console.log('Bugsnag.notify native error')
  NativeModules.CrashyCrashy.handledError()
}

const App: () => React$Node = () => {
  return (
    <>
      <StatusBar barStyle="dark-content" />
      <SafeAreaView>
        <ScrollView
          contentInsetAdjustmentBehavior="automatic"
          style={styles.scrollView}>
          {global.HermesInternal == null ? null : (
            <View style={styles.engine}>
              <Text style={styles.footer}>Engine: Hermes</Text>
            </View>
          )}
          <View style={styles.body}>
            <Text>React Native CLI end-to-end test app</Text>
            <Button style={styles.clickyButton}
                    accessibilityLabel='js_notify'
                    title='JS Notify'
                    onPress={jsNotify}/>
            <Button style={styles.clickyButton}
                    accessibilityLabel='native_notify'
                    title='Native Notify'
                    onPress={nativeNotify}/>
          </View>
        </ScrollView>
      </SafeAreaView>
    </>
  );
};

const styles = StyleSheet.create({
  scrollView: {
    backgroundColor: Colors.lighter,
  },
  engine: {
    position: 'absolute',
    right: 0,
  },
  body: {
    backgroundColor: Colors.white,
  },
  sectionContainer: {
    marginTop: 32,
    paddingHorizontal: 24,
  },
  sectionTitle: {
    fontSize: 24,
    fontWeight: '600',
    color: Colors.black,
  },
  sectionDescription: {
    marginTop: 8,
    fontSize: 18,
    fontWeight: '400',
    color: Colors.dark,
  },
  highlight: {
    fontWeight: '700',
  },
  footer: {
    color: Colors.dark,
    fontSize: 12,
    fontWeight: '600',
    padding: 4,
    paddingRight: 12,
    textAlign: 'right',
  },
  clickyButton: {
    backgroundColor: '#acbcef',
    borderWidth: 0.5,
    borderColor: '#000',
    borderRadius: 4,
    margin: 5,
    padding: 5
  }
});

export default App;
<|endoftext|>


<commit_before>var path = require('path');
var ps = require('ps-node');
var apps = require('./apps.js');

process.env = require('../process.env.json');

(() => {
    var os = require('os');
    if(os.hostname().indexOf('xmer') !== -1) {
        // Determine if it's my test server or not
        process.env.port = 8080;
    }
})();

module.export = (() => {
    var express = require('express'),
        app = express();

    console.log(process.env.dndImageLocation);
    app.use(process.env.dndImageLocation, express.static(path.join(__dirname + '/../bots/files'),{
        index: true,
        extensions: ['jpg', 'jpeg', 'JPG', 'JPEG', 'png', 'PNG', 'gif', 'GIF', 'webp', 'html']
    }));
    app.use('/public', express.static(path.join(__dirname + '/.public'),{
        index: false,
        extensions: ['js', 'html']
    }));

    app.get('/', (req, res) => {
       res.sendFile(path.join(__dirname + '/index.html'));
    });

    app.listen(process.env.port);
    console.log(`website listening on port ${process.env.port}`);
})();<commit_msg>changed static true to false<commit_after>var path = require('path');
var ps = require('ps-node');
var apps = require('./apps.js');

process.env = require('../process.env.json');

(() => {
    var os = require('os');
    if(os.hostname().indexOf('xmer') !== -1) {
        // Determine if it's my test server or not
        process.env.port = 8080;
    }
})();

module.export = (() => {
    var express = require('express'),
        app = express();

    app.use(process.env.dndImageLocation, express.static(path.join(__dirname + '/../bots/files'),{
        index: false,
        extensions: ['jpg', 'jpeg', 'JPG', 'JPEG', 'png', 'PNG', 'gif', 'GIF', 'webp', 'html']
    }));
    app.use('/public', express.static(path.join(__dirname + '/.public'),{
        index: false,
        extensions: ['js', 'html']
    }));

    app.get('/', (req, res) => {
       res.sendFile(path.join(__dirname + '/index.html'));
    });

    app.listen(process.env.port);
    console.log(`website listening on port ${process.env.port}`);
})();<|endoftext|>


<commit_before>var levelup = require('levelup')
var sublevel = require('sublevelup')
var transaction = require('level-transactions')
var ginga = require('ginga')
var xtend = require('xtend')
var H = require('highland')
// var iterate = require('./iterate')
// var through = require('through2')
var inherits = require('util').inherits
var EventEmitter = require('events').EventEmitter

var END = '\uffff'

var defaults = {
  db: process.browser ? require('leveldown') : require('level-js'),
  fields: { '*': true }
}
var override = {
  keyEncoding: 'utf8',
  valueEncoding: 'json'
}

// ginga params middleware
function params () {
  var names = Array.prototype.slice.call(arguments)
  var len = names.length
  return function (ctx) {
    var l = Math.min(ctx.args.length, len)
    for (var i = 0; i < l; i++) ctx[names[i]] = ctx.args[i]
  }
}

function countTokens (tokens) {
  var counts = {}
  tokens.forEach(function (token) {
    counts[token] = (counts[token] || 0) + 1
  })
  return counts
}

function Levi (dir, opts) {
  if (!(this instanceof Levi)) return new Levi(dir, opts)
  opts = xtend(defaults, opts, override)

  var db = typeof dir === 'string' ?
    sublevel(levelup(dir, opts)) :
    sublevel(dir, opts)

  this.options = db.options

  // store: key -> value
  // tokens: key -> tokens
  // term frequency: token!key -> tf
  this.store = db
  this.meta = db.sublevel('meta')
  this.tokens = db.sublevel('tokens')
  this.tf = db.sublevel('tf')

  EventEmitter.call(this)
  this.setMaxListeners(Infinity)
}

// Pipeline plugins
Levi.tokenizer = require('./tokenizer')
Levi.stemmer = require('./stemmer')
Levi.stopword = require('./stopword')

inherits(Levi, EventEmitter)
Levi.fn = ginga(Levi.prototype)

Levi.fn.define('get', params('key'), function (ctx, done) {
  this.store.get(ctx.key, done)
})

Levi.fn.define('pipeline', params('value'), function (ctx, done) {
  if (!ctx.tokens) {
    return done(new Error('Missing tokenization pipeline.'))
  }
  H(ctx.tokens).collect().pull(done)
})

// preparation on put or del index
function pre (ctx, next) {
  ctx.options = xtend(this.options, ctx.options)
  ctx.tx = transaction(this.store)
  ctx.on('end', function (err) {
    if (err) ctx.tx.rollback(err)
  })

  if (
    ctx.key === '' ||
    ctx.key === null ||
    ctx.key === undefined
  ) return next(new Error('Key required.'))
  ctx.key = String(ctx.key)

  next()
}

// clean up old index
function clean (ctx, next) {
  var self = this
  ctx.tx.get(ctx.key, function (err, value) {
    if (err && !err.notFound) return next(err)
    // skip if not exists
    if (!value) return next()
    if (!ctx.value) ctx.value = value
    // del store item
    ctx.tx.del(ctx.key)
    // decrement size
    ctx.tx.get('size', { prefix: self.meta }, function (err, size) {
      // size must be gt 0 here
      ctx.tx.put('size', size - 1, { prefix: self.meta })
    })
    // delete all tfs that contains key
    ctx.tx.get(ctx.key, { prefix: self.tokens }, function (err, tokens) {
      if (err) return next(err)
      tokens.forEach(function (token) {
        ctx.tx.del(token + '!' + ctx.key, { prefix: self.tf })
      })
      next()
    })
  })
}

// put new index
function index (ctx, next) {
  var self = this
  if (!ctx.value) return next(new Error('Value required.'))

  // increment size
  ctx.tx.get('size', { prefix: self.meta }, function (err, size) {
    ctx.tx.put('size', (size || 0) + 1, { prefix: self.meta })
  })
  // put store item
  ctx.tx.put(ctx.key, ctx.value)

  if (typeof ctx.value === 'string') {
    // string value pipeline no fields
    this.pipeline(ctx.value, function (err, tokens) {
      if (err) return next(err)
      var total = tokens.length
      var counts = countTokens(tokens)
      for (var token in counts) {
        // put tfs
        ctx.tx.put(
          token + '!' + ctx.key,
          counts[token] / total,
          { prefix: self.tf }
        )
      }
      // put tokens
      ctx.tx.put(
        ctx.key,
        Object.keys(counts),
        { prefix: self.tokens }
      )
      next()
    })
  } else {
    // field based pipeline
    var fields = ctx.options.fields
    var tfs = {}
    H(Object.keys(ctx.value))
    .map(function (field) {
      return {
        name: field,
        value: ctx.value[field],
        boost: Number(fields[field] || fields['*'])
      }
    })
    .filter(function (field) {
      return field.boost
    })
    .map(H.wrapCallback(function (field, cb) {
      self.pipeline(field.value, function (err, tokens) {
        if (err) return cb(err)
        var total = tokens.length
        var counts = countTokens(tokens)
        var boost = field.boost
        for (var token in counts) {
          tfs[token] = (tfs[token] || 0) + (counts[token] / total * boost)
        }
        cb(null, field.name)
      })
    }))
    .series()
    .collect()
    .pull(function (err, fields) {
      if (err) return next(err)
      for (var token in tfs) {
        // put tfs
        ctx.tx.put(token + '!' + ctx.key, tfs[token], { prefix: self.tf })
      }
      // put tokens
      ctx.tx.put(ctx.key, Object.keys(tfs), { prefix: self.tokens })
      next()
    })
  }
}

// commit index write
function write (ctx, done) {
  ctx.tx.commit(done)
}

Levi.fn.define('del', params('key', 'options'), pre, clean, write)
Levi.fn.define('put', params('key', 'value', 'options'), pre, clean, index, write)
Levi.fn.define('index', params('key', 'options'), pre, clean, index, write)

Levi.fn.define('rebuildIndex', function (ctx, done) {
  // todo stream through store and .index(key)
})

Levi.fn.createSearchStream =
Levi.fn.searchStream = function (q, opts) {
  opts = xtend(this.options, opts)
  var self = this
  var offset = Number(opts.offset) > 0 ? opts.offset : 0
  var limit = Number(opts.limit) > 0 ? opts.limit : Infinity
  var values = opts.values !== false

  H(function (push, next) {
    // pipeline query
    self.pipeline(q, function (err, tokens) {
      if (err) return push(err)
      next(H(tokens))
    })
  })
  .map(function (token) {
    return H(self.tf.createReadStream({
      gt: token + '!',
      lt: token + '!' + END
    }))
  })
  .reduce1() // todo union and idf
  .series()
  .sortBy(function (a, b) {
    return b.score - a.score
  })
  .drop(offset)
  .take(limit)
  .map(H.wrapCallback(function (doc, cb) {
    if (values) {
      self.get(doc.key, function (err, val) {
        if (err) return cb(err)
        doc.value = val
        cb(null, doc)
      })
    } else {
      cb(null, doc)
    }
  }))
}

Levi.fn.createLiveStream =
Levi.fn.liveStream = function (q, opts) {
  opts = xtend(this.options, opts)
}

module.exports = Levi
<commit_msg>prepare tfidf<commit_after>var levelup = require('levelup')
var sublevel = require('sublevelup')
var transaction = require('level-transactions')
var ginga = require('ginga')
var xtend = require('xtend')
var H = require('highland')
// var iterate = require('./iterate')
// var through = require('through2')
var inherits = require('util').inherits
var EventEmitter = require('events').EventEmitter

var END = '\uffff'

var defaults = {
  db: process.browser ? require('leveldown') : require('level-js'),
  fields: { '*': true }
}
var override = {
  keyEncoding: 'utf8',
  valueEncoding: 'json'
}

// ginga params middleware
function params () {
  var names = Array.prototype.slice.call(arguments)
  var len = names.length
  return function (ctx) {
    var l = Math.min(ctx.args.length, len)
    for (var i = 0; i < l; i++) ctx[names[i]] = ctx.args[i]
  }
}

function countTokens (tokens) {
  var counts = {}
  tokens.forEach(function (token) {
    counts[token] = (counts[token] || 0) + 1
  })
  return counts
}

function Levi (dir, opts) {
  if (!(this instanceof Levi)) return new Levi(dir, opts)
  opts = xtend(defaults, opts, override)

  var db = typeof dir === 'string' ?
    sublevel(levelup(dir, opts)) :
    sublevel(dir, opts)

  this.options = db.options

  // store: key -> value
  // tokens: key -> tokens
  // tfidf: token -> idf
  // tfidf: token!key -> tf
  this.store = db
  this.meta = db.sublevel('meta')
  this.tokens = db.sublevel('tokens')
  this.tfidf = db.sublevel('tfidf')

  EventEmitter.call(this)
  this.setMaxListeners(Infinity)
}

// Pipeline plugins
Levi.tokenizer = require('./tokenizer')
Levi.stemmer = require('./stemmer')
Levi.stopword = require('./stopword')

inherits(Levi, EventEmitter)
Levi.fn = ginga(Levi.prototype)

Levi.fn.define('get', params('key'), function (ctx, done) {
  this.store.get(ctx.key, done)
})

Levi.fn.define('pipeline', params('value'), function (ctx, done) {
  if (!ctx.tokens) {
    return done(new Error('Missing tokenization pipeline.'))
  }
  H(ctx.tokens).collect().pull(done)
})

// prepare transaction and checks
function pre (ctx, next) {
  ctx.options = xtend(this.options, ctx.options)
  ctx.tx = transaction(this.store)
  ctx.on('end', function (err) {
    if (err) ctx.tx.rollback(err)
  })

  if (
    ctx.key === '' ||
    ctx.key === null ||
    ctx.key === undefined
  ) return next(new Error('Key required.'))
  ctx.key = String(ctx.key)

  next()
}

// clean up old index
function del (ctx, next) {
  var self = this
  ctx.tx.get(ctx.key, function (err, value) {
    if (err && !err.notFound) return next(err)
    // skip if not exists
    if (!value) return next()
    // keep value if reindexing
    if (!ctx.value) ctx.value = value
    // del store item
    ctx.tx.del(ctx.key)
    // decrement size
    ctx.tx.get('size', { prefix: self.meta }, function (err, size) {
      // size must be gt 0 here
      ctx.tx.put('size', size - 1, { prefix: self.meta })
    })
    // delete all tfs that contains key
    ctx.tx.get(ctx.key, { prefix: self.tokens }, function (err, tokens) {
      if (err) return next(err)
      tokens.forEach(function (token) {
        ctx.tx.del(token + '!' + ctx.key, { prefix: self.tfidf })
      })
      next()
    })
  })
}

// put new index
function put (ctx, next) {
  var self = this
  if (!ctx.value) return next(new Error('Value required.'))

  // increment size
  ctx.tx.get('size', { prefix: self.meta }, function (err, size) {
    ctx.tx.put('size', (size || 0) + 1, { prefix: self.meta })
  })
  // put store item
  ctx.tx.put(ctx.key, ctx.value)

  if (typeof ctx.value === 'string') {
    // string value pipeline no fields
    this.pipeline(ctx.value, function (err, tokens) {
      if (err) return next(err)
      var total = tokens.length
      var counts = countTokens(tokens)
      for (var token in counts) {
        // put tfs
        ctx.tx.put(
          token + '!' + ctx.key,
          counts[token] / total,
          { prefix: self.tfidf }
        )
      }
      // put tokens
      ctx.tx.put(
        ctx.key,
        Object.keys(counts),
        { prefix: self.tokens }
      )
      next()
    })
  } else {
    // field based pipeline
    var fields = ctx.options.fields
    var tfs = {}
    H(Object.keys(ctx.value))
    .map(function (field) {
      return {
        name: field,
        value: ctx.value[field],
        boost: Number(fields[field] || fields['*'])
      }
    })
    .filter(function (field) {
      return field.boost
    })
    .map(H.wrapCallback(function (field, cb) {
      self.pipeline(field.value, function (err, tokens) {
        if (err) return cb(err)
        var total = tokens.length
        var counts = countTokens(tokens)
        var boost = field.boost
        for (var token in counts) {
          tfs[token] = (tfs[token] || 0) + (counts[token] / total * boost)
        }
        cb(null, field.name)
      })
    }))
    .series()
    .collect()
    .pull(function (err, fields) {
      if (err) return next(err)
      for (var token in tfs) {
        // put tfs
        ctx.tx.put(token + '!' + ctx.key, tfs[token], { prefix: self.tfidf })
      }
      // put tokens
      ctx.tx.put(ctx.key, Object.keys(tfs), { prefix: self.tokens })
      next()
    })
  }
}

// commit index write
function write (ctx, done) {
  ctx.tx.commit(done)
}

Levi.fn.define('del', params('key', 'options'), pre, del, write)
Levi.fn.define('put', params('key', 'value', 'options'), pre, del, put, write)
Levi.fn.define('index', params('key', 'options'), pre, del, put, write)

Levi.fn.define('rebuildIndex', function (ctx, done) {
  // todo stream through store and .index(key)
})

Levi.fn.createSearchStream =
Levi.fn.searchStream = function (q, opts) {
  opts = xtend(this.options, opts)
  var self = this
  var offset = Number(opts.offset) > 0 ? opts.offset : 0
  var limit = Number(opts.limit) > 0 ? opts.limit : Infinity
  var values = opts.values !== false

  H(function (push, next) {
    // pipeline query
    self.pipeline(q, function (err, tokens) {
      if (err) return push(err)
      next(H(tokens))
    })
  })
  .map(function (token) {
    return H(self.tfidf.createReadStream({
      gt: token + '!',
      lt: token + '!' + END
    }))
  })
  .reduce1() // todo union and idf
  .series()
  .sortBy(function (a, b) {
    return b.score - a.score
  })
  .drop(offset)
  .take(limit)
  .map(H.wrapCallback(function (doc, cb) {
    if (values) {
      self.get(doc.key, function (err, val) {
        if (err) return cb(err)
        doc.value = val
        cb(null, doc)
      })
    } else {
      cb(null, doc)
    }
  }))
}

Levi.fn.createLiveStream =
Levi.fn.liveStream = function (q, opts) {
  opts = xtend(this.options, opts)
}

module.exports = Levi
<|endoftext|>


<commit_before>var Challenge = require('../models/challenge');
var Category = require('../models/category');
var User = require('../models/user');

module.exports = {

  //POST /challenges
  createChallenge: function(req, res, next) {
    var body = req.body;

    Category.findById(body.categoryId, function(err, category) {
      if (err) throw err;
      User.findById(body.ownerId, function(err, owner) {
        if (err) throw err;
        var newChallenge = Challenge({
          description: body.description,
          category: category,
          ownerId: body.ownerId,
          state: "open",
          startDate: new Date(),
          endDate: new Date(body.endDate),
          location: owner.location,
          data: body.data
        });
        owner.challenges.published.push(newChallenge);
        owner.save(function(err){
          if (err) throw err;
          newChallenge.save(function(err) {
            if (err) throw err;
            res.send('Challenge: ' + body.description + ' has been created!');
          });
        });
      });
    });
  },

  // GET /challenges
  getChallenges: function(req, res, next) {
    Challenge.find({},function (err, challenges) {
      if (err) throw err;
      res.status(200).json(challenges);
    });
  },

  // GET /challenges/:id
  getChallenge: function(req, res, next) {
    Challenge.findById(req.params.id,function (err, challenge) {
      if (err) throw err;
      res.status(200).json(challenge);
    });
  },

  // DELETE /challenges/:id
  deleteChallenge: function(req, res, next) {
    Challenge.findByIdAndRemove(req.params.id, function(err) {
      if (err) throw err;
      res.sendStatus(204);
    });
  },

  //POST /challenges/:id/action/:action[{lock|complete}]
  applyActionToChallenge: function(req, res, next) {
    switch (req.params.action) {
      case "lock":
        //get the challenge
        Challenge.findById(req.params.id,function (err, challenge) {
          if (err) throw err;
          // update the challenge copy state and save
          challenge.state = "locked";
          challenge.lockerId = req.body.lockerId;
          challenge.save(function(err){
            if (err) throw err;
            // update the owner's copy
            User.findById(challenge.ownerId, function(err, owner) {
              if (err) throw err;
              var published = owner.challenges.published;
              for (var i = 0; i < published.length; i++) {
                if (published[i]._id == req.params.id) {
                  published.splice(i,1,challenge);
                  break;
                }
              }
              owner.save(function(err){
                if (err) throw err;
                // create the locker's copy in "active" challenges
                User.findById(req.body.lockerId, function(err, locker) {
                  if (err) throw err;
                  locker.challenges.active.push(challenge);
                  locker.save(function(err){
                    if (err) throw err;
                    res.sendStatus(200);
                  });
                });
              });
            });
          });
        });
        break;
      case "complete":
        //get the challenge
        Challenge.findById(req.params.id,function (err, challenge) {
          if (err) throw err;
          // update the challenge copy state and save
          challenge.state = "completed";
          challenge.save(function(err){
            if (err) throw err;
            // update the owner's copy
            User.findById(challenge.ownerId, function(err, owner) {
              if (err) throw err;
              var published = owner.challenges.published;
              for (var i = 0, len = published.length; i < len; i++) {
                if (published[i]._id == req.params.id) {
                  published.splice(i,1,challenge);
                  break;
                }
              }
              owner.save(function(err){
                if (err) throw err;
                // create the locker's copy in "active" challenges
                User.findById(challenge.lockerId, function(err, locker) {
                  if (err) throw err;
                  var activeChallenges = locker.challenges.active;
                  for (var i = 0, len = activeChallenges.length; i < len; i++) {
                    if (activeChallenges[i]._id == req.params.id) {
                      activeChallenges.splice(i,1);
                      break;
                    }
                  }
                  locker.challenges.completed.push(challenge);
                  locker.save(function(err){
                    if (err) throw err;
                    //TODO add awards thing!
                    res.sendStatus(200);
                  });
                });
              });
            });
          });
        });
        break;
      default:
        res.sendStatus(400);
        break;
    }
  }

};
<commit_msg>unfinished work - end of the hackathon<commit_after>var Challenge = require('../models/challenge');
var Category = require('../models/category');
var User = require('../models/user');
var Award = require('../models/award');

function awardUser(user) {
  Award.find({},function (err, awards){
    if (err) throw err;
    for (var i = 0; i < awards.length; i++) {
      //TODO
    }
  });
}

module.exports = {

  //POST /challenges
  createChallenge: function(req, res, next) {
    var body = req.body;

    Category.findById(body.categoryId, function(err, category) {
      if (err) throw err;
      User.findById(body.ownerId, function(err, owner) {
        if (err) throw err;
        var newChallenge = Challenge({
          description: body.description,
          category: category,
          ownerId: body.ownerId,
          state: "open",
          startDate: new Date(),
          endDate: new Date(body.endDate),
          location: owner.location,
          data: body.data
        });
        owner.challenges.published.push(newChallenge);
        owner.save(function(err){
          if (err) throw err;
          newChallenge.save(function(err) {
            if (err) throw err;
            res.send('Challenge: ' + body.description + ' has been created!');
          });
        });
      });
    });
  },

  // GET /challenges
  getChallenges: function(req, res, next) {
    Challenge.find({},function (err, challenges) {
      if (err) throw err;
      res.status(200).json(challenges);
    });
  },

  // GET /challenges/:id
  getChallenge: function(req, res, next) {
    Challenge.findById(req.params.id,function (err, challenge) {
      if (err) throw err;
      res.status(200).json(challenge);
    });
  },

  // DELETE /challenges/:id
  deleteChallenge: function(req, res, next) {
    Challenge.findByIdAndRemove(req.params.id, function(err) {
      if (err) throw err;
      res.sendStatus(204);
    });
  },

  //POST /challenges/:id/action/:action[{lock|complete}]
  applyActionToChallenge: function(req, res, next) {
    switch (req.params.action) {
      case "lock":
        //get the challenge
        Challenge.findById(req.params.id,function (err, challenge) {
          if (err) throw err;
          // update the challenge copy state and save
          challenge.state = "locked";
          challenge.lockerId = req.body.lockerId;
          challenge.save(function(err){
            if (err) throw err;
            // update the owner's copy
            User.findById(challenge.ownerId, function(err, owner) {
              if (err) throw err;
              var published = owner.challenges.published;
              for (var i = 0; i < published.length; i++) {
                if (published[i]._id == req.params.id) {
                  published.splice(i,1,challenge);
                  break;
                }
              }
              owner.save(function(err){
                if (err) throw err;
                // create the locker's copy in "active" challenges
                User.findById(req.body.lockerId, function(err, locker) {
                  if (err) throw err;
                  locker.challenges.active.push(challenge);
                  locker.save(function(err){
                    if (err) throw err;
                    res.sendStatus(200);
                  });
                });
              });
            });
          });
        });
        break;
      case "complete":
        //get the challenge
        Challenge.findById(req.params.id,function (err, challenge) {
          if (err) throw err;
          // update the challenge copy state and save
          challenge.state = "completed";
          challenge.save(function(err){
            if (err) throw err;
            // update the owner's copy
            User.findById(challenge.ownerId, function(err, owner) {
              if (err) throw err;
              var published = owner.challenges.published;
              for (var i = 0, len = published.length; i < len; i++) {
                if (published[i]._id == req.params.id) {
                  published.splice(i,1,challenge);
                  break;
                }
              }
              owner.save(function(err){
                if (err) throw err;
                // create the locker's copy in "active" challenges
                User.findById(challenge.lockerId, function(err, locker) {
                  if (err) throw err;
                  var activeChallenges = locker.challenges.active;
                  for (var i = 0, len = activeChallenges.length; i < len; i++) {
                    if (activeChallenges[i]._id == req.params.id) {
                      activeChallenges.splice(i,1);
                      break;
                    }
                  }
                  locker.challenges.completed.push(challenge);
                  //TODO awardUser(locker); // add awards as needed
                  locker.save(function(err){
                    if (err) throw err;
                    res.sendStatus(200);
                  });
                });
              });
            });
          });
        });
        break;
      default:
        res.sendStatus(400);
        break;
    }
  }

};
<|endoftext|>