<commit_before>/**
 * Module dependencies.
 */
var http = require('http')
  , AuthenticationError = require('../errors/authenticationerror');

/**
 * Authenticates requests.
 *
 * Applies the `name`ed strategy (or strategies) to the incoming request, in
 * order to authenticate the request.  If authentication is successful, the user
 * will be logged in and populated at `req.user` and a session will be
 * established by default.  If authentication fails, an unauthorized response
 * will be sent.
 *
 * Options:
 *   - `session`          Save login state in session, defaults to _true_
 *   - `successRedirect`  After successful login, redirect to given URL
 *   - `failureRedirect`  After failed login, redirect to given URL
 *   - `assignProperty`   Assign the object provided by the verify callback to given property
 *
 * An optional `callback` can be supplied to allow the application to overrride
 * the default manner in which authentication attempts are handled.  The
 * callback has the following signature, where `user` will be set to the
 * authenticated user on a successful authentication attempt, or `false`
 * otherwise.  An optional `info` argument will be passed, containing additional
 * details provided by the strategy's verify callback.
 *
 *     app.get('/protected', function(req, res, next) {
 *       passport.authenticate('local', function(err, user, info) {
 *         if (err) { return next(err) }
 *         if (!user) { return res.redirect('/signin') }
 *         res.redirect('/account');
 *       })(req, res, next);
 *     });
 *
 * Note that if a callback is supplied, it becomes the application's
 * responsibility to log-in the user, establish a session, and otherwise perform
 * the desired operations.
 *
 * Examples:
 *
 *     passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' });
 *
 *     passport.authenticate('basic', { session: false });
 *
 *     passport.authenticate('twitter');
 *
 * @param {String|Array} name
 * @param {Object} options
 * @param {Function} callback
 * @return {Function}
 * @api public
 */
module.exports = function authenticate(passport, name, options, callback) {
  if (typeof options == 'function') {
    callback = options;
    options = {};
  }
  options = options || {};

  var multi = true;

  // Cast `name` to an array, allowing authentication to pass through a chain of
  // strategies.  The first strategy to succeed, redirect, or error will halt
  // the chain.  Authentication failures will proceed through each strategy in
  // series, ultimately failing if all strategies fail.
  //
  // This is typically used on API endpoints to allow clients to authenticate
  // using their preferred choice of Basic, Digest, token-based schemes, etc.
  // It is not feasible to construct a chain of multiple strategies that involve
  // redirection (for example both Facebook and Twitter), since the first one to
  // redirect will halt the chain.
  if (!Array.isArray(name)) {
    name = [ name ];
    multi = false;
  }

  return function authenticate(req, res, next) {
    // accumulator for failures from each strategy in the chain
    var failures = [];

    function allFailed() {
      if (callback) {
        if (!multi) {
          return callback(null, false, failures[0].challenge, failures[0].status);
        } else {
          var challenges = failures.map(function(f) { return f.challenge; });
          var statuses = failures.map(function(f) { return f.status; });
          return callback(null, false, challenges, statuses);
        }
      }

      // Strategies are ordered by priority.  For the purpose of flashing a
      // message, the first failure will be displayed.
      var failure = failures[0] || {}
        , challenge = failure.challenge || {}
        , msg;

      if (options.failureFlash) {
        var flash = options.failureFlash;
        if (typeof flash == 'string') {
          flash = { type: 'error', message: flash };
        }
        flash.type = flash.type || 'error';

        var type = flash.type || challenge.type || 'error';
        msg = flash.message || challenge.message || challenge;
        if (typeof msg == 'string') {
          req.flash(type, msg);
        }
      }
      if (options.failureMessage) {
        msg = options.failureMessage;
        if (typeof msg == 'boolean') {
          msg = challenge.message || challenge;
        }
        if (typeof msg == 'string') {
          req.session.messages = req.session.messages || [];
          req.session.messages.push(msg);
        }
      }
      if (options.failureRedirect) {
        return res.redirect(options.failureRedirect);
      }

      // When failure handling is not delegated to the application, the default
      // is to respond with 401 Unauthorized.  Note that the WWW-Authenticate
      // header will be set according to the strategies in use (see
      // actions#fail).  If multiple strategies failed, each of their challenges
      // will be included in the response.
      var rchallenge = []
        , rstatus, status;

      for (var j = 0, len = failures.length; j < len; j++) {
        failure = failures[j];
        challenge = failure.challenge;
        status = failure.status;

        rstatus = rstatus || status;
        if (typeof challenge == 'string') {
          rchallenge.push(challenge);
        }
      }

      res.statusCode = rstatus || 401;
      if (res.statusCode == 401 && rchallenge.length) {
        res.setHeader('WWW-Authenticate', rchallenge);
      }
      if (options.failWithError) {
        return next(new AuthenticationError(http.STATUS_CODES[res.statusCode], rstatus));
      }
      res.end(http.STATUS_CODES[res.statusCode]);
    }

    (function attempt(i) {
      var layer = name[i];
      // If no more strategies exist in the chain, authentication has failed.
      if (!layer) { return allFailed(); }

      // Get the strategy, which will be used as prototype from which to create
      // a new instance.  Action functions will then be bound to the strategy
      // within the context of the HTTP request/response pair.
      var prototype = passport._strategy(layer);
      if (!prototype) { return next(new Error('Unknown authentication strategy "' + layer + '"')); }

      var strategy = Object.create(prototype);

      // ----- BEGIN STRATEGY AUGMENTATION -----
      // Augment the new strategy instance with action functions.  These action
      // functions are bound via closure the the request/response pair.  The end
      // goal of the strategy is to invoke *one* of these action methods, in
      // order to indicate successful or failed authentication, redirect to a
      // third-party identity provider, etc.

      /**
       * Authenticate `user`, with optional `info`.
       *
       * Strategies should call this function to successfully authenticate a
       * user.  `user` should be an object supplied by the application after it
       * has been given an opportunity to verify credentials.  `info` is an
       * optional argument containing additional user information.  This is
       * useful for third-party authentication strategies to pass profile
       * details.
       *
       * @param {Object} user
       * @param {Object} info
       * @api public
       */
      strategy.success = function(user, info) {
        if (callback) {
          return callback(null, user, info);
        }

        info = info || {};
        var msg;

        if (options.successFlash) {
          var flash = options.successFlash;
          if (typeof flash == 'string') {
            flash = { type: 'success', message: flash };
          }
          flash.type = flash.type || 'success';

          var type = flash.type || info.type || 'success';
          msg = flash.message || info.message || info;
          if (typeof msg == 'string') {
            req.flash(type, msg);
          }
        }
        if (options.successMessage) {
          msg = options.successMessage;
          if (typeof msg == 'boolean') {
            msg = info.message || info;
          }
          if (typeof msg == 'string') {
            req.session.messages = req.session.messages || [];
            req.session.messages.push(msg);
          }
        }
        if (options.assignProperty) {
          req[options.assignProperty] = user;
          return next();
        }

        req.logIn(user, options, function(err) {
          if (err) { return next(err); }

          function complete() {
            if (options.successReturnToOrRedirect) {
              var url = options.successReturnToOrRedirect;
              if (req.session && req.session.returnTo) {
                url = req.session.returnTo;
                delete req.session.returnTo;
              }
              return res.redirect(url);
            }
            if (options.successRedirect) {
              return res.redirect(options.successRedirect);
            }
            next();
          }

          if (options.authInfo !== false) {
            passport.transformAuthInfo(info, req, function(err, tinfo) {
              if (err) { return next(err); }
              req.authInfo = tinfo;
              complete();
            });
          } else {
            complete();
          }
        });
      };

      /**
       * Fail authentication, with optional `challenge` and `status`, defaulting
       * to 401.
       *
       * Strategies should call this function to fail an authentication attempt.
       *
       * @param {String} challenge
       * @param {Number} status
       * @api public
       */
      strategy.fail = function(challenge, status) {
        if (typeof challenge == 'number') {
          status = challenge;
          challenge = undefined;
        }

        // push this failure into the accumulator and attempt authentication
        // using the next strategy
        failures.push({ challenge: challenge, status: status });
        attempt(i + 1);
      };

      /**
       * Redirect to `url` with optional `status`, defaulting to 302.
       *
       * Strategies should call this function to redirect the user (via their
       * user agent) to a third-party website for authentication.
       *
       * @param {String} url
       * @param {Number} status
       * @api public
       */
      strategy.redirect = function(url, status) {
        // NOTE: Do not use `res.redirect` from Express, because it can't decide
        //       what it wants.
        //
        //       Express 2.x: res.redirect(url, status)
        //       Express 3.x: res.redirect(status, url) -OR- res.redirect(url, status)
        //         - as of 3.14.0, deprecated warnings are issued if res.redirect(url, status)
        //           is used
        //       Express 4.x: res.redirect(status, url)
        //         - all versions (as of 4.8.7) continue to accept res.redirect(url, status)
        //           but issue deprecated versions

        res.statusCode = status || 302;
        res.setHeader('Location', url);
        res.setHeader('Content-Length', '0');
        res.end();
      };

      /**
       * Pass without making a success or fail decision.
       *
       * Under most circumstances, Strategies should not need to call this
       * function.  It exists primarily to allow previous authentication state
       * to be restored, for example from an HTTP session.
       *
       * @api public
       */
      strategy.pass = function() {
        next();
      };

      /**
       * Internal error while performing authentication.
       *
       * Strategies should call this function when an internal error occurs
       * during the process of performing authentication; for example, if the
       * user directory is not available.
       *
       * @param {Error} err
       * @api public
       */
      strategy.error = function(err) {
        if (callback) {
          return callback(err);
        }

        next(err);
      };

      // ----- END STRATEGY AUGMENTATION -----

      strategy.authenticate(req, options);
    })(0); // attempt
  };
};
<commit_msg>Add documentation for message and flash options<commit_after>/**
 * Module dependencies.
 */
var http = require('http')
  , AuthenticationError = require('../errors/authenticationerror');

/**
 * Authenticates requests.
 *
 * Applies the `name`ed strategy (or strategies) to the incoming request, in
 * order to authenticate the request.  If authentication is successful, the user
 * will be logged in and populated at `req.user` and a session will be
 * established by default.  If authentication fails, an unauthorized response
 * will be sent.
 *
 * Options:
 *   - `session`          Save login state in session, defaults to _true_
 *   - `successRedirect`  After successful login, redirect to given URL
 *   - `successMessage`   True to store success message in
 *                        req.session.messages, or a string to use as override
 *                        message for success.
 *   - `successFlash`     True to flash success messages or a string to use as a flash
 *                        message for success (overrides any from the strategy itself).
 *   - `failureRedirect`  After failed login, redirect to given URL
 *   - `failureMessage`   True to store failure message in
 *                        req.session.messages, or a string to use as override
 *                        message for failure.
 *   - `failureFlash`     True to flash failure messages or a string to use as a flash
 *                        message for failures (overrides any from the strategy itself).
 *   - `assignProperty`   Assign the object provided by the verify callback to given property
 *
 * An optional `callback` can be supplied to allow the application to overrride
 * the default manner in which authentication attempts are handled.  The
 * callback has the following signature, where `user` will be set to the
 * authenticated user on a successful authentication attempt, or `false`
 * otherwise.  An optional `info` argument will be passed, containing additional
 * details provided by the strategy's verify callback - this could be information about
 * a successful authentication or a challenge message for a failed authentication.
 * An optional `status` argument will be passed when authentication fails - this could
 * be a HTTP response code for a remote authentication failure or similar.
 *
 *     app.get('/protected', function(req, res, next) {
 *       passport.authenticate('local', function(err, user, info, status) {
 *         if (err) { return next(err) }
 *         if (!user) { return res.redirect('/signin') }
 *         res.redirect('/account');
 *       })(req, res, next);
 *     });
 *
 * Note that if a callback is supplied, it becomes the application's
 * responsibility to log-in the user, establish a session, and otherwise perform
 * the desired operations.
 *
 * Examples:
 *
 *     passport.authenticate('local', { successRedirect: '/', failureRedirect: '/login' });
 *
 *     passport.authenticate('basic', { session: false });
 *
 *     passport.authenticate('twitter');
 *
 * @param {String|Array} name
 * @param {Object} options
 * @param {Function} callback
 * @return {Function}
 * @api public
 */
module.exports = function authenticate(passport, name, options, callback) {
  if (typeof options == 'function') {
    callback = options;
    options = {};
  }
  options = options || {};

  var multi = true;

  // Cast `name` to an array, allowing authentication to pass through a chain of
  // strategies.  The first strategy to succeed, redirect, or error will halt
  // the chain.  Authentication failures will proceed through each strategy in
  // series, ultimately failing if all strategies fail.
  //
  // This is typically used on API endpoints to allow clients to authenticate
  // using their preferred choice of Basic, Digest, token-based schemes, etc.
  // It is not feasible to construct a chain of multiple strategies that involve
  // redirection (for example both Facebook and Twitter), since the first one to
  // redirect will halt the chain.
  if (!Array.isArray(name)) {
    name = [ name ];
    multi = false;
  }

  return function authenticate(req, res, next) {
    // accumulator for failures from each strategy in the chain
    var failures = [];

    function allFailed() {
      if (callback) {
        if (!multi) {
          return callback(null, false, failures[0].challenge, failures[0].status);
        } else {
          var challenges = failures.map(function(f) { return f.challenge; });
          var statuses = failures.map(function(f) { return f.status; });
          return callback(null, false, challenges, statuses);
        }
      }

      // Strategies are ordered by priority.  For the purpose of flashing a
      // message, the first failure will be displayed.
      var failure = failures[0] || {}
        , challenge = failure.challenge || {}
        , msg;

      if (options.failureFlash) {
        var flash = options.failureFlash;
        if (typeof flash == 'string') {
          flash = { type: 'error', message: flash };
        }
        flash.type = flash.type || 'error';

        var type = flash.type || challenge.type || 'error';
        msg = flash.message || challenge.message || challenge;
        if (typeof msg == 'string') {
          req.flash(type, msg);
        }
      }
      if (options.failureMessage) {
        msg = options.failureMessage;
        if (typeof msg == 'boolean') {
          msg = challenge.message || challenge;
        }
        if (typeof msg == 'string') {
          req.session.messages = req.session.messages || [];
          req.session.messages.push(msg);
        }
      }
      if (options.failureRedirect) {
        return res.redirect(options.failureRedirect);
      }

      // When failure handling is not delegated to the application, the default
      // is to respond with 401 Unauthorized.  Note that the WWW-Authenticate
      // header will be set according to the strategies in use (see
      // actions#fail).  If multiple strategies failed, each of their challenges
      // will be included in the response.
      var rchallenge = []
        , rstatus, status;

      for (var j = 0, len = failures.length; j < len; j++) {
        failure = failures[j];
        challenge = failure.challenge;
        status = failure.status;

        rstatus = rstatus || status;
        if (typeof challenge == 'string') {
          rchallenge.push(challenge);
        }
      }

      res.statusCode = rstatus || 401;
      if (res.statusCode == 401 && rchallenge.length) {
        res.setHeader('WWW-Authenticate', rchallenge);
      }
      if (options.failWithError) {
        return next(new AuthenticationError(http.STATUS_CODES[res.statusCode], rstatus));
      }
      res.end(http.STATUS_CODES[res.statusCode]);
    }

    (function attempt(i) {
      var layer = name[i];
      // If no more strategies exist in the chain, authentication has failed.
      if (!layer) { return allFailed(); }

      // Get the strategy, which will be used as prototype from which to create
      // a new instance.  Action functions will then be bound to the strategy
      // within the context of the HTTP request/response pair.
      var prototype = passport._strategy(layer);
      if (!prototype) { return next(new Error('Unknown authentication strategy "' + layer + '"')); }

      var strategy = Object.create(prototype);

      // ----- BEGIN STRATEGY AUGMENTATION -----
      // Augment the new strategy instance with action functions.  These action
      // functions are bound via closure the the request/response pair.  The end
      // goal of the strategy is to invoke *one* of these action methods, in
      // order to indicate successful or failed authentication, redirect to a
      // third-party identity provider, etc.

      /**
       * Authenticate `user`, with optional `info`.
       *
       * Strategies should call this function to successfully authenticate a
       * user.  `user` should be an object supplied by the application after it
       * has been given an opportunity to verify credentials.  `info` is an
       * optional argument containing additional user information.  This is
       * useful for third-party authentication strategies to pass profile
       * details.
       *
       * @param {Object} user
       * @param {Object} info
       * @api public
       */
      strategy.success = function(user, info) {
        if (callback) {
          return callback(null, user, info);
        }

        info = info || {};
        var msg;

        if (options.successFlash) {
          var flash = options.successFlash;
          if (typeof flash == 'string') {
            flash = { type: 'success', message: flash };
          }
          flash.type = flash.type || 'success';

          var type = flash.type || info.type || 'success';
          msg = flash.message || info.message || info;
          if (typeof msg == 'string') {
            req.flash(type, msg);
          }
        }
        if (options.successMessage) {
          msg = options.successMessage;
          if (typeof msg == 'boolean') {
            msg = info.message || info;
          }
          if (typeof msg == 'string') {
            req.session.messages = req.session.messages || [];
            req.session.messages.push(msg);
          }
        }
        if (options.assignProperty) {
          req[options.assignProperty] = user;
          return next();
        }

        req.logIn(user, options, function(err) {
          if (err) { return next(err); }

          function complete() {
            if (options.successReturnToOrRedirect) {
              var url = options.successReturnToOrRedirect;
              if (req.session && req.session.returnTo) {
                url = req.session.returnTo;
                delete req.session.returnTo;
              }
              return res.redirect(url);
            }
            if (options.successRedirect) {
              return res.redirect(options.successRedirect);
            }
            next();
          }

          if (options.authInfo !== false) {
            passport.transformAuthInfo(info, req, function(err, tinfo) {
              if (err) { return next(err); }
              req.authInfo = tinfo;
              complete();
            });
          } else {
            complete();
          }
        });
      };

      /**
       * Fail authentication, with optional `challenge` and `status`, defaulting
       * to 401.
       *
       * Strategies should call this function to fail an authentication attempt.
       *
       * @param {String} challenge
       * @param {Number} status
       * @api public
       */
      strategy.fail = function(challenge, status) {
        if (typeof challenge == 'number') {
          status = challenge;
          challenge = undefined;
        }

        // push this failure into the accumulator and attempt authentication
        // using the next strategy
        failures.push({ challenge: challenge, status: status });
        attempt(i + 1);
      };

      /**
       * Redirect to `url` with optional `status`, defaulting to 302.
       *
       * Strategies should call this function to redirect the user (via their
       * user agent) to a third-party website for authentication.
       *
       * @param {String} url
       * @param {Number} status
       * @api public
       */
      strategy.redirect = function(url, status) {
        // NOTE: Do not use `res.redirect` from Express, because it can't decide
        //       what it wants.
        //
        //       Express 2.x: res.redirect(url, status)
        //       Express 3.x: res.redirect(status, url) -OR- res.redirect(url, status)
        //         - as of 3.14.0, deprecated warnings are issued if res.redirect(url, status)
        //           is used
        //       Express 4.x: res.redirect(status, url)
        //         - all versions (as of 4.8.7) continue to accept res.redirect(url, status)
        //           but issue deprecated versions

        res.statusCode = status || 302;
        res.setHeader('Location', url);
        res.setHeader('Content-Length', '0');
        res.end();
      };

      /**
       * Pass without making a success or fail decision.
       *
       * Under most circumstances, Strategies should not need to call this
       * function.  It exists primarily to allow previous authentication state
       * to be restored, for example from an HTTP session.
       *
       * @api public
       */
      strategy.pass = function() {
        next();
      };

      /**
       * Internal error while performing authentication.
       *
       * Strategies should call this function when an internal error occurs
       * during the process of performing authentication; for example, if the
       * user directory is not available.
       *
       * @param {Error} err
       * @api public
       */
      strategy.error = function(err) {
        if (callback) {
          return callback(err);
        }

        next(err);
      };

      // ----- END STRATEGY AUGMENTATION -----

      strategy.authenticate(req, options);
    })(0); // attempt
  };
};
<|endoftext|>


<commit_before>var config = require('../user/config-user');

/*
 * Checks if a session exists in cache using the session token as an id and returns the session found
 *
 * @params {Object} mbaasApi object which allows access to cache
 * @params {String} sessionToken string that is used as an id for the specified session in cache.
 * @params {Function} cb function callback
 */
function checkSession(mbaasApi, sessionToken, cb) {
  var options = {
    "act": "load",
    "key": sessionToken
  };

  mbaasApi.cache(options, function(err, session) {
    return cb(err, session);
  });
}

/*
 * Saves specified session in cache
 *
 * @params {Object} mbaasApi object which allows access to cache
 * @params {String} sessionToken string that is used as an id for the specified session in cache.
 * @params {Object} session object which holds all the session details
 * @params {Function} cb function callback
 */
function saveSession(mbaasApi, sessionToken, session, cb) {

  var options = {
    "act": "save",
    "key": sessionToken,
    "expire": config.expiry || 1800,
    "value": session
  };

  mbaasApi.cache(options, function(err) {
    return cb(err, session);
  });
}

module.exports = {
  checkSession: checkSession,
  saveSession: saveSession
};<commit_msg>Stringify session before saving as redis does not support object data type<commit_after>var config = require('../user/config-user');

/*
 * Checks if a session exists in cache using the session token as an id and returns the session found
 *
 * @params {Object} mbaasApi object which allows access to cache
 * @params {String} sessionToken string that is used as an id for the specified session in cache.
 * @params {Function} cb function callback
 */
function checkSession(mbaasApi, sessionToken, cb) {
  var options = {
    "act": "load",
    "key": sessionToken
  };

  mbaasApi.cache(options, function(err, session) {
    return cb(err, JSON.parse(session));
  });
}

/*
 * Saves specified session in cache
 *
 * @params {Object} mbaasApi object which allows access to cache
 * @params {String} sessionToken string that is used as an id for the specified session in cache.
 * @params {Object} session object which holds all the session details
 * @params {Function} cb function callback
 */
function saveSession(mbaasApi, sessionToken, session, cb) {

  var options = {
    "act": "save",
    "key": sessionToken,
    "expire": config.expiry || 1800,
    "value": JSON.stringify(session)
  };

  mbaasApi.cache(options, function(err) {
    return cb(err, session);
  });
}

module.exports = {
  checkSession: checkSession,
  saveSession: saveSession
};<|endoftext|>


<commit_before>var builder = require('xmlbuilder');

/**
 * Sitemap index middleware.
 *
 * This middleware generates a sitemap index file, which is used to group
 * multiple sitemaps, informing search engines about pages on the site that are
 * available for crawling.
 *
 * While a convention has formed to use "sitemap.xml" as the name of a sitemap
 * file, no such collective agreement has formed around what to name a sitemap
 * index.  Google has published blog posts that use "sitemap_index.xml":
 *   - https://sitemaps.blogspot.com/2005/08/using-sitemap-index-files.html
 *   - https://webmasters.googleblog.com/2006/10/multiple-sitemaps-in-same-directory.html
 *
 * While there is no requirement to use any particular file name, evidence
 * indicates that the web has followed Google's example and "sitemap_index.xml"
 * occurs most commonly, followed by "sitemapindex.xml".  This research is
 * detailed in an analysis of robots.txt files performed by Intoli:
 *   - https://intoli.com/blog/analyzing-one-million-robots-txt-files/
 */
exports = module.exports = function(options) {
  options = options || {};

  return function sitemapindex(page, next) {
    page.isSitemap = true;

    var pages
      , res, smm, i, len;

    var sm = builder.create('sitemapindex', { version: '1.0', encoding: 'UTF-8' });
    sm.a('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9')

    pages = (page.locals && page.locals.sitemaps) || []

    pages = pages.filter(function(p) {
      return p.isSitemap == true && !p.isInSitemap;
    });

    for (i = 0, len = pages.length; i < len; i++) {
      res = pages[i];

      if (!res.fullURL) { return next(new Error('Unable to add "' + res.absoluteURL + '" to sitemap, set \'base url\' setting and try again')); }

      smm = sm.e('sitemap');
      smm.e('loc', res.fullURL);

      res.isInSitemap = true;
    }

    var xml = sm.end({ pretty: true });
    page.write(xml);
    page.end();
  };
};
<commit_msg>Clean up.<commit_after>var builder = require('xmlbuilder');

/**
 * Sitemap index middleware.
 *
 * This middleware generates a sitemap index file, which is used to group
 * multiple sitemaps, informing search engines about pages on the site that are
 * available for crawling.
 *
 * While a convention has formed to use "sitemap.xml" as the name of a sitemap
 * file, no such collective agreement has formed around what to name a sitemap
 * index.  Google has published blog posts that use "sitemap_index.xml":
 *   - https://sitemaps.blogspot.com/2005/08/using-sitemap-index-files.html
 *   - https://webmasters.googleblog.com/2006/10/multiple-sitemaps-in-same-directory.html
 *
 * While there is no requirement to use any particular file name, evidence
 * indicates that the web has followed Google's example and "sitemap_index.xml"
 * occurs most commonly, followed by "sitemapindex.xml".  This research is
 * detailed in an analysis of robots.txt files performed by Intoli:
 *   - https://intoli.com/blog/analyzing-one-million-robots-txt-files/
 */
exports = module.exports = function(options) {
  options = options || {};

  return function sitemapindex(page, next) {
    page.isSitemap = true;

    var index = builder.create('sitemapindex', { version: '1.0', encoding: 'UTF-8' })
      , pages = (page.locals && page.locals.sitemaps) || []
      , pg, sm, i, len;

    index.a('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9')

    for (i = 0, len = pages.length; i < len; i++) {
      pg = pages[i];

      if (pg.isInSitemap) { continue; }

      if (!pg.fullURL) { return next(new Error('Unable to add "' + pg.absoluteURL + '" to sitemap, set \'base url\' setting and try again')); }

      sm = index.e('sitemap');
      sm.e('loc', pg.fullURL);

      pg.isInSitemap = true;
    }

    var xml = index.end({ pretty: true });
    page.write(xml);
    page.end();
  };
};
<|endoftext|>


<commit_before>var {canonicalHost} = require('../../utils/host.js');
var utils = require('../../utils/utils.js');
var Server = require('./server.js');

class WebServer {

  constructor(embark, options) {
    this.embark = embark;
    this.logger = embark.logger;
    this.events = embark.events;
    this.webServerConfig = embark.config.webServerConfig;
    if (!this.webServerConfig.enabled) {
      return;
    }

    this.host = options.host || this.webServerConfig.host;
    this.port = options.port || this.webServerConfig.port;

    this.events.emit("status", __("Starting Server"));

    utils.pingEndpoint(this.host, this.port, 'http', 'http', '', (err) => {
      if (!err) { // Port already in use
        this.logger.warn(__('Webserver already running on port {{oldPort}}. Trying to connect on {{newPort}}',
          {oldPort: this.port, newPort: this.port + 1}));
        this.port++;
      }
      this.server = new Server({host: this.host, port: this.port});

      this.setServiceCheck();
      this.listenToCommands();
      this.registerConsoleCommands();
      this.server.start((_err, message) => this.logger.info(message));
    });
  }

  setServiceCheck() {
    let url = 'http://' + canonicalHost(this.host) + ':' + this.port;

    this.events.request("services:register", 'Webserver', function (cb) {
      utils.checkIsAvailable(url, function (available) {
        let devServer = __('Webserver') + ' (' + url + ')';
        let serverStatus = (available ? 'on' : 'off');
        return cb({name: devServer, status: serverStatus});
      });
    });

    this.events.on('check:wentOffline:Webserver', () => {
      this.logger.info(__("Webserver is offline"));
    });
  }

  listenToCommands() {
    this.events.setCommandHandler('start-webserver', (callback) => this.server.start(callback));
    this.events.setCommandHandler('stop-webserver',  (callback) => this.server.stop(callback));
  }

  registerConsoleCommands() {
    const self = this;
    self.embark.registerConsoleCommand((cmd, _options) => {
      return {
        match: () => cmd === "webserver start",
        process: (callback) => self.events.request("start-webserver", callback)
      };
    });

    self.embark.registerConsoleCommand((cmd, _options) => {
      return {
        match: () => cmd === "webserver stop",
        process: (callback) => self.events.request("stop-webserver", callback)
      };
    });
  }
}

module.exports = WebServer;
<commit_msg>increment port multiple times if multiple embarks<commit_after>var {canonicalHost} = require('../../utils/host.js');
var utils = require('../../utils/utils.js');
var Server = require('./server.js');

class WebServer {

  constructor(embark, options) {
    this.embark = embark;
    this.logger = embark.logger;
    this.events = embark.events;
    this.webServerConfig = embark.config.webServerConfig;
    if (!this.webServerConfig.enabled) {
      return;
    }

    this.host = options.host || this.webServerConfig.host;
    this.port = options.port || this.webServerConfig.port;

    this.events.emit("status", __("Starting Server"));

    this.testPort(() => {
      this.server = new Server({host: this.host, port: this.port});

      this.setServiceCheck();
      this.listenToCommands();
      this.registerConsoleCommands();
      this.server.start((_err, message) => this.logger.info(message));
    });
  }

  testPort(done) {
    utils.pingEndpoint(this.host, this.port, 'http', 'http', '', (err) => {
      if (err) { // Port is ok
        return done();
      }
      this.logger.warn(__('Webserver already running on port {{oldPort}}. Trying to connect on {{newPort}}',
        {oldPort: this.port, newPort: this.port + 1}));
      this.port++;
      this.testPort(done);
    });
  }

  setServiceCheck() {
    let url = 'http://' + canonicalHost(this.host) + ':' + this.port;

    this.events.request("services:register", 'Webserver', function (cb) {
      utils.checkIsAvailable(url, function (available) {
        let devServer = __('Webserver') + ' (' + url + ')';
        let serverStatus = (available ? 'on' : 'off');
        return cb({name: devServer, status: serverStatus});
      });
    });

    this.events.on('check:wentOffline:Webserver', () => {
      this.logger.info(__("Webserver is offline"));
    });
  }

  listenToCommands() {
    this.events.setCommandHandler('start-webserver', (callback) => this.server.start(callback));
    this.events.setCommandHandler('stop-webserver',  (callback) => this.server.stop(callback));
  }

  registerConsoleCommands() {
    const self = this;
    self.embark.registerConsoleCommand((cmd, _options) => {
      return {
        match: () => cmd === "webserver start",
        process: (callback) => self.events.request("start-webserver", callback)
      };
    });

    self.embark.registerConsoleCommand((cmd, _options) => {
      return {
        match: () => cmd === "webserver stop",
        process: (callback) => self.events.request("stop-webserver", callback)
      };
    });
  }
}

module.exports = WebServer;
<|endoftext|>


<commit_before>var generic_pool = require('generic-pool');
var async = require('async');
var mysql = require('db-mysql');
var _ = require('underscore');
var debug = false;

var create_pool = function(db_settings, pool_settings) {
  // Defaults.
  var db_defaults = {
    hostname: 'localhost',
    database: 'test',
    user: 'root',
  };
  _.defaults(db_settings, db_defaults);
  var pool_defaults = {
    name: 'mysql',
    max: 10,
  };
  _.defaults(pool_settings, pool_defaults);

  // create and destroy are configured internally.
  pool_settings.create = function(query_callback) {
    var db = new mysql.Database(db_settings);
    var post_connect = function(err, server) {
      query_callback(err, db);
    }
    db.connect(post_connect);
    if (debug) {
      debug_log("New connection created");
    }
  }
  pool_settings.destroy = function(db) {
    db.disconnect();
    if (debug) {
      debug_log("Connection destroyed");
    }
  }
  return generic_pool.Pool(pool_settings);
}

// Sets up query/pool methods for a pool.
var query_pool = function(pool) {

  // Processes multiple queries.
  var execute_queries = function() {
    var args = _.toArray(arguments);
    var callback = args.pop();

    // Look for any data to be passed to the query callback.
    if (!_.isFunction(_.last(args))) {
      var callback_data = args.pop();
    }

    // Called after all queries complete.
    var return_results = function(err, results) {
      if (debug) {
        debug_log("All queries complete, executing callback");
      }
      if (_.isArray(results)) {
        results.unshift(err);
      }
      else {
        results = err
      }
      callback.apply(null, results);
    }

    // Called for each query to be executed.
    var single_query = function(query_func, async_callback) {

      // Called after a resource has been acquired from the pool.
      var pool_acquired = function(err, db) {
        if (debug) {
          debug_log("Resource acquired");
        }
        if (err) {
          if (debug) {
            debug_log("Database error!");
            debug_log(err);
          }
          async_callback(err);
          return;
        }

        // Called when the query is finished.
        var execute_callback = function(err, rows, columns) {
          pool.release(db);
          if (debug) {
            debug_log("Resource released");
          }
          if (err) {
            if (debug) {
              debug_log("Query error!");
              debug_log(err);
            }
            async_callback(err);
            return;
          }
          var result = {};
          result.rows = rows;
          result.columns = columns;
          async_callback(null, result);
        }

        // The query function is given a query object, which it can use to
        // build the final query.
        var query = db.query();
        var query_func_args = [query, db];
        // Passed data is the first arg, because the others can be optional.
        if (!_.isUndefined(callback_data)) {
          query_func_args.unshift(callback_data);
        }
        var custom = query_func.apply(null, query_func_args);

        // Query built using query object.
        if (_.isUndefined(custom)) {
          if (debug) {
            debug_log("Executing query: " + query.sql());
          }
          query.execute(execute_callback);
        }
        // Returning false allows bypassing the query, pass the false along to
        // the callback.
        else if (custom === false) {
          async_callback(null, false);
        }
        // Query built with a custom query string.
        else {
          var query_string = "";
          var query_values = [];
          if (_.isString(custom)) {
            query_string = custom;
          }
          else {
            query_string = custom.shift();
            query_values = custom;
          }
          if (debug) {
            debug_log("Executing query: " + query_string + ", values: " + query_values.toString());
          }
          query.execute(query_string, query_values, execute_callback);
        }
      }
      pool.acquire(pool_acquired);
    }
    async.map(args, single_query, return_results);
  }

  // Executes passed queries in series, providing each subsequent query with
  // the previous query's results.
  var execute_query_series = function() {
    var query_args = _.toArray(arguments);
    var callback = query_args.pop();
    // Builds the waterfall function that executes an individual query.
    var waterfall_generator = function(query_func) {
      return function() {
        var args = _.toArray(arguments);
        // The function to continue the waterfall is always the last argument.
        var waterfall_callback = args.pop();
        // Results from the last query, if any.
        var last_results = args.pop();
        // Executed to collect query results, this will always be just one
        // result set since only one query is being run at a time.
        var execute_queries_callback = function(err, data) {
          // Calls the next query in the waterfall.
          waterfall_callback.call(null, err, data);
        }
        // Run one query, passing in the data array from previous queries.
        execute_queries(query_func, last_results, execute_queries_callback);
      }
    }
    // Passes the results from the last query in the waterfall to the original
    // result callback provided by the user.
    var waterfall_result_callback = function(err, data) {
      callback.call(null, err, data);
    }
    // Transform each individual query into a member of the waterfall.
    var waterfall_functions = _.map(query_args, waterfall_generator);
    async.waterfall(waterfall_functions, waterfall_result_callback)
  }

  return {
    pool: pool,
    query: execute_queries,
    querySeries: execute_query_series,
  };
}

var debug_log = function(message) {
  console.log(message);
}

var create = function(db_settings, pool_settings) {
  db_settings = _.isUndefined(db_settings) ? {} : db_settings;
  pool_settings = _.isUndefined(pool_settings) ? {} : pool_settings;
  var pool = create_pool(db_settings, pool_settings);
  if (debug) {
    debug_log("New query pool created");
  }
  return query_pool(pool);
}

var set_debug = function(value) {
  debug = value == true ? true : false;
}

exports.create = create;
exports.debug = set_debug;

<commit_msg>code comments for core lib.<commit_after>var generic_pool = require('generic-pool');
var async = require('async');
var mysql = require('db-mysql');
var _ = require('underscore');
var debug = false;

/**
 * Creates a pool of database connections.
 *
 * @param db_settings
 *   A hash of settings to pass to node-db. Any parameters accepted by the
 *   Database class are allowed.
 * @param pool_settings
 *   A hash of settings to pass to generic-pool. Any parameters accepted by the
 *   Pool class are allowed, except the create and destroy functions, which are
 *   managed internally.
 *
 * @return
 *   The configured connection pool.
 */
var create_pool = function(db_settings, pool_settings) {
  // Defaults.
  var db_defaults = {
    hostname: 'localhost',
    database: 'test',
    user: 'root',
  };
  _.defaults(db_settings, db_defaults);
  var pool_defaults = {
    name: 'mysql',
    max: 10,
  };
  _.defaults(pool_settings, pool_defaults);

  // Create and destroy are configured internally.
  pool_settings.create = function(query_callback) {
    var db = new mysql.Database(db_settings);
    var post_connect = function(err, server) {
      query_callback(err, db);
    }
    db.connect(post_connect);
    if (debug) {
      debug_log("New connection created");
    }
  }
  pool_settings.destroy = function(db) {
    db.disconnect();
    if (debug) {
      debug_log("Connection destroyed");
    }
  }
  return generic_pool.Pool(pool_settings);
}

/**
 * Sets up query/pool methods for a pool.
 *
 * @param pool
 *   A pool object as returned by create_pool().
 *
 * @return
 *   An object with the query pool and query methods.
 *
 * @see create_pool()
 */
var query_pool = function(pool) {

  /**
   * Processes multiple queries.
   */
  var execute_queries = function() {
    var args = _.toArray(arguments);

    // User-provided callback.
    var callback = args.pop();

    // Look for any data to be passed to the query callback.
    if (!_.isFunction(_.last(args))) {
      var callback_data = args.pop();
    }

    /**
     * Called after all queries complete.
     *
     * @param results
     *   An array of result objects.
     */
    var return_results = function(err, results) {
      if (debug) {
        debug_log("All queries complete, executing callback");
      }
      if (_.isArray(results)) {
        results.unshift(err);
      }
      else {
        results = err
      }
      callback.apply(null, results);
    }

    /**
     * Called for each query to be executed.
     *
     * @param query_func
     *   The user-provided query function.
     * @param async_callback
     *   The internal async callback function.
     */
    var single_query = function(query_func, async_callback) {

      /**
       * Called after a resource has been acquired from the pool.
       *
       * @param db
       *   The database object.
       */
      var pool_acquired = function(err, db) {
        if (debug) {
          debug_log("Resource acquired");
        }
        if (err) {
          if (debug) {
            debug_log("Database error!");
            debug_log(err);
          }
          async_callback(err);
          return;
        }

        /**
         * Called when the query is finished.
         *
         * @param rows
         *   An array of result objects.
         * @columns
         *   An object describing the table columns of the query.
         */
        var execute_callback = function(err, rows, columns) {
          pool.release(db);
          if (debug) {
            debug_log("Resource released");
          }
          if (err) {
            if (debug) {
              debug_log("Query error!");
              debug_log(err);
            }
            async_callback(err);
            return;
          }
          var result = {};
          result.rows = rows;
          result.columns = columns;
          async_callback(null, result);
        }

        // The query function is given a query object, which it can use to
        // build the final query.
        var query = db.query();
        var query_func_args = [query, db];
        // Passed data is the first arg, because the others can be optional.
        if (!_.isUndefined(callback_data)) {
          query_func_args.unshift(callback_data);
        }
        var custom = query_func.apply(null, query_func_args);

        // Query built using query object.
        if (_.isUndefined(custom)) {
          if (debug) {
            debug_log("Executing query: " + query.sql());
          }
          query.execute(execute_callback);
        }
        // Returning false allows bypassing the query, pass the false along to
        // the callback.
        else if (custom === false) {
          async_callback(null, false);
        }
        // Query built with a custom query string.
        else {
          var query_string = "";
          var query_values = [];
          if (_.isString(custom)) {
            query_string = custom;
          }
          else {
            query_string = custom.shift();
            query_values = custom;
          }
          if (debug) {
            debug_log("Executing query: " + query_string + ", values: " + query_values.toString());
          }
          query.execute(query_string, query_values, execute_callback);
        }
      }
      pool.acquire(pool_acquired);
    }
    async.map(args, single_query, return_results);
  }

  /**
   * Executes passed queries in series, providing each subsequent query with
   * the previous query's results.
   */
  var execute_query_series = function() {
    var query_args = _.toArray(arguments);

    // User-provided callback.
    var callback = query_args.pop();

    /**
     * Builds the waterfall function that executes an individual query.
     *
     * @param query_func
     *   A user-provided query function.
     *
     * @return
     *   The query function wrapped in an async waterfall function.
     */
    var waterfall_generator = function(query_func) {
      return function() {
        var args = _.toArray(arguments);
        // The function to continue the waterfall is always the last argument.
        var waterfall_callback = args.pop();
        // Results from the last query, if any.
        var last_results = args.pop();
        // Executed to collect query results, this will always be just one
        // result set since only one query is being run at a time.
        var execute_queries_callback = function(err, data) {
          // Calls the next query in the waterfall.
          waterfall_callback.call(null, err, data);
        }
        // Run one query, passing in the data array from previous queries.
        execute_queries(query_func, last_results, execute_queries_callback);
      }
    }

    /**
     * Passes the results from the last query in the waterfall to the original
     * result callback provided by the user.
     *
     * @param data
     *   The data result object.
     */
    var waterfall_result_callback = function(err, data) {
      callback.call(null, err, data);
    }
    // Transform each individual query into a member of the waterfall.
    var waterfall_functions = _.map(query_args, waterfall_generator);
    async.waterfall(waterfall_functions, waterfall_result_callback)
  }

  return {
    pool: pool,
    query: execute_queries,
    querySeries: execute_query_series,
  };
}

/**
 * Simple debug logging wrapper.
 *
 * @param message
 *   String of the message to output.
 */
var debug_log = function(message) {
  console.log(message);
}

/**
 * API function for creating new query pools.
 *
 * @see create_pool()
 */
var create = function(db_settings, pool_settings) {
  db_settings = _.isUndefined(db_settings) ? {} : db_settings;
  pool_settings = _.isUndefined(pool_settings) ? {} : pool_settings;
  var pool = create_pool(db_settings, pool_settings);
  if (debug) {
    debug_log("New query pool created");
  }
  return query_pool(pool);
}

/**
 * API function for enabling/disabling debugging.
 */
var set_debug = function(value) {
  debug = value == true ? true : false;
}

exports.create = create;
exports.debug = set_debug;

<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var util = require('util')
  , OpenIDStrategy = require('passport-openid').Strategy
  , SteamWebAPI = require('steam-web');

/**
 * `Strategy` constructor.
 *
 * The Steam authentication strategy authenticates requests by delegating to
 * Steam using the OpenID 2.0 protocol.
 *
 * Applications must supply a `validate` callback which accepts an `identifier`,
 * and optionally a service-specific `profile`, and then calls the `done`
 * callback supplying a `user`, which should be set to `false` if the
 * credentials are not valid.  If an exception occured, `err` should be set.
 *
 * Options:
 *   - `returnURL`  URL to which Steam will redirect the user after authentication
 *   - `realm`      the part of URL-space for which an OpenID authentication request is valid
 *   - `profile`    enable profile exchange, defaults to _true_
 *
 * Examples:
 *
 *     passport.use(new SteamStrategy({
 *         returnURL: 'http://localhost:3000/auth/steam/return',
 *         realm: 'http://localhost:3000/'
 *       },
 *       function(identifier, profile, done) {
 *         User.findByOpenID(identifier, function (err, user) {
 *           done(err, user);
 *         });
 *       }
 *     ));
 *
 * @param {Object} options
 * @param {Function} verify
 * @api public
 */
function Strategy(options, validate) {
  options = options || {};
  options.providerURL = options.providerURL || 'http://steamcommunity.com/openid';
  options.profile =  (options.profile === undefined) ? true : options.profile;
  options.stateless = true; //Steam only works as a stateless OpenID

  if(options.profile) {
    var steam = new SteamWebAPI({ apiKey: options.apiKey, format: 'json' });

    function getUserProfile() {
      var req = arguments[options.passReqToCallback ? 0 : undefined];
      var identifier = arguments[options.passReqToCallback ? 1 : 0];
      var profile = arguments[options.passReqToCallback ? 2 : 1];
      var done = arguments[options.passReqToCallback ? 3 : 2];

      steam.getPlayerSummaries({
        steamids: [ identifier ],
        callback: function(err, result) {
          profile = {
            provider: 'steam',
            _json: result.response.players[0],
            id: result.response.players[0].steamid,
            displayName: result.response.players[0].personaname,
            photos: [ { value: result.response.players[0].avatar }, { value: result.response.players[0].avatarmedium }, { value: result.response.players[0].avatarfull } ]
          };

          options.passReqToCallback ?
            validate(req, identifier, profile, done):
            validate(identifier, profile, done);
        }
      });
    }

    OpenIDStrategy.call(this, options, getUserProfile);
  } else {
    OpenIDStrategy.call(this, options, validate);
  }

  this.name = 'steam';
}

/**
 * Inherit from `OpenIDStrategy`.
 */
util.inherits(Strategy, OpenIDStrategy);

/**
 * Expose `Strategy`.
 */
module.exports = Strategy;
<commit_msg>Fix random crash<commit_after>/**
 * Module dependencies.
 */
var util = require('util')
  , OpenIDStrategy = require('passport-openid').Strategy
  , SteamWebAPI = require('steam-web');

/**
 * `Strategy` constructor.
 *
 * The Steam authentication strategy authenticates requests by delegating to
 * Steam using the OpenID 2.0 protocol.
 *
 * Applications must supply a `validate` callback which accepts an `identifier`,
 * and optionally a service-specific `profile`, and then calls the `done`
 * callback supplying a `user`, which should be set to `false` if the
 * credentials are not valid.  If an exception occured, `err` should be set.
 *
 * Options:
 *   - `returnURL`  URL to which Steam will redirect the user after authentication
 *   - `realm`      the part of URL-space for which an OpenID authentication request is valid
 *   - `profile`    enable profile exchange, defaults to _true_
 *
 * Examples:
 *
 *     passport.use(new SteamStrategy({
 *         returnURL: 'http://localhost:3000/auth/steam/return',
 *         realm: 'http://localhost:3000/'
 *       },
 *       function(identifier, profile, done) {
 *         User.findByOpenID(identifier, function (err, user) {
 *           done(err, user);
 *         });
 *       }
 *     ));
 *
 * @param {Object} options
 * @param {Function} verify
 * @api public
 */
function Strategy(options, validate) {
  options = options || {};
  options.providerURL = options.providerURL || 'http://steamcommunity.com/openid';
  options.profile =  (options.profile === undefined) ? true : options.profile;
  options.stateless = true; //Steam only works as a stateless OpenID

  if(options.profile) {
    var steam = new SteamWebAPI({ apiKey: options.apiKey, format: 'json' });

    function getUserProfile() {
      var req = arguments[options.passReqToCallback ? 0 : undefined];
      var identifier = arguments[options.passReqToCallback ? 1 : 0];
      var profile = arguments[options.passReqToCallback ? 2 : 1];
      var done = arguments[options.passReqToCallback ? 3 : 2];

      steam.getPlayerSummaries({
        steamids: [ identifier ],
        callback: function(err, result) {
          if (err) return done(err);

          profile = {
            provider: 'steam',
            _json: result.response.players[0],
            id: result.response.players[0].steamid,
            displayName: result.response.players[0].personaname,
            photos: [ { value: result.response.players[0].avatar }, { value: result.response.players[0].avatarmedium }, { value: result.response.players[0].avatarfull } ]
          };

          options.passReqToCallback ?
            validate(req, identifier, profile, done):
            validate(identifier, profile, done);
        }
      });
    }

    OpenIDStrategy.call(this, options, getUserProfile);
  } else {
    OpenIDStrategy.call(this, options, validate);
  }

  this.name = 'steam';
}

/**
 * Inherit from `OpenIDStrategy`.
 */
util.inherits(Strategy, OpenIDStrategy);

/**
 * Expose `Strategy`.
 */
module.exports = Strategy;
<|endoftext|>


<commit_before>var lazyCallback = require('sk/core/lazy').callback,
nodefs = require('node-fs'),
fs = require('fs'),
ini = require('ini');

exports.init = function(beet, outputDir)
{
    try
    {
        nodefs.mkdirSync(outputDir, 0755, true);
    }
    catch(e)
    {
    }

    return {
        db: function(db)
        {

            db.addListener('collection', function(collection)
            {

                var output = outputDir + '/'+ collection.name +'.conf';

                var saveNow = function()
                {

                    //ALL the applications
                    var objects = collection.objects();

                    //this will be the config content
                    var buffer = [],

                    //used to group programs
                    groupedPrograms = {};

                    //write out all the config data
                    for(var i = objects.length; i--;)
                    {
                        var script = objects[i];

                        //get the REAL directory for the config path
                        script.directory = fs.realpathSync(script.directory);

                        if(!groupedPrograms[script.group]) groupedPrograms[script.group] = [];

                        groupedPrograms[script.group].push(script.supervisordName);

                        buffer.push('[program:' + script.supervisordName + ']');

                        for(var property in script)
                        {
                            buffer.push(property + '=' + script[property]);
                        }

                        buffer.push('\n\n');
                    }

                    for(var groupName in groupedPrograms)
                    {
                        buffer.push('\n');
                        buffer.push('[group:' + groupName + ']');
                        buffer.push('programs=' + groupedPrograms[groupName].join(','));
                        buffer.push('\n');
                    }

                    fs.writeFileSync(output, buffer.join('\n'));

                    beet.client.reloadConfig(function(err, result)
                    {
                        beet.emit('restart');
                    });
                }

                try
                {
                    var settings = ini.decode(fs.readFileSync(output, 'utf8').replace(/;[^\n]+/g,'')),
                    programs = {},
                    programsAr = [];

                    for(var section in settings)
                    {
                        var sectionParts = section.split(':'),
                        type = sectionParts[0],
                        sectionName = sectionParts[1],
                        sectionSettings = settings[section];

                        if(type == 'program')
                        {
                            var program = programs[sectionParts[1]] = sectionSettings;

                            programsAr.push(program);
                        }
                        else
                        if(type == 'group')
                        {
                            (sectionSettings.programs || '').split(',').forEach(function(program)
                            {
                               programs[program].group = sectionName;
                            });
                        }

                    }

                    collection.objects(programsAr);
                }
                catch(e)
                {
                }

                var save = lazyCallback(saveNow, 500);

                collection.addListener("insert", save);
                collection.addListener("remove", save);
                collection.addListener("update", save);
                //collection.addListener("findOne", save);
            });
        }
    };

}

<commit_msg>properly add / remove processes to supervisord without restarting everything<commit_after>var lazyCallback = require('sk/core/lazy').callback,
nodefs = require('node-fs'),
fs = require('fs'),
ini = require('ini');

exports.init = function(beet, outputDir)
{
    try
    {
        nodefs.mkdirSync(outputDir, 0755, true);
    }
    catch(e)
    {
    }

    return {
        db: function(db)
        {

            db.addListener('collection', function(collection)
            {
                var output = outputDir + '/'+ collection.name +'.conf',
                updates = { start: {}, stop: {} };

                //OH GOD WHY >.>
                var reload = function(groups, callback)
                {
                    console.log(groups);

                    beet.client.reloadConfig(function(err, result)
                    {

                        var numReloading = 1;

                        function onReloaded()
                        {
                            if(!(--numReloading)) callback();
                        }

                        for(var group in groups.stop)
                        {
                            numReloading++;

                            console.log('Removing ' + group);

                            //first we need to stop the process...
                            beet.client.stopProcessGroup(group, function(err, result)
                            {

                                //ugh... then we need to remove it
                                beet.client.removeProcessGroup(group, function(err, result)
                                {
                                    if(groups.start[group])
                                    {

                                        //THEN we can start the process!
                                        beet.client.addProcessGroup(group, function(err, result)
                                        {
                                            onReloaded();
                                        });
                                    }
                                    else
                                    {
                                        onReloaded();
                                    }
                                });
                            });
                        }

                        onReloaded();

                    });
                }

                var saveNow = function()
                {

                    //ALL the applications
                    var objects = collection.objects();

                    //this will be the config content
                    var buffer = [],

                    //used to group programs
                    groupedPrograms = {};

                    //write out all the config data
                    for(var i = objects.length; i--;)
                    {
                        var script = objects[i];

                        //get the REAL directory for the config path
                        script.directory = fs.realpathSync(script.directory);

                        /*if(script.group)
                        {
                            if(!groupedPrograms[script.group]) groupedPrograms[script.group] = [];
                            groupedPrograms[script.group].push(script.supervisordName);
                        }*/

                        buffer.push('[program:' + script.supervisordName + ']');

                        for(var property in script)
                        {
                            buffer.push(property + '=' + script[property]);
                        }

                        buffer.push('\n\n');
                    }

                    for(var groupName in groupedPrograms)
                    {
                        buffer.push('\n');
                        buffer.push('[group:' + groupName + ']');
                        buffer.push('programs=' + groupedPrograms[groupName].join(','));
                        buffer.push('\n');
                    }

                    fs.writeFileSync(output, buffer.join('\n'));

                    console.log('reloading beet config');

                    reload(updates, function()
                    {
                        console.log('reloaded');

                        beet.emit('restart');
                    });

                    updates = { start: {}, stop: {} };
                }

                try
                {
                    var settings = ini.decode(fs.readFileSync(output, 'utf8').replace(/;[^\n]+/g,'')),
                    programs = {},
                    programsAr = [];

                    for(var section in settings)
                    {
                        var sectionParts = section.split(':'),
                        type = sectionParts[0],
                        sectionName = sectionParts[1],
                        sectionSettings = settings[section];

                        if(type == 'program')
                        {
                            var program = programs[sectionParts[1]] = sectionSettings;

                            programsAr.push(program);
                        }
                        /*else
                        if(type == 'group')
                        {
                            (sectionSettings.programs || '').split(',').forEach(function(program)
                            {
                               programs[program].group = sectionName;
                            });
                        }*/

                    }

                    collection.objects(programsAr);
                }
                catch(e)
                {
                }

                var save = lazyCallback(saveNow, 500);

                function addToStart(items)
                {
                    items.forEach(function(item)
                    {
                       updates.start[/*item.group || */item.supervisordName] = 1;
                       updates.stop[/*item.group || */item.supervisordName] = 1;
                    });

                    save();
                }

                function addToStop(items)
                {
                    items.forEach(function(item)
                    {
                       updates.stop[/*item.group || */item.supervisordName] = 1;
                    });

                    save();
                }

                collection.addListener("insert", addToStart);
                collection.addListener("update", addToStart);
                collection.addListener("remove", addToStop);
                //collection.addListener("findOne", save);
            });
        }
    };

}

<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var uptown = require('uptown');
var createClass = uptown.createClass;

module.exports = function(registry) {
  return createClass({
    constructor: function(content, meta, attributes) {
      // Lazy load this.meta and this.attributes because it's a Minim element
      // Otherwise, we get into circuluar calls
      if (meta) {
        this.meta.set(meta);
      }

      if (attributes) {
        this.attributes.set(attributes);
      }

      this.content = content !== undefined ? content : null;
    },

    primitive: function() {
      return;
    },

    /*
     * Creates a deep clone of the instance
     */
    clone: function() {
      return registry.fromRefract(this.toRefract());
    },

    toValue: function() {
      return this.content;
    },

    /// Finds the given elements in the element tree
    /// Returns ArrayElement of elements or null
    findRecursive: function() {
      var elementNames = [].concat.apply([], arguments);
      var ArrayElement = registry.getElementClass('array');
      var array = new ArrayElement();
      var parents;

      if (elementNames[elementNames.length - 1].element === 'array') {
        parents = elementNames.pop().clone();
      } else {
        parents = new ArrayElement();
      }

      var elementName = elementNames.pop();

      parents.push(this);

      var append = function(array, element) {
        array.push(element);
        return array;
      };

      var attachParents = function(element, parents) {
        var clonedElement = element.clone();
        clonedElement.parents = parents;
        return clonedElement;
      };

      // Checks the given element and appends element/sub-elements
      // that match element name to given array
      var checkElement = function(array, element) {
        if (element.element === elementName) {
          array.push(attachParents(element, parents));
        }

        var items = element.findRecursive(elementName, parents);
        if (items) {
          items.reduce(append, array);
        }

        parents.push(element);

        // Key-Value Pair
        if (element.key) {
          checkElement(array, element.key);
        }

        if (element.value) {
          checkElement(array, element.value);
        }

        parents.content.pop();

        return array;
      };

      if (this.content) {
        // Direct Element
        if (this.content.element) {
          checkElement(array, this.content);
        }

        // Element Array
        if (Array.isArray(this.content)) {
          this.content.reduce(checkElement, array);
        }
      }

      if (elementNames.length > 0) {
        array = array.filter(function (element) {
          var parentElements = element.parents.map(function (element) {
            return element.element;
          }).reverse();

          for (var namesIndex in elementNames) {
            var name = elementNames[namesIndex];
            var index = parentElements.indexOf(name);

            if (index !== -1) {
              parentElements.splice(0, index);
            } else {
              return false;
            }
          }

          return true;
        });
      }

      if (array.length > 0) {
        return array;
      }

      return null;
    },

    shouldRefract: function (element) {
      if (element.element !== element.primitive() || element.element === 'member') {
        return true;
      }

      if (element.attributes.keys().length || element.meta.keys().length) {
        return true;
      }

      return false;
    },

    toRefract: function(options) {
      var attributes = this.convertAttributesToRefract();
      var meta = this.convertMetaToRefract();
      var initial = {
        element: this.element,
        meta: meta,
        attributes: attributes,
        content: this.content
      };
      return _.extend(initial, options || {});
    },

    convertKeyToRefract: function (key, item) {
      if (this.shouldRefract(item)) {
        return item.toRefract();
      }

      if (item.element === 'array') {
        // This is a plain array, but maybe it contains elements with
        // additional information? Let's see!
        var values = [];

        for (var index = 0; index < item.length; index++) {
          var subItem = item.get(index);

          if (this.shouldRefract(subItem)) {
            values.push(subItem.toRefract());
          } else {
            values.push(subItem.toValue());
          }
        }

        return values;
      }

      if (item.element === 'object') {
        // This is an object, so we need to check if it's members contain
        // additional information
        // TODO
      }

      return item.toValue();
    },

    /*
     * Converts everything in `meta` into values
     */
    convertMetaToRefract: function() {
      var meta = {};

      this.meta.keys().forEach(function (key) {
        meta[key] = this.convertKeyToRefract(key, this.meta.get(key));
      }, this);

      return meta;
    },

    /*
     * Some attributes may be elements.
     */
    convertAttributesToRefract: function() {
      var attributes = {};

      this.attributes.keys().forEach(function (key) {
        attributes[key] = this.convertKeyToRefract(key, this.attributes.get(key));
      }, this);

      return attributes;
    },

    fromRefract: function(doc, options) {
      this.content = doc.content;

      if (doc.attributes) {
        traverseObject(doc.attributes, this.attributes, function (item) {
          return _.get(item, 'element');
        }, function (item) {
          return registry.fromRefract(item);
        });
      }

      if (doc.meta) {
        traverseObject(doc.meta, this.meta, function(item) {
          return _.get(item, 'element');
        }, function(item) {
          return registry.fromRefract(item);
        });
      }

      if (this.element !== doc.element) {
        this.element = doc.element;
      }

      return _.extend(this, options || {});
    },

    set: function(content) {
      this.content = content;
      return this;
    },

    equals: function(value) {
      return _.isEqual(this.toValue(), value);
    },

    getMetaProperty: function(name, value) {
      if (!this.meta.hasKey(name)) {
        this.meta.set(name, value);
      }

      return this.meta.get(name);
    },

    setMetaProperty: function(name, value) {
      this.meta.set(name, value);
    }
  }, {}, {
    element: {
      get: function() {
        // Returns 'element' so we don't have undefined as element
        return this._storedElement || 'element';
      },
      set: function(element) {
        this._storedElement = element;
      }
    },

    meta: {
      get: function() {
        if (!this._meta) {
          this._meta = registry.toElement({});
        }

        return this._meta;
      },
      set: function(value) {
        this.meta.set(value || {});
      }
    },

    attributes: {
      get: function() {
        if (!this._attributes) {
          this._attributes = registry.toElement({});
        }

        return this._attributes;
      },
      set: function(value) {
        this.attributes.set(value || {});
      }
    },

    id: {
      get: function() {
        return this.getMetaProperty('id', '');
      },
      set: function(element) {
        this.setMetaProperty('id', element);
      }
    },

    classes: {
      get: function() {
        return this.getMetaProperty('classes', []);
      },
      set: function(element) {
        this.setMetaProperty('classes', element);
      }
    },

    // TODO: Remove, not in Refract spec
    // Requires updating subclass test
    name: {
      get: function() {
        return this.getMetaProperty('name', '');
      },
      set: function(element) {
        this.setMetaProperty('name', element);
      }
    },

    title: {
      get: function() {
        return this.getMetaProperty('title', '');
      },
      set: function(element) {
        this.setMetaProperty('title', element);
      }
    },

    description: {
      get: function() {
        return this.getMetaProperty('description', '');
      },
      set: function(element) {
        this.setMetaProperty('description', element);
      }
    },

    links: {
      get: function() {
        return this.getMetaProperty('links', []);
      },
      set: function(element) {
        this.setMetaProperty('links', element);
      }
    }
  });

  //-----------------------------------------------------------------------------
  // Private Helpers

  function traverseObject(obj, el, test, convert) {
    var ArrayElement = registry.getElementClass('array');

    Object.keys(obj).forEach(function (key) {
      var value = obj[key];

      // TODO: Warning - this may raise a false positive :-(
      // Also, this does not implement nested objects with nested Refract Objects
      // In the future, we may need to support that, but currently, it's not needed.
      if (test(value)) {
        el.set(key, convert(value));
      } else if (_.isArray(value)) {
        var newArray = new ArrayElement();
        traverseArray(value, newArray, test, convert);
        el.set(key, newArray);
      } else {
        el.set(key, value);
      }
    });
  }

  function traverseArray(value, el, test, convert) {
    value.forEach(function(item) {
      if (test(item)) {
        el.push(convert(item));
      } else {
        el.push(item);
      }
    });
  }
};
<commit_msg>docs(findRecursive): Add comment with function signature<commit_after>'use strict';

var _ = require('lodash');
var uptown = require('uptown');
var createClass = uptown.createClass;

module.exports = function(registry) {
  return createClass({
    constructor: function(content, meta, attributes) {
      // Lazy load this.meta and this.attributes because it's a Minim element
      // Otherwise, we get into circuluar calls
      if (meta) {
        this.meta.set(meta);
      }

      if (attributes) {
        this.attributes.set(attributes);
      }

      this.content = content !== undefined ? content : null;
    },

    primitive: function() {
      return;
    },

    /*
     * Creates a deep clone of the instance
     */
    clone: function() {
      return registry.fromRefract(this.toRefract());
    },

    toValue: function() {
      return this.content;
    },

    /// Finds the given elements in the element tree
    /// Returns ArrayElement of elements or null
    /// findRecursive: function(names..., parents)
    findRecursive: function() {
      var elementNames = [].concat.apply([], arguments);
      var ArrayElement = registry.getElementClass('array');
      var array = new ArrayElement();
      var parents;

      if (elementNames[elementNames.length - 1].element === 'array') {
        parents = elementNames.pop().clone();
      } else {
        parents = new ArrayElement();
      }

      var elementName = elementNames.pop();

      parents.push(this);

      var append = function(array, element) {
        array.push(element);
        return array;
      };

      var attachParents = function(element, parents) {
        var clonedElement = element.clone();
        clonedElement.parents = parents;
        return clonedElement;
      };

      // Checks the given element and appends element/sub-elements
      // that match element name to given array
      var checkElement = function(array, element) {
        if (element.element === elementName) {
          array.push(attachParents(element, parents));
        }

        var items = element.findRecursive(elementName, parents);
        if (items) {
          items.reduce(append, array);
        }

        parents.push(element);

        // Key-Value Pair
        if (element.key) {
          checkElement(array, element.key);
        }

        if (element.value) {
          checkElement(array, element.value);
        }

        parents.content.pop();

        return array;
      };

      if (this.content) {
        // Direct Element
        if (this.content.element) {
          checkElement(array, this.content);
        }

        // Element Array
        if (Array.isArray(this.content)) {
          this.content.reduce(checkElement, array);
        }
      }

      if (elementNames.length > 0) {
        array = array.filter(function (element) {
          var parentElements = element.parents.map(function (element) {
            return element.element;
          }).reverse();

          for (var namesIndex in elementNames) {
            var name = elementNames[namesIndex];
            var index = parentElements.indexOf(name);

            if (index !== -1) {
              parentElements.splice(0, index);
            } else {
              return false;
            }
          }

          return true;
        });
      }

      if (array.length > 0) {
        return array;
      }

      return null;
    },

    shouldRefract: function (element) {
      if (element.element !== element.primitive() || element.element === 'member') {
        return true;
      }

      if (element.attributes.keys().length || element.meta.keys().length) {
        return true;
      }

      return false;
    },

    toRefract: function(options) {
      var attributes = this.convertAttributesToRefract();
      var meta = this.convertMetaToRefract();
      var initial = {
        element: this.element,
        meta: meta,
        attributes: attributes,
        content: this.content
      };
      return _.extend(initial, options || {});
    },

    convertKeyToRefract: function (key, item) {
      if (this.shouldRefract(item)) {
        return item.toRefract();
      }

      if (item.element === 'array') {
        // This is a plain array, but maybe it contains elements with
        // additional information? Let's see!
        var values = [];

        for (var index = 0; index < item.length; index++) {
          var subItem = item.get(index);

          if (this.shouldRefract(subItem)) {
            values.push(subItem.toRefract());
          } else {
            values.push(subItem.toValue());
          }
        }

        return values;
      }

      if (item.element === 'object') {
        // This is an object, so we need to check if it's members contain
        // additional information
        // TODO
      }

      return item.toValue();
    },

    /*
     * Converts everything in `meta` into values
     */
    convertMetaToRefract: function() {
      var meta = {};

      this.meta.keys().forEach(function (key) {
        meta[key] = this.convertKeyToRefract(key, this.meta.get(key));
      }, this);

      return meta;
    },

    /*
     * Some attributes may be elements.
     */
    convertAttributesToRefract: function() {
      var attributes = {};

      this.attributes.keys().forEach(function (key) {
        attributes[key] = this.convertKeyToRefract(key, this.attributes.get(key));
      }, this);

      return attributes;
    },

    fromRefract: function(doc, options) {
      this.content = doc.content;

      if (doc.attributes) {
        traverseObject(doc.attributes, this.attributes, function (item) {
          return _.get(item, 'element');
        }, function (item) {
          return registry.fromRefract(item);
        });
      }

      if (doc.meta) {
        traverseObject(doc.meta, this.meta, function(item) {
          return _.get(item, 'element');
        }, function(item) {
          return registry.fromRefract(item);
        });
      }

      if (this.element !== doc.element) {
        this.element = doc.element;
      }

      return _.extend(this, options || {});
    },

    set: function(content) {
      this.content = content;
      return this;
    },

    equals: function(value) {
      return _.isEqual(this.toValue(), value);
    },

    getMetaProperty: function(name, value) {
      if (!this.meta.hasKey(name)) {
        this.meta.set(name, value);
      }

      return this.meta.get(name);
    },

    setMetaProperty: function(name, value) {
      this.meta.set(name, value);
    }
  }, {}, {
    element: {
      get: function() {
        // Returns 'element' so we don't have undefined as element
        return this._storedElement || 'element';
      },
      set: function(element) {
        this._storedElement = element;
      }
    },

    meta: {
      get: function() {
        if (!this._meta) {
          this._meta = registry.toElement({});
        }

        return this._meta;
      },
      set: function(value) {
        this.meta.set(value || {});
      }
    },

    attributes: {
      get: function() {
        if (!this._attributes) {
          this._attributes = registry.toElement({});
        }

        return this._attributes;
      },
      set: function(value) {
        this.attributes.set(value || {});
      }
    },

    id: {
      get: function() {
        return this.getMetaProperty('id', '');
      },
      set: function(element) {
        this.setMetaProperty('id', element);
      }
    },

    classes: {
      get: function() {
        return this.getMetaProperty('classes', []);
      },
      set: function(element) {
        this.setMetaProperty('classes', element);
      }
    },

    // TODO: Remove, not in Refract spec
    // Requires updating subclass test
    name: {
      get: function() {
        return this.getMetaProperty('name', '');
      },
      set: function(element) {
        this.setMetaProperty('name', element);
      }
    },

    title: {
      get: function() {
        return this.getMetaProperty('title', '');
      },
      set: function(element) {
        this.setMetaProperty('title', element);
      }
    },

    description: {
      get: function() {
        return this.getMetaProperty('description', '');
      },
      set: function(element) {
        this.setMetaProperty('description', element);
      }
    },

    links: {
      get: function() {
        return this.getMetaProperty('links', []);
      },
      set: function(element) {
        this.setMetaProperty('links', element);
      }
    }
  });

  //-----------------------------------------------------------------------------
  // Private Helpers

  function traverseObject(obj, el, test, convert) {
    var ArrayElement = registry.getElementClass('array');

    Object.keys(obj).forEach(function (key) {
      var value = obj[key];

      // TODO: Warning - this may raise a false positive :-(
      // Also, this does not implement nested objects with nested Refract Objects
      // In the future, we may need to support that, but currently, it's not needed.
      if (test(value)) {
        el.set(key, convert(value));
      } else if (_.isArray(value)) {
        var newArray = new ArrayElement();
        traverseArray(value, newArray, test, convert);
        el.set(key, newArray);
      } else {
        el.set(key, value);
      }
    });
  }

  function traverseArray(value, el, test, convert) {
    value.forEach(function(item) {
      if (test(item)) {
        el.push(convert(item));
      } else {
        el.push(item);
      }
    });
  }
};
<|endoftext|>


<commit_before>const bodyParser = require('body-parser');
const { jsonrpc } = require('../../protocol');

const getErrorOutputMsg = (err) => (err instanceof Error) ? err.message : err;

module.exports = (app, Listeners) => {
  app.use(bodyParser.json({ type: 'application/json-rpc' }));

  app.post('/:serviceName', (req, res) => {
    let data = req.body;

    if (!res.finished) {
      let serviceName = req.params.serviceName;
      if (!Listeners.has(serviceName)) {
        res.status(503).send(jsonrpc.input('Can not found service'));
      } else {
        let listener = Listeners.get(serviceName)[data.method];
        if (!listener) {
          res.status(501).send(jsonrpc.input('Method can not found'));
        } else {
          Reflect
            .apply(listener, null, data.params)
            .then((result) => res.send(jsonrpc.input(result)))
            .catch((err) => res.status(500).send(jsonrpc.input(getErrorOutputMsg(err))));
        }
      }
    }

    app.use((res, req, next) => {
      res.status(404);
      next(new Error('Not Found.'));
    });

    app.use((err, req, res, next) => {
      if (!res.finished) {
        res.status(500).send(jsonrpc.input(getErrorOutputMsg(err)));
      }
    });
  });
};
<commit_msg>修复provider server结构错误可能导致的内存泄漏问题.<commit_after>const bodyParser = require('body-parser');
const { jsonrpc } = require('../../protocol');

const getErrorOutputMsg = (err) => (err instanceof Error) ? err.message : err;

module.exports = (app, Listeners) => {
  app.use(bodyParser.json({ type: 'application/json-rpc' }));

  app.post('/:serviceName', (req, res) => {
    let data = req.body;
    let serviceName = req.params.serviceName;
    if (!Listeners.has(serviceName)) {
      res.status(503).send(jsonrpc.input('Can not found service'));
    } else {
      let listener = Listeners.get(serviceName)[data.method];
      if (!listener) {
        res.status(501).send(jsonrpc.input('Method can not found'));
      } else {
        Reflect
          .apply(listener, null, data.params)
          .then((result) => res.send(jsonrpc.input(result)))
          .catch((err) => res.status(500).send(jsonrpc.input(getErrorOutputMsg(err))));
      }
    }
  });

  app.use((res, req, next) => {
    res.status(404);
    next(new Error('Not Found.'));
  });

  app.use((err, req, res, next) => {
    if (!res.finished) {
      res.status(500).send(jsonrpc.input(getErrorOutputMsg(err)));
    }
  });
};
<|endoftext|>


<commit_before>angular.module('toggle-switch', ['ng']).directive('toggleSwitch', function () {
    return {
        restrict: 'EA',
        replace: true,
        scope: {
            model: '=',
            disabled: '@',
            onLabel: '@',
            offLabel: '@',
            knobLabel: '@'
        },

        template: '

On Off

',
        link: function ($scope, element, attrs) {
            attrs.$observe('onLabel', function(val) {
                $scope.onLabel = angular.isDefined(val) ? val : 'On';
            });

            attrs.$observe('offLabel', function(val) {
                $scope.offLabel = angular.isDefined(val) ? val : 'Off';
            });

            attrs.$observe('knobLabel', function(val) {
                $scope.knobLabel = angular.isDefined(val) ? val : '\u00A0';
            });

            attrs.$observe('disabled', function(disabled) {
                $scope.disabled = disabled === 'true';
            });

            $scope.toggle = function toggle() {
                if(!$scope.disabled) {
                    element.children().addClass('switch-animate');
                    $scope.model = !$scope.model;
                }
            };
        }
    };
});

<commit_msg>angular-toggle-switch.js:   Text editor is trolling me big time. Set indentation on 2 spaces line by line. Hope this is it.<commit_after>angular.module('toggle-switch', ['ng']).directive('toggleSwitch', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: {
      model: '=',
      disabled: '@',
      onLabel: '@',
      offLabel: '@',
      knobLabel: '@'
    },

    template: '

On Off

',
    link: function ($scope, element, attrs) {
      attrs.$observe('onLabel', function(val) {
        $scope.onLabel = angular.isDefined(val) ? val : 'On';
      });

      attrs.$observe('offLabel', function(val) {
        $scope.offLabel = angular.isDefined(val) ? val : 'Off';
      });

      attrs.$observe('knobLabel', function(val) {
        $scope.knobLabel = angular.isDefined(val) ? val : '\u00A0';
      });

      attrs.$observe('disabled', function(disabled) {
        $scope.disabled = disabled === 'true';
      });

      $scope.toggle = function toggle() {
        if(!$scope.disabled) {
          element.children().addClass('switch-animate');
          $scope.model = !$scope.model;
        }
      };
    }
  };
});
<|endoftext|>


<commit_before>(function() {
  var module = angular.module('toggle-switch', ['ng']);

  module.provider('toggleSwitchConfig', function() {
    this.onLabel = 'On';
    this.offLabel = 'Off';
    this.knobLabel = '\u00a0';

    var self = this;
    this.$get = function() {
      return {
        onLabel: self.onLabel,
        offLabel: self.offLabel,
        knobLabel: self.knobLabel
      };
    };
  });

  module.directive('toggleSwitch', function (toggleSwitchConfig) {
    return {
      restrict: 'EA',
      replace: true,
      require:'ngModel',
      scope: {
        disabled: '@',
        onLabel: '@',
        offLabel: '@',
        knobLabel: '@'
      },
      template: '
' +
          '
' +
          '' +
          '' +
          '' +
          '
' +
          '
',
      compile: function(element, attrs) {
        if (!attrs.onLabel) { attrs.onLabel = toggleSwitchConfig.onLabel; }
        if (!attrs.offLabel) { attrs.offLabel = toggleSwitchConfig.offLabel; }
        if (!attrs.knobLabel) { attrs.knobLabel = toggleSwitchConfig.knobLabel; }

        return this.link;
      },
      link: function(scope, element, attrs, ngModelCtrl){
        var KEY_SPACE = 32;

        element.on('click', function() {
          scope.$apply(scope.toggle);
        });

        element.on('keydown', function(e) {
          var key = e.which ? e.which : e.keyCode;
          if (key === KEY_SPACE) {
            scope.$apply(scope.toggle);
          }
        });

        ngModelCtrl.$formatters.push(function(modelValue){
          return modelValue;
        });

        ngModelCtrl.$parsers.push(function(viewValue){
          return viewValue;
        });

        ngModelCtrl.$render = function(){
            scope.model = ngModelCtrl.$viewValue;
        };

        scope.toggle = function toggle() {
          console.log('disabled is', scope.disabled);
          if(!scope.disabled) {
            scope.model = !scope.model;
            ngModelCtrl.$setViewValue(scope.model);
          }
        };
      }
    };
  });
})();
<commit_msg>Remove console.log<commit_after>(function() {
  var module = angular.module('toggle-switch', ['ng']);

  module.provider('toggleSwitchConfig', function() {
    this.onLabel = 'On';
    this.offLabel = 'Off';
    this.knobLabel = '\u00a0';

    var self = this;
    this.$get = function() {
      return {
        onLabel: self.onLabel,
        offLabel: self.offLabel,
        knobLabel: self.knobLabel
      };
    };
  });

  module.directive('toggleSwitch', function (toggleSwitchConfig) {
    return {
      restrict: 'EA',
      replace: true,
      require:'ngModel',
      scope: {
        disabled: '@',
        onLabel: '@',
        offLabel: '@',
        knobLabel: '@'
      },
      template: '
' +
          '
' +
          '' +
          '' +
          '' +
          '
' +
          '
',
      compile: function(element, attrs) {
        if (!attrs.onLabel) { attrs.onLabel = toggleSwitchConfig.onLabel; }
        if (!attrs.offLabel) { attrs.offLabel = toggleSwitchConfig.offLabel; }
        if (!attrs.knobLabel) { attrs.knobLabel = toggleSwitchConfig.knobLabel; }

        return this.link;
      },
      link: function(scope, element, attrs, ngModelCtrl){
        var KEY_SPACE = 32;

        element.on('click', function() {
          scope.$apply(scope.toggle);
        });

        element.on('keydown', function(e) {
          var key = e.which ? e.which : e.keyCode;
          if (key === KEY_SPACE) {
            scope.$apply(scope.toggle);
          }
        });

        ngModelCtrl.$formatters.push(function(modelValue){
          return modelValue;
        });

        ngModelCtrl.$parsers.push(function(viewValue){
          return viewValue;
        });

        ngModelCtrl.$render = function(){
            scope.model = ngModelCtrl.$viewValue;
        };

        scope.toggle = function toggle() {
          if(!scope.disabled) {
            scope.model = !scope.model;
            ngModelCtrl.$setViewValue(scope.model);
          }
        };
      }
    };
  });
})();
<|endoftext|>