<commit_before>Ext.BLANK_IMAGE_URL = '/assets/ext/resources/images/default/s.gif';

Ext.namespace(
'Vps', 'Vpc',
'Vps.Component',
'Vps.User.Login',
'Vps.Auto',
'Vps.Form',
'Vps.Binding',
'Vpc.Advanced',
'Vps.Debug',
'Vps.Switch',
'Vps.Basic.LinkTag.Extern',
'Vps.Layout',
'Vps.Utils'
);

Ext.applyIf(Array.prototype, {

    //deprecated! -> forEach (ist auch ein JS-Standard!)
    each : function(fn, scope){
        Ext.each(this, fn, scope);
    },

    //to use array.forEach directly
    forEach : function(fn, scope){
        Ext.each(this, fn, scope);
    },

    //add is alias for push
    add : function() {
        this.push.apply(this, arguments);
    },

    //+ Jonas Raoni Soares Silva
    //@ http://jsfromhell.com/array/shuffle [rev. #1]
    shuffle : function() {
        for(var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x);
        return this;
    }
});

Ext.applyIf(Function.prototype, {

    interceptResult: function(fcn, scope) {
        if(typeof fcn != "function"){
            return this;
        }
        var method = this;
        var interception=function() {
            var retval = method.apply(this || window, arguments);
            var callArgs = Array.prototype.slice.call(arguments, 0);
            var args=[retval].concat(callArgs);
            var newRetval=fcn.apply(scope || this || window, args);
            return newRetval;
        };
        if (this.prototype){
            Ext.apply(interception.prototype, this.prototype)
            if (this.superclass){ interception.superclass=this.superclass; }
            if (this.override){ interception.override=this.override; }
        }
        return interception;
    }
});

//http://extjs.com/forum/showthread.php?t=26644
Vps.clone = function(o) {
    if('object' !== typeof o || o === null) {
        return o;
    }
    var c = 'function' === typeof o.pop ? [] : {};
    var p, v;
    for(p in o) {
        if(o.hasOwnProperty(p)) {
            v = o[p];
            if('object' === typeof v && v !== null) {
                c[p] = Vps.clone(v);
            }
            else {
                c[p] = v;
            }
        }
    }
    return c;
};

Ext.onReady(function()
{
//     Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

    if (Ext.QuickTips) {
        Ext.QuickTips.init();
    }

    if (Ext.isIE6) {
        Ext.each(Ext.DomQuery.select('.addHover'), function(el) {
            var extEl = Ext.fly(el);
            extEl.hover(
                function() { this.addClass('hover'); },
                function() { this.removeClass('hover'); },
                extEl
            );
        });
    }
});

Vps.application = { version: '{$application.version}' };

//log das auch ohne irgendwelche abh�nigkeiten funktioniert (zB im Selenium)
Vps.log = function(msg) {
    if (!Vps.debugDiv) {
        Vps.debugDiv = document.createElement('div');
        document.body.appendChild(Vps.debugDiv);
        Vps.debugDiv.style.position = 'absolute';
        Vps.debugDiv.style.zIndex = '300';
        Vps.debugDiv.style.top = 0;
        Vps.debugDiv.style.right = 0;
        Vps.debugDiv.style.backgroundColor = 'white';
        Vps.debugDiv.style.fontSize = '10px';
    }
    Vps.debugDiv.innerHTML += msg+'
';
};

Ext.ux.ErrorHandler.on('error', function(ex) {
    if(Ext.get('loading')) {
        Ext.get('loading').fadeOut({remove: true});
    }
    if (Ext.Msg) {
        Ext.Msg.alert(trlVps('Error'), trlVps("An error has occured"));
    }
    Ext.Ajax.request({
        url: '/vps/error/error/json-mail',
        ignoreErrors: true,
        params: {
            url: ex.url,
            lineNumber: ex.lineNumber,
            stack: Ext.encode(ex.stack),
            message: ex.message,
            location: location.href,
            referrer: document.referrer
        }
    });
});

if (!Vps.Debug.displayErrors) {
    Ext.ux.ErrorHandler.init();
}

//wird gesetzt in Vps.Connection
Vps.requestSentSinceLastKeepAlive = false;
Vps.keepAlive = function() {
    if (!Vps.requestSentSinceLastKeepAlive) {
        Ext.Ajax.request({
            url: '/vps/user/login/json-keep-alive',
            ignoreErrors: true
        });
    } else {
        Vps.requestSentSinceLastKeepAlive = false;
    }
    Vps.keepAlive.defer(1000 * 60 * 5);
};

Vps.keepAliveActivated = false;
Vps.activateKeepAlive = function() {
    if (Vps.keepAliveActivated) return;
    Vps.keepAliveActivated = true;
    Vps.keepAlive.defer(1000 * 60 * 5);
}

if (Vps.isApp) {
    Vps.activateKeepAlive();
}

Vps.contentReadyHandlers = [];
Vps.onContentReady = function(fn, scope) {
    if (Vps.isApp) {
        //in einer Ext-Anwendung mit Vps.main den contentReadHandler
        //nicht gleich ausführen, das paragraphs-panel führt es dafür aus
        Vps.contentReadyHandlers.push({
            fn: fn,
            scope: scope
        });
    } else {
        //normales Frontend
        Ext.onReady(fn, scope);
    }
};

Vps.handleError = function(error) {

    if (error instanceof String) error = { message: error };
    if (arguments[1]) error.title = arguments[1];
    if (arguments[2]) error.mail = arguments[2];
    if (!error.url) error.url = '';

    if ((error.checkRetry || Vps.Debug.displayErrors) && error.retry) {
        if (Vps.Debug.displayErrors) {
            title = error.title;
            msg = error.message;
        } else if (error.errorText) {
            title = error.errorText;
            msg = error.errorText;
        } else {
            title = (trlVps('Error'));
            msg = trlVps("A Server failure occured.");
            if (error.mail || (typeof error.mail == 'undefined')) {
                Ext.Ajax.request({
                    url: '/vps/error/error/json-mail',
                    params: {
                        url: error.url,
                        message: error.message,
                        location: location.href,
                        referrer: document.referrer
                    },
                    ignoreErrors: true
                });
            }
        }

            var win = new Ext.Window({
                    autoCreate : true,
                    title:title,
                    resizable:true,
                    constrain:true,
                    constrainHeader:true,
                    minimizable : false,
                    maximizable : false,
                    stateful: false,
                    modal: false,
                    shim:true,
                    buttonAlign:"center",
                    width:400,
                    minHeight: 300,
                    plain:true,
                    footer:true,
                    closable:false,
                    html: msg,
                    buttons: [{
                        text     : trlVps('Retry'),
                        handler  : function(){
                            error.retry.call(error.scope || window);
                            win.close();
                        }
                    },{
                        text     : trlVps('Abort'),
                        handler  : function(){
                            error.abort.call(error.scope || window);
                            win.close();
                        }
                }]

                });
                win.show();
    } else if (Vps.Debug.displayErrors) {
        Ext.Msg.show({
            title: error.title,
            msg: error.message,
            buttons: Ext.Msg.OK,
            modal: true,
            width: 800
        });
    } else {
        Ext.Msg.alert(trlVps('Error'), trlVps("A Server failure occured."));
        if (error.mail || (typeof error.mail == 'undefined')) {
            Ext.Ajax.request({
                url: '/vps/error/error/json-mail',
                params: {
                    url: error.url,
                    message: error.message,
                    location: location.href,
                    referrer: document.referrer
                }
            });
        }
    }
};

Vps.include =  function(url, restart)
{
    if (url.substr(-4) == '.css') {
        var s = document.createElement('link');
        s.setAttribute('type', 'text/css');
        s.setAttribute('href', url+'?'+Math.random());
        s.setAttribute('rel', 'stylesheet');
    } else {
        var s = document.createElement('script');
        s.setAttribute('type', 'text/javascript');
        s.setAttribute('src', url+'?'+Math.random());
    }
    s.onload = function () {
        if (restart) Vps.restart();
    };
    document.getElementsByTagName("head")[0].appendChild(s);
};

Vps.restart = function()
{
    Ext.getBody().unmask();
    if (Vps.currentViewport) {
        Vps.currentViewport.onDestroy();
        delete Vps.currentViewport;
    }
    Vps.main();
};

var restart = Vps.restart;
var include = Vps.include;
<commit_msg>workaround für JS fehler<commit_after>Ext.BLANK_IMAGE_URL = '/assets/ext/resources/images/default/s.gif';

Ext.namespace(
'Vps', 'Vpc',
'Vps.Component',
'Vps.User.Login',
'Vps.Auto',
'Vps.Form',
'Vps.Binding',
'Vpc.Advanced',
'Vps.Debug',
'Vps.Switch',
'Vps.Basic.LinkTag.Extern',
'Vps.Layout',
'Vps.Utils'
);

Ext.applyIf(Array.prototype, {

    //deprecated! -> forEach (ist auch ein JS-Standard!)
    each : function(fn, scope){
        Ext.each(this, fn, scope);
    },

    //to use array.forEach directly
    forEach : function(fn, scope){
        Ext.each(this, fn, scope);
    },

    //add is alias for push
    add : function() {
        this.push.apply(this, arguments);
    },

    //+ Jonas Raoni Soares Silva
    //@ http://jsfromhell.com/array/shuffle [rev. #1]
    shuffle : function() {
        for(var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x);
        return this;
    }
});

Ext.applyIf(Function.prototype, {

    interceptResult: function(fcn, scope) {
        if(typeof fcn != "function"){
            return this;
        }
        var method = this;
        var interception=function() {
            var retval = method.apply(this || window, arguments);
            var callArgs = Array.prototype.slice.call(arguments, 0);
            var args=[retval].concat(callArgs);
            var newRetval=fcn.apply(scope || this || window, args);
            return newRetval;
        };
        if (this.prototype){
            Ext.apply(interception.prototype, this.prototype)
            if (this.superclass){ interception.superclass=this.superclass; }
            if (this.override){ interception.override=this.override; }
        }
        return interception;
    }
});

//http://extjs.com/forum/showthread.php?t=26644
Vps.clone = function(o) {
    if('object' !== typeof o || o === null) {
        return o;
    }
    var c = 'function' === typeof o.pop ? [] : {};
    var p, v;
    for(p in o) {
        if(o.hasOwnProperty(p)) {
            v = o[p];
            if('object' === typeof v && v !== null) {
                c[p] = Vps.clone(v);
            }
            else {
                c[p] = v;
            }
        }
    }
    return c;
};

//workaround für Permission denied to access property 'dom' from non-chrome context
//siehe http://www.extjs.com/forum/showthread.php?t=74765
//fixed in Ext 3
Ext.Element.prototpye.origContains = Ext.Element.prototpye.contains;
Ext.Element.prototpye.contains = function(el) {
    try {
        return Ext.Element.prototpye.origContains.apply(this, arguments);
    } catch(e) {
        return false;
    }
};

Ext.onReady(function()
{
//     Ext.state.Manager.setProvider(new Ext.state.CookieProvider());

    if (Ext.QuickTips) {
        Ext.QuickTips.init();
    }

    if (Ext.isIE6) {
        Ext.each(Ext.DomQuery.select('.addHover'), function(el) {
            var extEl = Ext.fly(el);
            extEl.hover(
                function() { this.addClass('hover'); },
                function() { this.removeClass('hover'); },
                extEl
            );
        });
    }
});

Vps.application = { version: '{$application.version}' };

//log das auch ohne irgendwelche abh�nigkeiten funktioniert (zB im Selenium)
Vps.log = function(msg) {
    if (!Vps.debugDiv) {
        Vps.debugDiv = document.createElement('div');
        document.body.appendChild(Vps.debugDiv);
        Vps.debugDiv.style.position = 'absolute';
        Vps.debugDiv.style.zIndex = '300';
        Vps.debugDiv.style.top = 0;
        Vps.debugDiv.style.right = 0;
        Vps.debugDiv.style.backgroundColor = 'white';
        Vps.debugDiv.style.fontSize = '10px';
    }
    Vps.debugDiv.innerHTML += msg+'
';
};

Ext.ux.ErrorHandler.on('error', function(ex) {
    if(Ext.get('loading')) {
        Ext.get('loading').fadeOut({remove: true});
    }
    if (Ext.Msg) {
        Ext.Msg.alert(trlVps('Error'), trlVps("An error has occured"));
    }
    Ext.Ajax.request({
        url: '/vps/error/error/json-mail',
        ignoreErrors: true,
        params: {
            url: ex.url,
            lineNumber: ex.lineNumber,
            stack: Ext.encode(ex.stack),
            message: ex.message,
            location: location.href,
            referrer: document.referrer
        }
    });
});

if (!Vps.Debug.displayErrors) {
    Ext.ux.ErrorHandler.init();
}

//wird gesetzt in Vps.Connection
Vps.requestSentSinceLastKeepAlive = false;
Vps.keepAlive = function() {
    if (!Vps.requestSentSinceLastKeepAlive) {
        Ext.Ajax.request({
            url: '/vps/user/login/json-keep-alive',
            ignoreErrors: true
        });
    } else {
        Vps.requestSentSinceLastKeepAlive = false;
    }
    Vps.keepAlive.defer(1000 * 60 * 5);
};

Vps.keepAliveActivated = false;
Vps.activateKeepAlive = function() {
    if (Vps.keepAliveActivated) return;
    Vps.keepAliveActivated = true;
    Vps.keepAlive.defer(1000 * 60 * 5);
}

if (Vps.isApp) {
    Vps.activateKeepAlive();
}

Vps.contentReadyHandlers = [];
Vps.onContentReady = function(fn, scope) {
    if (Vps.isApp) {
        //in einer Ext-Anwendung mit Vps.main den contentReadHandler
        //nicht gleich ausführen, das paragraphs-panel führt es dafür aus
        Vps.contentReadyHandlers.push({
            fn: fn,
            scope: scope
        });
    } else {
        //normales Frontend
        Ext.onReady(fn, scope);
    }
};

Vps.handleError = function(error) {

    if (error instanceof String) error = { message: error };
    if (arguments[1]) error.title = arguments[1];
    if (arguments[2]) error.mail = arguments[2];
    if (!error.url) error.url = '';

    if ((error.checkRetry || Vps.Debug.displayErrors) && error.retry) {
        if (Vps.Debug.displayErrors) {
            title = error.title;
            msg = error.message;
        } else if (error.errorText) {
            title = error.errorText;
            msg = error.errorText;
        } else {
            title = (trlVps('Error'));
            msg = trlVps("A Server failure occured.");
            if (error.mail || (typeof error.mail == 'undefined')) {
                Ext.Ajax.request({
                    url: '/vps/error/error/json-mail',
                    params: {
                        url: error.url,
                        message: error.message,
                        location: location.href,
                        referrer: document.referrer
                    },
                    ignoreErrors: true
                });
            }
        }

            var win = new Ext.Window({
                    autoCreate : true,
                    title:title,
                    resizable:true,
                    constrain:true,
                    constrainHeader:true,
                    minimizable : false,
                    maximizable : false,
                    stateful: false,
                    modal: false,
                    shim:true,
                    buttonAlign:"center",
                    width:400,
                    minHeight: 300,
                    plain:true,
                    footer:true,
                    closable:false,
                    html: msg,
                    buttons: [{
                        text     : trlVps('Retry'),
                        handler  : function(){
                            error.retry.call(error.scope || window);
                            win.close();
                        }
                    },{
                        text     : trlVps('Abort'),
                        handler  : function(){
                            error.abort.call(error.scope || window);
                            win.close();
                        }
                }]

                });
                win.show();
    } else if (Vps.Debug.displayErrors) {
        Ext.Msg.show({
            title: error.title,
            msg: error.message,
            buttons: Ext.Msg.OK,
            modal: true,
            width: 800
        });
    } else {
        Ext.Msg.alert(trlVps('Error'), trlVps("A Server failure occured."));
        if (error.mail || (typeof error.mail == 'undefined')) {
            Ext.Ajax.request({
                url: '/vps/error/error/json-mail',
                params: {
                    url: error.url,
                    message: error.message,
                    location: location.href,
                    referrer: document.referrer
                }
            });
        }
    }
};

Vps.include =  function(url, restart)
{
    if (url.substr(-4) == '.css') {
        var s = document.createElement('link');
        s.setAttribute('type', 'text/css');
        s.setAttribute('href', url+'?'+Math.random());
        s.setAttribute('rel', 'stylesheet');
    } else {
        var s = document.createElement('script');
        s.setAttribute('type', 'text/javascript');
        s.setAttribute('src', url+'?'+Math.random());
    }
    s.onload = function () {
        if (restart) Vps.restart();
    };
    document.getElementsByTagName("head")[0].appendChild(s);
};

Vps.restart = function()
{
    Ext.getBody().unmask();
    if (Vps.currentViewport) {
        Vps.currentViewport.onDestroy();
        delete Vps.currentViewport;
    }
    Vps.main();
};

var restart = Vps.restart;
var include = Vps.include;
<|endoftext|>


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

import {RequestBank} from '../../testing/test-helper';

describe.configure().skipIfPropertiesObfuscated().run('amp' +
    '-analytics', function() {
  this.timeout(15000);

  describes.integration('amp-analytics basic request', {
    body:
      `<amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "endpoint": "${RequestBank.getUrl()}"
          },
          "triggers": {
            "pageview": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 2
              }
            }
          },
          "extraUrlParams": {
            "a": 1,
            "b": "\${title}"
          }
        }
        </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should send request', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/?a=2&b=AMP%20TEST');
        expect(req.headers.referer,
            'should keep referrer if no referrerpolicy specified').to.be.ok;
      });
    });
  });

  describes.integration('amp-analytics batch', {
    body:
      `<amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "endpoint": {
              "baseUrl": "${RequestBank.getUrl()}",
              "batchInterval": 1
            }
          },
          "triggers": {
            "pageview1": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 1,
                "b": "\${title}"
              }
            },
            "pageview2": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 1,
                "b": "\${title}"
              }
            }
          },
          "transport": {
            "beacon": false,
            "xhrpost": true
          }
        }
        </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should send request in batch', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/?a=1&b=AMP%20TEST&a=1&b=AMP%20TEST');
      });
    });
  });

  describes.integration('amp-analytics useBody', {
    body:
      `<amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "endpoint": "${RequestBank.getUrl()}"
          },
          "triggers": {
            "pageview": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 2
              }
            }
          },
          "transport": {
            "beacon": false,
            "xhrpost": true,
            "useBody": true
          },
          "extraUrlParams": {
            "a": 1,
            "b": "\${title}"
          }
        }
        </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should send request use POST body payload', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/');
        expect(JSON.parse(req.body)).to.deep.equal({a: 2, b: 'AMP TEST'});
      });
    });
  });

  describes.integration('amp-analytics batch useBody', {
    body:
      `<amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "endpoint": {
              "baseUrl": "${RequestBank.getUrl()}",
              "batchInterval": 1
            }
          },
          "triggers": {
            "pageview1": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 1,
                "b": "\${title}"
              }
            },
            "pageview2": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 1,
                "b": "\${title}"
              }
            }
          },
          "transport": {
            "beacon": false,
            "xhrpost": true,
            "useBody": true
          }
        }
        </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should send batch request use POST body payload', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/');
        expect(JSON.parse(req.body)).to.deep.equal([{
          a: 1, b: 'AMP TEST',
        }, {
          a: 1, b: 'AMP TEST',
        }]);
      });
    });
  });

  describes.integration('amp-analytics referrerPolicy', {
    body:
      `<amp-analytics>
          <script type="application/json">
          {
            "requests": {
              "endpoint": "${RequestBank.getUrl()}"
            },
            "triggers": {
              "pageview": {
                "on": "visible",
                "request": "endpoint"
              }
            },
            "transport": {
              "referrerPolicy": "no-referrer"
            }
          }
          </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should remove referrer if referrerpolicy=no-referrer', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/');
        expect(req.headers.referer).to.not.be.ok;
      });
    });
  });
});
<commit_msg>Add integration test for CLIENT_ID in amp-analytics (#19709)<commit_after>/**
 * Copyright 2018 The AMP HTML Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS-IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {RequestBank} from '../../testing/test-helper';

describe.configure().skipIfPropertiesObfuscated().run('amp' +
    '-analytics', function() {
  this.timeout(15000);

  describes.integration('amp-analytics basic request', {
    body: `
      <script>
        // initialize _cid cookie with a CLIENT_ID
        document.cookie='_cid=amp-12345';
      </script>
      <amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "endpoint": "${RequestBank.getUrl()}"
          },
          "triggers": {
            "pageview": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 2
              }
            }
          },
          "extraUrlParams": {
            "a": 1,
            "b": "\${title}",
            "cid": "\${clientId(_cid)}"
          }
        }
        </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    afterEach(() => {
      // clean up written _cid cookie
      document.cookie = '_cid=;expires=' + new Date(0).toUTCString();
    });

    it('should send request', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/?a=2&b=AMP%20TEST&cid=amp-12345');
        expect(req.headers.referer,
            'should keep referrer if no referrerpolicy specified').to.be.ok;
      });
    });
  });

  describes.integration('amp-analytics CLIENT_ID new user', {
    body: `
      <script>
        // expires existing _cid cookie if any
        document.cookie='_cid=;expires=' + new Date(0).toUTCString();
      </script>
      <amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "pageview": "${RequestBank.getUrl(1)}?cid=CLIENT_ID(_cid)"
          },
          "triggers": {
            "pageview": {
              "on": "visible",
              "request": "pageview"
            }
          }
        }
        </script>
      </amp-analytics>
      <amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "pageview": "${RequestBank.getUrl(2)}?cid=CLIENT_ID(_cid)"
          },
          "triggers": {
            "pageview": {
              "on": "visible",
              "request": "pageview"
            }
          }
        }
        </script>
      </amp-analytics>
      `,
    extensions: ['amp-analytics'],
  }, () => {
    afterEach(() => {
      // clean up written _cid cookie
      document.cookie = '_cid=;expires=' + new Date(0).toUTCString();
    });

    it('should assign new cid', () => {
      return Promise.all([
        RequestBank.withdraw(1),
        RequestBank.withdraw(2),
      ]).then(reqs => {
        const req1 = reqs[0];
        const req2 = reqs[1];
        expect(req1.url).to.match(/^\/\?cid=/);
        expect(req2.url).to.match(/^\/\?cid=/);
        const cid1 = req1.url.substr('/?cid='.length);
        const cid2 = req2.url.substr('/?cid='.length);
        expect(cid1).to.match(/^amp-/);
        expect(cid2).to.equal(cid1);
        expect(document.cookie).to.contain('_cid=' + cid1);
      });
    });
  });

  describes.integration('amp-analytics batch', {
    body:
      `<amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "endpoint": {
              "baseUrl": "${RequestBank.getUrl()}",
              "batchInterval": 1
            }
          },
          "triggers": {
            "pageview1": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 1,
                "b": "\${title}"
              }
            },
            "pageview2": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 1,
                "b": "\${title}"
              }
            }
          },
          "transport": {
            "beacon": false,
            "xhrpost": true
          }
        }
        </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should send request in batch', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/?a=1&b=AMP%20TEST&a=1&b=AMP%20TEST');
      });
    });
  });

  describes.integration('amp-analytics useBody', {
    body:
      `<amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "endpoint": "${RequestBank.getUrl()}"
          },
          "triggers": {
            "pageview": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 2
              }
            }
          },
          "transport": {
            "beacon": false,
            "xhrpost": true,
            "useBody": true
          },
          "extraUrlParams": {
            "a": 1,
            "b": "\${title}"
          }
        }
        </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should send request use POST body payload', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/');
        expect(JSON.parse(req.body)).to.deep.equal({a: 2, b: 'AMP TEST'});
      });
    });
  });

  describes.integration('amp-analytics batch useBody', {
    body:
      `<amp-analytics>
        <script type="application/json">
        {
          "requests": {
            "endpoint": {
              "baseUrl": "${RequestBank.getUrl()}",
              "batchInterval": 1
            }
          },
          "triggers": {
            "pageview1": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 1,
                "b": "\${title}"
              }
            },
            "pageview2": {
              "on": "visible",
              "request": "endpoint",
              "extraUrlParams": {
                "a": 1,
                "b": "\${title}"
              }
            }
          },
          "transport": {
            "beacon": false,
            "xhrpost": true,
            "useBody": true
          }
        }
        </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should send batch request use POST body payload', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/');
        expect(JSON.parse(req.body)).to.deep.equal([{
          a: 1, b: 'AMP TEST',
        }, {
          a: 1, b: 'AMP TEST',
        }]);
      });
    });
  });

  describes.integration('amp-analytics referrerPolicy', {
    body:
      `<amp-analytics>
          <script type="application/json">
          {
            "requests": {
              "endpoint": "${RequestBank.getUrl()}"
            },
            "triggers": {
              "pageview": {
                "on": "visible",
                "request": "endpoint"
              }
            },
            "transport": {
              "referrerPolicy": "no-referrer"
            }
          }
          </script>
      </amp-analytics>`,
    extensions: ['amp-analytics'],
  }, () => {
    it('should remove referrer if referrerpolicy=no-referrer', () => {
      return RequestBank.withdraw().then(req => {
        expect(req.url).to.equal('/');
        expect(req.headers.referer).to.not.be.ok;
      });
    });
  });
});
<|endoftext|>


<commit_before>exports = module.exports = function(container, logger) {
  // Load modules.
  var passport = require('passport');

  var authenticator = new passport.Authenticator();
  var schemeComps = container.components('http://i.bixbyjs.org/http/auth/Scheme');

  return Promise.all(schemeComps.map(function(comp) { return comp.create(); } ))
    .then(function(schemes) {
      // Register HTTP authentication schemes.
      schemes.forEach(function(scheme, i) {
        authenticator.use(schemeComps[i].a['@scheme'] || scheme.name, scheme);
        logger.info('Loaded HTTP authentication scheme: ' + (schemeComps[i].a['@scheme'] || scheme.name));
      });
    })
    .then(function() {
      return authenticator;
    });
}

exports['@implements'] = 'http://i.bixbyjs.org/http/Authenticator';
exports['@singleton'] = true;
exports['@require'] = [ '!container', 'http://i.bixbyjs.org/Logger' ];
<commit_msg>Clean up scheme loading.<commit_after>exports = module.exports = function(container, logger) {
  // Load modules.
  var passport = require('passport');

  var authenticator = new passport.Authenticator();
  var schemeComps = container.components('http://i.bixbyjs.org/http/auth/Scheme');

  return Promise.resolve(authenticator)
    .then(function(authenticator) {
      // Register HTTP authentication schemes.
      var schemeComps = container.components('http://i.bixbyjs.org/http/auth/Scheme');

      return Promise.all(schemeComps.map(function(comp) { return comp.create(); } ))
        .then(function(schemes) {
          schemes.forEach(function(scheme, i) {
            authenticator.use(schemeComps[i].a['@scheme'] || scheme.name, scheme);
            logger.info('Loaded HTTP authentication scheme: ' + (schemeComps[i].a['@scheme'] || scheme.name));
          });
        })
        .then(function() {
          return authenticator;
        });
    })
    .then(function(authenticator) {
      return authenticator;
    });
}

exports['@implements'] = 'http://i.bixbyjs.org/http/Authenticator';
exports['@singleton'] = true;
exports['@require'] = [ '!container', 'http://i.bixbyjs.org/Logger' ];
<|endoftext|>


<commit_before>'use strict';

module.exports = FieldEditor;

var util = require('util');
var path = require('path');
var fs   = require('fs');

var qforms = require('../../../../qforms');
var Editor = require('../Editor');

util.inherits(FieldEditor, Editor);

////////////////////////////////////////////////////////////////////////////////////////////////////
function FieldEditor(formEditor, name) {
    var self = this;
    self.formEditor = formEditor;
    self.parent     = formEditor;
    self.name       = name;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.getData = function() {
    var self = this;
    return self.parent.data.fields[self.name];
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.setData = function(data) {
    var self = this;
    self.parent.data.fields[self.name] = data;
    return self.formEditor.pageEditor.save();
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.setAttr = function(name, value) {
    var self = this;
    self.formEditor.setFieldAttr(self.name, name, value);
    return self.formEditor.pageEditor.save();
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.changeClass = function(newClassName) {
    var self = this;
    var data = this.getData();
    var newData = eval("qforms.{newClassName}Editor.createData(data['@attributes'])".replace('{newClassName}', newClassName));
    return self.setData(newData).then(function () {
        return newData;
    });
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.createEjs = function(params) {
    var self = this;
    var formData = self.formEditor.getData();
    var defaultEjsFilePath = path.join(self.defaultViewDirPath, formData['@class'] + self.getViewName() + '.ejs');
    return self.getCustomFilePath('ejs').then(function (customEjsFilePath) {
        var replaceFrom = formData['@class'] + self.getViewName();
        var replaceTo = params.page + '-' + params.form + '-' + params.field;
        return self.createFileByReplace(customEjsFilePath, defaultEjsFilePath, replaceFrom, replaceTo, null).then(function (ejs) {
            return ejs;
        });
    });
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.createCss = function(params) {
    var self = this;
    var formData = this.formEditor.getData();
    var defaultCssFilePath = path.join(this.defaultViewDirPath, formData['@class'] + this.getViewName() + '.css');
    return self.getCustomFilePath('css').then(function (customCssFilePath) {
        var replaceFrom = formData['@class'] + self.getViewName();
        var replaceTo   = params.page + '-' + params.form + '-' + params.field;
        return self.createFileByReplace(customCssFilePath, defaultCssFilePath, replaceFrom, replaceTo, null).then(function (ejs) {
            return ejs;
        });
    });
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.createJs = function(params) {
    var self = this;
    var templateFilePath = path.join(__dirname, 'Field.js.ejs');
    return self.getCustomFilePath('js').then(function (customJsFilePath) {
        return self.createFileByParams(customJsFilePath, templateFilePath, {
            page  : self.formEditor.pageEditor.pageFile.getAttr('name'),
            form  : self.formEditor.name,
            field : self.name,
            _class: self.constructor.name.replace('Editor', '')
        }).then(function (js) {
            return js;
        });
    });
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.getCollectionDirPath = function() {
    var self = this;
    return self.parent.getCustomDirPath().then(function (customDirPath) {
        var dirPath = path.join(customDirPath, 'fields');
        return qforms.Helper.createDirIfNotExists(dirPath).then(function () {
            return dirPath;
        });
    });
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.getCustomDirPath = function() {
    var self = this;
    return self.getCollectionDirPath().then(function (collectionDirPath) {
        var dirPath = path.join(collectionDirPath, self.name);
        return qforms.Helper.createDirIfNotExists(dirPath).then(function () {
            return dirPath;
        });
    });
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldEditor.prototype.getCustomFilePath = function(ext) {
    var self = this;
    return self.getCustomDirPath().then(function (customDirPath) {
        return path.join(customDirPath, self.name + '.' + ext);
    });
};<commit_msg>FieldEditor<commit_after>'use strict';

var util = require('util');
var path = require('path');
var fs   = require('fs');

var qforms = require('../../../../qforms');
var Editor = require('../Editor');

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class FieldEditor extends Editor {

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    constructor(formEditor, name) {
        super();
        var self = this;
        self.formEditor = formEditor;
        self.parent     = formEditor;
        self.name       = name;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    getData() {
        var self = this;
        return self.parent.data.fields[self.name];
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    setData(data) {
        var self = this;
        self.parent.data.fields[self.name] = data;
        return self.formEditor.pageEditor.save();
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    setAttr(name, value) {
        var self = this;
        self.formEditor.setFieldAttr(self.name, name, value);
        return self.formEditor.pageEditor.save();
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    changeClass(newClassName) {
        var self = this;
        var data = this.getData();
        var newData = eval("qforms.{newClassName}Editor.createData(data['@attributes'])".replace('{newClassName}', newClassName));
        return self.setData(newData).then(function () {
            return newData;
        });
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    createEjs(params) {
        var self = this;
        var formData = self.formEditor.getData();
        var defaultEjsFilePath = path.join(self.defaultViewDirPath, formData['@class'] + self.getViewName() + '.ejs');
        return self.getCustomFilePath('ejs').then(function (customEjsFilePath) {
            var replaceFrom = formData['@class'] + self.getViewName();
            var replaceTo = params.page + '-' + params.form + '-' + params.field;
            return self.createFileByReplace(customEjsFilePath, defaultEjsFilePath, replaceFrom, replaceTo, null).then(function (ejs) {
                return ejs;
            });
        });
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    createCss(params) {
        var self = this;
        var formData = this.formEditor.getData();
        var defaultCssFilePath = path.join(this.defaultViewDirPath, formData['@class'] + this.getViewName() + '.css');
        return self.getCustomFilePath('css').then(function (customCssFilePath) {
            var replaceFrom = formData['@class'] + self.getViewName();
            var replaceTo   = params.page + '-' + params.form + '-' + params.field;
            return self.createFileByReplace(customCssFilePath, defaultCssFilePath, replaceFrom, replaceTo, null).then(function (ejs) {
                return ejs;
            });
        });
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    createJs(params) {
        var self = this;
        var templateFilePath = path.join(__dirname, 'Field.js.ejs');
        return self.getCustomFilePath('js').then(function (customJsFilePath) {
            return self.createFileByParams(customJsFilePath, templateFilePath, {
                page  : self.formEditor.pageEditor.pageFile.getAttr('name'),
                form  : self.formEditor.name,
                field : self.name,
                _class: self.constructor.name.replace('Editor', '')
            }).then(function (js) {
                return js;
            });
        });
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    getCollectionDirPath() {
        var self = this;
        return self.parent.getCustomDirPath().then(function (customDirPath) {
            var dirPath = path.join(customDirPath, 'fields');
            return qforms.Helper.createDirIfNotExists(dirPath).then(function () {
                return dirPath;
            });
        });
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    getCustomDirPath() {
        var self = this;
        return self.getCollectionDirPath().then(function (collectionDirPath) {
            var dirPath = path.join(collectionDirPath, self.name);
            return qforms.Helper.createDirIfNotExists(dirPath).then(function () {
                return dirPath;
            });
        });
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    getCustomFilePath(ext) {
        var self = this;
        return self.getCustomDirPath().then(function (customDirPath) {
            return path.join(customDirPath, self.name + '.' + ext);
        });
    }

}

module.exports = FieldEditor;<|endoftext|>


<commit_before>var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var request = require("request");

//var connectedServers = {}
var serverQueue = []

http.listen(3000, function(){
  console.log('listening on *:3000');
});

//Returns the IP of the next server in the round-robin
function nextServer(){
    var ip = serverQueue.shift();
    serverQueue.push(ip);
    return ip;
}

app.get('/', function(req, res){
    var server = nextServer();
    request("http://" + server + ":3005" , function(error, response, body) {
        res.write("You were served by " + server + "\n")
        res.end(body);
    });
});

io.on('connection', function(socket){
  console.log(socket.request.connection._peername.address);
  var ip = socket.request.connection._peername.address;

  socket.on('cpu-usage', function(msg){
    if(serverQueue.indexOf(ip) === -1){
        serverQueue.push(ip);
    }

    //connectedServers[ip] = {time: new Date().getTime()};
    if(ip == "192.168.56.101"){
    io.emit('cpu-ip', JSON.stringify({ip: ip,
                                usage: msg}));
    }
  });

  socket.on('disconnect', function(){
    console.log('user disconnected');
    var index = serverQueue.indexOf(ip);
    if(index > -1){
        serverQueue.splice(index, 1);
    }
  });
});
<commit_msg>Changed CPU Usage to emit average<commit_after>var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var request = require("request");

//var connectedServers = {}
var serverQueue = []

http.listen(3000, function(){
  console.log('listening on *:3000');
});

//Returns the IP of the next server in the round-robin
function nextServer(){
    var ip = serverQueue.shift();
    serverQueue.push(ip);
    return ip;
}

app.get('/', function(req, res){
    var server = nextServer();
    request("http://" + server + ":3005" , function(error, response, body) {
        res.write("You were served by " + server + "\n")
        res.end(body);
    });
});

var cpu-usages = []
io.on('connection', function(socket){
  console.log(socket.request.connection._peername.address);
  var ip = socket.request.connection._peername.address;

  socket.on('cpu-usage', function(msg){
    if(serverQueue.indexOf(ip) === -1){
        serverQueue.push(ip);
    }

    cpu-usages.push(msg);

  });

  socket.on('disconnect', function(){
    console.log('user disconnected');
    var index = serverQueue.indexOf(ip);
    if(index > -1){
        serverQueue.splice(index, 1);
    }
  });
});

setTimeout(function(){
    var count = cpu-usages.length;
    if(count == 0){
        return;
    }

    var sum = 0;
    while(cpu-usages.length > 0){
        sum += cpu-usages.pop();
    }

    var average = sum / count;

    io.emit('cpu-ip', JSON.stringify({ip: "Average",
                                    usage: average.toString()}));
        }

}, 1000);
<|endoftext|>


<commit_before>//
// m16_001 #349
//
casper.test.begin('m16_001 #349 show WRLC due date', 3, function suite(test) {
casper.echo("Test environment: "+SERVER);
var USECASE='/item/2364479';
var ENTITY=SERVER+USECASE;
casper.echo(ENTITY);
    casper.start(ENTITY, function() {
    test.assertTextExists('Society of Arts', 'book title verified');
    test.assertTextDoesntExist('DUE', 'found word "DUE"');
    test.assertTextExists('Off site', 'Status "Off site" (not DUE) verified');
    }).run(function() {
        test.done();
    });
});
<commit_msg>changed Off site to Off-site<commit_after>//
// m16_001 #349
//
casper.test.begin('m16_001 #349 show WRLC due date', 3, function suite(test) {
casper.echo("Test environment: "+SERVER);
var USECASE='/item/2364479';
var ENTITY=SERVER+USECASE;
casper.echo(ENTITY);
    casper.start(ENTITY, function() {
    test.assertTextExists('Society of Arts', 'book title verified');
    test.assertTextDoesntExist('DUE', 'did not find found word "DUE"');
    test.assertTextExists('Off-site', 'Status "Off site" (not DUE) verified');
    }).run(function() {
        test.done();
    });
});
<|endoftext|>


<commit_before>angular.module('websockets test', [])
  // WebSocket function does not exist, has to be mocked!
  .value('WebSocket', WebSocket)
  .value('MockWebSocket', (function () {
    function MockWebSocket(url) {
      this._url = url;
    }

    return MockWebSocket;
  })())
  .factory('ComponentUsingMockWebSocket', [
    'MockWebSocket',
    function (MockWebSocket) {
      // just to prove it's injectable
      function ComponentUsingMockWebSocket(url) {
        this._socket = new MockWebSocket(url);
      }

      ComponentUsingMockWebSocket.prototype.getSocket = function () {
        return this._socket;
      };

      return ComponentUsingMockWebSocket;
    }
  ])
  .factory('ComponentUsingWebSocket', ['WebSocket',
    function(WebSocket) {
      function ComponentUsingWebSocket(url) {
        console.log('WebSocket', WebSocket);
        this._socket = new WebSocket(url);
      }

      ComponentUsingWebSocket.prototype.getSocket = function() {
        return this._socket;
      };

      return ComponentUsingWebSocket;

    }
  ]);

/* global ngDescribe, it */
ngDescribe({
  name: 'mock constructor function - using mock class',
  module: 'websockets test',
  inject: 'ComponentUsingMockWebSocket',
  only: false,
  tests: function (deps) {
    it('creates mock value', function () {
      var url = 'ws://mock';
      var mc = new deps.ComponentUsingMockWebSocket(url);
      la(mc.getSocket()._url === url);
    });
  }
});

ngDescribe({
  name: 'mock constructor function on the fly',
  module: 'websockets test',
  inject: 'ComponentUsingWebSocket',
  mocks: {
    'websockets test': {
      WebSocket: function (MockWebSocket, url) {
        // inject mock web socket implementation
        // the use it ourselves to create new instance
        la(check.fn(MockWebSocket));
        return new MockWebSocket(url);
      }
    }
  },
  only: false,
  tests: function (deps) {
    it('creates mock value', function () {
      var url = 'ws://mock';
      var mc = new deps.ComponentUsingWebSocket(url);
      var socket = mc.getSocket();
      la(check.object(socket), 'socket is an object', socket);
      la(socket._url === url, 'socket', socket, 'has expected url', url);
    });
  }
});
<commit_msg>white space<commit_after>angular.module('websockets test', [])
  // WebSocket function does not exist, has to be mocked!
  .value('WebSocket', WebSocket)
  .value('MockWebSocket', (function () {
    function MockWebSocket(url) {
      this._url = url;
    }

    return MockWebSocket;
  })())
  .factory('ComponentUsingMockWebSocket', [
    'MockWebSocket',
    function (MockWebSocket) {
      // just to prove it's injectable
      function ComponentUsingMockWebSocket(url) {
        this._socket = new MockWebSocket(url);
      }

      ComponentUsingMockWebSocket.prototype.getSocket = function () {
        return this._socket;
      };

      return ComponentUsingMockWebSocket;
    }
  ])
  .factory('ComponentUsingWebSocket', ['WebSocket',
    function (WebSocket) {
      function ComponentUsingWebSocket(url) {
        console.log('WebSocket', WebSocket);
        this._socket = new WebSocket(url);
      }

      ComponentUsingWebSocket.prototype.getSocket = function () {
        return this._socket;
      };

      return ComponentUsingWebSocket;

    }
  ]);

/* global ngDescribe, it */
ngDescribe({
  name: 'mock constructor function - using mock class',
  module: 'websockets test',
  inject: 'ComponentUsingMockWebSocket',
  only: false,
  tests: function (deps) {
    it('creates mock value', function () {
      var url = 'ws://mock';
      var mc = new deps.ComponentUsingMockWebSocket(url);
      la(mc.getSocket()._url === url);
    });
  }
});

ngDescribe({
  name: 'mock constructor function on the fly',
  module: 'websockets test',
  inject: 'ComponentUsingWebSocket',
  mocks: {
    'websockets test': {
      WebSocket: function (MockWebSocket, url) {
        // inject mock web socket implementation
        // the use it ourselves to create new instance
        la(check.fn(MockWebSocket));
        return new MockWebSocket(url);
      }
    }
  },
  only: false,
  tests: function (deps) {
    it('creates mock value', function () {
      var url = 'ws://mock';
      var mc = new deps.ComponentUsingWebSocket(url);
      var socket = mc.getSocket();
      la(check.object(socket), 'socket is an object', socket);
      la(socket._url === url, 'socket', socket, 'has expected url', url);
    });
  }
});
<|endoftext|>


<commit_before>module.exports = {

    // private property
    _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

    encodeBinary: function (input) {
        var output = "";
        var bytebuffer;
        var encodedCharIndexes = new Array(4);
        var inx = 0;
        var paddingBytes = 0;

        while (inx < input.length) {
            // Fill byte buffer array
            bytebuffer = new Array(3);
            for (jnx = 0; jnx < bytebuffer.length; jnx++)
                if (inx < input.length)
                    bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff; // throw away high-order byte, as documented at: https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data
                else
                    bytebuffer[jnx] = 0;

            // Get each encoded character, 6 bits at a time
            // index 1: first 6 bits
            encodedCharIndexes[0] = bytebuffer[0] >> 2;
            // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2)
            encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4);
            // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3)
            encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6);
            // index 3: forth 6 bits (6 least significant bits from input byte 3)
            encodedCharIndexes[3] = bytebuffer[2] & 0x3f;

            // Determine whether padding happened, and adjust accordingly
            paddingBytes = inx - (input.length - 1);
            switch (paddingBytes) {
                case 2:
                    // Set last 2 characters to padding char
                    encodedCharIndexes[3] = 64;
                    encodedCharIndexes[2] = 64;
                    break;
                case 1:
                    // Set last character to padding char
                    encodedCharIndexes[3] = 64;
                    break;
                default:
                    break; // No padding - proceed
            }
            // Now we will grab each appropriate character out of our keystring
            // based on our index array and append it to the output string
            for (jnx = 0; jnx < encodedCharIndexes.length; jnx++)
                output += this._keyStr.charAt(encodedCharIndexes[jnx]);
        }
        return output;
    }
}
<commit_msg>jshint fixes for b64 lib<commit_after>module.exports = {

    // private property
    _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

    encodeBinary: function (input) {
        var output = "";
        var bytebuffer;
        var encodedCharIndexes = new Array(4);
        var inx = 0;
        var jnx = 0;
        var paddingBytes = 0;

        while (inx < input.length) {
            // Fill byte buffer array
            bytebuffer = new Array(3);
            for (jnx = 0; jnx < bytebuffer.length; jnx++) {
                if (inx < input.length) {
                    // throw away high-order byte, as documented at:
                    // https://developer.mozilla.org/En/Using_XMLHttpRequest#Handling_binary_data
                    bytebuffer[jnx] = input.charCodeAt(inx++) & 0xff;
                }
                else {
                    bytebuffer[jnx] = 0;
                }
            }

            // Get each encoded character, 6 bits at a time
            // index 1: first 6 bits
            encodedCharIndexes[0] = bytebuffer[0] >> 2;
            // index 2: second 6 bits (2 least significant bits from input byte 1 + 4 most significant bits from byte 2)
            encodedCharIndexes[1] = ((bytebuffer[0] & 0x3) << 4) | (bytebuffer[1] >> 4);
            // index 3: third 6 bits (4 least significant bits from input byte 2 + 2 most significant bits from byte 3)
            encodedCharIndexes[2] = ((bytebuffer[1] & 0x0f) << 2) | (bytebuffer[2] >> 6);
            // index 3: forth 6 bits (6 least significant bits from input byte 3)
            encodedCharIndexes[3] = bytebuffer[2] & 0x3f;

            // Determine whether padding happened, and adjust accordingly
            paddingBytes = inx - (input.length - 1);
            switch (paddingBytes) {
                case 2:
                    // Set last 2 characters to padding char
                    encodedCharIndexes[3] = 64;
                    encodedCharIndexes[2] = 64;
                    break;

                case 1:
                    // Set last character to padding char
                    encodedCharIndexes[3] = 64;
                    break;

                default:
                    break; // No padding - proceed
            }

            // Now we will grab each appropriate character out of our keystring
            // based on our index array and append it to the output string
            for (jnx = 0; jnx < encodedCharIndexes.length; jnx++) {
                output += this._keyStr.charAt(encodedCharIndexes[jnx]);
            }
        }
        return output;
    }
};
<|endoftext|>


<commit_before>import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Autocomplete from 'react-autocomplete';
import isEmpty from 'lodash/isEmpty';
import { Link } from 'react-router-dom';

import Card         from '../../../../shared/Card';
import CheckboxList from '../../../../shared/CheckboxList';
import Icon         from '../../../../shared/Icon';
import LocalNav     from '../../../../shared/LocalNav';

import Pagination from '../Pagination';

import { actionCreators as actions } from '../../redux/modules/search';
import { actionCreators as paginationActions } from '../../redux/modules/pagination';

import './Catalogue.css';

export class Catalogue extends React.Component {

  render () {
    const { actions, search = {}, pagination = {} } = this.props;

    const cards = search.view === 'sellers' ? search.results : search[search.view];

    return (

        <form onSubmit={e => e.preventDefault()}>

Seller catalogue

                    Search by company name, role you need or the outcome you are after

                  <Autocomplete
                    value={search.keyword || ''}
                    inputProps={{
                      name: 'keyword',
                      id: 'keyword',
                      placeholder: 'Search'
                    }}
                    items={search.results.slice(0, 10)}
                    getItemValue={({ title }) => title}
                    onSelect={(value, item) => actions.updateKeyword(value)}
                    onChange={(e, value) => actions.updateKeyword(value)}
                    renderItem={(item, isHighlighted) => (

{item.title}

                    )}
                    renderMenu={(items, value, style) => {
                      //return ;
                      // renderMenu can't return null, internals of Autocomplete
                      // call clone on this result. Empty span will have to do.
                      if (!value || items.length === 0) {
                        return ;
                      }

                      return (

                          {items}

                      )
                    }}
                  />

                  <button type="submit" value="" style={{ border: 'none', backgroundColor: '#18788d', color: '#fff' }}>
                    <Icon value="search" size={22} />
                  </button>

Filter your results

              <LocalNav navClassName="filter-navigation" text="Filter your results">
                <CheckboxList
                  id="role"
                  list={search.role}
                  onChange={actions.updateRole}
                />

                <CheckboxList
                  id="type"
                  list={search.type}
                  onChange={actions.updateType}
                />

              </LocalNav>

              {search.error ? (

Something went wrong!

<Link to="/" onClick={(e) => {
                    e.preventDefault();
                    actions.resetQuery();
                  }}>Reset and try again</Link>.

              ) : (

                          <Link
                            to={{ search: 'view=sellers' }}
                            onClick={(e) => {
                              e.preventDefault();

                              if (pagination.page !== 1) {
                                  actions.updatePage(1);
                              }

                              actions.updateView('sellers');
                            }}
                            styleName={`${search.view === 'sellers' ? 'active-filter' : ''} filter`}>
                            {pagination['sellers'].total} Sellers
                          </Link>
                          <Link
                            to={{ search: 'view=products' }}
                            onClick={(e) => {
                              e.preventDefault();

                              if (pagination.page !== 1) {
                                  actions.updatePage(1);
                              }

                              actions.updateView('products');
                            }}
                            styleName={`${search.view === 'products' ? 'active-filter' : ''} filter`}>
                            {pagination['products'].total} Products
                          </Link>
                            {false && <Link
                            to={{ search: 'view=casestudies' }}
                            onClick={(e) => {
                              e.preventDefault();

                              if (pagination.page !== 1) {
                                  actions.updatePage(1);
                              }

                              actions.updateView('casestudies');
                            }}
                            styleName={`${search.view === 'casestudies' ? 'active-filter' : ''} filter`}>
                            {pagination['casestudies'].total} Case Studies
                          </Link> }

                          <fieldset>
                            <legend>Sort by</legend>

                              <input
                                type="radio"
                                name="sort_by"
                                id="sort-a-z"
                                value="a-z"
                                checked={search.sort_by === 'a-z'}
                                onChange={actions.updateSort}
                              />
                              A to Z

                              <input
                                type="radio"
                                name="sort_by"
                                id="sort-latest"
                                value="latest"
                                checked={search.sort_by === 'latest'}
                                onChange={actions.updateSort}
                              />
                              Newest

                          </fieldset>

                    {isEmpty(cards) ? (

No exact matches

Try tweaking your search criteria for more results or <Link to="/" onClick={(e) => {
                            e.preventDefault();
                            actions.resetQuery();
                          }}>clear all and start again</Link>.

                      ) :
                    (

                      {cards.map((result, i) => (
                        <Card {...result} key={i} />
                      ))}

)}

                    <Pagination
                      {...pagination[search.view]}
                      onClick={actions.updatePage}
                      onBack={actions.updatePage}
                      onNext={actions.updatePage}
                    />

              )}

        </form>

    )
  }
};

export const mapStateToProps = ({ search, pagination }, ownProps) => {
  return {
    search,
    pagination
  }
};

const mapDispatchToProps = dispatch => ({
  actions: bindActionCreators({ ...actions, ...paginationActions }, dispatch)
});

export default connect(mapStateToProps, mapDispatchToProps)(Catalogue);
<commit_msg>Enable case study search for buyers (#329)<commit_after>import React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Autocomplete from 'react-autocomplete';
import isEmpty from 'lodash/isEmpty';
import { Link } from 'react-router-dom';

import Card         from '../../../../shared/Card';
import CheckboxList from '../../../../shared/CheckboxList';
import Icon         from '../../../../shared/Icon';
import LocalNav     from '../../../../shared/LocalNav';

import Pagination from '../Pagination';

import { actionCreators as actions } from '../../redux/modules/search';
import { actionCreators as paginationActions } from '../../redux/modules/pagination';

import './Catalogue.css';

export class Catalogue extends React.Component {

  render () {
    const { actions, search = {}, pagination = {} } = this.props;

    const cards = search.view === 'sellers' ? search.results : search[search.view];

    return (

        <form onSubmit={e => e.preventDefault()}>

Seller catalogue

                    Search by company name, role you need or the outcome you are after

                  <Autocomplete
                    value={search.keyword || ''}
                    inputProps={{
                      name: 'keyword',
                      id: 'keyword',
                      placeholder: 'Search'
                    }}
                    items={search.results.slice(0, 10)}
                    getItemValue={({ title }) => title}
                    onSelect={(value, item) => actions.updateKeyword(value)}
                    onChange={(e, value) => actions.updateKeyword(value)}
                    renderItem={(item, isHighlighted) => (

{item.title}

                    )}
                    renderMenu={(items, value, style) => {
                      //return ;
                      // renderMenu can't return null, internals of Autocomplete
                      // call clone on this result. Empty span will have to do.
                      if (!value || items.length === 0) {
                        return ;
                      }

                      return (

                          {items}

                      )
                    }}
                  />

                  <button type="submit" value="" style={{ border: 'none', backgroundColor: '#18788d', color: '#fff' }}>
                    <Icon value="search" size={22} />
                  </button>

Filter your results

              <LocalNav navClassName="filter-navigation" text="Filter your results">
                <CheckboxList
                  id="role"
                  list={search.role}
                  onChange={actions.updateRole}
                />

                <CheckboxList
                  id="type"
                  list={search.type}
                  onChange={actions.updateType}
                />

              </LocalNav>

              {search.error ? (

Something went wrong!

<Link to="/" onClick={(e) => {
                    e.preventDefault();
                    actions.resetQuery();
                  }}>Reset and try again</Link>.

              ) : (

                          <Link
                            to={{ search: 'view=sellers' }}
                            onClick={(e) => {
                              e.preventDefault();

                              if (pagination.page !== 1) {
                                  actions.updatePage(1);
                              }

                              actions.updateView('sellers');
                            }}
                            styleName={`${search.view === 'sellers' ? 'active-filter' : ''} filter`}>
                            {pagination['sellers'].total} Sellers
                          </Link>
                          <Link
                            to={{ search: 'view=products' }}
                            onClick={(e) => {
                              e.preventDefault();

                              if (pagination.page !== 1) {
                                  actions.updatePage(1);
                              }

                              actions.updateView('products');
                            }}
                            styleName={`${search.view === 'products' ? 'active-filter' : ''} filter`}>
                            {pagination['products'].total} Products
                          </Link>
                            {search['casestudies'] !== null  && <Link
                            to={{ search: 'view=casestudies' }}
                            onClick={(e) => {
                              e.preventDefault();

                              if (pagination.page !== 1) {
                                  actions.updatePage(1);
                              }

                              actions.updateView('casestudies');
                            }}
                            styleName={`${search.view === 'casestudies' ? 'active-filter' : ''} filter`}>
                            {pagination['casestudies'].total} Case Studies
                          </Link> }

                          <fieldset>
                            <legend>Sort by</legend>

                              <input
                                type="radio"
                                name="sort_by"
                                id="sort-a-z"
                                value="a-z"
                                checked={search.sort_by === 'a-z'}
                                onChange={actions.updateSort}
                              />
                              A to Z

                              <input
                                type="radio"
                                name="sort_by"
                                id="sort-latest"
                                value="latest"
                                checked={search.sort_by === 'latest'}
                                onChange={actions.updateSort}
                              />
                              Newest

                          </fieldset>

                    {isEmpty(cards) ? (

No exact matches

Try tweaking your search criteria for more results or <Link to="/" onClick={(e) => {
                            e.preventDefault();
                            actions.resetQuery();
                          }}>clear all and start again</Link>.

                      ) :
                    (

                      {cards.map((result, i) => (
                        <Card {...result} key={i} />
                      ))}

)}

                    <Pagination
                      {...pagination[search.view]}
                      onClick={actions.updatePage}
                      onBack={actions.updatePage}
                      onNext={actions.updatePage}
                    />

              )}

        </form>

    )
  }
};

export const mapStateToProps = ({ search, pagination }, ownProps) => {
  return {
    search,
    pagination
  }
};

const mapDispatchToProps = dispatch => ({
  actions: bindActionCreators({ ...actions, ...paginationActions }, dispatch)
});

export default connect(mapStateToProps, mapDispatchToProps)(Catalogue);
<|endoftext|>


<commit_before>/**
 * @description
 * This module sets all configuration
 *
 * policyCompassConfig is exposed as a global variable in order to use it in
 * the main app.js file. If there's a way to do the same with dependency
 * injection, this should be fixed.
 */

var policyCompassConfig = {
    'URL': '/api/v1',
    'METRICS_MANAGER_URL': '/api/v1/metricsmanager',
    'VISUALIZATIONS_MANAGER_URL': '/api/v1/visualizationsmanager',
    'EVENTS_MANAGER_URL': '/api/v1/eventsmanager',
    'REFERENCE_POOL_URL': '/api/v1/references',
    'FCM_URL': '/api/v1/fcmmanager',
    'ELASTIC_URL' : 'localhost:9000',
    'ELASTIC_INDEX_NAME' : 'policycompass_search',
    // FIXME: disabling adhocracy doesn't work due to use of
    // UserState controller in index.html
    'ENABLE_ADHOCRACY': true,
    'ADHOCRACY_BACKEND_URL': 'http://localhost:6541',
    'ADHOCRACY_FRONTEND_URL': 'http://localhost:6551'
};

angular.module('pcApp.config', [])

.constant('API_CONF', policyCompassConfig);
<commit_msg>Updated Config Sample for Remote Service Use<commit_after>/**
 * @description
 * This module sets all configuration
 *
 * policyCompassConfig is exposed as a global variable in order to use it in
 * the main app.js file. If there's a way to do the same with dependency
 * injection, this should be fixed.
 */

// Set to true to use the frontend stand-alone without installing the services
var useRemoteServices = false;

// Configuration for locally installed services
var policyCompassConfig = {
    'URL': '/api/v1',
    'METRICS_MANAGER_URL': '/api/v1/metricsmanager',
    'VISUALIZATIONS_MANAGER_URL': '/api/v1/visualizationsmanager',
    'EVENTS_MANAGER_URL': '/api/v1/eventsmanager',
    'REFERENCE_POOL_URL': '/api/v1/references',
    'FCM_URL': '/api/v1/fcmmanager',
    'ELASTIC_URL' : 'localhost:9000',
    'ELASTIC_INDEX_NAME' : 'policycompass_search',
    // FIXME: disabling adhocracy doesn't work due to use of
    // UserState controller in index.html
    'ENABLE_ADHOCRACY': true,
    'ADHOCRACY_BACKEND_URL': 'http://localhost:6541',
    'ADHOCRACY_FRONTEND_URL': 'http://localhost:6551'
};

// Configuration for remote services
var remotePolicyCompassConfig = {
    'URL': '/api/v1',
    'METRICS_MANAGER_URL': 'https://services-dev.policycompass.eu/api/v1/metricsmanager',
    'VISUALIZATIONS_MANAGER_URL': 'https://services-dev.policycompass.eu/api/v1/visualizationsmanager',
    'EVENTS_MANAGER_URL': 'https://services-dev.policycompass.eu/api/v1/eventsmanager',
    'REFERENCE_POOL_URL': 'https://services-dev.policycompass.eu/api/v1/references',
    'FCM_URL': 'https://alpha.policycompass.eu/api/v1/fcmmanager',
    'ELASTIC_URL' : 'https://search-dev.policycompass.eu/',
    'ELASTIC_INDEX_NAME' : 'policycompass_search',
    'ENABLE_ADHOCRACY': true,
    'ADHOCRACY_BACKEND_URL': 'https://adhocracy-backend-dev.policycompass.eu',
    'ADHOCRACY_FRONTEND_URL': 'https://adhocracy-frontend-dev.policycompass.eu'
};

if(useRemoteServices == false) {
    angular.module('pcApp.config', []).constant('API_CONF', policyCompassConfig);
} else {
    angular.module('pcApp.config', []).constant('API_CONF', remotePolicyCompassConfig);
}

<|endoftext|>


<commit_before>/* http://nanobar.micronube.com/  ||  https://github.com/jacoborus/nanobar/    MIT LICENSE */

var addCss, Bar, Nanobar, move, place, init,
	cssCont = {
		width: '100%',
		height: '4px',
		zIndex: 9999,
		bottom: '0'
	},
	cssBar = {
		width: 0,
		height: '100%',
		clear: 'both',
		transition: 'height .3s'
	};

addCss = function (el, css) {
	var i;
	for (i in css) {
		el.style[i] = css[i];
	}
	el.style.float = 'left';
};

move = function () {
	var self = this,
		dist = this.width - this.here;

	if (dist < 0.1 && dist > -0.1) {
		place.call(this, this.here);
		this.moving = false;
		if (this.width == 100) {
			this.el.style.height = 0;
			setTimeout(function () {
				self.cont.el.removeChild(self.el);
			}, 300);
		}
	} else {
		place.call(this, this.width - (dist / 4));
		setTimeout(function () {
			self.go();
		}, 16);
	}
};

place = function (num) {
	this.width = num;
	this.el.style.width = this.width + '%';
};

init = function () {
	var bar = new Bar(this);
	this.bars.unshift(bar);
};

Bar = function (cont) {
	this.el = document.createElement('div');
	this.el.style.backgroundColor = cont.opts.bg;
	this.width = 0;
	this.here = 0;
	this.moving = false;
	this.cont = cont;
	addCss(this.el, cssBar);
	cont.el.appendChild(this.el);
};

Bar.prototype.go = function (num) {
	if (num) {
		this.here = num;
		if (!this.moving) {
			this.moving = true;
			move.call(this);
		}
	} else if (this.moving) {
		move.call(this);
	}
};

Nanobar = function () {
	var opts = this.opts = {}, el;
	opts.bg = '#F44336';
	this.bars = [];

	el = this.el = document.createElement('div');
	addCss(this.el, cssCont);
	el.style.position = 'fixed';
	document.getElementsByTagName('body')[0].appendChild(el);

	init.call(this);
};

Nanobar.prototype.go = function (p) {
	this.bars[0].go(p);
	if (p == 100) {
		init.call(this);
	}
};

EchoesWorks.bar = Nanobar;<commit_msg>remove unused code<commit_after>/* http://nanobar.micronube.com/  ||  https://github.com/jacoborus/nanobar/    MIT LICENSE */

var addCss, Bar, Nanobar, move, place, init,
	cssCont = {
		width: '100%',
		height: '4px',
		zIndex: 9999,
		bottom: '0'
	},
	cssBar = {
		width: 0,
		height: '100%',
		clear: 'both',
		transition: 'height .3s'
	};

addCss = function (el, css) {
	var i;
	for (i in css) {
		el.style[i] = css[i];
	}
	el.style.float = 'left';
};

move = function () {
	var self = this,
		dist = this.width - this.here;

	if (dist < 0.1 && dist > -0.1) {
		place.call(this, this.here);
		this.moving = false;
		if (this.width == 100) {
			this.el.style.height = 0;
			setTimeout(function () {
				self.cont.el.removeChild(self.el);
			}, 300);
		}
	} else {
		place.call(this, this.width - (dist / 4));
		setTimeout(function () {
			self.go();
		}, 16);
	}
};

place = function (num) {
	this.width = num;
	this.el.style.width = this.width + '%';
};

init = function () {
	var bar = new Bar(this);
	this.bars.unshift(bar);
};

Bar = function (cont) {
	this.el = document.createElement('div');
	this.el.style.backgroundColor = '#F44336';
	this.width = 0;
	this.here = 0;
	this.moving = false;
	this.cont = cont;
	addCss(this.el, cssBar);
	cont.el.appendChild(this.el);
};

Bar.prototype.go = function (num) {
	if (num) {
		this.here = num;
		if (!this.moving) {
			this.moving = true;
			move.call(this);
		}
	} else if (this.moving) {
		move.call(this);
	}
};

Nanobar = function () {
	this.bars = [];

	this.el = document.createElement('div');
	addCss(this.el, cssCont);
	this.el.style.position = 'fixed';
	document.getElementsByTagName('body')[0].appendChild(this.el);

	init.call(this);
};

Nanobar.prototype.go = function (p) {
	this.bars[0].go(p);
	if (p == 100) {
		init.call(this);
	}
};

EchoesWorks.bar = Nanobar;<|endoftext|>


<commit_before>/**
 * Router configuration
 */

var express = require('express');
var config  = require('./config');
var mongoose = require('mongoose');

// Load routes
var home = require('../routes/');
var user  = require('../routes/user');
var manage = require('../routes/manage');

var api = {
  home : require('../routes/api/home'),
  manage : require('../routes/api/manage'),
  user : require('../routes/api/user'),
  app : require('../routes/api/app')
};

// DB models
var App = mongoose.model('App');

function securityHeaders(req, res, next) {
  // https://www.owasp.org/index.php/REST_Security_Cheat_Sheet#Send_security_headers
  res.set('X-Content-Type-Options', 'nosniff');
  res.set('X-Frame-Options', 'deny');
  next();
}

function handleManage(req, res) {
  if(req.originalUrl.indexOf('manage') !== -1) {
    home.index(req, res);
    return true;
  }

  return false;
}

function ensureAuthenticated(req, res, next) {
  if(req.isAuthenticated()) return next();

  if(handleManage(req, res)) return;

  res.set('X-Auth-Required', 'true');
  //res.redirect('/login/?returnTo=' + encodeURIComponent(req.originalUrl));
  res.redirect('/u/login');
}

function ensureAuthenticatedAPI(req, res, next) {
  if(req.isAuthenticated()) return next();

  res.set('X-Auth-Required', 'true');
  res.status(401).send('Authentication is required');
}

function ensureAdmin(req, res, next) {
  if(req.user.roles.admin) return next();

  if(handleManage(req, res)) return;

  res.set('X-Auth-Required', 'true');
  //res.redirect('/login/?returnTo=' + encodeURIComponent(req.originalUrl));
  res.redirect('/login');
}

function ensureXhr(req, res, next) {
  // Requests from mobile app are not xhr, therefore don't use for now
  //if(!req.xhr) return res.send('');

  /**
   * For CORS
   *
  res.header('Access-Control-Allow-Origin',  req.headers.origin || "*");
  res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'content-Type,x-requested-with');
   */

  next();
}

function ensureApplication(req, res, next) {
  var token = req.get('App-Token');

  if(!token) {
    return res.status(401).send('Specify application token');
  }

  App
  .findOne({
    token : token
  })
  .exec(function (err, app) {
    if(err) console.log(err);

    // App is found
    if(app) {
      app.lastAccessed = new Date();
      app.save();

      return next();
    }

    return res.status(401).send('Specify application token');
  });
}

function setCache(res, val) {
  if(!val) return res.set('Cache-Control', 'no-cache');
  res.set('Cache-Control', 'public, max-age=' + val);
}

function setShortCacheHeader(req, res, next) {
  setCache(res, config[req.app.get('env')].cache.day);
  next();
}

function setLongCacheHeader(req, res, next) {
  setCache(res, config[req.app.get('env')].cache.month);
  next();
}

// Set up router
module.exports = function (passport) {

  /**
   * ===========================================================
   * API set up
   *   1) Manage API
   *   2) Home API
   *   3) User API
   *   4) Applications API
   */

  /**
   * Manage API
   */
  var manageApiRouter = express.Router();
  manageApiRouter
    .use(ensureAuthenticatedAPI)
    .use(ensureAdmin)
    .use(ensureXhr)

    .get(   '/model/:model/config', api.manage.modelConfig)
    .get(   '/model/:model',        api.manage.model)
    .put(   '/model/:model/:id',    api.manage.editModel)
    .delete('/model/:model/:id',    api.manage.deleteModel)

    .get('/model', api.manage.getModels)

    .get('/message',    api.manage.getMessages)
    .get('/serverdata', api.manage.getServerData)

    .post('/filter', api.manage.addFilter)

    .post(  '/app',     api.manage.addApp)
    .get(   '/app',     api.manage.getApps)
    .delete('/app/:id', api.manage.deleteApp);

  /**
   * Home API
   */
  var apiRouter = express.Router();
  apiRouter
    .get('/timestamp', api.home.getTimestamp) // For lukkari-sync to ping app

    .use(ensureXhr)
    .post('/message', api.home.sendMsg)

    .get('/schedule/:q/now', api.home.getNowSchedule)
    // For some API methods set cache header
    // Schedule pages use short
    .use(setShortCacheHeader)
    .get(  '/schedule/:q', api.home.getSchedule)
    // Categories use long
    .use(setLongCacheHeader)
    .get('/groups',   api.home.getGroups)
    .get('/teachers', api.home.getTeachers)
    .get('/rooms',    api.home.getRooms)
    .get('/filters',  api.home.getFilters)
    .get('*',         api.home.notFound);

  /**
   * User API
   */
  var userApiRouter = express.Router();
  userApiRouter
    .get('/login',
      passport.authenticate('basic', { session: true }),
      api.user.login
    )

    .use(ensureAuthenticatedAPI)
    .get(   '/schedule',      api.user.getSchedule)
    .get(   '/schedule/now',  api.user.getNowSchedule)
    .delete('/subject/:id',   api.user.removeSubject)
    .post(  '/subject/:id',   api.user.addSubject)
    .get(   '/subject',       api.user.findSubject)
    .get(   '/usertable',     api.user.getUserTable)
    .delete('/usertable/:id', api.user.removeFromUserTable);

  /**
   * Applications API
   */
  var appApiRouter = express.Router();
  appApiRouter
    .use(ensureApplication)
    .get('/new_version/:filter', api.app.newVersion)
    .post('/entry', api.app.addEntry);

  /**
   * =====================================================
   * Page set up
   *   1) Manage page
   *   2) User page
   *   3) Home page
   */

  /**
   * Manage page
   */
  var manageRouter = express.Router();
  manageRouter
    .use(ensureAuthenticated)
    .use(ensureAdmin)
    .get('/*', manage.index);

  /**
   * User page
   */
  var userRouter = express.Router();
  userRouter
    // Log in
    .get( '/login', user.login)
    .post('/login',
      passport.authenticate('local', {
        successRedirect: '/my',
        failureRedirect: '/u/login?wrong'
      })
    )

    // Sign up
    .get( '/signup', user.signup)
    .post('/signup', user.create)

    // When user logged
    .use(ensureAuthenticated)
    .get( '/',       user.me)
    .post('/',       user.update)
    .get( '/group',  user.selectGroup)
    .post('/group',  user.addGroup)
    .get('/logout',  user.logout);

  /**
   * Home page
   */
  var homeRouter = express.Router();
  homeRouter
    .use(setLongCacheHeader)
    // Main page
    .get('/*',      home.index);

  /**
   * ==================================================
   * Add all routers to the main router
   */

  var router = express.Router();

  router
    .use(securityHeaders)
    .use('/manage/api', manageApiRouter)
    .use('/manage',     manageRouter)
    .use('/u',          userRouter)
    .use('/api/app',    appApiRouter)
    .use('/api/user',   userApiRouter)
    .use('/api',        apiRouter)
    .use('/',           homeRouter);

  return router;
};
<commit_msg>Set cors headers<commit_after>/**
 * Router configuration
 */

var express = require('express');
var config  = require('./config');
var mongoose = require('mongoose');

// Load routes
var home = require('../routes/');
var user  = require('../routes/user');
var manage = require('../routes/manage');

var api = {
  home : require('../routes/api/home'),
  manage : require('../routes/api/manage'),
  user : require('../routes/api/user'),
  app : require('../routes/api/app')
};

// DB models
var App = mongoose.model('App');

function securityHeaders(req, res, next) {
  // https://www.owasp.org/index.php/REST_Security_Cheat_Sheet#Send_security_headers
  res.set('X-Content-Type-Options', 'nosniff');
  res.set('X-Frame-Options', 'deny');
  next();
}

function handleManage(req, res) {
  if(req.originalUrl.indexOf('manage') !== -1) {
    home.index(req, res);
    return true;
  }

  return false;
}

function ensureAuthenticated(req, res, next) {
  if(req.isAuthenticated()) return next();

  if(handleManage(req, res)) return;

  res.set('X-Auth-Required', 'true');
  //res.redirect('/login/?returnTo=' + encodeURIComponent(req.originalUrl));
  res.redirect('/u/login');
}

function ensureAuthenticatedAPI(req, res, next) {
  if(req.isAuthenticated()) return next();

  res.set('X-Auth-Required', 'true');
  res.status(401).send('Authentication is required');
}

function ensureAdmin(req, res, next) {
  if(req.user.roles.admin) return next();

  if(handleManage(req, res)) return;

  res.set('X-Auth-Required', 'true');
  //res.redirect('/login/?returnTo=' + encodeURIComponent(req.originalUrl));
  res.redirect('/login');
}

function ensureXhr(req, res, next) {
  // Requests from mobile app are not xhr, therefore don't use for now
  //if(!req.xhr) return res.send('');

  /**
   * CORS
   */
  res.set('Access-Control-Allow-Origin',  '*');
  res.set('Access-Control-Allow-Credentials', true);
  res.set('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS');
  res.set('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');

  next();
}

function ensureApplication(req, res, next) {
  var token = req.get('App-Token');

  if(!token) {
    return res.status(401).send('Specify application token');
  }

  App
  .findOne({
    token : token
  })
  .exec(function (err, app) {
    if(err) console.log(err);

    // App is found
    if(app) {
      app.lastAccessed = new Date();
      app.save();

      return next();
    }

    return res.status(401).send('Specify application token');
  });
}

function setCache(res, val) {
  if(!val) return res.set('Cache-Control', 'no-cache');
  res.set('Cache-Control', 'public, max-age=' + val);
}

function setShortCacheHeader(req, res, next) {
  setCache(res, config[req.app.get('env')].cache.day);
  next();
}

function setLongCacheHeader(req, res, next) {
  setCache(res, config[req.app.get('env')].cache.month);
  next();
}

// Set up router
module.exports = function (passport) {

  /**
   * ===========================================================
   * API set up
   *   1) Manage API
   *   2) Home API
   *   3) User API
   *   4) Applications API
   */

  /**
   * Manage API
   */
  var manageApiRouter = express.Router();
  manageApiRouter
    .use(ensureAuthenticatedAPI)
    .use(ensureAdmin)
    .use(ensureXhr)

    .get(   '/model/:model/config', api.manage.modelConfig)
    .get(   '/model/:model',        api.manage.model)
    .put(   '/model/:model/:id',    api.manage.editModel)
    .delete('/model/:model/:id',    api.manage.deleteModel)

    .get('/model', api.manage.getModels)

    .get('/message',    api.manage.getMessages)
    .get('/serverdata', api.manage.getServerData)

    .post('/filter', api.manage.addFilter)

    .post(  '/app',     api.manage.addApp)
    .get(   '/app',     api.manage.getApps)
    .delete('/app/:id', api.manage.deleteApp);

  /**
   * Home API
   */
  var apiRouter = express.Router();
  apiRouter
    .get('/timestamp', api.home.getTimestamp) // For lukkari-sync to ping app

    .use(ensureXhr)
    .post('/message', api.home.sendMsg)

    .get('/schedule/:q/now', api.home.getNowSchedule)
    // For some API methods set cache header
    // Schedule pages use short
    .use(setShortCacheHeader)
    .get(  '/schedule/:q', api.home.getSchedule)
    // Categories use long
    .use(setLongCacheHeader)
    .get('/groups',   api.home.getGroups)
    .get('/teachers', api.home.getTeachers)
    .get('/rooms',    api.home.getRooms)
    .get('/filters',  api.home.getFilters)
    .get('*',         api.home.notFound);

  /**
   * User API
   */
  var userApiRouter = express.Router();
  userApiRouter
    .get('/login',
      passport.authenticate('basic', { session: true }),
      api.user.login
    )

    .use(ensureAuthenticatedAPI)
    .get(   '/schedule',      api.user.getSchedule)
    .get(   '/schedule/now',  api.user.getNowSchedule)
    .delete('/subject/:id',   api.user.removeSubject)
    .post(  '/subject/:id',   api.user.addSubject)
    .get(   '/subject',       api.user.findSubject)
    .get(   '/usertable',     api.user.getUserTable)
    .delete('/usertable/:id', api.user.removeFromUserTable);

  /**
   * Applications API
   */
  var appApiRouter = express.Router();
  appApiRouter
    .use(ensureApplication)
    .get('/new_version/:filter', api.app.newVersion)
    .post('/entry', api.app.addEntry);

  /**
   * =====================================================
   * Page set up
   *   1) Manage page
   *   2) User page
   *   3) Home page
   */

  /**
   * Manage page
   */
  var manageRouter = express.Router();
  manageRouter
    .use(ensureAuthenticated)
    .use(ensureAdmin)
    .get('/*', manage.index);

  /**
   * User page
   */
  var userRouter = express.Router();
  userRouter
    // Log in
    .get( '/login', user.login)
    .post('/login',
      passport.authenticate('local', {
        successRedirect: '/my',
        failureRedirect: '/u/login?wrong'
      })
    )

    // Sign up
    .get( '/signup', user.signup)
    .post('/signup', user.create)

    // When user logged
    .use(ensureAuthenticated)
    .get( '/',       user.me)
    .post('/',       user.update)
    .get( '/group',  user.selectGroup)
    .post('/group',  user.addGroup)
    .get('/logout',  user.logout);

  /**
   * Home page
   */
  var homeRouter = express.Router();
  homeRouter
    .use(setLongCacheHeader)
    // Main page
    .get('/*',      home.index);

  /**
   * ==================================================
   * Add all routers to the main router
   */

  var router = express.Router();

  router
    .use(securityHeaders)
    .use('/manage/api', manageApiRouter)
    .use('/manage',     manageRouter)
    .use('/u',          userRouter)
    .use('/api/app',    appApiRouter)
    .use('/api/user',   userApiRouter)
    .use('/api',        apiRouter)
    .use('/',           homeRouter);

  return router;
};
<|endoftext|>


<commit_before>'use strict';

import dbg from 'debug';
import app from './../../app';
import http from 'http';

const debug = dbg('nerd-stack:server');
const port = normalizePort(process.env.PORT || '3000');

app.set('port', port);

let server = http.createServer(app);
server.listen(port);

server.on('error', onError);
server.on('listening', onListening);

function normalizePort(val) {
  const returnable = parseInt(val, 10);

  if (isNaN(returnable)) {
    // named pipe
    return val;
  }

  if (returnable >= 0) {
    // port number
    return returnable;
  }

  return false;
}

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  const bind = typeof port === 'string'
      ? 'Pipe ' + port
      : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      error.message = error.message + '. ' + bind + ' requires elevated privileges';
      throw error;
    case 'EADDRINUSE':
      error.message = error.message + '. ' + bind + ' is already in use';

      setTimeout(function () {
        server.close();
        server.listen(port);
      }, 1000);
      break;
    default:
      throw error;
  }
}

function onListening() {
  const addr = server.address();
  const bind = typeof addr === 'string'
      ? 'pipe ' + addr
      : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

process.on('SIGTERM', function () {
  server.close();
});
<commit_msg>Update server.js<commit_after>'use strict';

import dbg from 'debug';
import app from './../../app';
import http from 'http';

function normalizePort(val) {
  const returnable = parseInt(val, 10);

  if (isNaN(returnable)) {
    // named pipe
    return val;
  }

  if (returnable >= 0) {
    // port number
    return returnable;
  }

  return false;
}

const debug = dbg('nerd-stack:server');
const port = normalizePort(process.env.PORT || '3000');

app.set('port', port);

let server = http.createServer(app);
server.listen(port);

server.on('error', onError);
server.on('listening', onListening);

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  const bind = typeof port === 'string'
      ? 'Pipe ' + port
      : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      error.message = error.message + '. ' + bind + ' requires elevated privileges';
      throw error;
    case 'EADDRINUSE':
      error.message = error.message + '. ' + bind + ' is already in use';

      setTimeout(function () {
        server.close();
        server.listen(port);
      }, 1000);
      break;
    default:
      throw error;
  }
}

function onListening() {
  const addr = server.address();
  const bind = typeof addr === 'string'
      ? 'pipe ' + addr
      : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

process.on('SIGTERM', function () {
  server.close();
});
<|endoftext|>