<commit_before>var titles;
var descriptions;

var showAbout = false;
var showContact = false;
var trans = false;

$(document).ready(function() {

    $("#fullBg").backstretch(["img/main/1.jpg"],{duration: 4500, fade: 3500});
    titles = ["001", "002", "003", "004", "005", "006", "007", "008", "009", "010"];
    descriptions = ["Description description content description stuff",
                    "stuff stuff stuff describing things that are real",
                    "Description description content description stuff",
                    "stuff stuff stuff describing things that are real",
                    "Description description content description stuff",
                    "stuff stuff stuff describing things that are real",
                    "Description description content description stuff",
                    "stuff stuff stuff describing things that are real",
                    "Description description content description stuff",
                    "stuff stuff stuff describing things that are real"]

    $("#projName").html(titles[0]);
    $("#projDesc").html(descriptions[0]);

    var Menu;
    if (Modernizr.csstransitions && Modernizr.csstransforms) {
        Menu = {
            el: {
                ham: $('.menu'),
                menuTop: $('.menu-top'),
                menuMiddle: $('.menu-middle'),
                menuBottom: $('.menu-bottom')
            },
            init: function() {
                Menu.bindUIactions();
            },
            bindUIactions: function() {
                Menu.el.ham
                .on('click',
                    function(event) {
                    Menu.activateMenu(event);
                    event.preventDefault();
                    $("#my-menu").trigger("open.mm");
                    }
                );
            },
            activateMenu: function() {
                Menu.el.menuTop.toggleClass('menu-top-click');
                Menu.el.menuMiddle.toggleClass('menu-middle-click');
                Menu.el.menuBottom.toggleClass('menu-bottom-click');
            }
        };
        Menu.init();
    } else {

    };

    $("#my-menu").mmenu({
        offCanvas: {
           position  : "right"
        }
     }).on( "closing.mm", function() {
        Menu.el.menuTop.removeClass('menu-top-click');
        Menu.el.menuMiddle.removeClass('menu-middle-click');
        Menu.el.menuBottom.removeClass('menu-bottom-click');
     }).css("visibility","visible");

    $("body").addClass("good");

});

$( window ).load(function() {
    // if (jQuery.browser.mobile == true) {
    //     isMobile = true;
    // };

    var bgArray = $('#fullBg').data('backstretch');
    for (var i = 2; i <= 11; i++) {
        bgArray.images.push('img/main/' + i + '.jpg');
    };
    // bgArray.images.push('img/main/2.jpg');
    // bgArray.images.push('img/main/3.jpg');
});

$(window).on("backstretch.before", function (e, instance, index) {
  //$("#projName, #projDesc").animate({ opacity: 0 });
});

$(window).on("backstretch.after", function (e, instance, index) {
    $("#projName").html(titles[index]);
    $("#projDesc").html(descriptions[index]);
    //$("#projName, #projDesc").animate({ opacity: 1 });
    // $("#labelPane").css("visibility","visible");
});

$(".mediaButton").click(function(){
    var what = $(this).attr("data-control");
     $("#fullBg").backstretch(what);

    if (what == "pause") {
        //alert(what);
        $(this).attr("data-control","resume");
        $(this).addClass("play");
    } else if (what == "resume") {
        //alert(what);
        $(this).attr("data-control","pause");
        $(this).removeClass("play");
    };
});

$(".navLink").click(function(){
    var dest = $(this).attr("data-dest");
    var winHeight = window.innerHeight;

    if (dest == "about" && !trans) {
        if (!showAbout && !showContact) {
            trans = true;
            $("#labelPane").fadeOut( "slow", function(){
                $("#headerbg").animate({height: winHeight +"px"}, function(){
                    $("#aboutInfo").fadeIn("slow",function(){
                        showAbout = true;
                        trans = false;
                    });
                });
            });
        } else if (showAbout && !showContact) {
            trans = true;
            $("#aboutInfo").fadeOut("slow",function(){
                $("#headerbg").animate({height: "100%"},function(){
                    $("#labelPane").fadeIn("slow",function(){
                        showAbout = false;
                        trans = false;
                    });
                });
            });
        } else if (!showAbout && showContact) {
            trans = true;
            $("#contactInfo").fadeOut(function(){
                showContact = false;
                $("#aboutInfo").fadeIn("slow",function(){
                    showAbout = true;
                    trans = false;
                });
            });
        };

    } else if (dest == "contact" && !trans) {
        if (!showContact && !showAbout) {
            trans = true;
            $("#labelPane").fadeOut( "slow", function(){
                $("#headerbg").animate({height: winHeight +"px"}, function(){
                    $("#contactInfo").fadeIn("slow",function(){
                        showContact = true;
                        trans = false;
                    });
                });
            });
        } else if (showContact && !showAbout) {
            trans = true;
            $("#contactInfo").fadeOut("slow",function(){
                $("#headerbg").animate({height: "100%"},function(){
                    $("#labelPane").fadeIn("slow",function(){
                        showContact = false;
                        trans = false;
                    });
                });
            });
        } else if (!showContact && showAbout) {
            trans = true;
            $("#aboutInfo").fadeOut(function(){
                showAbout = false;
                $("#contactInfo").fadeIn("slow",function(){
                    showContact = true;
                    trans = false;
                });
            });
        };
    };
});

on_resize(function() {

    // $("#entry1, #entry2, #entry3, #entry4").css('left', '');
    // $("#arrowL").css("visibility","hidden");
    // $("#arrowR").css("visibility","visible");

})();

// debulked onresize handler
function on_resize(c,t){onresize=function(){clearTimeout(t);t=setTimeout(c,250)};return c};

/**
 * jQuery.browser.mobile (http://detectmobilebrowser.com/)
 *
 * jQuery.browser.mobile will be true if the browser is a mobile device
 *
 **/
(function(a){(jQuery.browser=jQuery.browser||{}).mobile=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera);

// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

<commit_msg>changed timing<commit_after>var titles;
var descriptions;

var showAbout = false;
var showContact = false;
var trans = false;

$(document).ready(function() {

    $("#fullBg").backstretch(["img/main/1.jpg"],{duration: 4500, fade: 3500});
    titles = ["001", "002", "003", "004", "005", "006", "007", "008", "009", "010"];
    descriptions = ["Description description content description stuff",
                    "stuff stuff stuff describing things that are real",
                    "Description description content description stuff",
                    "stuff stuff stuff describing things that are real",
                    "Description description content description stuff",
                    "stuff stuff stuff describing things that are real",
                    "Description description content description stuff",
                    "stuff stuff stuff describing things that are real",
                    "Description description content description stuff",
                    "stuff stuff stuff describing things that are real"]

    $("#projName").html(titles[0]);
    $("#projDesc").html(descriptions[0]);

    var Menu;
    if (Modernizr.csstransitions && Modernizr.csstransforms) {
        Menu = {
            el: {
                ham: $('.menu'),
                menuTop: $('.menu-top'),
                menuMiddle: $('.menu-middle'),
                menuBottom: $('.menu-bottom')
            },
            init: function() {
                Menu.bindUIactions();
            },
            bindUIactions: function() {
                Menu.el.ham
                .on('click',
                    function(event) {
                    Menu.activateMenu(event);
                    event.preventDefault();
                    $("#my-menu").trigger("open.mm");
                    }
                );
            },
            activateMenu: function() {
                Menu.el.menuTop.toggleClass('menu-top-click');
                Menu.el.menuMiddle.toggleClass('menu-middle-click');
                Menu.el.menuBottom.toggleClass('menu-bottom-click');
            }
        };
        Menu.init();
    } else {

    };

    $("#my-menu").mmenu({
        offCanvas: {
           position  : "right"
        }
     }).on( "closing.mm", function() {
        Menu.el.menuTop.removeClass('menu-top-click');
        Menu.el.menuMiddle.removeClass('menu-middle-click');
        Menu.el.menuBottom.removeClass('menu-bottom-click');
     }).css("visibility","visible");

    $("body").addClass("good");

});

$( window ).load(function() {
    // if (jQuery.browser.mobile == true) {
    //     isMobile = true;
    // };

    var bgArray = $('#fullBg').data('backstretch');
    for (var i = 2; i <= 11; i++) {
        bgArray.images.push('img/main/' + i + '.jpg');
    };
    // bgArray.images.push('img/main/2.jpg');
    // bgArray.images.push('img/main/3.jpg');
});

$(window).on("backstretch.before", function (e, instance, index) {
  //$("#projName, #projDesc").animate({ opacity: 0 });
});

$(window).on("backstretch.after", function (e, instance, index) {
    $("#projName").html(titles[index]);
    $("#projDesc").html(descriptions[index]);
    //$("#projName, #projDesc").animate({ opacity: 1 });
    // $("#labelPane").css("visibility","visible");
});

$(".mediaButton").click(function(){
    var what = $(this).attr("data-control");
     $("#fullBg").backstretch(what);

    if (what == "pause") {
        //alert(what);
        $(this).attr("data-control","resume");
        $(this).addClass("play");
    } else if (what == "resume") {
        //alert(what);
        $(this).attr("data-control","pause");
        $(this).removeClass("play");
    };
});

$(".navLink").click(function(){
    var dest = $(this).attr("data-dest");
    var winHeight = window.innerHeight;

    if (dest == "about" && !trans) {
        if (!showAbout && !showContact) {
            trans = true;
            $("#labelPane").fadeOut( "slow");
            $("#headerbg").animate({height: winHeight +"px"}, function(){
                $("#aboutInfo").fadeIn("slow",function(){
                    showAbout = true;
                    trans = false;
                });
            });
        } else if (showAbout && !showContact) {
            trans = true;
            $("#aboutInfo").fadeOut("slow",function(){
                $("#headerbg").animate({height: "100%"},function(){
                    $("#labelPane").fadeIn("slow",function(){
                        showAbout = false;
                        trans = false;
                    });
                });
            });
        } else if (!showAbout && showContact) {
            trans = true;
            $("#contactInfo").fadeOut(function(){
                showContact = false;
                $("#aboutInfo").fadeIn("slow",function(){
                    showAbout = true;
                    trans = false;
                });
            });
        };

    } else if (dest == "contact" && !trans) {
        if (!showContact && !showAbout) {
            trans = true;
            $("#labelPane").fadeOut( "slow");
            $("#headerbg").animate({height: winHeight +"px"}, function(){
                $("#contactInfo").fadeIn("slow",function(){
                    showContact = true;
                    trans = false;
                });
            });
        } else if (showContact && !showAbout) {
            trans = true;
            $("#contactInfo").fadeOut("slow",function(){
                $("#headerbg").animate({height: "100%"},function(){
                    $("#labelPane").fadeIn("slow",function(){
                        showContact = false;
                        trans = false;
                    });
                });
            });
        } else if (!showContact && showAbout) {
            trans = true;
            $("#aboutInfo").fadeOut(function(){
                showAbout = false;
                $("#contactInfo").fadeIn("slow",function(){
                    showContact = true;
                    trans = false;
                });
            });
        };
    };
});

on_resize(function() {

    // $("#entry1, #entry2, #entry3, #entry4").css('left', '');
    // $("#arrowL").css("visibility","hidden");
    // $("#arrowR").css("visibility","visible");

})();

// debulked onresize handler
function on_resize(c,t){onresize=function(){clearTimeout(t);t=setTimeout(c,250)};return c};

/**
 * jQuery.browser.mobile (http://detectmobilebrowser.com/)
 *
 * jQuery.browser.mobile will be true if the browser is a mobile device
 *
 **/
(function(a){(jQuery.browser=jQuery.browser||{}).mobile=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera);

// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeline', 'timelineEnd', 'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

<|endoftext|>


<commit_before>/**
 * Created by jduncan on 2/1/2016.
 */

(function(){
    'use strict';
    angular
        .module('SAKapp')
        .controller('NameServerController', ['$scope', '$http', '$log', '$q', 'toaster',  NameServerController]);

    function NameServerController ($scope, $http, $log, $q, toaster) {

        $scope.getServices = function (){

            var url = '/proxy?url=http://pz-discover.cf.piazzageo.io/api/v1/resources';
            var request = $http({
                method: "GET",
                url: url

            });
            request.success(
                function( html ) {

                    $scope.loggerHost = html["pz-logger"].host;
                    $scope.loggerType = html["pz-logger"].type;
                    $scope.loggerPort = html["pz-logger"].port;
                    $scope.uuidHost = html["pz-uuidgen"].host;
                    $scope.uuidType = html["pz-uuidgen"].type;
                    $scope.uuidPort = html["pz-uuidgen"].port;
                    $scope.alerterHost = html["pz-alerter"].host;
                    $scope.alerterType = html["pz-alerter"].type;
                    $scope.alerterPort = html["pz-alerter"].port;
                    $scope.kafkaHost = html["kafka"].host;
                    $scope.kafkaType = html["kafka"].type;
                    $scope.kafkaPort = html["kafka"].port;
                    $scope.zookeeperHost = html["zookeeper"].host;
                    $scope.zookeeperType = html["zookeeper"].type;
                    $scope.zookeeperPort = html["zookeeper"].port;
                    $scope.searchHost = html["elasticsearch"].host;
                    $scope.searchType = html["elasticsearch"].type;
                    $scope.searchPort = html["elasticsearch"].port;
                    //$scope.ingestHost = html["pzIngester"].host;
                    //$scope.ingestType = html["pzIngester"].type;
                    //$scope.ingestPort = html["pzIngester"].port;
                    $scope.serviceControllerHost = html["pz-servicecontroller"].address;
                    $scope.serviceControllerType = html["pz-servicecontroller"].type;
                    $scope.serviceControllerPort = html["pz-servicecontroller"].port;
                    $scope.dispatcherHost = html["pz-dispatcher"].host;
                    $scope.dispatcherType = html["pz-dispatcher"].type;
                    $scope.dispatcherPort = html["pz-dispatcher"].port;
                    $scope.gatewayHost = html["pz-gateway"].host;
                    $scope.gatewayType = html["pz-gateway"].type;
                    $scope.gatewayPort = html["pz-gateway"].port;
                    $scope.jobManagerHost = html["pz-jobmanager"].host;
                    $scope.jobManagerType = html["pz-jobmanager"].type;
                    $scope.jobManagerPort = html["pz-jobmanager"].port;
                }
            )
            request.error(function(){
                console.log("name-server.controller fail");
                toaster.pop('error', "Error", "There was an issue with your request. One or more services not found.");
            });

        };
    }

})();<commit_msg>Fix name server url<commit_after>/**
 * Created by jduncan on 2/1/2016.
 */

(function(){
    'use strict';
    angular
        .module('SAKapp')
        .controller('NameServerController', ['$scope', '$http', '$log', '$q', 'toaster',  NameServerController]);

    function NameServerController ($scope, $http, $log, $q, toaster) {

        $scope.getServices = function (){

            var url = '/proxy?url=pz-discover.cf.piazzageo.io/api/v1/resources';
            var request = $http({
                method: "GET",
                url: url

            });
            request.success(
                function( html ) {

                    $scope.loggerHost = html["pz-logger"].host;
                    $scope.loggerType = html["pz-logger"].type;
                    $scope.loggerPort = html["pz-logger"].port;
                    $scope.uuidHost = html["pz-uuidgen"].host;
                    $scope.uuidType = html["pz-uuidgen"].type;
                    $scope.uuidPort = html["pz-uuidgen"].port;
                    $scope.alerterHost = html["pz-alerter"].host;
                    $scope.alerterType = html["pz-alerter"].type;
                    $scope.alerterPort = html["pz-alerter"].port;
                    $scope.kafkaHost = html["kafka"].host;
                    $scope.kafkaType = html["kafka"].type;
                    $scope.kafkaPort = html["kafka"].port;
                    $scope.zookeeperHost = html["zookeeper"].host;
                    $scope.zookeeperType = html["zookeeper"].type;
                    $scope.zookeeperPort = html["zookeeper"].port;
                    $scope.searchHost = html["elasticsearch"].host;
                    $scope.searchType = html["elasticsearch"].type;
                    $scope.searchPort = html["elasticsearch"].port;
                    //$scope.ingestHost = html["pzIngester"].host;
                    //$scope.ingestType = html["pzIngester"].type;
                    //$scope.ingestPort = html["pzIngester"].port;
                    $scope.serviceControllerHost = html["pz-servicecontroller"].address;
                    $scope.serviceControllerType = html["pz-servicecontroller"].type;
                    $scope.serviceControllerPort = html["pz-servicecontroller"].port;
                    $scope.dispatcherHost = html["pz-dispatcher"].host;
                    $scope.dispatcherType = html["pz-dispatcher"].type;
                    $scope.dispatcherPort = html["pz-dispatcher"].port;
                    $scope.gatewayHost = html["pz-gateway"].host;
                    $scope.gatewayType = html["pz-gateway"].type;
                    $scope.gatewayPort = html["pz-gateway"].port;
                    $scope.jobManagerHost = html["pz-jobmanager"].host;
                    $scope.jobManagerType = html["pz-jobmanager"].type;
                    $scope.jobManagerPort = html["pz-jobmanager"].port;
                }
            )
            request.error(function(){
                console.log("name-server.controller fail");
                toaster.pop('error', "Error", "There was an issue with your request. One or more services not found.");
            });

        };
    }

})();<|endoftext|>


<commit_before>/**
 * @namespace ajax
 * @summary module to make ajax requests
 */
var ajax = (function() {
    "use strict";
    /**
     * @summary loader HTML element injected into loaderTarget when ajax is running
     * @private
     * @type {Element}
     */
    var loader = document.createElement("div");
    loader.className = "ajax-loader";

    /**
     * @memberof ajax
     * @summary injects the loader element into loaderTarget
     * @private
     * @param target {Element}
     */
    function startLoader(target) {
        target.appendChild(loader);
    }

    /**
     * @memberof ajax
     * @summary removes the loader from loaderTarget
     * @private
     * @param target {Element}
     */
    function stopLoader(target) {
        target.removeChild(loader);
    }

    /**
     * @memberof ajax
     * @summary executes the XMLHttpRequest
     * @private
     * @param c {object} request configuration hash
     */
    function sendRequest(c) {
        var req = new XMLHttpRequest();

        if (c.loaderTarget) {
            startLoader(c.loaderTarget);
        }

        // start XMLHttpRequest
        req.open(c.method, c.url, c.async);
        setRequestHeaders(req, c.setHeaders);

        // request now going through
        req.onreadystatechange = function() {
            // Headers & status are received
            if (req.readyState === 2) {
                if (c.onHeaders) {
                    c.onHeaders(req.getAllResponseHeaders());
                }
            }

            // request is complete and successful
            if (req.readyState === 4) {
                // loader needs to be removed BEFORE callbacks
                if (c.loaderTarget) {
                    stopLoader(c.loaderTarget);
                }

                // process success or failure callbacks
                if (req.status.toString().charAt(0) === "2" && c.onSuccess) {
                    c.onSuccess({
                        response: getResponse(req, c),
                        status: req.status,
                        getHeader: function(name) {
                            req.getResponseHeader.call(req, name);
                        }
                    });
                } else if (c.onFailure) {
                    c.onFailure({
                        response: getResponse(req, c),
                        status: req.status,
                        getHeader: function(name) {
                            req.getResponseHeader.call(req, name);
                        }
                    });
                }
            }
        };
        req.send(c.data);
    }

    /**
     * @memberof ajax
     * @summary sets basic headers for the request and sets the additional ones provided by the configuration
     * @private
     * @param req {object} XMLHttpRequest object
     * @param headers {object} additional headers to be injected
     */
    function setRequestHeaders(req, headers) {
        // set default values
        if (!headers["Content-Type"]) {
            headers["Content-Type"] = "application/json;charset=utf-8";
        }

        if (!headers.Accept) {
            headers.Accept = "application/json";
        }

        if (!headers["X-Requested-With"]) {
            headers["X-Requested-With"] = "XMLHttpRequest";
        }

        // get all object (t) keys from own properties
        // inject them as request headers
        Object.keys(headers).forEach(function(header) {
            req.setRequestHeader(header, headers[header]);
        });

        // xhr2 spec
        if (req.responseType) {
            req.responseType = c.responseType; // "arraybuffer", "blob", "document", "json", "text"
        }
    }

    /**
     * @memberof ajax
     * @summary parses the response data based on provided responseType
     * @private
     * @param req {object} XMLHttpRequest object
     * @param c {object} configuration hash
     * @returns the parsed data
     */
    function getResponse(req, c) {
        var r = req.response;

        if (c.responseType && c.responseType === "json" && r !== "") {
            r = JSON.parse(r);
        }

        return r;
    }

    /**
     * @memberof ajax
     * @private
     * @summary verifies content provided by configuration object
     * @param c {object} configuration hash
     * @returns {boolean} result of validation (true|false)
     */
    function validateConfig(c) {
        if (Object.prototype.toString.call(c.url) !== "[object String]") {
            throw new TypeError("ajax: requires a URL string");
        }

        if (c.loaderTarget && c.loaderTarget.nodeType !== 1) {
            throw new TypeError("ajax: 'loaderTarget' is not an HTML element");
        }

        if (Object.prototype.toString.call(c.method) === "[object String]") {
            c.method = c.method.toUpperCase();
            if (!["GET","POST","PUT","DELETE"].some(function(method) {
                return method === c.method;
            })) {
                throw new TypeError("ajax: 'method' must have one of the following values:\nGET\nPOST\nPUT\nDelete");
            }
        } else {
            throw Error("ajax: query 'method' is required");
        }

        if (c.setHeaders && Object.prototype.toString.call(c.setHeaders) !== "[object Object]") {
            throw new TypeError("ajax: 'setHeaders' is not an object");
        }

        if (c.onFailure && Object.prototype.toString.call(c.onFailure) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }
        if (c.onSuccess && Object.prototype.toString.call(c.onSuccess) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }
        if (c.onHeaders && Object.prototype.toString.call(c.onHEaders) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }

        if (c.responseType) {
            if (!["json","text","arraybuffer","document","blob"].some(function(value) {
                    return value === c.responseType;
                })) {
                throw new Error("ajax: responseType must have one of the following value:\njson\ntext\ndocument\nblob\narraybuffer");
            }
        }

        return true;
    }

    /**
     * @memberof ajax
     * @private
     * @summary builds the final request configuration object
     * @param c {object} configuration hash
     * @returns {
     *  {
     *   async: boolean,
     *   data: (object|null),
     *   setHeaders: (object|{}),
     *   method: string,
     *   onFailure: (function|null),
     *   onHeaders: (function|null),
     *   onSuccess: (function|null),
     *   responseType: (string),
     *   url: string,
     *   loaderTarget: (Element|null)
     *   }
     *  }
     */
    function finalizeConfig(c) {
        return {
            async: !!c.async,
            data: c.data || null,
            setHeaders: c.setHeaders || {},
            method: c.method,
            onFailure: c.onFailure || null,
            onHeaders: c.onHeaders || null,
            onSuccess: c.onSuccess || null,
            responseType: c.responseType || "text",
            url: encodeURI(c.url).replace(/%5B/g, "[").replace(/%5D/g, "]"),
            loaderTarget: c.loadTarget || null
        };
    }

    function query(c) {
        if (validateConfig(c)) {
            sendRequest(finalizeConfig(c));
        }
    }

    return query;
}());
<commit_msg>added "XMLHttpRequest" context as this to the payload.getHeader method otherwise the feature was refused...<commit_after>/**
 * @namespace ajax
 * @summary module to make ajax requests
 */
var ajax = (function() {
    "use strict";
    /**
     * @summary loader HTML element injected into loaderTarget when ajax is running
     * @private
     * @type {Element}
     */
    var loader = document.createElement("div");
    loader.className = "ajax-loader";

    /**
     * @memberof ajax
     * @summary injects the loader element into loaderTarget
     * @private
     * @param target {Element}
     */
    function startLoader(target) {
        target.appendChild(loader);
    }

    /**
     * @memberof ajax
     * @summary removes the loader from loaderTarget
     * @private
     * @param target {Element}
     */
    function stopLoader(target) {
        target.removeChild(loader);
    }

    /**
     * @memberof ajax
     * @summary executes the XMLHttpRequest
     * @private
     * @param c {object} request configuration hash
     */
    function sendRequest(c) {
        var req = new XMLHttpRequest();

        if (c.loaderTarget) {
            startLoader(c.loaderTarget);
        }

        // start XMLHttpRequest
        req.open(c.method, c.url, c.async);
        setRequestHeaders(req, c.setHeaders);

        // request now going through
        req.onreadystatechange = function() {
            // Headers & status are received
            if (req.readyState === 2) {
                if (c.onHeaders) {
                    c.onHeaders(req.getAllResponseHeaders());
                }
            }

            // request is complete and successful
            if (req.readyState === 4) {
                // loader needs to be removed BEFORE callbacks
                if (c.loaderTarget) {
                    stopLoader(c.loaderTarget);
                }

                // process success or failure callbacks
                if (req.status.toString().charAt(0) === "2" && c.onSuccess) {
                    c.onSuccess({
                        response: getResponse(req, c),
                        status: req.status,
                        getHeader: function(name) {
                            return req.getResponseHeader.call(req, name);
                        }
                    });
                } else if (c.onFailure) {
                    c.onFailure({
                        response: getResponse(req, c),
                        status: req.status,
                        getHeader: function(name) {
                            return req.getResponseHeader.call(req, name);
                        }
                    });
                }
            }
        };
        req.send(c.data);
    }

    /**
     * @memberof ajax
     * @summary sets basic headers for the request and sets the additional ones provided by the configuration
     * @private
     * @param req {object} XMLHttpRequest object
     * @param headers {object} additional headers to be injected
     */
    function setRequestHeaders(req, headers) {
        // set default values
        if (!headers["Content-Type"]) {
            headers["Content-Type"] = "application/json;charset=utf-8";
        }

        if (!headers.Accept) {
            headers.Accept = "application/json";
        }

        if (!headers["X-Requested-With"]) {
            headers["X-Requested-With"] = "XMLHttpRequest";
        }

        // get all object (t) keys from own properties
        // inject them as request headers
        Object.keys(headers).forEach(function(header) {
            req.setRequestHeader(header, headers[header]);
        });

        // xhr2 spec
        if (req.responseType) {
            req.responseType = c.responseType; // "arraybuffer", "blob", "document", "json", "text"
        }
    }

    /**
     * @memberof ajax
     * @summary parses the response data based on provided responseType
     * @private
     * @param req {object} XMLHttpRequest object
     * @param c {object} configuration hash
     * @returns the parsed data
     */
    function getResponse(req, c) {
        var r = req.response;

        if (c.responseType && c.responseType === "json" && r !== "") {
            r = JSON.parse(r);
        }

        return r;
    }

    /**
     * @memberof ajax
     * @private
     * @summary verifies content provided by configuration object
     * @param c {object} configuration hash
     * @returns {boolean} result of validation (true|false)
     */
    function validateConfig(c) {
        if (Object.prototype.toString.call(c.url) !== "[object String]") {
            throw new TypeError("ajax: requires a URL string");
        }

        if (c.loaderTarget && c.loaderTarget.nodeType !== 1) {
            throw new TypeError("ajax: 'loaderTarget' is not an HTML element");
        }

        if (Object.prototype.toString.call(c.method) === "[object String]") {
            c.method = c.method.toUpperCase();
            if (!["GET","POST","PUT","DELETE"].some(function(method) {
                return method === c.method;
            })) {
                throw new TypeError("ajax: 'method' must have one of the following values:\nGET\nPOST\nPUT\nDelete");
            }
        } else {
            throw Error("ajax: query 'method' is required");
        }

        if (c.setHeaders && Object.prototype.toString.call(c.setHeaders) !== "[object Object]") {
            throw new TypeError("ajax: 'setHeaders' is not an object");
        }

        if (c.onFailure && Object.prototype.toString.call(c.onFailure) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }
        if (c.onSuccess && Object.prototype.toString.call(c.onSuccess) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }
        if (c.onHeaders && Object.prototype.toString.call(c.onHEaders) !== "[object Function]") {
            throw new TypeError("ajax: onFailure must be a function");
        }

        if (c.responseType) {
            if (!["json","text","arraybuffer","document","blob"].some(function(value) {
                    return value === c.responseType;
                })) {
                throw new Error("ajax: responseType must have one of the following value:\njson\ntext\ndocument\nblob\narraybuffer");
            }
        }

        return true;
    }

    /**
     * @memberof ajax
     * @private
     * @summary builds the final request configuration object
     * @param c {object} configuration hash
     * @returns {
     *  {
     *   async: boolean,
     *   data: (object|null),
     *   setHeaders: (object|{}),
     *   method: string,
     *   onFailure: (function|null),
     *   onHeaders: (function|null),
     *   onSuccess: (function|null),
     *   responseType: (string),
     *   url: string,
     *   loaderTarget: (Element|null)
     *   }
     *  }
     */
    function finalizeConfig(c) {
        return {
            async: !!c.async,
            data: c.data || null,
            setHeaders: c.setHeaders || {},
            method: c.method,
            onFailure: c.onFailure || null,
            onHeaders: c.onHeaders || null,
            onSuccess: c.onSuccess || null,
            responseType: c.responseType || "text",
            url: encodeURI(c.url).replace(/%5B/g, "[").replace(/%5D/g, "]"),
            loaderTarget: c.loadTarget || null
        };
    }

    function query(c) {
        if (validateConfig(c)) {
            sendRequest(finalizeConfig(c));
        }
    }

    return query;
}());
<|endoftext|>


<commit_before><commit_msg>support running standalone<commit_after><|endoftext|>


<commit_before><commit_msg>Output query log<commit_after><|endoftext|>


<commit_before>'use strict'

/**
 * Dependencies
 * @ignore
 */
const BaseRequest = require('./BaseRequest')
const AccessToken = require('../AccessToken')
const AuthorizationCode = require('../AuthorizationCode')
const IDToken = require('../IDToken')
const { JWT, JWK, JWKSet } = require('@trust/jose')

/**
 * AuthenticationRequest
 */
class AuthenticationRequest extends BaseRequest {

  /**
   * Request Handler
   *
   * @param {HTTPRequest} req
   * @param {HTTPResponse} res
   * @param {Provider} provider
   */
  static handle (req, res, provider) {
    let {host} = provider
    let request = new AuthenticationRequest(req, res, provider)

    return Promise
      .resolve(request)
      .then(request.loadClient)
      .then(request.decodeRequestParam)
      .then(request.validate)
      .then(host.authenticate)
      .then(host.obtainConsent)
      .then(request.authorize)
      .catch(err => request.error(err))
  }

  /**
   * Constructor
   *
   * @param {HTTPRequest} req
   * @param {HTTPResponse} res
   * @param {Provider} provider
   */
  constructor (req, res, provider) {
    super(req, res, provider)
    this.params = AuthenticationRequest.getParams(this)
    this.responseTypes = AuthenticationRequest.getResponseTypes(this)
    this.responseMode = AuthenticationRequest.getResponseMode(this)
  }

  /**
   * loadClient
   *
   * @description
   * Loads the client registration from the backend store
   *
   * @param request {AuthenticationRequest}
   *
   * @returns {Promise<AuthenticationRequest>}
   */
  loadClient (request) {
    let { provider, params } = request

    if (!params.client_id) {
      // An error for the missing client_id will be thrown in validate()
      return Promise.resolve(request)
    }

    return provider.backend.get('clients', params.client_id)

      .then(client => {  // client registration
        request.client = client

        if (client && client.jwks) {
          // pre-registered client keys (for signing request objects, etc)
          return JWKSet.importKeys(client.jwks)
            .then(importedJwks => {
              client.jwks = importedJwks
            })
        }
      })

      .then(() => request)
  }

  /**
   * decodeRequestParam
   *
   * @description
   * Decodes, validates and loads a Request Object (passed by value)
   *
   * @see https://openid.net/specs/openid-connect-core-1_0.html#RequestObject
   *
   * @param request {AuthenticationRequest}
   *
   * @returns {Promise<AuthenticationRequest>}
   */
  decodeRequestParam (request) {
    let { params } = request

    if (!params['request']) {
      return Promise.resolve(request)  // Pass through, no request param present
    }

    let requestJwt

    return Promise.resolve()
      .then(() => JWT.decode(params['request']))

      .catch(err => {
        request.redirect({
          error: 'invalid_request_object',
          error_description: err.message
        })
      })

      .then(jwt => { requestJwt = jwt })

      .then(() => {
        if (requestJwt.payload.key) {
          return request.loadCnfKey(requestJwt.payload.key)
            .catch(err => {
              request.redirect({
                error: 'invalid_request_object',
                error_description: 'Error importing cnf key: ' + err.message
              })
            })
        }
      })

      .then(() => request.validateRequestParam(requestJwt))

      .then(requestJwt => {
        request.params = Object.assign({}, params, requestJwt.payload)
      })

      .then(() => request)
  }

  /**
   * loadCnfKey
   *
   * @description
   * Loads the Proof of Possession confirmation key (from the `request` param)
   *
   * @see https://tools.ietf.org/html/rfc7800#section-3.1
   * @see https://tools.ietf.org/html/draft-ietf-oauth-pop-key-distribution-03#section-5
   *
   * @param jwk {JWK}
   *
   * @returns {Promise<JWK>} Imported key
   */
  loadCnfKey (jwk) {
    // jwk.use = jwk.use || 'sig'  // make sure key usage is not omitted

    // Importing the key serves as additional validation
    return JWK.importKey(jwk)
      .then(importedJwk => {
        this.cnfKey = importedJwk  // has a cryptoKey property

        return importedJwk
      })
  }

  /**
   * validateRequestParam
   *
   * @description
   * Validates the Request Object jwt (passed by value)
   *
   * @param requestJwt {JWT} Decoded request object
   *
   * @returns {Promise<JWT>} Resolves with the decoded request jwt
   */
  validateRequestParam (requestJwt) {
    let { params } = this
    let { payload } = requestJwt

    return Promise.resolve()

      .then(() => {
        // request and request_uri parameters MUST NOT be included in Request Objects
        if (payload.request) {
          return this.redirect({
            error: 'invalid_request_object',
            error_description: 'Illegal request claim in payload'
          })
        }
        if (payload.request_uri) {
          return this.redirect({
            error: 'invalid_request_object',
            error_description: 'Illegal request_uri claim in payload'
          })
        }
      })

      .then(() => {
        // So that the request is a valid OAuth 2.0 Authorization Request, values
        // for the response_type and client_id parameters MUST be included using
        // the OAuth 2.0 request syntax, since they are REQUIRED by OAuth 2.0.
        // The values for these parameters MUST match those in the Request Object,
        // if present.
        if (payload.client_id && payload.client_id !== params.client_id) {
          return this.forbidden({
            error: 'unauthorized_client',
            error_description: 'Mismatching client id in request object'
          })
        }

        if (payload.response_type && payload.response_type !== params.response_type) {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Mismatching response type in request object',
          })
        }

        // Even if a scope parameter is present in the Request Object value, a scope
        // parameter MUST always be passed using the OAuth 2.0 request syntax
        // containing the openid scope value to indicate to the underlying OAuth 2.0
        // logic that this is an OpenID Connect request.
        if (payload.scope && payload.scope !== params.scope) {
          return this.redirect({
            error: 'invalid_scope',
            error_description: 'Mismatching scope in request object',
          })
        }

        // TODO: What to do with this? SHOULD considered harmful, indeed...
        // If signed, the Request Object SHOULD contain the Claims iss
        // (issuer) and aud (audience) as members. The iss value SHOULD be the
        // Client ID of the RP, unless it was signed by a different party than the
        // RP. The aud value SHOULD be or include the OP's Issuer Identifier URL.
      })

      .then(() => this.validateRequestParamSignature(requestJwt))

      .then(() => requestJwt)
  }

  /**
   * validateRequestParamSignature
   *
   * @param requestJwt {JWT} Decoded request object
   *
   * @returns {Promise}
   */
  validateRequestParamSignature (requestJwt) {
    // From https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata

    // request_object_signing_alg
    //   OPTIONAL. JWS [JWS] alg algorithm [JWA] that MUST be used for signing
    //   Request Objects sent to the OP. All Request Objects from this Client
    //   MUST be rejected, if not signed with this algorithm. Request Objects
    //   are described in Section 6.1 of OpenID Connect Core 1.0 [OpenID.Core].
    //   This algorithm MUST be used both when the Request Object is passed by
    //   value (using the request parameter) and when it is passed by reference
    //   (using the request_uri parameter). Servers SHOULD support RS256.
    //   The value none MAY be used. The default, if omitted, is that any
    //   algorithm supported by the OP and the RP MAY be used.

    // From https://openid.net/specs/openid-connect-core-1_0.html#SignedRequestObject

    // The Request Object MAY be signed or unsigned (plaintext). When it is
    // plaintext, this is indicated by use of the none algorithm [JWA] in the
    // JOSE Header.

    // For Signature Validation, the alg Header Parameter in the JOSE Header
    // MUST match the value of the request_object_signing_alg set during Client
    // Registration or a value that was pre-registered by
    // other means. The signature MUST be validated against the appropriate key
    // for that client_id and algorithm.

    if (!this.client) {
      // No client_id, or no registration found for it
      // An error will be thrown downstream in `validate()`
      return Promise.resolve()
    }

    let clientJwks = this.client.jwks
    let registeredSigningAlg = this.client['request_object_signing_alg']

    let signedRequest = requestJwt.header.alg !== 'none'
    let signatureRequired = clientJwks ||
      (registeredSigningAlg && registeredSigningAlg !== 'none')

    if (!signedRequest && !signatureRequired) {
      // Unsigned, signature not required - ok
      return Promise.resolve()
    }

    return Promise.resolve()
      .then(() => {
        if (signedRequest && !clientJwks) {
          // No keys pre-registered, but the request is signed. Throw error
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Signed request object, but no jwks pre-registered',
          })
        }

        if (signedRequest && registeredSigningAlg === 'none') {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Signed request object, but no signature allowed by request_object_signing_alg',
          })
        }

        if (!signedRequest && signatureRequired) {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Signature required for request object',
          })
        }

        if (registeredSigningAlg && requestJwt.header.alg !== registeredSigningAlg) {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Request signed by algorithm that does not match registered request_object_signing_alg value',
          })
        }

        // Request is signed. Validate signature against registered jwks
        let keyMatch = requestJwt.resolveKeys(clientJwks)

        if (!keyMatch) {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Cannot resolve signing key for request object',
          })
        }

        return requestJwt.verify()
          .then(verified => {
            if (!verified) {
              return this.redirect({
                error: 'invalid_request',
                error_description: 'Invalid request object signature',
              })
            }
          })
      })
  }

  /**
   * Validate Request
   *
   * @param {AuthenticationRequest} request
   *
   * @returns {AuthenticationRequest}
   */
  validate (request) {
    const { params, client } = request

    // CLIENT ID IS REQUIRED
    if (!params.client_id) {
      return request.forbidden({
        error: 'unauthorized_client',
        error_description: 'Missing client id'
      })
    }

    // REDIRECT URI IS REQUIRED
    if (!params.redirect_uri) {
      return request.badRequest({
        error: 'invalid_request',
        error_description: 'Missing redirect uri',
      })
    }

    // UNKNOWN CLIENT
    if (!client) {
      return request.unauthorized({
        error: 'unauthorized_client',
        error_description: 'Unknown client'
      })
    }

    // REDIRECT_URI MUST MATCH
    if (!client.redirect_uris.includes(params.redirect_uri)) {
      return request.badRequest({
        error: 'invalid_request',
        error_description: 'Mismatching redirect uri'
      })
    }

    // RESPONSE TYPE IS REQUIRED
    if (!params.response_type) {
      return request.redirect({
        error: 'invalid_request',
        error_description: 'Missing response type',
      })
    }

    // SCOPE IS REQUIRED
    if (!params.scope) {
      return request.redirect({
        error: 'invalid_scope',
        error_description: 'Missing scope',
      })
    }

    // OPENID SCOPE IS REQUIRED
    if (!params.scope.includes('openid')) {
      return request.redirect({
        error: 'invalid_scope',
        error_description: 'Missing openid scope'
      })
    }

    // NONCE MAY BE REQUIRED
    if (!request.requiredNonceProvided()) {
      return request.redirect({
        error: 'invalid_request',
        error_description: 'Missing nonce'
      })
    }

    // RESPONSE TYPE MUST BE SUPPORTED
    // TODO is this something the client can configure too?
    if (!request.supportedResponseType()) {
      return request.redirect({
        error: 'unsupported_response_type',
        error_description: 'Unsupported response type'
      })
    }

    // RESPONSE MODE MUST BE SUPPORTED
    // TODO is this something the client can configure too?
    if (!request.supportedResponseMode()) {
      return request.redirect({
        error: 'unsupported_response_mode',
        error_description: 'Unsupported response mode'
      })
    }

    // VALID REQUEST
    return request
  }

  /**
   * Supported Response Type
   *
   * @returns {bool}
   */
  supportedResponseType () {
    let {params, provider} = this
    let supportedResponseTypes = provider.response_types_supported
    let requestedResponseType = params.response_type

    // TODO
    // verify that the requested response types are permitted
    // by client registration
    //
    // let registeredResponseTypes = client.response_types
    return supportedResponseTypes.includes(requestedResponseType)
  }

  /**
   * Supported Response Mode
   *
   * @returns {bool}
   */
  supportedResponseMode () {
    let {params, provider} = this
    let supportedResponseModes = provider.response_modes_supported
    let requestedResponseMode = params.response_mode

    if (!requestedResponseMode) {
      return true
    } else {
      return supportedResponseModes.indexOf(requestedResponseMode) !== -1
    }
  }

  /**
   * Required Nonce Provided
   *
   * @returns {bool}
   */
  requiredNonceProvided () {
    let {params} = this
    let {nonce, response_type: responseType} = params
    let requiring = ['id_token', 'token']

    if (!nonce && requiring.some(type => responseType.indexOf(type) !== -1)) {
      return false
    } else {
      return true
    }
  }

  /**
   * Authorize
   *
   * @param {AuthenticationRequest} request
   * @returns {Promise}
   */
  authorize (request) {
    if (request.consent === true) {
      return request.allow(request)
    } else {
      return request.deny(request)
    }
  }

  /**
   * Allow
   *
   * Given a completely validated request with an authenticated user and
   * consent, build a response incorporating auth code, tokens, and session
   * state.
   */
  allow (request) {
    return Promise.resolve({}) // initialize empty response
      .then(response => request.includeAccessToken(response))
      .then(response => request.includeAuthorizationCode(response))
      .then(response => request.includeIDToken(response))
      //.then(this.includeSessionState.bind(this))
      .then(response => request.redirect(response))
      // do some error handling here
  }

  /**
   * Deny
   *
   * Handle user's rejection of the client.
   */
  deny (request) {
    this.redirect({
      error: 'access_denied'
    })
  }

  /**
   * Include Access Token
   *
   * @returns {Promise}
   */
  includeAccessToken (response) {
    let {responseTypes} = this

    if (responseTypes.includes('token')) {
      return AccessToken.issueForRequest(this, response)
    }

    return Promise.resolve(response)
  }

  /**
   * Include Authorization Code
   *
   * @returns {Promise}
   */
  includeAuthorizationCode (response) {
    let {responseTypes, params, scope} = this
    let {provider, client, subject} = this
    let {backend} = provider

    if (responseTypes.includes('code')) {
      let code = this.random(16)
      let sub = subject['_id']
      let aud = client['client_id']
      let iat = Math.floor(Date.now() / 1000)
      let exp = iat + 600
      let max = params['max_age'] || client['default_max_age']
      let nonce = params['nonce']
      let redirect_uri = params['redirect_uri']

      let ac = new AuthorizationCode({
        code, sub, aud, exp, max, scope, nonce, redirect_uri
      })

      return backend.put('codes', code, ac)
        .then(() => {
          response['code'] = code
          return response
        })
    }

    return Promise.resolve(response)
  }

  /**
   * Include ID Token
   *
   * @returns {Promise}
   */
  includeIDToken (response) {
    let {responseTypes} = this

    if (responseTypes.includes('id_token')) {
      return IDToken.issueForRequest(this, response)
    }

    return Promise.resolve(response)
  }

  /**
   * Include Session State
   */
  includeSessionState (response) {
    // ...
  }
}

/**
 * Export
 */
module.exports = AuthenticationRequest

<commit_msg>feat(AuthenticationRequest): Drop hash fragment when validating redirect_uri<commit_after>'use strict'

/**
 * Dependencies
 * @ignore
 */
const BaseRequest = require('./BaseRequest')
const AccessToken = require('../AccessToken')
const AuthorizationCode = require('../AuthorizationCode')
const IDToken = require('../IDToken')
const { JWT, JWK, JWKSet } = require('@trust/jose')
const { URL } = require('whatwg-url')

/**
 * AuthenticationRequest
 */
class AuthenticationRequest extends BaseRequest {

  /**
   * Request Handler
   *
   * @param {HTTPRequest} req
   * @param {HTTPResponse} res
   * @param {Provider} provider
   */
  static handle (req, res, provider) {
    let {host} = provider
    let request = new AuthenticationRequest(req, res, provider)

    return Promise
      .resolve(request)
      .then(request.loadClient)
      .then(request.decodeRequestParam)
      .then(request.validate)
      .then(host.authenticate)
      .then(host.obtainConsent)
      .then(request.authorize)
      .catch(err => request.error(err))
  }

  /**
   * Constructor
   *
   * @param {HTTPRequest} req
   * @param {HTTPResponse} res
   * @param {Provider} provider
   */
  constructor (req, res, provider) {
    super(req, res, provider)
    this.params = AuthenticationRequest.getParams(this)
    this.responseTypes = AuthenticationRequest.getResponseTypes(this)
    this.responseMode = AuthenticationRequest.getResponseMode(this)
  }

  /**
   * loadClient
   *
   * @description
   * Loads the client registration from the backend store
   *
   * @param request {AuthenticationRequest}
   *
   * @returns {Promise<AuthenticationRequest>}
   */
  loadClient (request) {
    let { provider, params } = request

    if (!params.client_id) {
      // An error for the missing client_id will be thrown in validate()
      return Promise.resolve(request)
    }

    return provider.backend.get('clients', params.client_id)

      .then(client => {  // client registration
        request.client = client

        if (client && client.jwks) {
          // pre-registered client keys (for signing request objects, etc)
          return JWKSet.importKeys(client.jwks)
            .then(importedJwks => {
              client.jwks = importedJwks
            })
        }
      })

      .then(() => request)
  }

  /**
   * decodeRequestParam
   *
   * @description
   * Decodes, validates and loads a Request Object (passed by value)
   *
   * @see https://openid.net/specs/openid-connect-core-1_0.html#RequestObject
   *
   * @param request {AuthenticationRequest}
   *
   * @returns {Promise<AuthenticationRequest>}
   */
  decodeRequestParam (request) {
    let { params } = request

    if (!params['request']) {
      return Promise.resolve(request)  // Pass through, no request param present
    }

    let requestJwt

    return Promise.resolve()
      .then(() => JWT.decode(params['request']))

      .catch(err => {
        request.redirect({
          error: 'invalid_request_object',
          error_description: err.message
        })
      })

      .then(jwt => { requestJwt = jwt })

      .then(() => {
        if (requestJwt.payload.key) {
          return request.loadCnfKey(requestJwt.payload.key)
            .catch(err => {
              request.redirect({
                error: 'invalid_request_object',
                error_description: 'Error importing cnf key: ' + err.message
              })
            })
        }
      })

      .then(() => request.validateRequestParam(requestJwt))

      .then(requestJwt => {
        request.params = Object.assign({}, params, requestJwt.payload)
      })

      .then(() => request)
  }

  /**
   * loadCnfKey
   *
   * @description
   * Loads the Proof of Possession confirmation key (from the `request` param)
   *
   * @see https://tools.ietf.org/html/rfc7800#section-3.1
   * @see https://tools.ietf.org/html/draft-ietf-oauth-pop-key-distribution-03#section-5
   *
   * @param jwk {JWK}
   *
   * @returns {Promise<JWK>} Imported key
   */
  loadCnfKey (jwk) {
    // jwk.use = jwk.use || 'sig'  // make sure key usage is not omitted

    // Importing the key serves as additional validation
    return JWK.importKey(jwk)
      .then(importedJwk => {
        this.cnfKey = importedJwk  // has a cryptoKey property

        return importedJwk
      })
  }

  /**
   * validateRequestParam
   *
   * @description
   * Validates the Request Object jwt (passed by value)
   *
   * @param requestJwt {JWT} Decoded request object
   *
   * @returns {Promise<JWT>} Resolves with the decoded request jwt
   */
  validateRequestParam (requestJwt) {
    let { params } = this
    let { payload } = requestJwt

    return Promise.resolve()

      .then(() => {
        // request and request_uri parameters MUST NOT be included in Request Objects
        if (payload.request) {
          return this.redirect({
            error: 'invalid_request_object',
            error_description: 'Illegal request claim in payload'
          })
        }
        if (payload.request_uri) {
          return this.redirect({
            error: 'invalid_request_object',
            error_description: 'Illegal request_uri claim in payload'
          })
        }
      })

      .then(() => {
        // So that the request is a valid OAuth 2.0 Authorization Request, values
        // for the response_type and client_id parameters MUST be included using
        // the OAuth 2.0 request syntax, since they are REQUIRED by OAuth 2.0.
        // The values for these parameters MUST match those in the Request Object,
        // if present.
        if (payload.client_id && payload.client_id !== params.client_id) {
          return this.forbidden({
            error: 'unauthorized_client',
            error_description: 'Mismatching client id in request object'
          })
        }

        if (payload.response_type && payload.response_type !== params.response_type) {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Mismatching response type in request object',
          })
        }

        // Even if a scope parameter is present in the Request Object value, a scope
        // parameter MUST always be passed using the OAuth 2.0 request syntax
        // containing the openid scope value to indicate to the underlying OAuth 2.0
        // logic that this is an OpenID Connect request.
        if (payload.scope && payload.scope !== params.scope) {
          return this.redirect({
            error: 'invalid_scope',
            error_description: 'Mismatching scope in request object',
          })
        }

        // TODO: What to do with this? SHOULD considered harmful, indeed...
        // If signed, the Request Object SHOULD contain the Claims iss
        // (issuer) and aud (audience) as members. The iss value SHOULD be the
        // Client ID of the RP, unless it was signed by a different party than the
        // RP. The aud value SHOULD be or include the OP's Issuer Identifier URL.
      })

      .then(() => this.validateRequestParamSignature(requestJwt))

      .then(() => requestJwt)
  }

  /**
   * validateRequestParamSignature
   *
   * @param requestJwt {JWT} Decoded request object
   *
   * @returns {Promise}
   */
  validateRequestParamSignature (requestJwt) {
    // From https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata

    // request_object_signing_alg
    //   OPTIONAL. JWS [JWS] alg algorithm [JWA] that MUST be used for signing
    //   Request Objects sent to the OP. All Request Objects from this Client
    //   MUST be rejected, if not signed with this algorithm. Request Objects
    //   are described in Section 6.1 of OpenID Connect Core 1.0 [OpenID.Core].
    //   This algorithm MUST be used both when the Request Object is passed by
    //   value (using the request parameter) and when it is passed by reference
    //   (using the request_uri parameter). Servers SHOULD support RS256.
    //   The value none MAY be used. The default, if omitted, is that any
    //   algorithm supported by the OP and the RP MAY be used.

    // From https://openid.net/specs/openid-connect-core-1_0.html#SignedRequestObject

    // The Request Object MAY be signed or unsigned (plaintext). When it is
    // plaintext, this is indicated by use of the none algorithm [JWA] in the
    // JOSE Header.

    // For Signature Validation, the alg Header Parameter in the JOSE Header
    // MUST match the value of the request_object_signing_alg set during Client
    // Registration or a value that was pre-registered by
    // other means. The signature MUST be validated against the appropriate key
    // for that client_id and algorithm.

    if (!this.client) {
      // No client_id, or no registration found for it
      // An error will be thrown downstream in `validate()`
      return Promise.resolve()
    }

    let clientJwks = this.client.jwks
    let registeredSigningAlg = this.client['request_object_signing_alg']

    let signedRequest = requestJwt.header.alg !== 'none'
    let signatureRequired = clientJwks ||
      (registeredSigningAlg && registeredSigningAlg !== 'none')

    if (!signedRequest && !signatureRequired) {
      // Unsigned, signature not required - ok
      return Promise.resolve()
    }

    return Promise.resolve()
      .then(() => {
        if (signedRequest && !clientJwks) {
          // No keys pre-registered, but the request is signed. Throw error
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Signed request object, but no jwks pre-registered',
          })
        }

        if (signedRequest && registeredSigningAlg === 'none') {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Signed request object, but no signature allowed by request_object_signing_alg',
          })
        }

        if (!signedRequest && signatureRequired) {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Signature required for request object',
          })
        }

        if (registeredSigningAlg && requestJwt.header.alg !== registeredSigningAlg) {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Request signed by algorithm that does not match registered request_object_signing_alg value',
          })
        }

        // Request is signed. Validate signature against registered jwks
        let keyMatch = requestJwt.resolveKeys(clientJwks)

        if (!keyMatch) {
          return this.redirect({
            error: 'invalid_request',
            error_description: 'Cannot resolve signing key for request object',
          })
        }

        return requestJwt.verify()
          .then(verified => {
            if (!verified) {
              return this.redirect({
                error: 'invalid_request',
                error_description: 'Invalid request object signature',
              })
            }
          })
      })
  }

  /**
   * Validate Request
   *
   * @param {AuthenticationRequest} request
   *
   * @returns {AuthenticationRequest}
   */
  validate (request) {
    const { params, client } = request

    // CLIENT ID IS REQUIRED
    if (!params.client_id) {
      return request.forbidden({
        error: 'unauthorized_client',
        error_description: 'Missing client id'
      })
    }

    // REDIRECT URI IS REQUIRED
    if (!params.redirect_uri) {
      return request.badRequest({
        error: 'invalid_request',
        error_description: 'Missing redirect uri',
      })
    }

    // UNKNOWN CLIENT
    if (!client) {
      return request.unauthorized({
        error: 'unauthorized_client',
        error_description: 'Unknown client'
      })
    }

    // REDIRECT_URI MUST MATCH
    if (!AuthenticationRequest.validateRedirectUri(client.redirect_uris, params.redirect_uri)) {
      return request.badRequest({
        error: 'invalid_request',
        error_description: 'Mismatching redirect uri'
      })
    }

    // RESPONSE TYPE IS REQUIRED
    if (!params.response_type) {
      return request.redirect({
        error: 'invalid_request',
        error_description: 'Missing response type',
      })
    }

    // SCOPE IS REQUIRED
    if (!params.scope) {
      return request.redirect({
        error: 'invalid_scope',
        error_description: 'Missing scope',
      })
    }

    // OPENID SCOPE IS REQUIRED
    if (!params.scope.includes('openid')) {
      return request.redirect({
        error: 'invalid_scope',
        error_description: 'Missing openid scope'
      })
    }

    // NONCE MAY BE REQUIRED
    if (!request.requiredNonceProvided()) {
      return request.redirect({
        error: 'invalid_request',
        error_description: 'Missing nonce'
      })
    }

    // RESPONSE TYPE MUST BE SUPPORTED
    // TODO is this something the client can configure too?
    if (!request.supportedResponseType()) {
      return request.redirect({
        error: 'unsupported_response_type',
        error_description: 'Unsupported response type'
      })
    }

    // RESPONSE MODE MUST BE SUPPORTED
    // TODO is this something the client can configure too?
    if (!request.supportedResponseMode()) {
      return request.redirect({
        error: 'unsupported_response_mode',
        error_description: 'Unsupported response mode'
      })
    }

    // VALID REQUEST
    return request
  }

  static validateRedirectUri (registeredUris, redirectUri) {
    // Drop hash fragment when validating against pre-registered uris
    let uriNoHash = (uri) => {
      uri = new URL(uri)
      uri.hash = ''
      return uri.toString()
    }

    return registeredUris.some(uri => uriNoHash(uri) === uriNoHash(redirectUri))
  }

  /**
   * Supported Response Type
   *
   * @returns {bool}
   */
  supportedResponseType () {
    let {params, provider} = this
    let supportedResponseTypes = provider.response_types_supported
    let requestedResponseType = params.response_type

    // TODO
    // verify that the requested response types are permitted
    // by client registration
    //
    // let registeredResponseTypes = client.response_types
    return supportedResponseTypes.includes(requestedResponseType)
  }

  /**
   * Supported Response Mode
   *
   * @returns {bool}
   */
  supportedResponseMode () {
    let {params, provider} = this
    let supportedResponseModes = provider.response_modes_supported
    let requestedResponseMode = params.response_mode

    if (!requestedResponseMode) {
      return true
    } else {
      return supportedResponseModes.indexOf(requestedResponseMode) !== -1
    }
  }

  /**
   * Required Nonce Provided
   *
   * @returns {bool}
   */
  requiredNonceProvided () {
    let {params} = this
    let {nonce, response_type: responseType} = params
    let requiring = ['id_token', 'token']

    if (!nonce && requiring.some(type => responseType.indexOf(type) !== -1)) {
      return false
    } else {
      return true
    }
  }

  /**
   * Authorize
   *
   * @param {AuthenticationRequest} request
   * @returns {Promise}
   */
  authorize (request) {
    if (request.consent === true) {
      return request.allow(request)
    } else {
      return request.deny(request)
    }
  }

  /**
   * Allow
   *
   * Given a completely validated request with an authenticated user and
   * consent, build a response incorporating auth code, tokens, and session
   * state.
   */
  allow (request) {
    return Promise.resolve({}) // initialize empty response
      .then(response => request.includeAccessToken(response))
      .then(response => request.includeAuthorizationCode(response))
      .then(response => request.includeIDToken(response))
      //.then(this.includeSessionState.bind(this))
      .then(response => request.redirect(response))
      // do some error handling here
  }

  /**
   * Deny
   *
   * Handle user's rejection of the client.
   */
  deny (request) {
    this.redirect({
      error: 'access_denied'
    })
  }

  /**
   * Include Access Token
   *
   * @returns {Promise}
   */
  includeAccessToken (response) {
    let {responseTypes} = this

    if (responseTypes.includes('token')) {
      return AccessToken.issueForRequest(this, response)
    }

    return Promise.resolve(response)
  }

  /**
   * Include Authorization Code
   *
   * @returns {Promise}
   */
  includeAuthorizationCode (response) {
    let {responseTypes, params, scope} = this
    let {provider, client, subject} = this
    let {backend} = provider

    if (responseTypes.includes('code')) {
      let code = this.random(16)
      let sub = subject['_id']
      let aud = client['client_id']
      let iat = Math.floor(Date.now() / 1000)
      let exp = iat + 600
      let max = params['max_age'] || client['default_max_age']
      let nonce = params['nonce']
      let redirect_uri = params['redirect_uri']

      let ac = new AuthorizationCode({
        code, sub, aud, exp, max, scope, nonce, redirect_uri
      })

      return backend.put('codes', code, ac)
        .then(() => {
          response['code'] = code
          return response
        })
    }

    return Promise.resolve(response)
  }

  /**
   * Include ID Token
   *
   * @returns {Promise}
   */
  includeIDToken (response) {
    let {responseTypes} = this

    if (responseTypes.includes('id_token')) {
      return IDToken.issueForRequest(this, response)
    }

    return Promise.resolve(response)
  }

  /**
   * Include Session State
   */
  includeSessionState (response) {
    // ...
  }
}

/**
 * Export
 */
module.exports = AuthenticationRequest

<|endoftext|>


<commit_before>/**
 * Created by Dzmitry Siver on 23.05.2017.
 */

window.onload = function () {

    var game = new Phaser.Game(1000, 800, Phaser.AUTO, 'game-wrapper', {preload: preload, create: create, update: update, render: render});

    var drone,
        movementThrust = 200,
        rotationThrust = 0.03;

    function preload() {

        game.load.image('drone', 'sprites/drone.png');

    }

    function create() {

        /**
         * creating world
         */
        game.world.setBounds(0, 0, 5000, 5000);
        game.physics.startSystem(Phaser.Physics.P2JS);

        /**
         * creating drone
         */
        drone = game.add.sprite(game.world.centerX, game.world.centerY, 'drone');
        drone.anchor.setTo(0.5, 0.5);
        game.physics.p2.enable(drone);
        drone.body.collideWorldBounds = true;
        drone.body.angularDamping = 0.5;
        drone.body.damping = 0.5;

        /**
         * creating camera
         */
        game.camera.focusOnXY(game.world.centerX, game.world.centerY);

        // Prevent directions and space key events bubbling up to browser,
        // since these keys will make web page scroll which is not expected.
        game.input.keyboard.addKeyCapture([
            Phaser.Keyboard.LEFT,
            Phaser.Keyboard.RIGHT,
            Phaser.Keyboard.UP,
            Phaser.Keyboard.DOWN,
            Phaser.Keyboard.SPACEBAR
        ]);
    }

    function update() {

        // Check key states every frame.
        // Move ONLY one of the left and right key is hold.
        if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
        {
            drone.body.angularVelocity -= rotationThrust;
        }
        else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT))
        {
            drone.body.angularVelocity += rotationThrust;
        }
        else if (game.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)) {
            if (drone.body.angularVelocity > 0) {
                drone.body.angularVelocity -= 0.01;
            } else {
                drone.body.angularVelocity += 0.01;
            }

            if (drone.body.velocity.x > 0) {
                drone.body.velocity.x -= 0.5;
            } else {
                drone.body.velocity.x += 0.5;
            }

            if (drone.body.velocity.y > 0) {
                drone.body.velocity.y -= 0.5;
            } else {
                drone.body.velocity.y += 0.5;
            }

        }

        if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) {
            drone.body.thrust(movementThrust);
        } else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
            drone.body.thrust(-movementThrust);
        }
    }

    function render() {

        // Camera
        game.debug.cameraInfo(game.camera, 32, 32);
        game.debug.spriteInfo(drone, 32, 500);
        game.debug.text(drone.body.velocity.x, 600, 32);

    }

};<commit_msg>Thrusting updated.<commit_after>/**
 * Created by Dzmitry Siver on 23.05.2017.
 */

window.onload = function () {

    var game = new Phaser.Game(1000, 800, Phaser.AUTO, 'game-wrapper', {
        preload: preload,
        create: create,
        update: update,
        render: render
    });

    var drone,
        movementThrust = 300,
        rotationThrust = 0.03;

    function preload() {

        game.load.image('drone', 'sprites/drone.png');

    }

    function create() {

        /**
         * creating world
         */
        game.world.setBounds(0, 0, 5000, 5000);
        game.physics.startSystem(Phaser.Physics.P2JS);
        game.time.advancedTiming = true;

        /**
         * creating drone
         */
        drone = game.add.sprite(game.world.centerX, game.world.centerY, 'drone');
        drone.anchor.setTo(0.5, 0.5);
        game.physics.p2.enable(drone);
        drone.body.collideWorldBounds = true;
        drone.body.angularDamping = 0.1;
        drone.body.damping = 0.1;

        /**
         * creating camera
         */
        game.camera.focusOnXY(game.world.centerX, game.world.centerY);

        // Prevent directions and space key events bubbling up to browser,
        // since these keys will make web page scroll which is not expected.
        game.input.keyboard.addKeyCapture([
            Phaser.Keyboard.LEFT,
            Phaser.Keyboard.RIGHT,
            Phaser.Keyboard.UP,
            Phaser.Keyboard.DOWN,
            Phaser.Keyboard.SPACEBAR
        ]);
    }

    function stabilizeDrone() {
        var velocityX = drone.body.velocity.x,
            velocityY = drone.body.velocity.y,
            velocityAngular = drone.body.angularVelocity,
            stabilizationVelocity = 2;

        if (Math.abs(velocityAngular) < rotationThrust ) {
            drone.body.angularVelocity = 0;
        } else {
            if (velocityAngular > 0) {
                drone.body.angularVelocity -= rotationThrust;
            } else if (velocityAngular < 0) {
                drone.body.angularVelocity += rotationThrust;
            }
        }

        // TODO: Damping velocity based on X/Y coords causes incorrect body positioning;
        // TODO: Create complex damping function based on body angle and using only Trhust() functions.
        // Velocity X
        if (Math.abs(velocityX) < stabilizationVelocity ) {
            drone.body.velocity.x = 0;
        } else {
            if (velocityX > 0) {
                drone.body.velocity.x -= stabilizationVelocity;
            } else if (velocityX < 0) {
                drone.body.velocity.x += stabilizationVelocity;
            }
        }

        // Velocity Y
        if (Math.abs(velocityY) < stabilizationVelocity ) {
            drone.body.velocity.y = 0;
        } else {
            if (drone.body.velocity.y > 0) {
                drone.body.velocity.y -= stabilizationVelocity;
            } else if (drone.body.velocity.y < 0) {
                drone.body.velocity.y += stabilizationVelocity;
            }
        }
    }

    function update() {

        if (game.input.keyboard.isDown(Phaser.Keyboard.Q)) {
            drone.body.angularVelocity -= rotationThrust;
        }
        else if (game.input.keyboard.isDown(Phaser.Keyboard.E)) {
            drone.body.angularVelocity += rotationThrust;
        }

        if (game.input.keyboard.isDown(Phaser.Keyboard.A)) {
            drone.body.thrustLeft(movementThrust);
        } else if (game.input.keyboard.isDown(Phaser.Keyboard.D)) {
            drone.body.thrustRight(movementThrust);
        }

        if (game.input.keyboard.isDown(Phaser.Keyboard.W)) {
            drone.body.thrust(movementThrust);
        } else if (game.input.keyboard.isDown(Phaser.Keyboard.S)) {
            drone.body.thrust(-movementThrust);
        }

        if (game.input.keyboard.isDown(Phaser.Keyboard.SPACEBAR)) {
            stabilizeDrone();
        }
    }

    function render() {

        // Camera
        game.debug.cameraInfo(game.camera, 32, 32);
        game.debug.spriteInfo(drone, 32, 700);
        game.debug.text(drone.body.velocity.x || '--', 800, 32, "#00ff00");
        game.debug.text(game.time.fps || '--', 800, 700, "#00ff00");

    }

};<|endoftext|>


<commit_before><commit_msg>fix: Unbind a property never binded (like in a if)<commit_after><|endoftext|>


<commit_before>define( ['three', 'boardSize', 'camera', 'container', 'controls', 'dat', 'geometry', 'light', 'material', 'renderer', 'rtt', 'scene', 'texture', 'shader!simple.vert', 'shader!copy.frag', 'shader!shift.frag', 'shader!solidify.frag', 'shader!spawn.frag'],
function ( THREE, boardSize, camera, container, controls, dat, geometry, light, material, renderer, RenderToTarget, scene, texture, simpleVert, copyFrag, shiftFrag, solidifyFrag, spawnFrag ) {
  var app = {
    addPass: function ( fragmentShader, input ) {
      fragmentShader.define( 'STEP', 1 / boardSize );
      var mat = new THREE.ShaderMaterial( {
        uniforms: {
          uTexture: { type: 't', value: input },
          uRandom: { type: 'f', value: 0 }
        },
        vertexShader: simpleVert.value,
        fragmentShader: fragmentShader.value
      });
      return new RenderToTarget( mat, boardSize );
    },
    init: function () {
      app.reset();

      // Spawn pass (create new stuff)
      app.spawnPass = app.addPass( spawnFrag, null ); // Will add target later

      // Shift pass (move it along)
      app.shiftPass = app.addPass( shiftFrag, null ); // Will add target later

      // Solidify pass (detect we've hit something)
      app.solidifyPass = app.addPass( solidifyFrag, app.shiftPass.renderTarget  );

      // Copy pass (copy from shift, so shift can read)
      app.copyPass = app.addPass( copyFrag, app.solidifyPass.renderTarget  );

      // Bootstrapped, now point spawn and shift at copy to complete loop
      app.spawnPass.material.uniforms.uTexture.value = app.copyPass.renderTarget;
      app.shiftPass.material.uniforms.uTexture.value = app.copyPass.renderTarget;

      // Copy to display layer
      material.display.uniforms.uTexture.value = app.copyPass.renderTarget;

      // Add game board to visible stage
      var mesh = new THREE.Mesh( geometry.plane, material.display );
      scene.add( mesh );

      // Add debug passes above main game
      var spacing = 600;
      var offset = -spacing;
      [app.spawnPass, app.shiftPass, app.solidifyPass].forEach( function ( pass ) {
        mesh = new THREE.Mesh( geometry.plane, material.createDebugShader( pass.renderTarget ) );
        mesh.position.x = offset;
        mesh.position.y = spacing;
        offset += spacing;
        scene.add( mesh );
      } );

      // Listen for clicks
      renderer.domElement.addEventListener( 'click', app.raycast );

      // GUI controls
      app.gui = new dat.GUI();
      app.gui.add( app, 'simulationRate', 1, 100 ).step( 1 );
      app.gui.add( app, 'spawnRate', 1, 10 ).step( 1 );
      app.gui.add( app, 'renderThrottle', 1, 100 ).step( 1 );
      app.gui.add( app, 'clear');
    },
    reset: function () {
      app.needsClear = true;
      app.frame = 0;
      app.simulationFrame = 0;
      app.simulationRate = 1; // How many simulations frames are done per render step
      app.spawnRate = 5;
      app.renderThrottle = 40; // How rAF calls we have per render step (1 for no throttling)
    },
    blank: new THREE.Texture(),
    needsClear: false,
    clear: function () {
      app.needsClear = true;
    },
    simulate: function () {
      if ( app.needsClear ) {
        // Read blank texture into copyPass to clear out game state
        app.copyPass.material.uniforms.uTexture.value = app.blank;
        app.copyPass.process();
        app.copyPass.material.uniforms.uTexture.value = app.solidifyPass.renderTarget;
        app.needsClear = false;
      }

      // Spawn new block
      if ( app.simulationFrame % app.spawnRate === 0 ) {
        app.spawnPass.material.uniforms.uRandom.value = Math.random();
        app.spawnPass.process();

        // When we spawn, want to have solidify read from spawn...
        app.solidifyPass.material.uniforms.uTexture.value = app.spawnPass.renderTarget;
        app.solidifyPass.process();
        app.copyPass.process();
      }

      // Standard game step
      app.solidifyPass.material.uniforms.uTexture.value = app.shiftPass.renderTarget;
      app.shiftPass.process();
      app.solidifyPass.process();
      app.copyPass.process();
      app.simulationFrame++;
    },
    animate: function () {
      window.requestAnimationFrame( app.animate );
      app.tick();
    },
    tick: function () {
      //controls.update();

      if ( app.frame % app.renderThrottle === 0 ) {
        for ( var i = 0; i < app.simulationRate; i++ ) { app.simulate(); }
      }
      app.frame++;

      // Move camera towards target location
      if ( app.cameraTarget ) {
        camera.position.lerp( app.cameraTarget, 0.1 );
      }
      renderer.render( scene, camera );
    },
    cameraTarget: new THREE.Vector3( 0, 0, 360 ),
    raycast: function ( e ) {
      // Reliably get mouse position across browsers
      var target = e.target || e.srcElement,
      rect = target.getBoundingClientRect(),
      offsetX = e.clientX || e.pageX,
      offsetY = e.clientY || e.pageY;
      offsetX -= rect.left,
      offsetY -= rect.top;

      var mouse = {
        x: ( offsetX / rect.width ) * 2 - 1, // -1 -> 1
        y: -( offsetY / rect.height ) * 2 + 1 // 1 -> -1
      };
      var vector = new THREE.Vector3( mouse.x, mouse.y, camera.near );
      vector.unproject( camera );
      var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
      // See if the ray from the camera into the world hits one of our meshes
      var intersects = raycaster.intersectObjects( scene.children, true );
      if ( intersects.length > 0 ) {
        var object = intersects[0].object;
        app.cameraTarget = object.position.clone();
        app.cameraTarget.z = 400;
      } else {
        app.cameraTarget.set( 0, 300, 1200 );
      }
    }
  };

  return app;
} );
<commit_msg>Better camera positions<commit_after>define( ['three', 'boardSize', 'camera', 'container', 'controls', 'dat', 'geometry', 'light', 'material', 'renderer', 'rtt', 'scene', 'texture', 'shader!simple.vert', 'shader!copy.frag', 'shader!shift.frag', 'shader!solidify.frag', 'shader!spawn.frag'],
function ( THREE, boardSize, camera, container, controls, dat, geometry, light, material, renderer, RenderToTarget, scene, texture, simpleVert, copyFrag, shiftFrag, solidifyFrag, spawnFrag ) {
  var app = {
    addPass: function ( fragmentShader, input ) {
      fragmentShader.define( 'STEP', 1 / boardSize );
      var mat = new THREE.ShaderMaterial( {
        uniforms: {
          uTexture: { type: 't', value: input },
          uRandom: { type: 'f', value: 0 }
        },
        vertexShader: simpleVert.value,
        fragmentShader: fragmentShader.value
      });
      return new RenderToTarget( mat, boardSize );
    },
    init: function () {
      app.reset();

      // Spawn pass (create new stuff)
      app.spawnPass = app.addPass( spawnFrag, null ); // Will add target later

      // Shift pass (move it along)
      app.shiftPass = app.addPass( shiftFrag, null ); // Will add target later

      // Solidify pass (detect we've hit something)
      app.solidifyPass = app.addPass( solidifyFrag, app.shiftPass.renderTarget  );

      // Copy pass (copy from shift, so shift can read)
      app.copyPass = app.addPass( copyFrag, app.solidifyPass.renderTarget  );

      // Bootstrapped, now point spawn and shift at copy to complete loop
      app.spawnPass.material.uniforms.uTexture.value = app.copyPass.renderTarget;
      app.shiftPass.material.uniforms.uTexture.value = app.copyPass.renderTarget;

      // Copy to display layer
      material.display.uniforms.uTexture.value = app.copyPass.renderTarget;

      // Add game board to visible stage
      var mesh = new THREE.Mesh( geometry.plane, material.display );
      scene.add( mesh );

      // Add debug passes above main game
      var spacing = 600;
      var offset = -spacing;
      [app.spawnPass, app.shiftPass, app.solidifyPass].forEach( function ( pass ) {
        mesh = new THREE.Mesh( geometry.plane, material.createDebugShader( pass.renderTarget ) );
        mesh.position.x = offset;
        mesh.position.y = spacing;
        offset += spacing;
        scene.add( mesh );
      } );

      // Listen for clicks
      renderer.domElement.addEventListener( 'click', app.raycast );

      // GUI controls
      app.gui = new dat.GUI();
      app.gui.add( app, 'simulationRate', 1, 100 ).step( 1 );
      app.gui.add( app, 'spawnRate', 1, 10 ).step( 1 );
      app.gui.add( app, 'renderThrottle', 1, 100 ).step( 1 );
      app.gui.add( app, 'clear');
      app.gui.close();
    },
    reset: function () {
      app.needsClear = true;
      app.frame = 0;
      app.simulationFrame = 0;
      app.simulationRate = 1; // How many simulations frames are done per render step
      app.spawnRate = 5;
      app.renderThrottle = 40; // How rAF calls we have per render step (1 for no throttling)
      app.cameraTarget = new THREE.Vector3( 0, 0, 360 );
    },
    blank: new THREE.Texture(),
    needsClear: false,
    clear: function () {
      app.needsClear = true;
    },
    simulate: function () {
      if ( app.needsClear ) {
        // Read blank texture into copyPass to clear out game state
        app.copyPass.material.uniforms.uTexture.value = app.blank;
        app.copyPass.process();
        app.copyPass.material.uniforms.uTexture.value = app.solidifyPass.renderTarget;
        app.needsClear = false;
      }

      // Spawn new block
      if ( app.simulationFrame % app.spawnRate === 0 ) {
        app.spawnPass.material.uniforms.uRandom.value = Math.random();
        app.spawnPass.process();

        // When we spawn, want to have solidify read from spawn...
        app.solidifyPass.material.uniforms.uTexture.value = app.spawnPass.renderTarget;
        app.solidifyPass.process();
        app.copyPass.process();
      }

      // Standard game step
      app.solidifyPass.material.uniforms.uTexture.value = app.shiftPass.renderTarget;
      app.shiftPass.process();
      app.solidifyPass.process();
      app.copyPass.process();
      app.simulationFrame++;
    },
    animate: function () {
      window.requestAnimationFrame( app.animate );
      app.tick();
    },
    tick: function () {
      //controls.update();

      if ( app.frame % app.renderThrottle === 0 ) {
        for ( var i = 0; i < app.simulationRate; i++ ) { app.simulate(); }
      }
      app.frame++;

      // Move camera towards target location
      if ( app.cameraTarget ) {
        camera.position.lerp( app.cameraTarget, 0.1 );
      }
      renderer.render( scene, camera );
    },
    raycast: function ( e ) {
      // Reliably get mouse position across browsers
      var target = e.target || e.srcElement,
      rect = target.getBoundingClientRect(),
      offsetX = e.clientX || e.pageX,
      offsetY = e.clientY || e.pageY;
      offsetX -= rect.left,
      offsetY -= rect.top;

      var mouse = {
        x: ( offsetX / rect.width ) * 2 - 1, // -1 -> 1
        y: -( offsetY / rect.height ) * 2 + 1 // 1 -> -1
      };
      var vector = new THREE.Vector3( mouse.x, mouse.y, camera.near );
      vector.unproject( camera );
      var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
      // See if the ray from the camera into the world hits one of our meshes
      var intersects = raycaster.intersectObjects( scene.children, true );
      if ( intersects.length > 0 ) {
        var object = intersects[0].object;
        app.cameraTarget = object.position.clone();
        app.cameraTarget.z = 360;
      } else {
        app.cameraTarget.set( 0, 300, 800 );
      }
    }
  };

  return app;
} );
<|endoftext|>


<commit_before><commit_msg>clickable-npm-scripts:refresh command<commit_after><|endoftext|>