<commit_before>var fos = require('filter-objects');
var _ = require('lodash');

function makeIsAuthorized(getAclRules, getAuthzdAclIds, propsToTest, defaultOptions) {

  getMatchedRules = makeGetMatchedRulesFn(propsToTest, defaultOptions);
  var ia = isAuthorized(getMatchedRules, getAclRules, getAuthzdAclIds);
  return ia;
}

function setOptionsOnProps(propsToTest, myDefaultOptions) {
  /* Sets all options on propsToTest
     Option value will be determined for *each option value* if that option value
     exists in (in order; ie, first found sets the value) :
      1. propsToTest by propsToTest property (eg; 'method', 'path')
      2. defaultPropOptions by propsToTest property (eg; 'method', 'path')
          (cascaded to all nested props; eq query.filter will be set to query option)
      3. myDefaultOptions parameter
      4. globalDefaultOptions

      Example:
      propsToTest = ['method','baseUrl','query.sort',{'query.filter':{regExpMatch: false}]
      myDefaultOptions = {variablesInTObj: true}

      method = {
        regExpMatch: false            // defaultPropOptions
        regExpIgnoreCase: false       // defaultPropOptions
        variablesInTObj: false        // defaultPropOptions
      }

      baseUrl = {
        regExpMatch: true             // globalDefaulOptions
        regExpIgnoreCase: true        // globalDefaulOptions
        variablesInTObj: true         // myDefaultOptions
      }

      query.sort = {
        regExpMatch: true             // defaultPropOptions
        regExpIgnoreCase: false       // defaultPropOptions
        variablesInTObj: false        // defaultPropOptions
      }

      query.sort = {
        regExpMatch: false            // propsToTest
        regExpIgnoreCase: false       // defaultPropOptions
        variablesInTObj: false        // defaultPropOptions
      }

  */

  var defaultPropOptions =
    {'method': {
       'regExpMatch': false,
       'regExpIgnoreCase': false,
       'variablesInTObj': false},
     'query': {
       'regExpMatch': true,
       'regExpIgnoreCase': false,
       'variablesInTObj': false},
    };

  // set each property option and their nested property options (eg; query.filter)
  //   to defaultPropOptions if it isn't set in propsToTest
  fos.setNestedPropOptions(propsToTest, defaultPropOptions);

  // options when no options are stipulated for a given property
  var globalDefaultOptions = {
      matchIfTObjPropMissing: true,
      matchIfPObjPropMissing: false,
      matchIfBothPropMissing: true,
      regExpMatch: true,
      regExpReverse: true,
      regExpIgnoreCase: true,
      regExpAnchorStart: true,
      regExpAnchorEnd: true,
      variables: {},
      variablesInTObj: false,
      variablesStartStr: '~',
      variablesEndStr: '#',
    };

  //set options to myDefaultOptions where properties are set to globalDefaultOptions
  //   property value if that property doesn't exist on myDefaultOptions
  // var options = setOptionsDefault(myDefaultOptions, globalDefaultOptions);
  options = {};
  _.defaultsDeep(options,myDefaultOptions, globalDefaultOptions);

  fos.setOptionsOnProps(propsToTest, options);

  return propsToTest;

}

function makeGetMatchedRulesFn(propsToTest, myDefaultOptions) {

  var defaultPropsToTest = ['path', 'baseUrl', 'method'];

  propsToTest = propsToTest && Object.keys(propsToTest).length > 0 ?
    propsToTest : defaultPropsToTest;

  setOptionsOnProps(propsToTest,myDefaultOptions);

  var filterRules = fos.makeFilterFn(propsToTest, options);

  return function(req, getAclRules, callback) {
    getAclRules(function(err, rules) {
      var matchedRules = filterRules(req, rules);
      return callback(err, matchedRules);
    });
  };

}

function isAuthorized(getMatchedRules, getAclRules, getAuthzdAclIds) {

  return function(req, callback) {
    var ids;
    var matchedRules;

    var checkAuthzdIdsWithRules = function(err) {
      // allows getMatchedRules and getAuthzdAclIds to be called in parallel
      // getMatchedRules and getAuthzdAclIds each call this function in their cb
      //    but the overall callback is only executed after both are complete
      if(err) return callback(err);
      if(ids !== undefined && matchedRules !== undefined) {
        // have both ids & rules so can now process results
        // console.log(matchedRules);
        var isAuthorized =
          matchedRules && _.isArray(matchedRules) && matchedRules.length > 0 &&
          ids && _.isArray(ids) && ids.length > 0 &&
          matchedRules.every(function(rule) {
            return ids.some(function(inCode) {
              var re = new RegExp('^'+inCode+'$');
              var idMatchesRule = re.test(rule.id);
              return idMatchesRule;
            });
        });
        if(isAuthorized) {
          return callback(null, true);
        } else {
          return callback(new Error('Not authorized'));
        }
      }
    };

    getMatchedRules(req, getAclRules, getMatchedRulesCb);
    getAuthzdAclIds(req, getAuthzdAclIdsCb);

    function getMatchedRulesCb(err, returnedRules) {
      matchedRules = returnedRules || null;
      checkAuthzdIdsWithRules(err);
    }

    function getAuthzdAclIdsCb(err, returnedIds) {
      ids = returnedIds || null;
      checkAuthzdIdsWithRules(err);
    }
  };
}

function setOptionsDefault(options, optionsDefault) {
  //if a property doesn't exist on options object, that property is set to
  //  the value of that property on optionsDefault
  //Allows an options object to be passed in with only those properties that
  //  are wanted to over-ride the default option properties
  if (options) {
    var optionsDefaultKeys = Object.keys(optionsDefault);
    // set each property on options to default for those that aren't set; eg,
    //  options.checkMethod = options.checkMethod || optionsDefault.checkMethod
    for (var i = optionsDefaultKeys.length - 1; i >= 0; i--) {
      options[optionsDefaultKeys[i]] =
        options.hasOwnProperty(optionsDefaultKeys[i]) ?
          options[optionsDefaultKeys[i]] :
          optionsDefault[optionsDefaultKeys[i]];
    }
  } else {
    options = optionsDefault;
  }

  return options;
}

function getPropsFromRules(rules, keysToIgnore) {
  // return an array of strings that are the keys of rules objects
  // in dot notation form.  Do not return any strings that are in keysToIgnore
  // keysToIgnore = array of strings.
  // eg; rules = [{method:'POST', query:{sort:'ASC'}},'pathname':'/api/blah']
  //   would return ['method', 'query.sort', 'pathname']
  keysToIgnore = keysToIgnore && _.isArray(keysToIgnore) ? keysToIgnore : [];
  // always ignore 'id' property which is reserved property name
  keysToIgnore.push('id');
  var props = getKeysFromArrayOfObjs(rules, keysToIgnore);
  return props;
}

function getKeysFromArrayOfObjs(arrayOfObjs, keysToIgnore) {
  // returns an array of strings that is a unique list of object keys
  //   in dot notation across all objects in an array
  // keysToIgnore is an optional.  Is an array of strings.
  //   Any key in arrayOfObjs will not be included in return array
  //   if that string is in keysToIgnore
  arrayOfObjs = arrayOfObjs ? arrayOfObjs : [];
  arrayOfObjs = _.isArray(arrayOfObjs) ? arrayOfObjs : [arrayOfObjs];

  var keys = [];
  // get all props being tested in rules and de-dupe
  arrayOfObjs.forEach(function(obj){
    // var ps = fos.getObjectProperties(rule);
    var objKeys = fos.getObjectProperties(obj);
    keys = keys.concat(objKeys);
  });

  keys = uniq(keys);

  keys = _.difference(keys,keysToIgnore);

  return keys;

  function uniq(a) {
      var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];

      return a.filter(function(item) {
          var type = typeof item;
          if(type in prims)
              return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
          else
              return objs.indexOf(item) >= 0 ? false : objs.push(item);
      });
  }

} // end of getKeysFromArrayOfObjs

module.exports = {
  makeGetMatchedRulesFn: makeGetMatchedRulesFn,
  makeIsAuthorized: makeIsAuthorized,
  getPropsFromRules: getPropsFromRules,
  setOptionsOnProps: setOptionsOnProps
};
<commit_msg>Provide better error messages if not authorized<commit_after>var fos = require('filter-objects');
var _ = require('lodash');

function makeIsAuthorized(getAclRules, getAuthzdAclIds, propsToTest, defaultOptions) {

  getMatchedRules = makeGetMatchedRulesFn(propsToTest, defaultOptions);
  var ia = isAuthorized(getMatchedRules, getAclRules, getAuthzdAclIds);
  return ia;
}

function setOptionsOnProps(propsToTest, myDefaultOptions) {
  /* Sets all options on propsToTest
     Option value will be determined for *each option value* if that option value
     exists in (in order; ie, first found sets the value) :
      1. propsToTest by propsToTest property (eg; 'method', 'path')
      2. defaultPropOptions by propsToTest property (eg; 'method', 'path')
          (cascaded to all nested props; eq query.filter will be set to query option)
      3. myDefaultOptions parameter
      4. globalDefaultOptions

      Example:
      propsToTest = ['method','baseUrl','query.sort',{'query.filter':{regExpMatch: false}]
      myDefaultOptions = {variablesInTObj: true}

      method = {
        regExpMatch: false            // defaultPropOptions
        regExpIgnoreCase: false       // defaultPropOptions
        variablesInTObj: false        // defaultPropOptions
      }

      baseUrl = {
        regExpMatch: true             // globalDefaulOptions
        regExpIgnoreCase: true        // globalDefaulOptions
        variablesInTObj: true         // myDefaultOptions
      }

      query.sort = {
        regExpMatch: true             // defaultPropOptions
        regExpIgnoreCase: false       // defaultPropOptions
        variablesInTObj: false        // defaultPropOptions
      }

      query.sort = {
        regExpMatch: false            // propsToTest
        regExpIgnoreCase: false       // defaultPropOptions
        variablesInTObj: false        // defaultPropOptions
      }

  */

  var defaultPropOptions =
    {'method': {
       'regExpMatch': false,
       'regExpIgnoreCase': false,
       'variablesInTObj': false},
     'query': {
       'regExpMatch': true,
       'regExpIgnoreCase': false,
       'variablesInTObj': false},
    };

  // set each property option and their nested property options (eg; query.filter)
  //   to defaultPropOptions if it isn't set in propsToTest
  fos.setNestedPropOptions(propsToTest, defaultPropOptions);

  // options when no options are stipulated for a given property
  var globalDefaultOptions = {
      matchIfTObjPropMissing: true,
      matchIfPObjPropMissing: false,
      matchIfBothPropMissing: true,
      regExpMatch: true,
      regExpReverse: true,
      regExpIgnoreCase: true,
      regExpAnchorStart: true,
      regExpAnchorEnd: true,
      variables: {},
      variablesInTObj: false,
      variablesStartStr: '~',
      variablesEndStr: '#',
    };

  //set options to myDefaultOptions where properties are set to globalDefaultOptions
  //   property value if that property doesn't exist on myDefaultOptions
  // var options = setOptionsDefault(myDefaultOptions, globalDefaultOptions);
  options = {};
  _.defaultsDeep(options,myDefaultOptions, globalDefaultOptions);

  fos.setOptionsOnProps(propsToTest, options);

  return propsToTest;

}

function makeGetMatchedRulesFn(propsToTest, myDefaultOptions) {

  var defaultPropsToTest = ['path', 'baseUrl', 'method'];

  propsToTest = propsToTest && Object.keys(propsToTest).length > 0 ?
    propsToTest : defaultPropsToTest;

  setOptionsOnProps(propsToTest,myDefaultOptions);

  var filterRules = fos.makeFilterFn(propsToTest, options);

  return function(req, getAclRules, callback) {
    getAclRules(function(err, rules) {
      var matchedRules = filterRules(req, rules);
      // var matchedRules = filterRules(req, rules);
      return callback(err, matchedRules);
    });
  };

}

function isAuthorized(getMatchedRules, getAclRules, getAuthzdAclIds) {

  return function(req, callback) {
    var ids;
    var matchedRules;

    var checkAuthzdIdsWithRules = function(err) {
      // allows getMatchedRules and getAuthzdAclIds to be called in parallel
      // getMatchedRules and getAuthzdAclIds each call this function in their cb
      //    but the overall callback is only executed after both are complete
      if(err) return callback(err);
      var errMessage = "Not authorized";
      if(ids !== undefined && matchedRules !== undefined) {
        // have both ids & rules so can now process results
        // console.log(matchedRules);
        var hasAtLeastOnMatchedRule = matchedRules &&
          _.isArray(matchedRules) &&
          matchedRules.length > 0;
        if(!hasAtLeastOnMatchedRule) {
          return callback(
            new Error(errMessage + ": no acl rules match the request"));
        }

        var hasAtLeastOneAuthId = ids && _.isArray(ids) && ids.length > 0;
        if(!hasAtLeastOneAuthId) {
          return callback(
            new Error(errMessage + ": no authorization ids from getAuthzdAclIds"));
        }

        var everyMatchedRuleIsAuthzd =
          matchedRules.every(function(rule) {
            return ids.some(function(inCode) {
              var re = new RegExp('^'+inCode+'$');
              var idMatchesRule = re.test(rule.id);
              return idMatchesRule;
            });
        });

        if(everyMatchedRuleIsAuthzd) {
          return callback(null, true);
        } else {
          var e = new Error(errMessage + 'at least one acl rule does not' +
            'have authorization');
          e.authznIds = ids;
          e.matchedRules = matchedRules;
          return callback(e);
        }
      }
    };

    getMatchedRules(req, getAclRules, getMatchedRulesCb);
    getAuthzdAclIds(req, getAuthzdAclIdsCb);

    function getMatchedRulesCb(err, returnedRules) {
      matchedRules = returnedRules || null;
      checkAuthzdIdsWithRules(err);
    }

    function getAuthzdAclIdsCb(err, returnedIds) {
      ids = returnedIds || null;
      checkAuthzdIdsWithRules(err);
    }
  };
}

function setOptionsDefault(options, optionsDefault) {
  //if a property doesn't exist on options object, that property is set to
  //  the value of that property on optionsDefault
  //Allows an options object to be passed in with only those properties that
  //  are wanted to over-ride the default option properties
  if (options) {
    var optionsDefaultKeys = Object.keys(optionsDefault);
    // set each property on options to default for those that aren't set; eg,
    //  options.checkMethod = options.checkMethod || optionsDefault.checkMethod
    for (var i = optionsDefaultKeys.length - 1; i >= 0; i--) {
      options[optionsDefaultKeys[i]] =
        options.hasOwnProperty(optionsDefaultKeys[i]) ?
          options[optionsDefaultKeys[i]] :
          optionsDefault[optionsDefaultKeys[i]];
    }
  } else {
    options = optionsDefault;
  }

  return options;
}

function getPropsFromRules(rules, keysToIgnore) {
  // return an array of strings that are the keys of rules objects
  // in dot notation form.  Do not return any strings that are in keysToIgnore
  // keysToIgnore = array of strings.
  // eg; rules = [{method:'POST', query:{sort:'ASC'}},'pathname':'/api/blah']
  //   would return ['method', 'query.sort', 'pathname']
  keysToIgnore = keysToIgnore && _.isArray(keysToIgnore) ? keysToIgnore : [];
  // always ignore 'id' property which is reserved property name
  keysToIgnore.push('id');
  var props = getKeysFromArrayOfObjs(rules, keysToIgnore);
  return props;
}

function getKeysFromArrayOfObjs(arrayOfObjs, keysToIgnore) {
  // returns an array of strings that is a unique list of object keys
  //   in dot notation across all objects in an array
  // keysToIgnore is an optional.  Is an array of strings.
  //   Any key in arrayOfObjs will not be included in return array
  //   if that string is in keysToIgnore
  arrayOfObjs = arrayOfObjs ? arrayOfObjs : [];
  arrayOfObjs = _.isArray(arrayOfObjs) ? arrayOfObjs : [arrayOfObjs];

  var keys = [];
  // get all props being tested in rules and de-dupe
  arrayOfObjs.forEach(function(obj){
    // var ps = fos.getObjectProperties(rule);
    var objKeys = fos.getObjectProperties(obj);
    keys = keys.concat(objKeys);
  });

  keys = uniq(keys);

  keys = _.difference(keys,keysToIgnore);

  return keys;

  function uniq(a) {
      var prims = {"boolean":{}, "number":{}, "string":{}}, objs = [];

      return a.filter(function(item) {
          var type = typeof item;
          if(type in prims)
              return prims[type].hasOwnProperty(item) ? false : (prims[type][item] = true);
          else
              return objs.indexOf(item) >= 0 ? false : objs.push(item);
      });
  }

} // end of getKeysFromArrayOfObjs

module.exports = {
  makeGetMatchedRulesFn: makeGetMatchedRulesFn,
  makeIsAuthorized: makeIsAuthorized,
  getPropsFromRules: getPropsFromRules,
  setOptionsOnProps: setOptionsOnProps
};
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2014 and beyond Dwayne Charrington
 * Email: dwaynecharrington (at) gmail (dot) com
 * Twitter: abolitionof_
 * Licensed under MIT
 * @author Dwayne Charrington
 * @version 1.0
 */

(function($, window, document, History, undefined) {

    // Events trigger

    // While loading: wpAjax.loading: (event)
    // Content loaded: wpAjax.complete: (event)
    // If failed: wpAjax.failed: (event)

    /*
        Example:

        //To configure wpAjax:
        wpAjax.configure({
            content: "#content" // Element with our content which will be AJAX''d out
        });

        // Call this from within a click event
        wpAjax.trigger("http://www.someurl.com");

        // Request is currently happening (with current URL and new URL)
        $(document).on("wpAjax.loading", function(event) {
            // Methods are;
            // event.previousUrl
            // event.previousSlug
            // event.previousID
            // event.url
        });

        // All data has loaded
        $(document).on("wpAjax.complete", function(event) {
            // Methods are;
            // event.previousUrl
            // event.previousSlug
            // event.previousID
            // event.content
            // event.url
            // event.slug
            // event.ID
        });

        $(document).on("wpAjax.failed", function(event) {
            // Methods are;
            // event.url
        });

        // When a particular page via its slug is loaded
        $(document).on("wpAjax.pageload-slug", function(event) {

        });

        // When a particular page via its slug is being left (loading a new page)
        $(document).on("wpAjax.pageleave-slug", function(event) {

        });
    */

    var currentRequest = null,
         previousUrl = "",
         previousSlug = "",
         previousID = 0,
         requestCount = 0;

    // Main WP Ajax object
    var wpAjax = {};

    // Options
    var settings = {
        content: '#content',      // This is our container
        cacheRequests: true,  // Use HTML5 localStorage to cache pages?
        cacheExpiry: 1,          // Time in hours cached items should be cached for
        waitForImages: true,   // Wait for images to load before loading a page?
        debug: false               // Debug mode shows console messages if true
    },
    o = settings;

    // These two elements never disappear and are always consistent
    var $body    = $("body");
    var $wpvars  = $("wpvars");
    var $content = $(o.content);

    // Statechange when the URL changes, we roll
    $(window).off("statechange").on("statechange", function() {
        var State = History.getState();

        log("Event.statechange: HTML5 History statechange event trigger with URL: "+State.url);

        if (previousUrl !== State.url) {
            log("Event.statechange: Calling the wpAjax.loadPage function with State.url as its parameter");
            wpAjax.loadPage(State.url);
        } else {
            log("Event.statechange: User is already on the requested page to load. No request will be made.");
        }
    });

    // Init events like initial page loading functionality
    wpAjax.initEvents = function() {
        log("initEvents: Called the init events function. About to trigger even with slug: "+wpvars.pagename);
        var pageLoadEvent = jQuery.Event("wpAjax.pageload-"+wpvars.pagename);
        $(document).trigger(pageLoadEvent);
    };

    // Allows us to configure wpAjax
    wpAjax.configure = function(options) {
        log("configure: Setting options for Wpajax");
        $.extend(settings, options);
        return this;
    };

    // Return the configuration object
    wpAjax.getConfiguration = function() {
        return settings;
    };

    // Helper function for checking the current URL
    wpAjax.getCurrentUrl = function() {
        log("getCurrentUrl: Getting the current browser address URL");
        return window.location.href;
    };

    // Trigger a page load
    wpAjax.trigger = function(url) {
        log("trigger: Calling History.pushState which will trigger a statechange");

        // Store current URL as the previous URL
        previousUrl = wpAjax.getCurrentUrl();

        // Store the current page/post slug
        previousSlug = wpvars.pagename;

        // Store the current page/post ID
        previousID = wpvars.pageid;

        var pageLeaveEvent = jQuery.Event("wpAjax.pageleave-"+previousSlug);
        $(document).trigger(pageLeaveEvent);

        wpAjax.getTitle(url, function(title) {
            History.pushState({}, title, url);
        });
    };

    // Have we reached our page limit
    wpAjax.pageLimitReached = function() {
        return (wpvars.max == wpvars.paged);
    };

    // What is the current page we are on
    wpAjax.getCurrentPageNumber = function() {
        return wpvars.paged;
    };

    // Get the maximum number of pages in our results
    wpAjax.getMaxPages = function() {
        return wpvars.max;
    };

    // Load page function
    wpAjax.loadPage = function(url) {

        log("loadPage: No other request is taking place, we are good to go");

        // Apply a loading class to the body
        $("body").addClass("loading-page");

        var loadingEvent = jQuery.Event("wpAjax.loading", {
            previousUrl: previousUrl,
            previousSlug: previousSlug,
            previousID: previousID,
            url: url
        });

        // Trigger loading event
        $(document).trigger(loadingEvent);

        // Before content is loaded in, fade out the old content
        wpAjax.fadeOutContent(function() {

           // Perform our AJAX request
            wpAjax.doRequest(url, function(data) {
                wpAjax.processRequest(data, url);
            }, function() {
                wpAjax.fadeInContent();

                log("loadPage: Called doRequest and the request failed. Throwing a failed event on document");

                var failedEvent = jQuery.Event("wpAjax.failed", {
                    url: url
                });

                // Trigger failed event
                $(document).trigger(failedEvent);
            });

        });

        log("loadPage: Loading class applied to body, loading event fired and content element faded out");

    };

    // Fade out the content area
    wpAjax.fadeOutContent = function(callback) {
        log("fadeOutContent: Animating content element out");

        if (arguments.length === 0) callback = function() {};

        $content.animate({opacity:0}, 800, callback);
    };

    // Fade in the content area
    wpAjax.fadeInContent = function(callback) {
        log("fadeInContent: Animating content element in");

        if (arguments.length === 0) callback = function() {};

        $content.animate({opacity:1}, 800, callback);
    };

    // Performs an AJAX request to get the page title
    // Also has the advantage of pre-fetching the page
    // for us as well.
    wpAjax.getTitle = function(url, callback) {
        var title = "";

        log("getTitle: Calling wpAjax.doRequest now to get the title");

        wpAjax.doRequest(url, function(data) {
            title = $(data).filter("title").text();
            log("getTitle: doRequest AJAX call successful. Title returned: "+title+" ");

            if ($.isFunction(callback)) {
                callback(title);
            }
        }, function() {
            if ($.isFunction(callback)) {
                callback(title);
            }
        });
    };

    // Handles performing the page load request
    // Leaves checking for other requests and validity to other functions
    wpAjax.doRequest = function(url, success, error) {

        log("doRequest: About to perform an AJAX call");

        // Do the fetching and stuff...
        currentRequest = $.ajax({
            url: url,
            localCache: o.cacheRequests,
            cacheTTL: o.cacheExpiry,
            type: 'GET',
            dataType: 'html',
            requestCount: ++requestCount,
            beforeSend: function() {
                // Check if we have a promise and cancel any current requests
                if (currentRequest !== null) {
                    currentRequest.abort();
                }
            },
            success: function(response, textStatus, jqXHR) {
                log("doRequest: AJAX success callback");
                if (requestCount !== this.requestCount) return;
                success(response, textStatus, jqXHR);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                log("doRequest: AJAX error callback");
                if ($.isFunction(error)) {
                    error(jqXHR, textStatus, errorThrown);
                }
            }
        });

    };

    // Once our AJAX request is done, this function is called
    // Which allows us to process the response
    wpAjax.processRequest = function(data, url) {
        var _html = $(data);

        var _content = _html.find(o.content).html();
        var _wpvars  = _html.filter("#wpvars").html();

        log("processRequest: Processing the data returned by a successful AJAX call");

        // Do we have content?
        if (_content && _content.length) {

            // Get latest version of WP Vars object
            $("#wpvars").remove();

            var s = document.createElement("script");
            s.id = "wpvars";
            s.type = "text/javascript";
            s.text = _wpvars;
            $body.append(s);

            var completeEvent = jQuery.Event("wpAjax.complete", {
                previousUrl: previousUrl,
                previousSlug: previousSlug,
                previousID: previousID,
                content: data,
                url: url,
                slug: wpvars.pagename,
                ID: wpvars.pageid
            });

            var pageLoadEvent = jQuery.Event("wpAjax.pageload-"+wpvars.pagename);

            log("processRequest: Content found from the AJAX request, determining what to do with it");

            // We want to wait for images to load before proceeding
            if (o.waitForImages) {

                log("processRequest Wait for images option is enabled, finding images");

                // We have images to preload
                if ($(_content).find("img").length) {

                    log("processRequest: We found images. Waiting for all images in the returned data to preload");

                    // Populate the content element
                    wpAjax.populateContent(_content, function(contentEl) {

                        log("processRequest: Populated the content element with content, about to preload iamges");

                        // Wait for any newly populated images to load
                        contentEl.waitForImages(function() {

                            log("processRequest: All images in AJAX loaded content have preloaded");

                            // Replace body classes with those of the loaded body classes
                            $body.attr("class", data.match(/body class=\"(.*?)\"/)[1]);

                            $(document).trigger(completeEvent);
                            $(document).trigger(pageLoadEvent);
                        });

                    });

                } else {
                    // Populate the content element
                    wpAjax.populateContent(_content, function(contentEl) {

                        log("processRequest: Requested AJAX content has been added to the content element and classes changed");

                        // Replace body classes with those of the loaded body classes
                        $body.attr("class", data.match(/body class=\"(.*?)\"/)[1]);

                        $(document).trigger(completeEvent);
                        $(document).trigger(pageLoadEvent);
                    });
                }

            } else {
                // Populate the content element
                wpAjax.populateContent(_content, function(contentEl) {

                    log("processRequest: Requested AJAX content has been added to the content element and classes changed");

                    // Replace body classes with those of the loaded body classes
                    $("body").attr("class", data.match(/body class=\"(.*?)\"/)[1]);

                    $(document).trigger(completeEvent);
                    $(document).trigger(pageLoadEvent);
                });
            }

            // Fade in the content DIV now we've done what we've wanted with it
            wpAjax.fadeInContent();

        } else {
            log("processRequest: Returned AJAX content is empty. Could be a problem server-side.");
        }
    };

    // Populates the appropriate content DIV with our
    // load content from the AJAX request (if successful)
    wpAjax.populateContent = function(content, callback) {
        log("populateContent: About to populate the content element with returned HTML");

        // Populate the content element
        $content.html(content);

        // If we have a callback function
        if ($.isFunction(callback)) {
            log("populateContent: We've added in the content, calling the callback function with the element as an argument");
            callback($content);
        }
    };

    // Console log wrapper checks if debugging is on
    function log(msg) {
        if (o.debug) {
            console.log(msg);
        }
    }

    // Expose our method to the world
    window.wpAjax = wpAjax;

})(jQuery, window, window.document, window.History);

wpAjax.initEvents();

// Regex selector for jQuery: http://james.padolsey.com/javascript/regex-selector-for-jquery/
(function($, undefined) {

    jQuery.expr[':'].regex = function(elem, index, match) {
        var matchParams = match[3].split(','),
            validLabels = /^(data|css):/,
            attr = {
                method: matchParams[0].match(validLabels) ?
                            matchParams[0].split(':')[0] : 'attr',
                property: matchParams.shift().replace(validLabels,'')
            },
            regexFlags = 'ig',
            regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
        return regex.test(jQuery(elem)[attr.method](attr.property));
    };

})(jQuery);

(function($, undefined) {

    // github.com/paulirish/jquery-ajax-localstorage-cache
    // dependent on Modernizr's localStorage test
    $.ajaxPrefilter( function( options, originalOptions, jqXHR ) {

      // Modernizr.localstorage, version 3 12/12/13
      function hasLocalStorage() {
        var mod = 'modernizr';
        try {
          localStorage.setItem(mod, mod);
          localStorage.removeItem(mod);
          return true;
        } catch(e) {
          return false;
        }
      }

      // Cache it ?
      if ( !hasLocalStorage() || !options.localCache ) return;

      var hourstl = options.cacheTTL || 5;

      var cacheKey = options.cacheKey ||
                     options.url.replace( /jQuery.*/,'' ) + options.type + (options.data || '');

      // isCacheValid is a function to validate cache
      if ( options.isCacheValid &&  ! options.isCacheValid() ){
        localStorage.removeItem( cacheKey );
      }
      // if there's a TTL that's expired, flush this item
      var ttl = localStorage.getItem(cacheKey + 'cachettl');
      if ( ttl && ttl < +new Date() ){
        localStorage.removeItem( cacheKey );
        localStorage.removeItem( cacheKey  + 'cachettl' );
        ttl = 'expired';
      }

      var value = localStorage.getItem( cacheKey );
      if ( value ){
        //In the cache? So get it, apply success callback & abort the XHR request
        // parse back to JSON if we can.
        if ( options.dataType.indexOf( 'json' ) === 0 ) value = JSON.parse( value );
        options.success( value );
        // Abort is broken on JQ 1.5 :(
        jqXHR.abort();
      } else {

        //If it not in the cache, we change the success callback, just put data on localstorage and after that apply the initial callback
        if ( options.success ) {
          options.realsuccess = options.success;
        }
        options.success = function( data ) {
          var strdata = data;
          if ( this.dataType.indexOf( 'json' ) === 0 ) strdata = JSON.stringify( data );

          // Save the data to localStorage catching exceptions (possibly QUOTA_EXCEEDED_ERR)
          try {
            localStorage.setItem( cacheKey, strdata );
          } catch (e) {
            // Remove any incomplete data that may have been saved before the exception was caught
            localStorage.removeItem( cacheKey );
            localStorage.removeItem( cacheKey + 'cachettl' );
            if ( options.cacheError ) options.cacheError( e, cacheKey, strdata );
          }

          if ( options.realsuccess ) options.realsuccess( data );
        };

        // store timestamp
        if ( ! ttl || ttl === 'expired' ) {
          localStorage.setItem( cacheKey  + 'cachettl', +new Date() + 1000 * 60 * 60 * hourstl );
        }

      }
    });

})(jQuery);
<commit_msg>Remove initEvents call<commit_after>/**
 * Copyright (c) 2014 and beyond Dwayne Charrington
 * Email: dwaynecharrington (at) gmail (dot) com
 * Twitter: abolitionof_
 * Licensed under MIT
 * @author Dwayne Charrington
 * @version 1.0
 */

(function($, window, document, History, undefined) {

    // Events trigger

    // While loading: wpAjax.loading: (event)
    // Content loaded: wpAjax.complete: (event)
    // If failed: wpAjax.failed: (event)

    /*
        Example:

        //To configure wpAjax:
        wpAjax.configure({
            content: "#content" // Element with our content which will be AJAX''d out
        });

        // Call this from within a click event
        wpAjax.trigger("http://www.someurl.com");

        // Request is currently happening (with current URL and new URL)
        $(document).on("wpAjax.loading", function(event) {
            // Methods are;
            // event.previousUrl
            // event.previousSlug
            // event.previousID
            // event.url
        });

        // All data has loaded
        $(document).on("wpAjax.complete", function(event) {
            // Methods are;
            // event.previousUrl
            // event.previousSlug
            // event.previousID
            // event.content
            // event.url
            // event.slug
            // event.ID
        });

        $(document).on("wpAjax.failed", function(event) {
            // Methods are;
            // event.url
        });

        // When a particular page via its slug is loaded
        $(document).on("wpAjax.pageload-slug", function(event) {

        });

        // When a particular page via its slug is being left (loading a new page)
        $(document).on("wpAjax.pageleave-slug", function(event) {

        });
    */

    var currentRequest = null,
         previousUrl = "",
         previousSlug = "",
         previousID = 0,
         requestCount = 0;

    // Main WP Ajax object
    var wpAjax = {};

    // Options
    var settings = {
        content: '#content',      // This is our container
        cacheRequests: true,  // Use HTML5 localStorage to cache pages?
        cacheExpiry: 1,          // Time in hours cached items should be cached for
        waitForImages: true,   // Wait for images to load before loading a page?
        debug: false               // Debug mode shows console messages if true
    },
    o = settings;

    // These two elements never disappear and are always consistent
    var $body    = $("body");
    var $wpvars  = $("wpvars");
    var $content = $(o.content);

    // Statechange when the URL changes, we roll
    $(window).off("statechange").on("statechange", function() {
        var State = History.getState();

        log("Event.statechange: HTML5 History statechange event trigger with URL: "+State.url);

        if (previousUrl !== State.url) {
            log("Event.statechange: Calling the wpAjax.loadPage function with State.url as its parameter");
            wpAjax.loadPage(State.url);
        } else {
            log("Event.statechange: User is already on the requested page to load. No request will be made.");
        }
    });

    // Init events like initial page loading functionality
    wpAjax.initEvents = function() {
        log("initEvents: Called the init events function. About to trigger even with slug: "+wpvars.pagename);
        var pageLoadEvent = jQuery.Event("wpAjax.pageload-"+wpvars.pagename);
        $(document).trigger(pageLoadEvent);
    };

    // Allows us to configure wpAjax
    wpAjax.configure = function(options) {
        log("configure: Setting options for Wpajax");
        $.extend(settings, options);
        return this;
    };

    // Return the configuration object
    wpAjax.getConfiguration = function() {
        return settings;
    };

    // Helper function for checking the current URL
    wpAjax.getCurrentUrl = function() {
        log("getCurrentUrl: Getting the current browser address URL");
        return window.location.href;
    };

    // Trigger a page load
    wpAjax.trigger = function(url) {
        log("trigger: Calling History.pushState which will trigger a statechange");

        // Store current URL as the previous URL
        previousUrl = wpAjax.getCurrentUrl();

        // Store the current page/post slug
        previousSlug = wpvars.pagename;

        // Store the current page/post ID
        previousID = wpvars.pageid;

        var pageLeaveEvent = jQuery.Event("wpAjax.pageleave-"+previousSlug);
        $(document).trigger(pageLeaveEvent);

        wpAjax.getTitle(url, function(title) {
            History.pushState({}, title, url);
        });
    };

    // Have we reached our page limit
    wpAjax.pageLimitReached = function() {
        return (wpvars.max == wpvars.paged);
    };

    // What is the current page we are on
    wpAjax.getCurrentPageNumber = function() {
        return wpvars.paged;
    };

    // Get the maximum number of pages in our results
    wpAjax.getMaxPages = function() {
        return wpvars.max;
    };

    // Load page function
    wpAjax.loadPage = function(url) {

        log("loadPage: No other request is taking place, we are good to go");

        // Apply a loading class to the body
        $("body").addClass("loading-page");

        var loadingEvent = jQuery.Event("wpAjax.loading", {
            previousUrl: previousUrl,
            previousSlug: previousSlug,
            previousID: previousID,
            url: url
        });

        // Trigger loading event
        $(document).trigger(loadingEvent);

        // Before content is loaded in, fade out the old content
        wpAjax.fadeOutContent(function() {

           // Perform our AJAX request
            wpAjax.doRequest(url, function(data) {
                wpAjax.processRequest(data, url);
            }, function() {
                wpAjax.fadeInContent();

                log("loadPage: Called doRequest and the request failed. Throwing a failed event on document");

                var failedEvent = jQuery.Event("wpAjax.failed", {
                    url: url
                });

                // Trigger failed event
                $(document).trigger(failedEvent);
            });

        });

        log("loadPage: Loading class applied to body, loading event fired and content element faded out");

    };

    // Fade out the content area
    wpAjax.fadeOutContent = function(callback) {
        log("fadeOutContent: Animating content element out");

        if (arguments.length === 0) callback = function() {};

        $content.animate({opacity:0}, 800, callback);
    };

    // Fade in the content area
    wpAjax.fadeInContent = function(callback) {
        log("fadeInContent: Animating content element in");

        if (arguments.length === 0) callback = function() {};

        $content.animate({opacity:1}, 800, callback);
    };

    // Performs an AJAX request to get the page title
    // Also has the advantage of pre-fetching the page
    // for us as well.
    wpAjax.getTitle = function(url, callback) {
        var title = "";

        log("getTitle: Calling wpAjax.doRequest now to get the title");

        wpAjax.doRequest(url, function(data) {
            title = $(data).filter("title").text();
            log("getTitle: doRequest AJAX call successful. Title returned: "+title+" ");

            if ($.isFunction(callback)) {
                callback(title);
            }
        }, function() {
            if ($.isFunction(callback)) {
                callback(title);
            }
        });
    };

    // Handles performing the page load request
    // Leaves checking for other requests and validity to other functions
    wpAjax.doRequest = function(url, success, error) {

        log("doRequest: About to perform an AJAX call");

        // Do the fetching and stuff...
        currentRequest = $.ajax({
            url: url,
            localCache: o.cacheRequests,
            cacheTTL: o.cacheExpiry,
            type: 'GET',
            dataType: 'html',
            requestCount: ++requestCount,
            beforeSend: function() {
                // Check if we have a promise and cancel any current requests
                if (currentRequest !== null) {
                    currentRequest.abort();
                }
            },
            success: function(response, textStatus, jqXHR) {
                log("doRequest: AJAX success callback");
                if (requestCount !== this.requestCount) return;
                success(response, textStatus, jqXHR);
            },
            error: function(jqXHR, textStatus, errorThrown) {
                log("doRequest: AJAX error callback");
                if ($.isFunction(error)) {
                    error(jqXHR, textStatus, errorThrown);
                }
            }
        });

    };

    // Once our AJAX request is done, this function is called
    // Which allows us to process the response
    wpAjax.processRequest = function(data, url) {
        var _html = $(data);

        var _content = _html.find(o.content).html();
        var _wpvars  = _html.filter("#wpvars").html();

        log("processRequest: Processing the data returned by a successful AJAX call");

        // Do we have content?
        if (_content && _content.length) {

            // Get latest version of WP Vars object
            $("#wpvars").remove();

            var s = document.createElement("script");
            s.id = "wpvars";
            s.type = "text/javascript";
            s.text = _wpvars;
            $body.append(s);

            var completeEvent = jQuery.Event("wpAjax.complete", {
                previousUrl: previousUrl,
                previousSlug: previousSlug,
                previousID: previousID,
                content: data,
                url: url,
                slug: wpvars.pagename,
                ID: wpvars.pageid
            });

            var pageLoadEvent = jQuery.Event("wpAjax.pageload-"+wpvars.pagename);

            log("processRequest: Content found from the AJAX request, determining what to do with it");

            // We want to wait for images to load before proceeding
            if (o.waitForImages) {

                log("processRequest Wait for images option is enabled, finding images");

                // We have images to preload
                if ($(_content).find("img").length) {

                    log("processRequest: We found images. Waiting for all images in the returned data to preload");

                    // Populate the content element
                    wpAjax.populateContent(_content, function(contentEl) {

                        log("processRequest: Populated the content element with content, about to preload iamges");

                        // Wait for any newly populated images to load
                        contentEl.waitForImages(function() {

                            log("processRequest: All images in AJAX loaded content have preloaded");

                            // Replace body classes with those of the loaded body classes
                            $body.attr("class", data.match(/body class=\"(.*?)\"/)[1]);

                            $(document).trigger(completeEvent);
                            $(document).trigger(pageLoadEvent);
                        });

                    });

                } else {
                    // Populate the content element
                    wpAjax.populateContent(_content, function(contentEl) {

                        log("processRequest: Requested AJAX content has been added to the content element and classes changed");

                        // Replace body classes with those of the loaded body classes
                        $body.attr("class", data.match(/body class=\"(.*?)\"/)[1]);

                        $(document).trigger(completeEvent);
                        $(document).trigger(pageLoadEvent);
                    });
                }

            } else {
                // Populate the content element
                wpAjax.populateContent(_content, function(contentEl) {

                    log("processRequest: Requested AJAX content has been added to the content element and classes changed");

                    // Replace body classes with those of the loaded body classes
                    $("body").attr("class", data.match(/body class=\"(.*?)\"/)[1]);

                    $(document).trigger(completeEvent);
                    $(document).trigger(pageLoadEvent);
                });
            }

            // Fade in the content DIV now we've done what we've wanted with it
            wpAjax.fadeInContent();

        } else {
            log("processRequest: Returned AJAX content is empty. Could be a problem server-side.");
        }
    };

    // Populates the appropriate content DIV with our
    // load content from the AJAX request (if successful)
    wpAjax.populateContent = function(content, callback) {
        log("populateContent: About to populate the content element with returned HTML");

        // Populate the content element
        $content.html(content);

        // If we have a callback function
        if ($.isFunction(callback)) {
            log("populateContent: We've added in the content, calling the callback function with the element as an argument");
            callback($content);
        }
    };

    // Console log wrapper checks if debugging is on
    function log(msg) {
        if (o.debug) {
            console.log(msg);
        }
    }

    // Expose our method to the world
    window.wpAjax = wpAjax;

})(jQuery, window, window.document, window.History);

// Regex selector for jQuery: http://james.padolsey.com/javascript/regex-selector-for-jquery/
(function($, undefined) {

    jQuery.expr[':'].regex = function(elem, index, match) {
        var matchParams = match[3].split(','),
            validLabels = /^(data|css):/,
            attr = {
                method: matchParams[0].match(validLabels) ?
                            matchParams[0].split(':')[0] : 'attr',
                property: matchParams.shift().replace(validLabels,'')
            },
            regexFlags = 'ig',
            regex = new RegExp(matchParams.join('').replace(/^\s+|\s+$/g,''), regexFlags);
        return regex.test(jQuery(elem)[attr.method](attr.property));
    };

})(jQuery);

(function($, undefined) {

    // github.com/paulirish/jquery-ajax-localstorage-cache
    // dependent on Modernizr's localStorage test
    $.ajaxPrefilter( function( options, originalOptions, jqXHR ) {

      // Modernizr.localstorage, version 3 12/12/13
      function hasLocalStorage() {
        var mod = 'modernizr';
        try {
          localStorage.setItem(mod, mod);
          localStorage.removeItem(mod);
          return true;
        } catch(e) {
          return false;
        }
      }

      // Cache it ?
      if ( !hasLocalStorage() || !options.localCache ) return;

      var hourstl = options.cacheTTL || 5;

      var cacheKey = options.cacheKey ||
                     options.url.replace( /jQuery.*/,'' ) + options.type + (options.data || '');

      // isCacheValid is a function to validate cache
      if ( options.isCacheValid &&  ! options.isCacheValid() ){
        localStorage.removeItem( cacheKey );
      }
      // if there's a TTL that's expired, flush this item
      var ttl = localStorage.getItem(cacheKey + 'cachettl');
      if ( ttl && ttl < +new Date() ){
        localStorage.removeItem( cacheKey );
        localStorage.removeItem( cacheKey  + 'cachettl' );
        ttl = 'expired';
      }

      var value = localStorage.getItem( cacheKey );
      if ( value ){
        //In the cache? So get it, apply success callback & abort the XHR request
        // parse back to JSON if we can.
        if ( options.dataType.indexOf( 'json' ) === 0 ) value = JSON.parse( value );
        options.success( value );
        // Abort is broken on JQ 1.5 :(
        jqXHR.abort();
      } else {

        //If it not in the cache, we change the success callback, just put data on localstorage and after that apply the initial callback
        if ( options.success ) {
          options.realsuccess = options.success;
        }
        options.success = function( data ) {
          var strdata = data;
          if ( this.dataType.indexOf( 'json' ) === 0 ) strdata = JSON.stringify( data );

          // Save the data to localStorage catching exceptions (possibly QUOTA_EXCEEDED_ERR)
          try {
            localStorage.setItem( cacheKey, strdata );
          } catch (e) {
            // Remove any incomplete data that may have been saved before the exception was caught
            localStorage.removeItem( cacheKey );
            localStorage.removeItem( cacheKey + 'cachettl' );
            if ( options.cacheError ) options.cacheError( e, cacheKey, strdata );
          }

          if ( options.realsuccess ) options.realsuccess( data );
        };

        // store timestamp
        if ( ! ttl || ttl === 'expired' ) {
          localStorage.setItem( cacheKey  + 'cachettl', +new Date() + 1000 * 60 * 60 * hourstl );
        }

      }
    });

})(jQuery);
<|endoftext|>


<commit_before>"use strict";

const config = require( `./config` );
const Module = require( `module` );
const path = require( `path` );
const whoCalled = require( `./util/whoCalled` );

const resolveFilename = Module._resolveFilename;

const rawLength = 2;
const rRaw = /^::/;

const wiresResolveFilename = ( request, parent ) => (
    rRaw.test( request ) ?
        resolveFilename( request.substr( rawLength ), parent ) :
        config(
            path.dirname( parent ? parent.filename : process.cwd() )
        ).handleExpression( request, parent, resolveFilename )
);

let installed = false;

const wires = request => {
    const caller = whoCalled();
    const parent = caller === `module.js` ? null : require.cache[ caller ];
    const resolved = wiresResolveFilename( request, parent );
    const moduleObject = require.cache[ resolved ];
    return moduleObject ? moduleObject.exports : require( resolved );
};

wires.install = () => {
    if ( !installed ) {
        installed = true;
        Module._resolveFilename = wiresResolveFilename;
    }
};

module.exports = wires;
<commit_msg>Pre-emptively control if request is a wires expression so as to avoid unnecessary and very costly config constructions<commit_after>"use strict";

const config = require( `./config` );
const Module = require( `module` );
const path = require( `path` );
const whoCalled = require( `./util/whoCalled` );

const resolveFilename = Module._resolveFilename;

const rawLength = 2;
const rExpr = /^[#?:~>]|{[#?]/;
const rRaw = /^::/;

const wiresResolveFilename = ( request, parent ) => {
    if ( rRaw.test( request ) ) {
        return resolveFilename( request.slice( rawLength ), parent );
    }
    if ( rExpr.test( request ) ) {
        return config(
            path.dirname( parent ? parent.filename : process.cwd() )
        ).handleExpression( request, parent, resolveFilename );
    }
    return resolveFilename( request, parent );
};

let installed = false;

const wires = request => {
    const caller = whoCalled();
    const parent = caller === `module.js` ? null : require.cache[ caller ];
    const resolved = wiresResolveFilename( request, parent );
    const moduleObject = require.cache[ resolved ];
    return moduleObject ? moduleObject.exports : require( resolved );
};

wires.install = () => {
    if ( !installed ) {
        installed = true;
        Module._resolveFilename = wiresResolveFilename;
    }
};

module.exports = wires;
<|endoftext|>


<commit_before>// ==UserScript==
// @name           pixiv_rm_sharebtn
// @namespace      http://shikato.org/pixiv_rm_likebtn
// @author         shikato
// @description    pixivの「いいね」などの危険なシェア系ボタンを削除します
// @version        0.0.1
// @include        http://www.pixiv.net/member_illust.php*
/* load jQuery */
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js
// ==/UserScript==
setInterval(function () {
  if (!$('.share-button').length) return;
  $('.share-button').remove();
}, 300);

<commit_msg>:up: 0.0.2<commit_after>// ==UserScript==
// @name           pixiv_rm_sharebtn
// @namespace      http://shikato.org/pixiv_rm_likebtn
// @author         shikato
// @description    pixivの「いいね」などの危険なシェア系ボタンを削除します
// @version        0.0.2
// @include        https://www.pixiv.net/member_illust.php*
/* load jQuery */
// @require https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js
// ==/UserScript==
setInterval(function () {
  if (!$('._reaction-buttons-container').length) return;
  $('._reaction-buttons-container').remove();
}, 300);

<|endoftext|>


<commit_before>var crypto = require("crypto");
var moment = require("moment");

var PasswordReboot = function(secret) {

  this._DELIMITER = ":";

  function createHmac(token) {
    return crypto
      .createHmac("sha1", secret)
      .update(token)
      .digest("hex");
  }

  this.createToken = function (user, minutesUntilExpiration) {
    var expirationTime = moment()
      .add({ minutes: minutesUntilExpiration || 20 })
      .unix();
    var hmac = createHmac(JSON.stringify(user) + expirationTime);
    return expirationTime + this._DELIMITER + hmac;
  };

  this.verifyToken = function verifyToken(user, token) {
    var parts = token.split(this._DELIMITER);
    var expirationTime = parts[0];
    var hmac = parts[1];
    var now = moment();
    var expired = now.isAfter(moment.unix(expirationTime));
    if (expired) {
      return false;
    }
    return createHmac(JSON.stringify(user) + expirationTime) === hmac;
  }

};

module.exports = PasswordReboot;
<commit_msg>added documentation to the delimiter property<commit_after>var crypto = require("crypto");
var moment = require("moment");

var PasswordReboot = function(secret) {

  /**
   * The delimiter used to specify the boundary between the token expiration
   * timestamp and the token hash-based message authentication code.
   * @constant
   * @readonly
   * @type {String}
   */
  this._DELIMITER = ":";

  function createHmac(message) {
    return crypto
      .createHmac("sha1", secret)
      .update(message)
      .digest("hex");
  }

  this.createToken = function (user, minutesUntilExpiration) {
    var expirationTime = moment()
      .add({ minutes: minutesUntilExpiration || 20 })
      .unix();
    var hmac = createHmac(JSON.stringify(user) + expirationTime);
    return expirationTime + this._DELIMITER + hmac;
  };

  this.verifyToken = function verifyToken(user, token) {
    var parts = token.split(this._DELIMITER);
    var expirationTime = parts[0];
    var hmac = parts[1];
    var now = moment();
    var expired = now.isAfter(moment.unix(expirationTime));
    if (expired) {
      return false;
    }
    return createHmac(JSON.stringify(user) + expirationTime) === hmac;
  }

};

module.exports = PasswordReboot;
<|endoftext|>


<commit_before>import { Platform, AppRegistry, NativeEventEmitter, NativeModules, View } from 'react-native';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';

const { TrackPlayerModule: TrackPlayer } = NativeModules;

function resolveAsset(uri) {
    if(!uri) return undefined;
    return resolveAssetSource(uri);
}

function resolveUrl(url) {
    if(!url) return undefined;
    return resolveAssetSource(url) || url;
}

function updateOptions(data) {
    // Resolve the asset for each icon
    data.icon = resolveAsset(data.icon);
    data.playIcon = resolveAsset(data.playIcon);
    data.pauseIcon = resolveAsset(data.pauseIcon);
    data.stopIcon = resolveAsset(data.stopIcon);
    data.previousIcon = resolveAsset(data.previousIcon);
    data.nextIcon = resolveAsset(data.nextIcon);

    return TrackPlayer.updateOptions(data);
}

function add(tracks, insertBeforeId) {
    if(!Array.isArray(tracks)) {
        tracks = [tracks];
    }

    // Resolve the URL for each track
    for(let i = 0; i < tracks.length; i++) {
        tracks[i].url = resolveUrl(tracks[i].url);
        tracks[i].artwork = resolveUrl(tracks[i].artwork);
    }

    return TrackPlayer.add(tracks, insertBeforeId);
}

function remove(tracks) {
    if(!Array.isArray(tracks)) {
        tracks = [tracks];
    }

    return TrackPlayer.remove(tracks);
}

function warpEventResponse(handler, event, payload) {
    // transform into headlessTask format and return to handler
    const additionalKeys = payload || {};
    handler({ type: event, ...additionalKeys });
}

function registerEventHandler(handler) {
    if (Platform.OS !== 'android') {
        const emitter = new NativeEventEmitter(TrackPlayer);

        const events = [
            'playback-state',
            'playback-error',
            'playback-queue-ended',
            'playback-track-changed',

            'remote-play',
            'remote-pause',
            'remote-stop',
            'remote-next',
            'remote-previous',
        ];

        for (let i = 0; i < events.length; i++) {
            emitter.addListener(events[i], warpEventResponse.bind(null, handler, events[i]));
        }
    } else {
        AppRegistry.registerHeadlessTask('TrackPlayer', () => handler);
    }
}

// We'll declare each one of the constants and functions manually so IDEs can show a list of them
// We should also add documentation here, but I'll leave this task to another day

// States
module.exports.STATE_NONE = TrackPlayer.STATE_NONE;
module.exports.STATE_PLAYING = TrackPlayer.STATE_PLAYING;
module.exports.STATE_PAUSED = TrackPlayer.STATE_PAUSED;
module.exports.STATE_STOPPED = TrackPlayer.STATE_STOPPED;
module.exports.STATE_BUFFERING = TrackPlayer.STATE_BUFFERING;

// Capabilities
module.exports.CAPABILITY_PLAY = TrackPlayer.CAPABILITY_PLAY;
module.exports.CAPABILITY_PLAY_FROM_ID = TrackPlayer.CAPABILITY_PLAY_FROM_ID;
module.exports.CAPABILITY_PLAY_FROM_SEARCH = TrackPlayer.CAPABILITY_PLAY_FROM_SEARCH;
module.exports.CAPABILITY_PAUSE = TrackPlayer.CAPABILITY_PAUSE;
module.exports.CAPABILITY_STOP = TrackPlayer.CAPABILITY_STOP;
module.exports.CAPABILITY_SEEK_TO = TrackPlayer.CAPABILITY_SEEK_TO;
module.exports.CAPABILITY_SKIP = TrackPlayer.CAPABILITY_SKIP;
module.exports.CAPABILITY_SKIP_TO_NEXT = TrackPlayer.CAPABILITY_SKIP_TO_NEXT;
module.exports.CAPABILITY_SKIP_TO_PREVIOUS = TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS;
module.exports.CAPABILITY_SET_RATING = TrackPlayer.CAPABILITY_SET_RATING;

// Rating Types
module.exports.RATING_HEART = TrackPlayer.RATING_HEART;
module.exports.RATING_THUMBS_UP_DOWN = TrackPlayer.RATING_THUMBS_UP_DOWN;
module.exports.RATING_3_STARS = TrackPlayer.RATING_3_STARS;
module.exports.RATING_4_STARS = TrackPlayer.RATING_4_STARS;
module.exports.RATING_5_STARS = TrackPlayer.RATING_5_STARS;
module.exports.RATING_PERCENTAGE = TrackPlayer.RATING_PERCENTAGE;

// Cast States
module.exports.CAST_NO_DEVICES_AVAILABLE = TrackPlayer.CAST_NO_DEVICES_AVAILABLE;
module.exports.CAST_NOT_CONNECTED = TrackPlayer.CAST_NOT_CONNECTED;
module.exports.CAST_CONNECTING = TrackPlayer.CAST_CONNECTING;
module.exports.CAST_CONNECTED = TrackPlayer.CAST_CONNECTED;

// General
module.exports.setupPlayer = TrackPlayer.setupPlayer;
module.exports.destroy = TrackPlayer.destroy;
module.exports.updateOptions = updateOptions;
module.exports.registerEventHandler = registerEventHandler;

// Player Queue Commands
module.exports.add = add;
module.exports.remove = remove;
module.exports.skip = TrackPlayer.skip;
module.exports.skipToNext = TrackPlayer.skipToNext;
module.exports.skipToPrevious = TrackPlayer.skipToPrevious;

// Player Playback Commands
module.exports.reset = TrackPlayer.reset;
module.exports.play = TrackPlayer.play;
module.exports.pause = TrackPlayer.pause;
module.exports.stop = TrackPlayer.stop;
module.exports.seekTo = TrackPlayer.seekTo;
module.exports.setVolume = TrackPlayer.setVolume;

// Player Getters
module.exports.getTrack = TrackPlayer.getTrack;
module.exports.getCurrentTrack = TrackPlayer.getCurrentTrack;
module.exports.getVolume = TrackPlayer.getVolume;
module.exports.getDuration = TrackPlayer.getDuration;
module.exports.getPosition = TrackPlayer.getPosition;
module.exports.getBufferedPosition = TrackPlayer.getBufferedPosition;
module.exports.getState = TrackPlayer.getState;

// Cast Getters
module.exports.getCastState = TrackPlayer.getCastState;

// Components
module.exports.ProgressComponent = require('./ProgressComponent');

if(TrackPlayer.CAST_SUPPORT_AVAILABLE) {
    module.exports.CastButton = require('./CastButton');
} else {
    module.exports.CastButton = View; // Cast Unavailable
}
<commit_msg>Fixed issues with immutable objects<commit_after>import { Platform, AppRegistry, NativeEventEmitter, NativeModules, View } from 'react-native';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';

const { TrackPlayerModule: TrackPlayer } = NativeModules;

function resolveAsset(uri) {
    if(!uri) return undefined;
    return resolveAssetSource(uri);
}

function resolveUrl(url) {
    if(!url) return undefined;
    return resolveAssetSource(url) || url;
}

function setupPlayer(options) {
    return TrackPlayer.setupPlayer(options || {});
}

function updateOptions(data) {
    // Clone the object before modifying it, so we don't run into problems with immutable objects
    data = Object.assign({}, data);

    // Resolve the asset for each icon
    data.icon = resolveAsset(data.icon);
    data.playIcon = resolveAsset(data.playIcon);
    data.pauseIcon = resolveAsset(data.pauseIcon);
    data.stopIcon = resolveAsset(data.stopIcon);
    data.previousIcon = resolveAsset(data.previousIcon);
    data.nextIcon = resolveAsset(data.nextIcon);

    return TrackPlayer.updateOptions(data);
}

function add(tracks, insertBeforeId) {
    if(!Array.isArray(tracks)) {
        tracks = [tracks];
    }

    for(let i = 0; i < tracks.length; i++) {
        // Clone the object before modifying it
        tracks[i] = Object.assign({}, data);

        // Resolve the URLs
        tracks[i].url = resolveUrl(tracks[i].url);
        tracks[i].artwork = resolveUrl(tracks[i].artwork);
    }

    return TrackPlayer.add(tracks, insertBeforeId);
}

function remove(tracks) {
    if(!Array.isArray(tracks)) {
        tracks = [tracks];
    }

    return TrackPlayer.remove(tracks);
}

function warpEventResponse(handler, event, payload) {
    // transform into headlessTask format and return to handler
    const additionalKeys = payload || {};
    handler({ type: event, ...additionalKeys });
}

function registerEventHandler(handler) {
    if (Platform.OS !== 'android') {
        const emitter = new NativeEventEmitter(TrackPlayer);

        const events = [
            'playback-state',
            'playback-error',
            'playback-queue-ended',
            'playback-track-changed',

            'remote-play',
            'remote-pause',
            'remote-stop',
            'remote-next',
            'remote-previous',
        ];

        for (let i = 0; i < events.length; i++) {
            emitter.addListener(events[i], warpEventResponse.bind(null, handler, events[i]));
        }
    } else {
        AppRegistry.registerHeadlessTask('TrackPlayer', () => handler);
    }
}

// We'll declare each one of the constants and functions manually so IDEs can show a list of them
// We should also add documentation here, but I'll leave this task to another day

// States
module.exports.STATE_NONE = TrackPlayer.STATE_NONE;
module.exports.STATE_PLAYING = TrackPlayer.STATE_PLAYING;
module.exports.STATE_PAUSED = TrackPlayer.STATE_PAUSED;
module.exports.STATE_STOPPED = TrackPlayer.STATE_STOPPED;
module.exports.STATE_BUFFERING = TrackPlayer.STATE_BUFFERING;

// Capabilities
module.exports.CAPABILITY_PLAY = TrackPlayer.CAPABILITY_PLAY;
module.exports.CAPABILITY_PLAY_FROM_ID = TrackPlayer.CAPABILITY_PLAY_FROM_ID;
module.exports.CAPABILITY_PLAY_FROM_SEARCH = TrackPlayer.CAPABILITY_PLAY_FROM_SEARCH;
module.exports.CAPABILITY_PAUSE = TrackPlayer.CAPABILITY_PAUSE;
module.exports.CAPABILITY_STOP = TrackPlayer.CAPABILITY_STOP;
module.exports.CAPABILITY_SEEK_TO = TrackPlayer.CAPABILITY_SEEK_TO;
module.exports.CAPABILITY_SKIP = TrackPlayer.CAPABILITY_SKIP;
module.exports.CAPABILITY_SKIP_TO_NEXT = TrackPlayer.CAPABILITY_SKIP_TO_NEXT;
module.exports.CAPABILITY_SKIP_TO_PREVIOUS = TrackPlayer.CAPABILITY_SKIP_TO_PREVIOUS;
module.exports.CAPABILITY_SET_RATING = TrackPlayer.CAPABILITY_SET_RATING;

// Rating Types
module.exports.RATING_HEART = TrackPlayer.RATING_HEART;
module.exports.RATING_THUMBS_UP_DOWN = TrackPlayer.RATING_THUMBS_UP_DOWN;
module.exports.RATING_3_STARS = TrackPlayer.RATING_3_STARS;
module.exports.RATING_4_STARS = TrackPlayer.RATING_4_STARS;
module.exports.RATING_5_STARS = TrackPlayer.RATING_5_STARS;
module.exports.RATING_PERCENTAGE = TrackPlayer.RATING_PERCENTAGE;

// Cast States
module.exports.CAST_NO_DEVICES_AVAILABLE = TrackPlayer.CAST_NO_DEVICES_AVAILABLE;
module.exports.CAST_NOT_CONNECTED = TrackPlayer.CAST_NOT_CONNECTED;
module.exports.CAST_CONNECTING = TrackPlayer.CAST_CONNECTING;
module.exports.CAST_CONNECTED = TrackPlayer.CAST_CONNECTED;

// General
module.exports.setupPlayer = setupPlayer;
module.exports.destroy = TrackPlayer.destroy;
module.exports.updateOptions = updateOptions;
module.exports.registerEventHandler = registerEventHandler;

// Player Queue Commands
module.exports.add = add;
module.exports.remove = remove;
module.exports.skip = TrackPlayer.skip;
module.exports.skipToNext = TrackPlayer.skipToNext;
module.exports.skipToPrevious = TrackPlayer.skipToPrevious;

// Player Playback Commands
module.exports.reset = TrackPlayer.reset;
module.exports.play = TrackPlayer.play;
module.exports.pause = TrackPlayer.pause;
module.exports.stop = TrackPlayer.stop;
module.exports.seekTo = TrackPlayer.seekTo;
module.exports.setVolume = TrackPlayer.setVolume;

// Player Getters
module.exports.getTrack = TrackPlayer.getTrack;
module.exports.getCurrentTrack = TrackPlayer.getCurrentTrack;
module.exports.getVolume = TrackPlayer.getVolume;
module.exports.getDuration = TrackPlayer.getDuration;
module.exports.getPosition = TrackPlayer.getPosition;
module.exports.getBufferedPosition = TrackPlayer.getBufferedPosition;
module.exports.getState = TrackPlayer.getState;

// Cast Getters
module.exports.getCastState = TrackPlayer.getCastState;

// Components
module.exports.ProgressComponent = require('./ProgressComponent');

if(TrackPlayer.CAST_SUPPORT_AVAILABLE) {
    module.exports.CastButton = require('./CastButton');
} else {
    module.exports.CastButton = View; // Cast Unavailable
}
<|endoftext|>


<commit_before>/* global angular */

hqDefine("js/icds_dashboard_utils", function () {
    function populateDashboardConstants(appName) {
        var initialPageData = hqImport("hqwebapp/js/initial_page_data");
        angular.module(appName).constant('isAlertActive', window.angular.element('.alert-maintenance').children().length === 1);
        angular.module(appName).constant('isMobile', initialPageData.get("is_mobile"));
        angular.module(appName).constant('locationHierarchy', initialPageData.get("location_hierarchy"));
        angular.module(appName).constant('userLocationId', initialPageData.get("user_location_id"));
        angular.module(appName).constant('userLocationType', initialPageData.get("user_location_type"));
        angular.module(appName).constant('allUserLocationId', initialPageData.get("all_user_location_id"));
        angular.module(appName).constant('reportAnIssueUrl', initialPageData.get("report_an_issue_url"));
        angular.module(appName).constant('isWebUser', initialPageData.get("is_web_user"));
        angular.module(appName).constant('haveAccessToFeatures', initialPageData.get("have_access_to_features"));
        angular.module(appName).constant('haveAccessToAllLocations', initialPageData.get("have_access_to_all_locations"));
        angular.module(appName).constant('stateLevelAccess', initialPageData.get("state_level_access"));
        angular.module(appName).constant('navMetadata', initialPageData.get("nav_metadata"));
        angular.module(appName).constant('userFullName', initialPageData.get("user_full_name"));
        angular.module(appName).constant('userUsername', initialPageData.get("user_username"));
        angular.module(appName).constant('genders', [
            {id: '', name: 'All'},
            {id: 'M', name: 'Male'},
            {id: 'F', name: 'Female'},
        ]);
        angular.module(appName).constant('ages', [
            {id: '', name: 'All'},
            {id: '6', name: '0-6 months (0-180 days)'},
            {id: '12', name: '6-12 months (181-365 days)'},
            {id: '24', name: '12-24 months (366-730 days)'},
            {id: '36', name: '24-36 months (731-1095 days)'},
            {id: '48', name: '36-48 months (1096-1460 days)'},
            {id: '60', name: '48-60 months (1461-1825 days)'},
            {id: '72', name: '60-72 months (1826-2190 days)'},
        ]);
        angular.module(appName).constant('agesServiceDeliveryDashboard', [
            {id: '0_3', name: 'PW, LW & Children 0-3 years (0-1095 days)'},
            {id: '3_6', name: 'Children 3-6 years (1096-2190 days)'},
        ]);
        angular.module(appName).constant('mobileMapsEnabled', initialPageData.get("mobile_maps_enabled"));
    }

    function addMaternalChildRoutes($routeProvider, defaultStep) {
        return $routeProvider.when("/maternal_and_child", {
                redirectTo: "/maternal_and_child/underweight_children/" + defaultStep,
            })
            .when("/maternal_and_child/underweight_children", {
                redirectTo: "/maternal_and_child/underweight_children/" + defaultStep,
            })
            .when("/maternal_and_child/underweight_children/:step", {
                template: "<underweight-children-report></underweight-children-report>",
            })
            .when("/maternal_and_child/wasting", {
                redirectTo: "/maternal_and_child/wasting/" + defaultStep,
            })
            .when("/maternal_and_child/wasting/:step", {
                template: "<prevalence-of-severe></prevalence-of-severe>",
            })
            .when("/maternal_and_child/stunting", {
                redirectTo: "/maternal_and_child/stunting/" + defaultStep,
            })
            .when("/maternal_and_child/stunting/:step", {
                template: "<prevalence-of-stunting></prevalence-of-stunting>",
            })
            .when("/maternal_and_child/low_birth", {
                redirectTo: "/maternal_and_child/low_birth/" + defaultStep,
            })
            .when("/maternal_and_child/low_birth/:step", {
                template: "<newborn-low-weight></newborn-low-weight>",
            })
            .when("/maternal_and_child/early_initiation", {
                redirectTo: "/maternal_and_child/early_initiation/" + defaultStep,
            })
            .when("/maternal_and_child/early_initiation/:step", {
                template: "<early-initiation-breastfeeding></early-initiation-breastfeeding>",
            })
            .when("/maternal_and_child/exclusive_breastfeeding", {
                redirectTo: "/maternal_and_child/exclusive_breastfeeding/" + defaultStep,
            })
            .when("/maternal_and_child/exclusive_breastfeeding/:step", {
                template: "<exclusive-breastfeeding></exclusive-breastfeeding>",
            })
            .when("/maternal_and_child/children_initiated", {
                redirectTo: "/maternal_and_child/children_initiated/" + defaultStep,
            })
            .when("/maternal_and_child/children_initiated/:step", {
                template: "<children-initiated></children-initiated>",
            })
            .when("/maternal_and_child/institutional_deliveries", {
                redirectTo: "/maternal_and_child/institutional_deliveries/" + defaultStep,
            })
            .when("/maternal_and_child/institutional_deliveries/:step", {
                template: "<institutional-deliveries></institutional-deliveries>",
            })
            .when("/maternal_and_child/immunization_coverage", {
                redirectTo: "/maternal_and_child/immunization_coverage/" + defaultStep,
            })
            .when("/maternal_and_child/immunization_coverage/:step", {
                template: "<immunization-coverage></immunization-coverage>",
            });
    }
    function addCasReachRoutes($routeProvider, defaultStep) {
        return $routeProvider.when("/icds_cas_reach", {
                redirectTo: "/icds_cas_reach/awc_daily_status/" + defaultStep,
            })
            .when("/icds_cas_reach/awc_daily_status", {
                redirectTo: "/icds_cas_reach/awc_daily_status/" + defaultStep,
            })
            .when("/icds_cas_reach/awc_daily_status/:step", {
                template: "<awc-daily-status></awc-daily-status>",
            })
            .when("/icds_cas_reach/awcs_covered", {
                redirectTo: "/icds_cas_reach/awcs_covered/" + defaultStep,
            })
            .when("/icds_cas_reach/awcs_covered/:step", {
                template: "<awcs-covered></awcs-covered>",
            });
    }
    function addDemographicsRoutes($routeProvider, defaultStep) {
        return $routeProvider.when("/demographics", {
            redirectTo: "/demographics/registered_household/" + defaultStep,
        })
        .when("/demographics/registered_household", {
            redirectTo: "/demographics/registered_household/" + defaultStep,
        })
        .when("/demographics/registered_household/:step", {
            template: "<registered-household></registered-household>",
        })
        .when("/demographics/enrolled_children", {
            redirectTo: "/demographics/enrolled_children/" + defaultStep,
        })
        .when("/demographics/enrolled_children/:step", {
            template: "<enrolled-children></enrolled-children>",
        })
        .when("/demographics/enrolled_women", {
            redirectTo: "/demographics/enrolled_women/" + defaultStep,
        })
        .when("/demographics/enrolled_women/:step", {
            template: "<enrolled-women></enrolled-women>",
        })
        .when("/demographics/lactating_enrolled_women", {
            redirectTo: "/demographics/lactating_enrolled_women/" + defaultStep,
        })
        .when("/demographics/lactating_enrolled_women/:step", {
            template: "<lactating-enrolled-women></lactating-enrolled-women>",
        })
        .when("/demographics/adolescent_girls", {
            redirectTo: "/demographics/adolescent_girls/" + defaultStep,
        })
        .when("/demographics/adolescent_girls/:step", {
            template: "<adolescent-girls></adolescent-girls>",
        })
        .when("/demographics/adhaar", {
            redirectTo: "/demographics/adhaar/" + defaultStep,
        })
        .when("/demographics/adhaar/:step", {
            template: "<adhaar-beneficiary></adhaar-beneficiary>",
        });
    }
    function addAWCInfrastructureRoutes($routeProvider, defaultStep) {
        return $routeProvider.when("/awc_infrastructure", {
            redirectTo: "/awc_infrastructure/clean_water/" + defaultStep,
        })
        .when("/awc_infrastructure/clean_water", {
            redirectTo: "/awc_infrastructure/clean_water/" + defaultStep,
        })
        .when("/awc_infrastructure/clean_water/:step", {
            template: "<clean-water></clean-water>",
        })
        .when("/awc_infrastructure/functional_toilet", {
            redirectTo: "/awc_infrastructure/functional_toilet/" + defaultStep,
        })
        .when("/awc_infrastructure/functional_toilet/:step", {
            template: "<functional-toilet></functional-toilet>",
        })
        .when("/awc_infrastructure/medicine_kit", {
            redirectTo: "/awc_infrastructure/medicine_kit/" + defaultStep,
        })
        .when("/awc_infrastructure/medicine_kit/:step", {
            template: "<medicine-kit></medicine-kit>",
        })
        .when("/awc_infrastructure/infantometer", {
            redirectTo: "/awc_infrastructure/infantometer/" + defaultStep,
        })
        .when("/awc_infrastructure/infantometer/:step", {
            template: "<infantometer></infantometer>",
        })
        .when("/awc_infrastructure/stadiometer", {
            redirectTo: "/awc_infrastructure/stadiometer/" + defaultStep,
        })
        .when("/awc_infrastructure/stadiometer/:step", {
            template: "<stadiometer></stadiometer>",
        })
        .when("/awc_infrastructure/infants_weight_scale", {
            redirectTo: "/awc_infrastructure/infants_weight_scale/" + defaultStep,
        })
        .when("/awc_infrastructure/infants_weight_scale/:step", {
            template: "<infants-weight-scale></infants-weight-scale>",
        })
        .when("/awc_infrastructure/adult_weight_scale", {
            redirectTo: "/awc_infrastructure/adult_weight_scale/" + defaultStep,
        })
        .when("/awc_infrastructure/adult_weight_scale/:step", {
            template: "<adult-weight-scale></adult-weight-scale>",
        });

    }
    function addAWCReportRoutes($routeProvider) {
        $routeProvider.when("/awc_reports", {
                redirectTo: "/awc_reports/pse",
            })
            .when("/awc_reports/:step", {
                template: "<awc-reports></awc-reports>",
            });
    }
    function addSharedRoutes($routeProvider, defaultStep) {
        addMaternalChildRoutes($routeProvider, defaultStep);
        addCasReachRoutes($routeProvider, defaultStep);
        addDemographicsRoutes($routeProvider, defaultStep);
        addAWCInfrastructureRoutes($routeProvider, defaultStep);
        addAWCReportRoutes($routeProvider);
    }
    return {
        populateDashboardConstants: populateDashboardConstants,
        addMaternalChildRoutes: addMaternalChildRoutes,
        addCasReachRoutes: addCasReachRoutes,
        addAWCReportRoutes: addAWCReportRoutes,
        addSharedRoutes: addSharedRoutes,
    };
});
<commit_msg>remove uncalled methods from public API<commit_after>/* global angular */

hqDefine("js/icds_dashboard_utils", function () {
    function populateDashboardConstants(appName) {
        var initialPageData = hqImport("hqwebapp/js/initial_page_data");
        angular.module(appName).constant('isAlertActive', window.angular.element('.alert-maintenance').children().length === 1);
        angular.module(appName).constant('isMobile', initialPageData.get("is_mobile"));
        angular.module(appName).constant('locationHierarchy', initialPageData.get("location_hierarchy"));
        angular.module(appName).constant('userLocationId', initialPageData.get("user_location_id"));
        angular.module(appName).constant('userLocationType', initialPageData.get("user_location_type"));
        angular.module(appName).constant('allUserLocationId', initialPageData.get("all_user_location_id"));
        angular.module(appName).constant('reportAnIssueUrl', initialPageData.get("report_an_issue_url"));
        angular.module(appName).constant('isWebUser', initialPageData.get("is_web_user"));
        angular.module(appName).constant('haveAccessToFeatures', initialPageData.get("have_access_to_features"));
        angular.module(appName).constant('haveAccessToAllLocations', initialPageData.get("have_access_to_all_locations"));
        angular.module(appName).constant('stateLevelAccess', initialPageData.get("state_level_access"));
        angular.module(appName).constant('navMetadata', initialPageData.get("nav_metadata"));
        angular.module(appName).constant('userFullName', initialPageData.get("user_full_name"));
        angular.module(appName).constant('userUsername', initialPageData.get("user_username"));
        angular.module(appName).constant('genders', [
            {id: '', name: 'All'},
            {id: 'M', name: 'Male'},
            {id: 'F', name: 'Female'},
        ]);
        angular.module(appName).constant('ages', [
            {id: '', name: 'All'},
            {id: '6', name: '0-6 months (0-180 days)'},
            {id: '12', name: '6-12 months (181-365 days)'},
            {id: '24', name: '12-24 months (366-730 days)'},
            {id: '36', name: '24-36 months (731-1095 days)'},
            {id: '48', name: '36-48 months (1096-1460 days)'},
            {id: '60', name: '48-60 months (1461-1825 days)'},
            {id: '72', name: '60-72 months (1826-2190 days)'},
        ]);
        angular.module(appName).constant('agesServiceDeliveryDashboard', [
            {id: '0_3', name: 'PW, LW & Children 0-3 years (0-1095 days)'},
            {id: '3_6', name: 'Children 3-6 years (1096-2190 days)'},
        ]);
        angular.module(appName).constant('mobileMapsEnabled', initialPageData.get("mobile_maps_enabled"));
    }

    function addMaternalChildRoutes($routeProvider, defaultStep) {
        return $routeProvider.when("/maternal_and_child", {
                redirectTo: "/maternal_and_child/underweight_children/" + defaultStep,
            })
            .when("/maternal_and_child/underweight_children", {
                redirectTo: "/maternal_and_child/underweight_children/" + defaultStep,
            })
            .when("/maternal_and_child/underweight_children/:step", {
                template: "<underweight-children-report></underweight-children-report>",
            })
            .when("/maternal_and_child/wasting", {
                redirectTo: "/maternal_and_child/wasting/" + defaultStep,
            })
            .when("/maternal_and_child/wasting/:step", {
                template: "<prevalence-of-severe></prevalence-of-severe>",
            })
            .when("/maternal_and_child/stunting", {
                redirectTo: "/maternal_and_child/stunting/" + defaultStep,
            })
            .when("/maternal_and_child/stunting/:step", {
                template: "<prevalence-of-stunting></prevalence-of-stunting>",
            })
            .when("/maternal_and_child/low_birth", {
                redirectTo: "/maternal_and_child/low_birth/" + defaultStep,
            })
            .when("/maternal_and_child/low_birth/:step", {
                template: "<newborn-low-weight></newborn-low-weight>",
            })
            .when("/maternal_and_child/early_initiation", {
                redirectTo: "/maternal_and_child/early_initiation/" + defaultStep,
            })
            .when("/maternal_and_child/early_initiation/:step", {
                template: "<early-initiation-breastfeeding></early-initiation-breastfeeding>",
            })
            .when("/maternal_and_child/exclusive_breastfeeding", {
                redirectTo: "/maternal_and_child/exclusive_breastfeeding/" + defaultStep,
            })
            .when("/maternal_and_child/exclusive_breastfeeding/:step", {
                template: "<exclusive-breastfeeding></exclusive-breastfeeding>",
            })
            .when("/maternal_and_child/children_initiated", {
                redirectTo: "/maternal_and_child/children_initiated/" + defaultStep,
            })
            .when("/maternal_and_child/children_initiated/:step", {
                template: "<children-initiated></children-initiated>",
            })
            .when("/maternal_and_child/institutional_deliveries", {
                redirectTo: "/maternal_and_child/institutional_deliveries/" + defaultStep,
            })
            .when("/maternal_and_child/institutional_deliveries/:step", {
                template: "<institutional-deliveries></institutional-deliveries>",
            })
            .when("/maternal_and_child/immunization_coverage", {
                redirectTo: "/maternal_and_child/immunization_coverage/" + defaultStep,
            })
            .when("/maternal_and_child/immunization_coverage/:step", {
                template: "<immunization-coverage></immunization-coverage>",
            });
    }
    function addCasReachRoutes($routeProvider, defaultStep) {
        return $routeProvider.when("/icds_cas_reach", {
                redirectTo: "/icds_cas_reach/awc_daily_status/" + defaultStep,
            })
            .when("/icds_cas_reach/awc_daily_status", {
                redirectTo: "/icds_cas_reach/awc_daily_status/" + defaultStep,
            })
            .when("/icds_cas_reach/awc_daily_status/:step", {
                template: "<awc-daily-status></awc-daily-status>",
            })
            .when("/icds_cas_reach/awcs_covered", {
                redirectTo: "/icds_cas_reach/awcs_covered/" + defaultStep,
            })
            .when("/icds_cas_reach/awcs_covered/:step", {
                template: "<awcs-covered></awcs-covered>",
            });
    }
    function addDemographicsRoutes($routeProvider, defaultStep) {
        return $routeProvider.when("/demographics", {
            redirectTo: "/demographics/registered_household/" + defaultStep,
        })
        .when("/demographics/registered_household", {
            redirectTo: "/demographics/registered_household/" + defaultStep,
        })
        .when("/demographics/registered_household/:step", {
            template: "<registered-household></registered-household>",
        })
        .when("/demographics/enrolled_children", {
            redirectTo: "/demographics/enrolled_children/" + defaultStep,
        })
        .when("/demographics/enrolled_children/:step", {
            template: "<enrolled-children></enrolled-children>",
        })
        .when("/demographics/enrolled_women", {
            redirectTo: "/demographics/enrolled_women/" + defaultStep,
        })
        .when("/demographics/enrolled_women/:step", {
            template: "<enrolled-women></enrolled-women>",
        })
        .when("/demographics/lactating_enrolled_women", {
            redirectTo: "/demographics/lactating_enrolled_women/" + defaultStep,
        })
        .when("/demographics/lactating_enrolled_women/:step", {
            template: "<lactating-enrolled-women></lactating-enrolled-women>",
        })
        .when("/demographics/adolescent_girls", {
            redirectTo: "/demographics/adolescent_girls/" + defaultStep,
        })
        .when("/demographics/adolescent_girls/:step", {
            template: "<adolescent-girls></adolescent-girls>",
        })
        .when("/demographics/adhaar", {
            redirectTo: "/demographics/adhaar/" + defaultStep,
        })
        .when("/demographics/adhaar/:step", {
            template: "<adhaar-beneficiary></adhaar-beneficiary>",
        });
    }
    function addAWCInfrastructureRoutes($routeProvider, defaultStep) {
        return $routeProvider.when("/awc_infrastructure", {
            redirectTo: "/awc_infrastructure/clean_water/" + defaultStep,
        })
        .when("/awc_infrastructure/clean_water", {
            redirectTo: "/awc_infrastructure/clean_water/" + defaultStep,
        })
        .when("/awc_infrastructure/clean_water/:step", {
            template: "<clean-water></clean-water>",
        })
        .when("/awc_infrastructure/functional_toilet", {
            redirectTo: "/awc_infrastructure/functional_toilet/" + defaultStep,
        })
        .when("/awc_infrastructure/functional_toilet/:step", {
            template: "<functional-toilet></functional-toilet>",
        })
        .when("/awc_infrastructure/medicine_kit", {
            redirectTo: "/awc_infrastructure/medicine_kit/" + defaultStep,
        })
        .when("/awc_infrastructure/medicine_kit/:step", {
            template: "<medicine-kit></medicine-kit>",
        })
        .when("/awc_infrastructure/infantometer", {
            redirectTo: "/awc_infrastructure/infantometer/" + defaultStep,
        })
        .when("/awc_infrastructure/infantometer/:step", {
            template: "<infantometer></infantometer>",
        })
        .when("/awc_infrastructure/stadiometer", {
            redirectTo: "/awc_infrastructure/stadiometer/" + defaultStep,
        })
        .when("/awc_infrastructure/stadiometer/:step", {
            template: "<stadiometer></stadiometer>",
        })
        .when("/awc_infrastructure/infants_weight_scale", {
            redirectTo: "/awc_infrastructure/infants_weight_scale/" + defaultStep,
        })
        .when("/awc_infrastructure/infants_weight_scale/:step", {
            template: "<infants-weight-scale></infants-weight-scale>",
        })
        .when("/awc_infrastructure/adult_weight_scale", {
            redirectTo: "/awc_infrastructure/adult_weight_scale/" + defaultStep,
        })
        .when("/awc_infrastructure/adult_weight_scale/:step", {
            template: "<adult-weight-scale></adult-weight-scale>",
        });

    }
    function addAWCReportRoutes($routeProvider) {
        $routeProvider.when("/awc_reports", {
                redirectTo: "/awc_reports/pse",
            })
            .when("/awc_reports/:step", {
                template: "<awc-reports></awc-reports>",
            });
    }
    function addSharedRoutes($routeProvider, defaultStep) {
        addMaternalChildRoutes($routeProvider, defaultStep);
        addCasReachRoutes($routeProvider, defaultStep);
        addDemographicsRoutes($routeProvider, defaultStep);
        addAWCInfrastructureRoutes($routeProvider, defaultStep);
        addAWCReportRoutes($routeProvider);
    }
    return {
        populateDashboardConstants: populateDashboardConstants,
        addSharedRoutes: addSharedRoutes,
    };
});
<|endoftext|>


<commit_before>var exec = require('exec-queue'),
    _ = require('lodash'),
    log4js = require('log4js'),
    logger = log4js.getLogger('GooglePlay'),
    sem = require('semaphore')(1),
    config = require('config'),
    download = require('./download.js'),
    re = new RegExp("[^;]+;([^;]+);");

function init(keyword, outputDir, callback) {
  var crawlerPath = config.get('plugin.GooglePlayCrawlerPath');
  COMMAND = "java -jar " + crawlerPath + "/googleplaycrawler-0.3.jar -f " + crawlerPath + "/crawler.conf search " + keyword;
  exec(COMMAND, function(error, stdout, stderr) {
    if (stderr || error) {
      return logger.error("init::STDerr:" + stderr + ". Error:" + error);
    }
    var output = stdout.split(/\n/);
    var packages = [];
    output = _.rest(output);
    output = _.compact(output);
    logger.info("init::" + output.length + " APKs detected for keyword [" + keyword + "]");

    output.forEach(function(outputLine) {
      var matchArr = outputLine.match(/[^;]+;([^;]+);[^;]+;([^;]+);/);
      if (matchArr.length == 3) {
        packageName = outputLine.match(/[^;]+;([^;]+);[^;]+;([^;]+);/)[1];
        price = outputLine.match(/[^;]+;([^;]+);[^;]+;([^;]+);/)[2];
        if (price.toUpperCase() == "FREE") {
          packages.push(packageName);
        }
      }
      else {
        logger.error("init::Nonconformed app query information: " + outputLine);
      }
    })

    logger.info("init::" + output.length + " free apps for keyword [" + keyword + "]");
    packages.forEach(function(packageName) {
      sem.take(function() {
        logger.debug("Semaphore sem taken");
        if (packageName === packages[packages.length - 1]) {
          var last = true;
        }
        else {
          var last = false;
        }
        logger.debug("init::Begin download " + packageName)
        download(packageName, outputDir, crawlerPath, function(tempAPKPath, htmlPath, tempCommentPath) {
          logger.debug("init::Finish download " + packageName);
          logger.debug("Semaphore sem leave");
          sem.leave();
          callback(tempAPKPath, htmlPath, tempCommentPath, last);
        })
      });
    });
  });
}

module.exports.init = init
<commit_msg>Remove semaphore debug logging<commit_after>var exec = require('exec-queue'),
    _ = require('lodash'),
    log4js = require('log4js'),
    logger = log4js.getLogger('GooglePlay'),
    sem = require('semaphore')(1),
    config = require('config'),
    download = require('./download.js'),
    re = new RegExp("[^;]+;([^;]+);");

function init(keyword, outputDir, callback) {
  var crawlerPath = config.get('plugin.GooglePlayCrawlerPath');
  COMMAND = "java -jar " + crawlerPath + "/googleplaycrawler-0.3.jar -f " + crawlerPath + "/crawler.conf search " + keyword;
  exec(COMMAND, function(error, stdout, stderr) {
    if (stderr || error) {
      return logger.error("init::STDerr:" + stderr + ". Error:" + error);
    }
    var output = stdout.split(/\n/);
    var packages = [];
    output = _.rest(output);
    output = _.compact(output);
    logger.info("init::" + output.length + " APKs detected for keyword [" + keyword + "]");

    output.forEach(function(outputLine) {
      var matchArr = outputLine.match(/[^;]+;([^;]+);[^;]+;([^;]+);/);
      if (matchArr.length == 3) {
        packageName = outputLine.match(/[^;]+;([^;]+);[^;]+;([^;]+);/)[1];
        price = outputLine.match(/[^;]+;([^;]+);[^;]+;([^;]+);/)[2];
        if (price.toUpperCase() == "FREE") {
          packages.push(packageName);
        }
      }
      else {
        logger.error("init::Nonconformed app query information: " + outputLine);
      }
    })

    logger.info("init::" + output.length + " free apps for keyword [" + keyword + "]");
    packages.forEach(function(packageName) {
      sem.take(function() {
        if (packageName === packages[packages.length - 1]) {
          var last = true;
        }
        else {
          var last = false;
        }
        logger.debug("init::Begin download " + packageName)
        download(packageName, outputDir, crawlerPath, function(tempAPKPath, htmlPath, tempCommentPath) {
          logger.debug("init::Finish download " + packageName);
          sem.leave();
          callback(tempAPKPath, htmlPath, tempCommentPath, last);
        })
      });
    });
  });
}

module.exports.init = init
<|endoftext|>