<commit_before>//=========================================
//  样式补丁模块
//==========================================
$.define("css_fix", !!top.getComputedStyle, function(){
    //$.log("已加载css_fix模块");
    var adapter = $.cssAdapter = {},
    ropacity = /opacity=([^)]*)/i,
    ralpha = /alpha\([^)]*\)/i,
    rnumpx = /^-?\d+(?:px)?$/i,
    rtransform = /(\w+)\(([^)]+)\)/g,
    rnum = /^-?\d/;
    //=========================　处理　opacity　=========================
    adapter[ "opacity:get" ] = function( node, op ){
        //这是最快的获取IE透明值的方式，不需要动用正则了！
        if(node.filters.alpha){
            op = node.filters.alpha.opacity;
        }else if(node.filters["DXImageTransform.Microsoft.Alpha"]){
            op = node.filters["DXImageTransform.Microsoft.Alpha"].opacity
        }else{
            op = (node.currentStyle.filter ||"opacity=100").match(ropacity)[1];
        }
        return (op  ? op /100 :op)+"";//如果是零就不用除100了
    }
    //http://www.freemathhelp.com/matrix-multiplication.html
    //金丝楠木是皇家专用木材，一般只有皇帝可以使用做梓宫。
    adapter[ "opacity:set" ] = function( node, _, value ){
        var currentStyle = node.currentStyle, style = node.style;
        if(!currentStyle.hasLayout)
            style.zoom = 1;//让元素获得hasLayout
        value = (value > 0.999) ? 1: (value < 0.001) ? 0 : value;
        if(node.filters.alpha){
            //必须已经定义过透明滤镜才能使用以下便捷方式
            node.filters.alpha.opacity = value * 100;
        }else{
            style.filter = "alpha(opacity="+((value * 100) | 0)+")";
        }
        //IE7的透明滤镜当其值为100时会让文本模糊不清
        if(value === 1){
            style.filter = currentStyle.filter.replace(ralpha,'');
        }
    }
    var runselectable = /^(br|input|link|meta|hr|col|area|base|hr|embed|param|iframe|textarea|input|select|script|noscript)/i
    adapter[ "userSelect:set" ] = function( node, name, value ) {
        if(!runselectable.test(node.nodeName)){//跳过不显示的标签与表单控件
            var allow = /none/.test(value||"all");
            node.unselectable  = allow ? "" : "on";
            node.onselectstart = allow ? "" : function(){
                return false;
            };
        }
    };
    var ie8 = !!top.XDomainRequest,
    border = {
        thin:   ie8 ? '1px' : '2px',
        medium: ie8 ? '3px' : '4px',
        thick:  ie8 ? '5px' : '6px'
    };
    adapter[ "_default:get" ] = function(node, name){
        var ret = node.currentStyle && node.currentStyle[name];
        if ((!rnumpx.test(ret) && rnum.test(ret))) {
            var style = node.style,
            left = style.left,
            rsLeft = node.runtimeStyle && node.runtimeStyle.left ;
            if (rsLeft) {
                node.runtimeStyle.left = node.currentStyle.left;
            }
            style.left = name === 'fontSize' ? '1em' : (ret || 0);
            ret = style.pixelLeft + "px";
            style.left = left;
            if (rsLeft) {
                node.runtimeStyle.left = rsLeft;
            }
        }
        if( ret == "medium" ){
            name = name.replace("Width","Style");
            //border width 默认值为medium，即使其为0"
            if(arguments.callee(node,name) == "none"){
                ret = "0px";
            }
        }
        if(/margin|padding|border/.test(name) && ret === "auto"){
            ret = "0px";
        }
        return ret === "" ? "auto" : border[ret] ||  ret;
    }
    var ident  = "DXImageTransform.Microsoft.Matrix"

    adapter[ "transform:get" ] = function(node, name){
        var m = $._data(node,"matrix")
        if(!m){
            if(!node.currentStyle.hasLayout){
                node.style.zoom = 1;
            }
            //IE9下请千万别设置  <meta content="IE=8" http-equiv="X-UA-Compatible"/>
            //http://www.cnblogs.com/Libra/archive/2009/03/24/1420731.html
            if(!node.filters[ident]){
                var old = node.currentStyle.filter;//防止覆盖已有的滤镜
                node.style.filter =  (old ? old +"," : "") + " progid:" + ident + "(sizingMethod='auto expand')";
            }
            var f = node.filters[ident];
            m = new $.Matrix2D( f.M11, f.M12, f.M21, f.M22, f.Dx, f.Dy);
            $._data(node,"matrix",m ) //保存到缓存系统，省得每次都计算
        }
        return name === true ? m : m.toString();
    }
    //deg	degrees, 角度
    //grad	grads, 百分度
    //rad	radians, 弧度
    function toRadian(value) {
        return ~value.indexOf("deg") ?
        parseInt(value,10) *  Math.PI/180:
        ~value.indexOf("grad") ?
        parseInt(value,10) * Math.PI/200:
        parseFloat(value);
    }
    var f = false;
    adapter[ "transform:set" ] = function(node, name, value){
        var m = adapter[ "transform:get" ](node, true).set( 1,0,0,1,0,0 );
        var el = $(node);//处理元素的定位问题，保存原来元素与offsetParent的距离
        if(node._mass_top == null && el.css("position") != "static"){
            var p = el.position()
            node._mass_top = p.top;
            node._mass_left = p.left;
        }
        value.toLowerCase().replace(rtransform,function(_,method,array){
            array = array.replace(/px/g,"").match($.rword) || [];
            if(/skew|rotate/.test(method)){//角度必须带单位
                array[0] = toRadian(array[0] );//IE矩阵滤镜的方向是相反的
                array[1] = toRadian(array[1] || "0");
            }
            if(method == "scale" && array[1] == void 0){
                array[1] = array[0] //sy如果没有定义等于sx
            }
            if(method !== "matrix"){
                method = method.replace(/(x|y)$/i,function(_,b){
                    return  b.toUpperCase();//处理translateX translateY scaleX scaleY skewX skewY等大小写问题
                })
            }
            m[method].apply(m, array);
            var filter = node.filters[ident];
            filter.M11 =  filter.M22 = 1;//重置矩形
            filter.M12 =  filter.M21 = 0;
            var width  = node.offsetWidth,height = node.offsetHeight;//取得未变形前的宽高
            filter.M11 = m.a;
            filter.M12 = m.c;//★★★注意这里的顺序, IE滤镜和其他浏览器定义的角度方向相反
            filter.M21 = m.b;
            filter.M22 = m.d;
            filter.Dx  = m.tx;
            filter.Dy  = m.ty;
            var tw = node.offsetWidth,th = node.offsetHeight;//取得变形后高宽
            node.style.position = "relative";
            if(!f){
                f = true;
                console.log("-------------")
                console.log((width - tw)/2  + m.tx)//(node._mass_left | 0) +
                   console.log("-------------")
            }
            node.style.left = (node._mass_left | 0) + (width - tw)/2  + m.tx + "px";
            node.style.top =  (node._mass_top | 0) + ( height - th)/2  + m.ty + "px";
        //http://extremelysatisfactorytotalitarianism.com/blog/?p=922
        //http://someguynameddylan.com/lab/transform-origin-in-internet-explorer.php
        });
        $._data(node,"matrix",m )
    }
});
//2011.10.21 去掉opacity:setter 的style.visibility处理
//2011.11.21 将IE的矩阵滤镜的相应代码转移到这里
//2012.5.9 完美支持CSS3 transform 2D

   <commit_msg>更节能的adapter[ "transform:set" ]<commit_after>//=========================================
//  样式补丁模块
//==========================================
$.define("css_fix", !!top.getComputedStyle, function(){
    //$.log("已加载css_fix模块");
    var adapter = $.cssAdapter = {},
    ropacity = /opacity=([^)]*)/i,
    ralpha = /alpha\([^)]*\)/i,
    rnumpx = /^-?\d+(?:px)?$/i,
    rtransform = /(\w+)\(([^)]+)\)/g,
    rnum = /^-?\d/;
    //=========================　处理　opacity　=========================
    adapter[ "opacity:get" ] = function( node, op ){
        //这是最快的获取IE透明值的方式，不需要动用正则了！
        if(node.filters.alpha){
            op = node.filters.alpha.opacity;
        }else if(node.filters["DXImageTransform.Microsoft.Alpha"]){
            op = node.filters["DXImageTransform.Microsoft.Alpha"].opacity
        }else{
            op = (node.currentStyle.filter ||"opacity=100").match(ropacity)[1];
        }
        return (op  ? op /100 :op)+"";//如果是零就不用除100了
    }
    //http://www.freemathhelp.com/matrix-multiplication.html
    //金丝楠木是皇家专用木材，一般只有皇帝可以使用做梓宫。
    adapter[ "opacity:set" ] = function( node, _, value ){
        var currentStyle = node.currentStyle, style = node.style;
        if(!currentStyle.hasLayout)
            style.zoom = 1;//让元素获得hasLayout
        value = (value > 0.999) ? 1: (value < 0.001) ? 0 : value;
        if(node.filters.alpha){
            //必须已经定义过透明滤镜才能使用以下便捷方式
            node.filters.alpha.opacity = value * 100;
        }else{
            style.filter = "alpha(opacity="+((value * 100) | 0)+")";
        }
        //IE7的透明滤镜当其值为100时会让文本模糊不清
        if(value === 1){
            style.filter = currentStyle.filter.replace(ralpha,'');
        }
    }
    var runselectable = /^(br|input|link|meta|hr|col|area|base|hr|embed|param|iframe|textarea|input|select|script|noscript)/i
    adapter[ "userSelect:set" ] = function( node, name, value ) {
        if(!runselectable.test(node.nodeName)){//跳过不显示的标签与表单控件
            var allow = /none/.test(value||"all");
            node.unselectable  = allow ? "" : "on";
            node.onselectstart = allow ? "" : function(){
                return false;
            };
        }
    };
    var ie8 = !!top.XDomainRequest,
    border = {
        thin:   ie8 ? '1px' : '2px',
        medium: ie8 ? '3px' : '4px',
        thick:  ie8 ? '5px' : '6px'
    };
    adapter[ "_default:get" ] = function(node, name){
        var ret = node.currentStyle && node.currentStyle[name];
        if ((!rnumpx.test(ret) && rnum.test(ret))) {
            var style = node.style,
            left = style.left,
            rsLeft = node.runtimeStyle && node.runtimeStyle.left ;
            if (rsLeft) {
                node.runtimeStyle.left = node.currentStyle.left;
            }
            style.left = name === 'fontSize' ? '1em' : (ret || 0);
            ret = style.pixelLeft + "px";
            style.left = left;
            if (rsLeft) {
                node.runtimeStyle.left = rsLeft;
            }
        }
        if( ret == "medium" ){
            name = name.replace("Width","Style");
            //border width 默认值为medium，即使其为0"
            if(arguments.callee(node,name) == "none"){
                ret = "0px";
            }
        }
        if(/margin|padding|border/.test(name) && ret === "auto"){
            ret = "0px";
        }
        return ret === "" ? "auto" : border[ret] ||  ret;
    }
    var ident  = "DXImageTransform.Microsoft.Matrix"

    adapter[ "transform:get" ] = function(node, name){
        var m = $._data(node,"matrix")
        if(!m){
            if(!node.currentStyle.hasLayout){
                node.style.zoom = 1;
            }
            //IE9下请千万别设置  <meta content="IE=8" http-equiv="X-UA-Compatible"/>
            //http://www.cnblogs.com/Libra/archive/2009/03/24/1420731.html
            if(!node.filters[ident]){
                var old = node.currentStyle.filter;//防止覆盖已有的滤镜
                node.style.filter =  (old ? old +"," : "") + " progid:" + ident + "(sizingMethod='auto expand')";
            }
            var f = node.filters[ident];
            m = new $.Matrix2D( f.M11, f.M12, f.M21, f.M22, f.Dx, f.Dy);
            $._data(node,"matrix",m ) //保存到缓存系统，省得每次都计算
        }
        return name === true ? m : m.toString();
    }
    //deg	degrees, 角度
    //grad	grads, 百分度
    //rad	radians, 弧度
    function toRadian(value) {
        return ~value.indexOf("deg") ?
        parseInt(value,10) *  Math.PI/180:
        ~value.indexOf("grad") ?
        parseInt(value,10) * Math.PI/200:
        parseFloat(value);
    }

    adapter[ "transform:set" ] = function(node, name, value){
        var m = adapter[ "transform:get" ](node, true).set( 1,0,0,1,0,0 );
        var filter = node.filters[ident];
        filter.M11 =  filter.M22 = 1;//重置矩形
        filter.M12 =  filter.M21 = 0;
        var width = node.offsetWidth
        var height = node.offsetHeight
        var el = $(node);//处理元素的定位问题，保存原来元素与offsetParent的距离
        if(node._mass_top == null && el.css("position") != "static"){
            var p = el.position()
            node._mass_top = p.top;
            node._mass_left = p.left;
        }
        value.toLowerCase().replace(rtransform,function(_,method,array){
            array = array.replace(/px/g,"").match($.rword) || [];
            if(/skew|rotate/.test(method)){//角度必须带单位
                array[0] = toRadian(array[0] );//IE矩阵滤镜的方向是相反的
                array[1] = toRadian(array[1] || "0");
            }
            if(method == "scale" && array[1] == void 0){
                array[1] = array[0] //sy如果没有定义等于sx
            }
            if(method !== "matrix"){
                method = method.replace(/(x|y)$/i,function(_,b){
                    return  b.toUpperCase();//处理translateX translateY scaleX scaleY skewX skewY等大小写问题
                })
            }
            m[method].apply(m, array);
            filter.M11 = m.a;//0
            filter.M12 = m.c;//2★★★注意这里的顺序, IE滤镜和其他浏览器定义的角度方向相反
            filter.M21 = m.b;//1
            filter.M22 = m.d;//3
            filter.Dx  = m.tx;
            filter.Dy  = m.ty;
        //http://extremelysatisfactorytotalitarianism.com/blog/?p=922
        //http://someguynameddylan.com/lab/transform-origin-in-internet-explorer.php
        });
        node.style.position = "relative";
        node.style.left = node._mass_left + ( width - node.offsetWidth )/2  + m.tx  + "px";
        node.style.top = node._mass_top + ( height - node.offsetHeight) /2  + m.ty  + "px";

        $._data(node,"matrix",m )
    }
});
//2011.10.21 去掉opacity:setter 的style.visibility处理
//2011.11.21 将IE的矩阵滤镜的相应代码转移到这里
//2012.5.9 完美支持CSS3 transform 2D

   <|endoftext|>


<commit_before>var apijs = require("tnt.api");

var http = require("httpplease");
var promises = require('httpplease-promises');
var withcredentials = require('./withcredentials.js');
var Promise = require('es6-promise').Promise;
var json = require("httpplease/plugins/json");
jsonHttp = http.use(withcredentials).use(json).use(promises(Promise));
var jsonreq = require("httpplease/plugins/jsonrequest");
jsonReqHttp = http.use(withcredentials).use(jsonreq).use(promises(Promise));
// http = http.use(promises(Promise));
var structure = require("./structure.js");

var cttvApi = function () {

    var req; // can be json or not

    var credentials = {
        token : undefined, // is a promise or a string
        appname : "",
        secret : "",
        expiry : undefined
    };

    var config = {
        verbose: false,
        prefix: "https://www.targetvalidation.org/api/",
        version: "1.2",
        format: "json"
    };

    var getToken = function () {
        var tokenUrl = _.url.requestToken(credentials);
        credentials.token = jsonHttp.get({
            "url": tokenUrl
        });
        return credentials.token;
    };

    var _ = {};
    _.call = function (myurl, data, format) {
        // Response format json or not
        if (!format) {
            format = "json";
        }
        if (format === "json") {
            req = jsonHttp;
        } else {
            req = jsonReqHttp;
        }

        // No auth
        if ((!credentials.token) && (!credentials.appname) && (!credentials.secret)) {
            if (config.verbose) {
                console.log("    CttvApi running in non-authentication mode");
            }

            if (data){ // post
                return req.post({
                    "url": myurl,
                    "body": data,
                    "headers": {
                        "Accept": "*/*"
                    }
                });
            }

            return req.get({
                "url" : myurl,
                "headers": {
                    "Accept": "*/*"
                }
            });
        }

        // Auth - but not token
        if (!credentials.token) {
            if (config.verbose) {
                console.log("No credential token, requesting one...");
            }

            return getToken()
                .then(callApi)
                .catch(catchErr);
        // Auth & token
        } else {
            if (config.verbose) {
                console.log("Current token is: " + credentials.token);
            }
            var tokenPromise = new Promise (function (resolve) {
                resolve ({
                    body: {
                        token: credentials.token
                    }
                });
            });
            if (typeof credentials.token !== "string") { // The token is still a string
                tokenPromise = credentials.token;
            }

            return tokenPromise
                // .then (function () {
                //     return callApi
                //     // return jsonHttp.get({
                //     //     "url" : myurl,
                //     //     "headers": {
                //     //         "Auth-token": credentials.token
                //     //     }
                //     // })
                //     .catch(catchErr);
                .then (callApi)
                .catch(catchErr);
                // });
        }

        function callApi (resp) {
            if (config.verbose) {
                console.log("   ======> Got a new token: " + resp.body.token);
            }
            credentials.token = resp.body.token;
            var headers = {
                "Auth-token": resp.body.token
            };
            var myPromise;
            if (data) { // post
                myPromise = req.post ({
                    "url": myurl,
                    "headers": headers,
                    "body": data
                });
            } else { // get
                myPromise = req.get ({
                    "url": myurl,
                    "headers": headers
                });

            }
            return myPromise;
        }

        function catchErr (err) {
            // Logic to deal with expired tokens
            switch (err.status) {
                case (401) : // Probably wrong credentials
                if (err.body.message === "authentication credentials not valid") {
                    if (config.verbose) {
                        console.log("    --- Received an api error -- Possibly the credentials are wrong (" + err.status + "), so I'll make the call without credentials");
                    }
                    console.warn('wrong authentication appname (' + credentials.appname + ') or secret (' + credentials.secret + ') -- I will remove the credentials and try the same call again');
                    // Remove credentials and run in non-authentication mode
                    credentials.appname = undefined;
                    credentials.secret = undefined;
                    credentials.token = undefined;
                    return _.call(myurl, data);
                }
                break;

                case (419) : // Token expired
                if (config.verbose) {
                    console.log("     --- Received an api error -- Possibly the token has expired (" + err.status + "), so I'll request a new one");
                }
                if (typeof credentials.token === "string" ) {
                    credentials.token = undefined;
                }
                return _.call(myurl, data);

                case (429) : // Too many calls
                if (config.verbose) {
                    console.log("     --- Received an api error -- Probably too many calls made to the api (" + err.status + "), so I'll wait some time to fetch the data");
                }
                var delayedPromise = new Promise (function (resolve) {
                    setTimeout(function (){
                        if (config.verbose) {
                            console.log(" *** trying again after receiving a too many requests error");
                        }
                        resolve(_.call(myurl, data));
                    }, 10000);
                });
                return delayedPromise;

                default:
                throw err;
            }
        }

    };

    apijs(_)
        .getset(credentials)
        .getset(config);

    // Utils
    _.utils = {};
    _.utils.flat2tree = structure.flat2tree;

    // URL object
    _.url = {};

    // prefixes
    var prefixFilterby = "public/evidence/filter?";
    var prefixAssociations = "public/association/filter?";
    var prefixSearch = "public/search?";
    var prefixGene = "private/target/";
    var prefixDisease = "private/disease/"; // updated from "efo" to "disease"
    var prefixToken = "public/auth/request_token?";
    var prefixAutocomplete = "private/autocomplete?";
    var prefixQuickSearch = "private/quicksearch?";
    var prefixExpression = "private/target/expression?";
    var prefixProxy = "proxy/generic/";
    var prefixTarget = "private/target/"; // this replaces prefixGene
    var prefixTargetRelation = "private/relation/target/";
    var prefixDiseaseRelation = "private/relation/disease/";
    var prefixLogSession = "private/utils/logevent";
    var prefixMultiSearch = "private/besthitsearch?";
    var prefixStats = "public/utils/stats";
    var prefixTargetsEnrichment = "private/enrichment/targets?";

    _.url.gene = function (obj) {
        return config.prefix + config.version + "/" + prefixGene + obj.gene_id;
    };

    _.url.target = function (obj) {
        if (obj && obj.target_id) {
            // One target
            return config.prefix + config.version + "/" + prefixTarget + obj.target_id;
        }
        // Multiple targets (optionally we can specify specific fields)
        return config.prefix + config.version + "/" + prefixTarget + parseUrlParams(obj);
    };

    _.url.disease = function (obj) {
        return config.prefix + config.version + "/" + prefixDisease + obj.code;
    };

    _.url.search = function (obj) {
        return config.prefix + config.version + "/" + prefixSearch + parseUrlParams(obj);
    };

    _.url.associations = function (obj) {
        return config.prefix + config.version + "/" + prefixAssociations + parseUrlParams(obj);
    };

    _.url.filterby = function (obj) {
        return config.prefix + config.version + "/" + prefixFilterby + parseUrlParams(obj);
    };

    _.url.requestToken = function (obj) {
        return config.prefix + config.version + "/" + prefixToken + "app_name=" + obj.appname + "&secret=" + obj.secret + (credentials.expiry ? ("&expiry=" + credentials.expiry) : "" );
    };

    _.url.autocomplete = function (obj) {
        return config.prefix + config.version + "/" + prefixAutocomplete + parseUrlParams(obj);
    };

    _.url.quickSearch = function (obj) {
        return config.prefix + config.version + "/" + prefixQuickSearch + parseUrlParams(obj);
    };

    _.url.expression = function (obj) {
        return config.prefix + config.version + "/" + prefixExpression + parseUrlParams(obj);
    };

    _.url.bestHitSearch = function (obj) {
        return config.prefix + config.version + "/" + prefixMultiSearch + parseUrlParams(obj);
    };

    _.url.proxy = function (obj) {
        return config.prefix + config.version + "/" + prefixProxy + obj.url;
    };

    _.url.targetRelation = function(obj){
        return config.prefix + config.version + "/" + prefixTargetRelation + obj.id + '?' + parseUrlParams(obj);
    };

    _.url.diseaseRelation = function(obj){
        var id = obj.id;
        delete(obj.id);
        return config.prefix + config.version + "/" + prefixDiseaseRelation + id + "?" + parseUrlParams(obj);
    };

    _.url.logSession = function (obj) {
        return config.prefix + config.version + "/" + prefixLogSession + '?' + parseUrlParams(obj);
    };

    _.url.stats = function () {
        return config.prefix + config.version + "/" + prefixStats;
    };

    _.url.targetsEnrichment = function (obj) {
        return config.prefix + config.version + "/" + prefixTargetsEnrichment + parseUrlParams(obj);
    };

    /**
    * This takes a params object and returns the params concatenated in a string.
    * If a parameter is an array, it adds each item, all with hte same key.
    * Example:
    *   obj = {q:'braf',size:20,filters:['id','pvalue']};
    *   console.log( parseUrlParams(obj) );
    *   // prints "q=braf&size=20&filters=id&filters=pvalue"
    */
    var parseUrlParams = function(obj){
        var opts = [];
        for(var i in obj){
            if( obj.hasOwnProperty(i)){
                if(obj[i].constructor === Array){
                    opts.push(i+"="+(obj[i].join("&"+i+"=")));
                } else {
                    opts.push(i+"="+obj[i]);
                }
            }
        }
        return opts.join("&");
    };

    return _;
};

module.exports = cttvApi;
<commit_msg>Make sending the credentials cookie an option that can be turned on via a method call on the api object<commit_after>var apijs = require("tnt.api");

var http = require("httpplease");
var promises = require('httpplease-promises');
var withcredentials = require('./withcredentials.js');
var Promise = require('es6-promise').Promise;
var json = require("httpplease/plugins/json");
jsonHttp = http.use(json).use(promises(Promise));
var jsonreq = require("httpplease/plugins/jsonrequest");
jsonReqHttp = http.use(jsonreq).use(promises(Promise));
// http = http.use(promises(Promise));
var structure = require("./structure.js");

var cttvApi = function () {

    var req; // can be json or not

    var credentials = {
        token : undefined, // is a promise or a string
        appname : "",
        secret : "",
        expiry : undefined
    };

    var config = {
        verbose: false,
        prefix: "https://www.targetvalidation.org/api/",
        version: "1.2",
        format: "json"
    };

    var sendCredentialsCookie = function() {
        jsonHttp = jsonHttp.use(withcredentials);
        jsonReqHttp = jsonReqHttp.use(withcredentials);
    };

    var getToken = function () {
        var tokenUrl = _.url.requestToken(credentials);
        credentials.token = jsonHttp.get({
            "url": tokenUrl
        });
        return credentials.token;
    };

    var _ = {};
    _.call = function (myurl, data, format) {
        // Response format json or not
        if (!format) {
            format = "json";
        }
        if (format === "json") {
            req = jsonHttp;
        } else {
            req = jsonReqHttp;
        }

        // No auth
        if ((!credentials.token) && (!credentials.appname) && (!credentials.secret)) {
            if (config.verbose) {
                console.log("    CttvApi running in non-authentication mode");
            }

            if (data){ // post
                return req.post({
                    "url": myurl,
                    "body": data,
                    "headers": {
                        "Accept": "*/*"
                    }
                });
            }

            return req.get({
                "url" : myurl,
                "headers": {
                    "Accept": "*/*"
                }
            });
        }

        // Auth - but not token
        if (!credentials.token) {
            if (config.verbose) {
                console.log("No credential token, requesting one...");
            }

            return getToken()
                .then(callApi)
                .catch(catchErr);
        // Auth & token
        } else {
            if (config.verbose) {
                console.log("Current token is: " + credentials.token);
            }
            var tokenPromise = new Promise (function (resolve) {
                resolve ({
                    body: {
                        token: credentials.token
                    }
                });
            });
            if (typeof credentials.token !== "string") { // The token is still a string
                tokenPromise = credentials.token;
            }

            return tokenPromise
                // .then (function () {
                //     return callApi
                //     // return jsonHttp.get({
                //     //     "url" : myurl,
                //     //     "headers": {
                //     //         "Auth-token": credentials.token
                //     //     }
                //     // })
                //     .catch(catchErr);
                .then (callApi)
                .catch(catchErr);
                // });
        }

        function callApi (resp) {
            if (config.verbose) {
                console.log("   ======> Got a new token: " + resp.body.token);
            }
            credentials.token = resp.body.token;
            var headers = {
                "Auth-token": resp.body.token
            };
            var myPromise;
            if (data) { // post
                myPromise = req.post ({
                    "url": myurl,
                    "headers": headers,
                    "body": data
                });
            } else { // get
                myPromise = req.get ({
                    "url": myurl,
                    "headers": headers
                });

            }
            return myPromise;
        }

        function catchErr (err) {
            // Logic to deal with expired tokens
            switch (err.status) {
                case (401) : // Probably wrong credentials
                if (err.body.message === "authentication credentials not valid") {
                    if (config.verbose) {
                        console.log("    --- Received an api error -- Possibly the credentials are wrong (" + err.status + "), so I'll make the call without credentials");
                    }
                    console.warn('wrong authentication appname (' + credentials.appname + ') or secret (' + credentials.secret + ') -- I will remove the credentials and try the same call again');
                    // Remove credentials and run in non-authentication mode
                    credentials.appname = undefined;
                    credentials.secret = undefined;
                    credentials.token = undefined;
                    return _.call(myurl, data);
                }
                break;

                case (419) : // Token expired
                if (config.verbose) {
                    console.log("     --- Received an api error -- Possibly the token has expired (" + err.status + "), so I'll request a new one");
                }
                if (typeof credentials.token === "string" ) {
                    credentials.token = undefined;
                }
                return _.call(myurl, data);

                case (429) : // Too many calls
                if (config.verbose) {
                    console.log("     --- Received an api error -- Probably too many calls made to the api (" + err.status + "), so I'll wait some time to fetch the data");
                }
                var delayedPromise = new Promise (function (resolve) {
                    setTimeout(function (){
                        if (config.verbose) {
                            console.log(" *** trying again after receiving a too many requests error");
                        }
                        resolve(_.call(myurl, data));
                    }, 10000);
                });
                return delayedPromise;

                default:
                throw err;
            }
        }

    };

    apijs(_)
        .getset(credentials)
        .getset(config)
        .method('sendCredentialsCookie', sendCredentialsCookie);

    // Utils
    _.utils = {};
    _.utils.flat2tree = structure.flat2tree;

    // URL object
    _.url = {};

    // prefixes
    var prefixFilterby = "public/evidence/filter?";
    var prefixAssociations = "public/association/filter?";
    var prefixSearch = "public/search?";
    var prefixGene = "private/target/";
    var prefixDisease = "private/disease/"; // updated from "efo" to "disease"
    var prefixToken = "public/auth/request_token?";
    var prefixAutocomplete = "private/autocomplete?";
    var prefixQuickSearch = "private/quicksearch?";
    var prefixExpression = "private/target/expression?";
    var prefixProxy = "proxy/generic/";
    var prefixTarget = "private/target/"; // this replaces prefixGene
    var prefixTargetRelation = "private/relation/target/";
    var prefixDiseaseRelation = "private/relation/disease/";
    var prefixLogSession = "private/utils/logevent";
    var prefixMultiSearch = "private/besthitsearch?";
    var prefixStats = "public/utils/stats";
    var prefixTargetsEnrichment = "private/enrichment/targets?";

    _.url.gene = function (obj) {
        return config.prefix + config.version + "/" + prefixGene + obj.gene_id;
    };

    _.url.target = function (obj) {
        if (obj && obj.target_id) {
            // One target
            return config.prefix + config.version + "/" + prefixTarget + obj.target_id;
        }
        // Multiple targets (optionally we can specify specific fields)
        return config.prefix + config.version + "/" + prefixTarget + parseUrlParams(obj);
    };

    _.url.disease = function (obj) {
        return config.prefix + config.version + "/" + prefixDisease + obj.code;
    };

    _.url.search = function (obj) {
        return config.prefix + config.version + "/" + prefixSearch + parseUrlParams(obj);
    };

    _.url.associations = function (obj) {
        return config.prefix + config.version + "/" + prefixAssociations + parseUrlParams(obj);
    };

    _.url.filterby = function (obj) {
        return config.prefix + config.version + "/" + prefixFilterby + parseUrlParams(obj);
    };

    _.url.requestToken = function (obj) {
        return config.prefix + config.version + "/" + prefixToken + "app_name=" + obj.appname + "&secret=" + obj.secret + (credentials.expiry ? ("&expiry=" + credentials.expiry) : "" );
    };

    _.url.autocomplete = function (obj) {
        return config.prefix + config.version + "/" + prefixAutocomplete + parseUrlParams(obj);
    };

    _.url.quickSearch = function (obj) {
        return config.prefix + config.version + "/" + prefixQuickSearch + parseUrlParams(obj);
    };

    _.url.expression = function (obj) {
        return config.prefix + config.version + "/" + prefixExpression + parseUrlParams(obj);
    };

    _.url.bestHitSearch = function (obj) {
        return config.prefix + config.version + "/" + prefixMultiSearch + parseUrlParams(obj);
    };

    _.url.proxy = function (obj) {
        return config.prefix + config.version + "/" + prefixProxy + obj.url;
    };

    _.url.targetRelation = function(obj){
        return config.prefix + config.version + "/" + prefixTargetRelation + obj.id + '?' + parseUrlParams(obj);
    };

    _.url.diseaseRelation = function(obj){
        var id = obj.id;
        delete(obj.id);
        return config.prefix + config.version + "/" + prefixDiseaseRelation + id + "?" + parseUrlParams(obj);
    };

    _.url.logSession = function (obj) {
        return config.prefix + config.version + "/" + prefixLogSession + '?' + parseUrlParams(obj);
    };

    _.url.stats = function () {
        return config.prefix + config.version + "/" + prefixStats;
    };

    _.url.targetsEnrichment = function (obj) {
        return config.prefix + config.version + "/" + prefixTargetsEnrichment + parseUrlParams(obj);
    };

    /**
    * This takes a params object and returns the params concatenated in a string.
    * If a parameter is an array, it adds each item, all with hte same key.
    * Example:
    *   obj = {q:'braf',size:20,filters:['id','pvalue']};
    *   console.log( parseUrlParams(obj) );
    *   // prints "q=braf&size=20&filters=id&filters=pvalue"
    */
    var parseUrlParams = function(obj){
        var opts = [];
        for(var i in obj){
            if( obj.hasOwnProperty(i)){
                if(obj[i].constructor === Array){
                    opts.push(i+"="+(obj[i].join("&"+i+"=")));
                } else {
                    opts.push(i+"="+obj[i]);
                }
            }
        }
        return opts.join("&");
    };

    return _;
};

module.exports = cttvApi;
<|endoftext|>


<commit_before>import d3 from 'd3';

export default class d3Chart {
  create(el, data) {
    var x = d3.scale.linear()
    .domain([0, d3.max(data)])
    .range([0, d3.max(data)*10]);

    d3.select(el)
      .selectAll("div")
        .data(data)
      .enter().append("div")
      .attr('class', 'bar')
        .style("width", function(d) { return x(d) + "px"; })
  }

  update(el, data) {
      d3.select(el).html('');
      this.create(el, data);
  }

}
<commit_msg>Update d3Chart.js<commit_after>import d3 from 'd3';

export default class d3Chart {
  create(el, data) {
    var x = d3.scale.linear()
    .domain([0, d3.max(data)])
    .range([0, d3.max(data)*10]);

    d3.select(el)
      .selectAll("div")
        .data(data)
      .enter().append("div")
      .attr('class', 'bar')

        .style("width", function(d) { return x(d) + "px"; })
  }

  update(el, data) {
      d3.select(el).html('');
      this.create(el, data);
  }

}
<|endoftext|>


<commit_before>import { defaultFetchParams } from './request-utils'
// import { keyForResource } from './resource-utils'
import { detachedOwnerRefsAnnotation, requestNamespaces } from '../state/actions/resources'
import { doRequest } from '../state/actions/requests'
import queryString from 'query-string'

const rulesReviewType = 'io.k8s.api.authorization.v1.SelfSubjectRulesReview'

const denyAll = {
  'get':false,
  'put':false,
  'delete':false,
  'logs':false,
  'exec':false,
  'watch':false,
}

const allowAll = {
  'get':true,
  'put':true,
  'delete':true,
  'logs':true,
  'exec':true,
  'watch':true,
}

export default class AccessEvaluator {

  constructor(props) {
    this.props = props
    this.getState = props.getState
    this.dispatch = props.dispatch
    this.permissions = {}
    this.initialize()
  }

  initialize = async () => {
    this.swagger = this.swagger || this.getState().apimodels.swagger
    this.kubeKinds = this.kubeKinds || this.getState().apimodels.kinds
    let that = this
    if (this.getState().session.user && this.swagger && this.swagger.definitions) {
      if (!('useRulesReview' in that) && rulesReviewType in that.swagger.definitions) {
        await doRequest(that.dispatch, that.getState, rulesReviewType + ':test', async () => {
          await rulesReview().then(async (resp) => {
            if (resp.status === 403) {
              that.useRulesReview = true
              that.rules = []
            } else {
              await that.getRules().then(rules => {
                that.rules = rules
                that.useRulesReview = true
              }).catch(error => {
                that.rules = null
                that.useRulesReview = false
              })
            }
          })
        })
      }
    }
  }

  /**
   * Returns an object where keys are the supported UI actions,
   * and values are 'true' when the action is permitted.
   *
   * @param {object} resource
   */
  getObjectAccess = async (resource) => {
    return this.getObjectPermissions(resource)
      .then(permissions => {
        // TODO: what about StatefulSet and DaemonSet?
        let replicas = (resource.status && (resource.status.readyReplicas || resource.status.replicas || resource.status.numberReady)) || -1

        if (!permissions) {
          return {
            get: false,
            edit: false,
            delete: false,
            logs: false,
            terminal: false,
            detach: false,
            scale: false,
            suspend: false,
          }
        } else {
          return {
            get: permissions.get,
            edit: permissions.put,
            delete: permissions.delete,
            logs: permissions.logs && (replicas > 0 || resource.kind === 'Pod'),
            terminal: permissions.exec && (replicas > 0 || resource.kind === 'Pod'),
            detach: permissions.put && resource.kind === 'Pod'
              && resource.metadata.annotations
              && !(detachedOwnerRefsAnnotation in resource.metadata.annotations),
            scale: permissions.put && replicas >= 0,
            suspend: permissions.put && replicas > 0,
          }
        }
      })
  }

  getObjectPermissions = async (resource) => {
    await this.initialize()

    let params = {
      kind: resource.kind,
      namespace: (resource.metadata.namespace && resource.metadata.namespace.replace(/~/, "")) || "",
      name: resource.metadata.name
    }
    let url = '/proxy/_/accessreview?' + queryString.stringify(params)
    return fetch(url, defaultFetchParams)
      .then(resp => {
        if (!resp.ok) {

        } else {
          return resp.json()
        }
      })
    // if (this.useRulesReview) {
    //   return resolveNamespacePermissions(resource, this.rules, this.kubeKinds)
    // }

    // let kubeKind = this.kubeKinds[resource.kind]
    // let clusterPerms = this.permissions[`${resource.kind}`] = this.permissions[`${resource.kind}`] || {}
    // let namespacePerms = {}
    // if (resource.metadata && resource.metadata.namespace) {
    //   namespacePerms = this.permissions[`${resource.kind}/${resource.metadata.namespace}`] =
    //   this.permissions[`${resource.kind}/${resource.metadata.namespace}`] || {}
    // }
    // let key = keyForResource(resource)
    // let objectPerms = this.permissions[key] = this.permissions[key] || {}
    // let permissions = {...clusterPerms, ...namespacePerms, ...objectPerms}

    // if ('get' in permissions &&
    //     'put' in permissions &&
    //     'delete' in permissions &&
    //     'logs' in permissions &&
    //     'exec' in permissions) {
    //   return permissions
    // }

    // let results = await resolveResourcePermissions(resource, permissions, kubeKind, this.kubeKinds)
    // for (let result of results) {
    //   let allowed = result.status.allowed
    //   let attrs = result.spec.resourceAttributes
    //   if (allowed) {
    //     let action = (attrs.subresource || attrs.verb).replace('log', 'logs')
    //     if (!('namespace' in attrs)) {
    //       clusterPerms[action] = true
    //     } else if (!('name' in attrs)) {
    //       namespacePerms[action] = true
    //     } else {
    //       objectPerms[action] = true
    //     }
    //   }
    // }

    // permissions = {...clusterPerms, ...namespacePerms, ...objectPerms}
    // if (!('get' in permissions)) {
    //   objectPerms.get = permissions.get = false
    // }
    // if (!('put' in permissions)) {
    //   objectPerms.put = permissions.put = false
    // }
    // if (!('delete' in permissions)) {
    //   objectPerms.delete = permissions.delete = false
    // }
    // if (!('logs' in permissions)) {
    //   objectPerms.logs = permissions.logs = false
    // }
    // if (!('exec' in permissions)) {
    //   objectPerms.exec = permissions.exec = false
    // }
    // return permissions
  }

  getRules = async () => {

    let requests = []
    let namespaces = this.getState().resources.namespaces
    if (!namespaces) {
      await this.dispatchEvent(requestNamespaces())
      namespaces = this.getState().resources.namespaces
    }

    for (let ns of namespaces) {
      requests.push(rulesReview(ns))
    }

    let rules = {}
    let results = await Promise.all(requests)
    for (let result of results) {
      if (result.status === 403) {
        // we can't actually use this method, even though the version supports it :(
        return null
      } else if (result.spec) {
        let ns = (result.spec && result.spec.namespace) || ''
        let nsRules = rules[ns] = rules[ns] || {}
        if (result.status.resourceRules) {
          for (let rule of result.status.resourceRules) {
            for (let resource of rule.resources) {
              let resourceNames = rule.resourceNames || ['']
              for (let name of resourceNames) {
                let kindKey = resource + (name ? ':' + name : '')
                let kindRules = nsRules[kindKey] = nsRules[kindKey] || {}
                for (let verb of rule.verbs) {
                  kindRules[verb] = true
                }
              }
            }
          }
        }
      }
    }

    return rules
  }

  /**
   * Returns an array of namespaces in which the current user
   * is allowed to watch the provided kubeKind object.
   *
   * If the user is allowed to watch this resource at the cluster
   * level, then ['*'] is returned.
   *
   * If the user is not allowed to watch this resource in any
   * namespaces, or the resource simply doesn't support watching
   * at any level, then [] is returned.
   *
   * @param {String} kind
   */
  getWatchableNamespaces = async (kind) => {
    await this.initialize()

    let kubeKind = this.kubeKinds[kind]
    if (!kubeKind.verbs.includes('watch')) {
      return []
    }

    if (this.useRulesReview) {
      return resolveWatchableFromRules(kind, this.rules, this.kubeKinds)
    }

    let requests = []
    requests.push(accessReview(kubeKind, 'watch'))
    if (kubeKind.namespaced) {
      for (let ns of this.getState().resources.namespaces) {
        requests.push(accessReview(kubeKind, 'watch', ns))
      }
    }
    let results = await Promise.all(requests)
    let clusterLevel = false
    let watchableNamespaces = []
    for (let result of results) {
      let allowed = result.status.allowed
      let attrs = result.spec.resourceAttributes
      if (allowed) {
        if ('namespace' in attrs) {
          watchableNamespaces.push(attrs.namespace)
        } else {
          clusterLevel = true
          break
        }
      }
    }
    return clusterLevel ? ['*'] : watchableNamespaces
  }
}

function resolveWatchableFromRules(kind, rules, kubeKinds) {
  let watchable = {}
  let kubeKind = kubeKinds[kind]
  let clusterPerms = resolveNamespacePermissions({kind: kind, metadata: {namespace: '', name: ''}}, rules, kubeKinds)
  if (clusterPerms.watch) {
    return ['*']
  } else if (kubeKind.namespaced) {
    for (let ns in rules) {
      let nsPerms = resolveNamespacePermissions({kind: kind, metadata: {namespace: ns, name: ''}}, rules, kubeKinds)
      if (nsPerms.watch) {
        watchable[ns] = true
      }
    }
    return Object.keys(watchable)
  }
}

function resolveNamespacePermissions(resource, rules, kubeKinds) {
  let nsRules = rules[resource.metadata.namespace || '']
  if (nsRules) {
    return resolveKindPermissions(resource, nsRules, kubeKinds)
  } else {
    return denyAll
  }
}

function resolveKindPermissions(resource, rules, kubeKinds) {
  if (rules) {
    let allKindsPerms = resolveVerbs(rules['*'])
    let plural = kubeKinds[resource.kind].plural
    let kindPerms = resolveVerbs(rules[plural])
    let namePerms = resolveVerbs(rules[`${plural}:${resource.metadata.name}`])
    return {...allKindsPerms, ...kindPerms, ...namePerms}
  }
}

function resolveVerbs(verbs) {
  if (verbs) {
    if ('*' in verbs) {
      return allowAll
    } else {
      return verbs
    }
  }
}

// async function resolveResourcePermissions(resource, permissions, kubeKind, kubeKinds) {
//   let requests = []
//   if (!('get' in permissions)) {
//     requests.push(accessReview(kubeKind, 'get'))
//     requests.push(accessReview(kubeKind, 'get', resource.metadata.namespace))
//     requests.push(accessReview(kubeKind, 'get', resource.metadata.namespace, resource.metadata.name))
//   }
//   if (!('watch' in permissions)) {
//     requests.push(accessReview(kubeKind, 'watch'))
//     requests.push(accessReview(kubeKind, 'watch', resource.metadata.namespace))
//   }
//   if (!('edit' in permissions)) {
//     requests.push(accessReview(kubeKind, 'put'))
//     requests.push(accessReview(kubeKind, 'put', resource.metadata.namespace))
//     requests.push(accessReview(kubeKind, 'put', resource.metadata.namespace, resource.metadata.name))
//   }
//   if (!('delete' in permissions)) {
//     requests.push(accessReview(kubeKind, 'delete'))
//     requests.push(accessReview(kubeKind, 'delete',
//       resource.metadata.namespace))
//     requests.push(accessReview(kubeKind, 'delete',
//       resource.metadata.namespace, resource.metadata.name))
//   }
//   if (!('logs' in permissions)) {
//     requests.push(accessReview(kubeKinds.Pod, 'get', '', '', 'log'))
//     requests.push(accessReview(kubeKinds.Pod, 'get',
//       resource.metadata.namespace, '', 'log'))
//     requests.push(accessReview(kubeKinds.Pod, 'get',
//       resource.metadata.namespace, resource.metadata.name, 'log'))
//   }
//   if (!('exec' in permissions)) {
//     requests.push(accessReview(kubeKinds.Pod, 'get', '', '', 'exec'))
//     requests.push(accessReview(kubeKinds.Pod, 'get',
//       resource.metadata.namespace, '', 'exec'))
//     requests.push(accessReview(kubeKinds.Pod, 'get',
//       resource.metadata.namespace, resource.metadata.name, 'exec'))
//   }
//   return Promise.all(requests)
// }

async function accessReview(kubeKind, verb, namespace='', name='', subresource='') {

  let body = {
    kind: 'SelfSubjectAccessReview',
    apiVersion: 'authorization.k8s.io/v1',
    spec: {}
  }
  if (namespace === '~') {
    namespace = ''
  }
  let group = ''
  if (kubeKind.base.startsWith('apis/')) {
    group = kubeKind.base.split('/')[1]
  }
  body.spec.resourceAttributes = {
    group: group,
    namespace: namespace,
    name: name,
    resource: kubeKind.plural,
    subresource: subresource,
    verb: verb,
    version: '*',
  }

  let bodyString = JSON.stringify(body)
  let url = '/proxy/apis/authorization.k8s.io/v1/selfsubjectaccessreviews'
  return await fetch( url, {...defaultFetchParams,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    method: 'POST',
    body: bodyString,
  }).then(resp => {
    if (!resp.ok) {
      return resp.text()
    } else {
      return resp.json()
    }
  })
  // if ('status' in result && 'allowed' in result.status) {
  //   return result.status.allowed
  // } else {
  //   console.error(`Unexpected response from selfsubjectaccessreviews: ${result}`)
  //   return false
  // }
}

async function rulesReview(namespace='') {

  let body = {
    kind: 'SelfSubjectRulesReview',
    apiVersion: 'authorization.k8s.io/v1',
    spec: {}
  }
  if (namespace === '~') {
    namespace = ''
  }
  body.spec = {
    namespace: namespace,
  }

  let bodyString = JSON.stringify(body)
  let url = '/proxy/apis/authorization.k8s.io/v1/selfsubjectrulesreviews'
  return await fetch( url, {...defaultFetchParams,
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    method: 'POST',
    body: bodyString,
  }).then(resp => {
    if (!resp.ok) {
      return resp
    } else {
      return resp.json()
    }
  }).then(json => {
    if (json && json.spec) {
      json.spec.namespace = namespace
    }
    return json
  })
}<commit_msg>clean up access evaluator; restore caching<commit_after>import { defaultFetchParams } from './request-utils'
import { detachedOwnerRefsAnnotation } from '../state/actions/resources'
import queryString from 'query-string'

export default class AccessEvaluator {

  constructor(props) {
    this.props = props
    this.getState = props.getState
    this.dispatch = props.dispatch
    this.permissions = {}
    this.initialize()
  }

  initialize = async () => {
    this.swagger = this.swagger || this.getState().apimodels.swagger
    this.kubeKinds = this.kubeKinds || this.getState().apimodels.kinds
  }

  /**
   * Returns an object where keys are the supported UI actions,
   * and values are 'true' when the action is permitted.
   *
   * @param {object} resource
   */
  getObjectAccess = async (resource) => {
    return this.getObjectPermissions(resource)
      .then(permissions => {
        // TODO: what about StatefulSet and DaemonSet?
        let replicas = (resource.status && (resource.status.readyReplicas || resource.status.replicas || resource.status.numberReady)) || -1
        return {
          get: !!permissions.get,
          edit: !!permissions.put,
          delete: !!permissions.delete,
          logs: !!permissions.logs && (replicas > 0 || resource.kind === 'Pod'),
          terminal: !!permissions.exec && (replicas > 0 || resource.kind === 'Pod'),
          detach: !!permissions.put && resource.kind === 'Pod'
            && resource.metadata.annotations
            && !(detachedOwnerRefsAnnotation in resource.metadata.annotations),
          scale: !!permissions.put && replicas >= 0,
          suspend: !!permissions.put && replicas > 0,
        }
      })
  }

  getObjectPermissions = async (resource) => {
    await this.initialize()

    let clusterPerms = this.permissions[`${resource.kind}`] = this.permissions[`${resource.kind}`] || {}
    let namespacePerms = {}
    if (resource.metadata && resource.metadata.namespace) {
      namespacePerms = this.permissions[`${resource.kind}/${resource.metadata.namespace}`] =
      this.permissions[`${resource.kind}/${resource.metadata.namespace}`] || {}
    }
    let key = resource.key
    let objectPerms = this.permissions[key] = this.permissions[key] || {}
    let permissions = {...clusterPerms, ...namespacePerms, ...objectPerms}

    if ('get' in permissions &&
        'put' in permissions &&
        'delete' in permissions &&
        'logs' in permissions &&
        'exec' in permissions) {
      return permissions
    }

    setTimeout(()=>{
      accessReview(resource.kind).then(perms=>{
        clusterPerms = Object.assign(clusterPerms, perms)
      })
    },250)

    setTimeout(()=>{
      accessReview(resource.kind, resource.metadata.namespace).then(perms=>{
        namespacePerms = Object.assign(namespacePerms, perms)
      })
    },250)

    return accessReview(resource.kind, resource.metadata.namespace, resource.metadata.name)
      .then(perms=>{
        objectPerms = Object.assign(objectPerms, perms)
        return perms
      })
  }
}

async function accessReview(kind, namespace='', name='') {

  let params = {
    kind: kind,
    namespace: (namespace && namespace.replace(/~/, "")) || "",
    name: name,
  }
  let url = '/proxy/_/accessreview?' + queryString.stringify(params)
  return fetch(url, defaultFetchParams)
    .then(resp => {
      if (!resp.ok) {
        return {}
      } else {
        return resp.json()
      }
    })
}
<|endoftext|>


<commit_before>const syncExec = require('sync-exec')

const commands = [
  'export DISPLAY=:99.0',
  'export LIGHTHOUSE_CHROMIUM_PATH="$(pwd)/chrome-linux/chrome"',
  'sh -e /etc/init.d/xvfb start',
  './node_modules/lighthouse/lighthouse-core/scripts/download-chrome.sh'
]

const setup = () => {
  console.log('Setting up Chrome')
  for (let command of commands) {
    const output = syncExec(command)
    if (output.stderr) throw output.stderr
  }
}

module.exports = setup
<commit_msg>throw error properly<commit_after>const syncExec = require('sync-exec')

const commands = [
  'export DISPLAY=:99.0',
  'export LIGHTHOUSE_CHROMIUM_PATH="$(pwd)/chrome-linux/chrome"',
  'sh -e /etc/init.d/xvfb start',
  './node_modules/lighthouse/lighthouse-core/scripts/download-chrome.sh'
]

const setup = () => {
  console.log('Setting up Chrome')
  for (let command of commands) {
    const output = syncExec(command)
    if (output.stderr) throw new Error(output.stderr)
  }
}

module.exports = setup
<|endoftext|>


<commit_before>$(window).keydown(function(e){
  console.log(e.which);
});
<commit_msg>redirect to search page when 'f' is pressed<commit_after>$(window).keydown(function(e){
  if (e.which === 70){ // the 'f' key
    var REPO_REGEX = new RegExp("github\.com/([^/]+/[^/]+)(/.*)?$"),
      repo = window.location.href.match(REPO_REGEX)[1];

    window.location = 'https://github.com/search?type=Code&q=query&repo=' + encodeURIComponent(repo);
  }
});
<|endoftext|>


<commit_before>
  // CSS

  dom.prototype.css = function (prop, value) {
    this.each(function (el) {
      el.style[prop] = value;
    });

    return new dom(this);
  };

  dom.prototype.width = function (width) {
    if (width) {
      this.each(function (el) {
        el.style.width = width;

        return new dom(this);
      });
    } else {
      this.one(function (el) {
        return el.style.width;
      });
    }
  };

  dom.prototype.height = function (height) {
    if (height) {
      this.each(function (el) {
        el.style.height = height;

        return new dom(this);
      });
    } else {
      this.one(function (el) {
        return el.style.height;
      });
    }
  };

  dom.prototype.color = function (color) {
    if (color) {
      this.style('color', color);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['color'];
      });
    }
  };

  dom.prototype.backgroundColor = function (backgroundColor) {
    if (backgroundColor) {
      this.style('background-color', backgroundColor);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['background-color'];
      });
    }
  };

  dom.prototype.background = function (background) {
    if (background) {
      this.style('background', background);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['background'];
      });
    }
  };

  dom.prototype.margin = function (margin) {
    if (margin) {
      this.style('margin', margin);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['margin'];
      });
    }
  };

  dom.prototype.padding = function (padding) {
    if (padding) {
      this.style('padding', padding);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['padding'];
      });
    }
  };

  dom.prototype.fontSize = function (fontSize) {
    if (fontSize) {
      this.style('font-size', fontSize);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['font-size'];
      });
    }
  };
<commit_msg>Fixed .css() to return current value if no value provided<commit_after>
  // CSS

  dom.prototype.css = function (prop, value) {
    if (value) {
      this.each(function (el) {
        el.style[prop] = value;
      });

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style[prop];
      });
    }
  };

  dom.prototype.width = function (width) {
    if (width) {
      this.each(function (el) {
        el.style.width = width;

        return new dom(this);
      });
    } else {
      this.one(function (el) {
        return el.style.width;
      });
    }
  };

  dom.prototype.height = function (height) {
    if (height) {
      this.each(function (el) {
        el.style.height = height;

        return new dom(this);
      });
    } else {
      this.one(function (el) {
        return el.style.height;
      });
    }
  };

  dom.prototype.color = function (color) {
    if (color) {
      this.style('color', color);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['color'];
      });
    }
  };

  dom.prototype.backgroundColor = function (backgroundColor) {
    if (backgroundColor) {
      this.style('background-color', backgroundColor);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['background-color'];
      });
    }
  };

  dom.prototype.background = function (background) {
    if (background) {
      this.style('background', background);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['background'];
      });
    }
  };

  dom.prototype.margin = function (margin) {
    if (margin) {
      this.style('margin', margin);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['margin'];
      });
    }
  };

  dom.prototype.padding = function (padding) {
    if (padding) {
      this.style('padding', padding);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['padding'];
      });
    }
  };

  dom.prototype.fontSize = function (fontSize) {
    if (fontSize) {
      this.style('font-size', fontSize);

      return new dom(this);
    } else {
      this.one(function (el) {
        return el.style['font-size'];
      });
    }
  };
<|endoftext|>


<commit_before>define(function (require) {
    'use strict';

    /**
     * Save documentElement.
     * @inner
     * @type {Object}
     */
    var docElem = document.documentElement;

    /**
     * Get the supported matches method.
     * @inner
     * @type {Function}
     */
    var nativeMatches = docElem.matches ||
                docElem.webkitMatchesSelector ||
                docElem.mozMatchesSelector ||
                docElem.oMatchesSelector ||
                docElem.msMatchesSelector ||
                docElem.matchesSelector;

    /**
     * Support for matches. Check whether a element matches a selector.
     * @param {HTMLElement} element
     * @param {string} selector
     * @return {boolean}
     */
    function matches(element, selector) {
        if (!element || element.nodeType != 1) {
            return false;
        }
        return nativeMatches.call(element, selector);
    };

    /**
     * Support for closest. Find the closest parent node that matches the selector.
     * @param {HTMLElement} element
     * @param {string} selector
     * @return {?HTMLElement}
     */
    var closest = docElem.closest ?
        function (element, selector) {
            return element.closest(selector);
        } :
        function (element, selector) {
            while (element) {
                if (matches(element, selector)) {
                    return element;
                }
                element = element.parentNode;
            };
            return null;
        };

    /**
     * Support for contains.
     * @param {HTMLElement} element
     * @param {HTMLElement} child
     * @return {boolean}
     */
    var contains = docElem.contains ?
        function (element, child) {
            return element && element.contains(child);
        } :
        function (element, child) {
            while (child) {
                if (element === child) {
                    return true;
                }
                child = child.parentElement;
            };
            return false;
        };

    /**
     * Find the nearest element that matches the selector from current element to target element.
     * @param {HTMLElement} element
     * @param {string} selector
     * @param {HTMLElement} target
     * @return {?HTMLElement}
     */
    function closestTo(element, selector, target) {
        var closestElement = closest(element, selector);
        return contains(target, closestElement) ? closestElement : null;
    };

    /**
     * Temp element for creating element by string.
     * @inner
     * @type {HTMLElement}
     */
    var createTmpElement = document.createElement('div');

    /**
     * Create a element by string
     * @param {string} str Html string
     * @return {HTMLElement}
     */
    function create(str) {
        createTmpElement.innerHTML = str;
        if (!createTmpElement.children.length) {
            return null;
        }
        var children = Array.prototype.slice.call(createTmpElement.children);
        createTmpElement.innerHTML = '';
        return children.length > 1 ? children : children[0];
    };

    return {
        closest: closest,
        closestTo: closestTo,
        matches: matches,
        contains: contains,
        create: create
    }
});
<commit_msg>Format finishing<commit_after>define(function (require) {
    'use strict';

    /**
     * Save documentElement.
     * @inner
     * @type {Object}
     */
    var docElem = document.documentElement;

    /**
     * Get the supported matches method.
     * @inner
     * @type {Function}
     */
    var nativeMatches = docElem.matches
            || docElem.webkitMatchesSelector
            || docElem.mozMatchesSelector
            || docElem.oMatchesSelector
            || docElem.msMatchesSelector
            || docElem.matchesSelector;

    /**
     * Support for matches. Check whether a element matches a selector.
     * @param {HTMLElement} element
     * @param {string} selector
     * @return {boolean}
     */
    function matches(element, selector) {
        if (!element || element.nodeType != 1) {
            return false;
        }
        return nativeMatches.call(element, selector);
    };

    /**
     * Support for closest. Find the closest parent node that matches the selector.
     * @param {HTMLElement} element
     * @param {string} selector
     * @return {?HTMLElement}
     */
    var closest = docElem.closest
            ? function (element, selector) {
                return element.closest(selector);
            }
            : function (element, selector) {
                while (element) {
                    if (matches(element, selector)) {
                        return element;
                    }
                    element = element.parentNode;
                };
                return null;
            };

    /**
     * Support for contains.
     * @param {HTMLElement} element
     * @param {HTMLElement} child
     * @return {boolean}
     */
    var contains = docElem.contains
            ? function (element, child) {
                return element && element.contains(child);
            }
            : function (element, child) {
                while (child) {
                    if (element === child) {
                        return true;
                    }
                    child = child.parentElement;
                };
                return false;
            };

    /**
     * Find the nearest element that matches the selector from current element to target element.
     * @param {HTMLElement} element
     * @param {string} selector
     * @param {HTMLElement} target
     * @return {?HTMLElement}
     */
    function closestTo(element, selector, target) {
        var closestElement = closest(element, selector);
        return contains(target, closestElement) ? closestElement : null;
    };

    /**
     * Temp element for creating element by string.
     * @inner
     * @type {HTMLElement}
     */
    var createTmpElement = document.createElement('div');

    /**
     * Create a element by string
     * @param {string} str Html string
     * @return {HTMLElement}
     */
    function create(str) {
        createTmpElement.innerHTML = str;
        if (!createTmpElement.children.length) {
            return null;
        }
        var children = Array.prototype.slice.call(createTmpElement.children);
        createTmpElement.innerHTML = '';
        return children.length > 1 ? children : children[0];
    };

    return {
        closest: closest,
        closestTo: closestTo,
        matches: matches,
        contains: contains,
        create: create
    }
});
<|endoftext|>


<commit_before>/**
 * Heavily inspired by https://github.com/csuwildcat/SelectorListener.
 */
(function() {

  'use strict';

  var domPrefixes = [
    'khtml',
    'moz',
    'ms',
    'o',
    'webkit',
  ];

  function skate(selector) {
    return new Skate(selector);
  }

  function Skate(selector) {
    this.selector = selector;
    this.events = {
      ready: [],
      insert: [],
      remove: []
    };

    if (CssKeyframeAdapter.supported) {
      this.adapter = new CssKeyframeAdapter(this);
    } else {
      this.adapter = new MutationEventAdapter(this);
    }

    this.listen();
  }

  Skate.prototype = {
    on: function(evt, fn) {
      this.events[evt].push(fn);
      return this;
    },

    off: function(evt, fn) {
      if (fn) {
        this.events[evt].splice(this.events[evt].indexOf(fn), 1);
      } else {
        this.events[evt] = [];
      }

      return this;
    },

    listen: function() {
      this.adapter.listen();
      return this;
    },

    deafen: function() {
      this.adapter.deafen();
      return this;
    },

    trigger: function(evt, data) {
      this.events[evt].forEach(function(fn) {
        fn(data);
      });

      return this;
    }
  };

  function CssKeyframeAdapter(component) {
    ++CssKeyframeAdapter.count;
    this.events = {};
    this.listeners = {};
    this.selectors = {};
    abstractAdapter(this, component);
  }

  CssKeyframeAdapter.count = 0;
  CssKeyframeAdapter.head = document.getElementsByTagName('head')[0];
  CssKeyframeAdapter.keyframes = document.createElement('style');
  CssKeyframeAdapter.animations = document.createElement('style');
  CssKeyframeAdapter.events = ['animationstart', 'oAnimationStart', 'MSAnimationStart', 'webkitAnimationStart'];

  CssKeyframeAdapter.prefix = function() {
    var css = document.documentElement.style;
    var prefix = false;

    if (typeof css.animation !== 'undefined') {
      return '';
    }

    domPrefixes.some(function(domPrefix) {
      if (typeof css[domPrefix + 'Animation'] !== 'undefined') {
        prefix = domPrefix;
        return true;
      }
    });

    return prefix;
  };

  CssKeyframeAdapter.cssPrefix = function() {
    var prefix = CssKeyframeAdapter.prefix();
    return prefix ? '-' + prefix + '-' : '';
  };

  CssKeyframeAdapter.supported = function() {
    return typeof CssKeyframeAdapter.prefix() === 'string';
  };

  CssKeyframeAdapter.prototype = {
    constructor: CssKeyframeAdapter,

    listen: function() {
      var that = this;
      var ctor = this.constructor;
      var index = ctor.count - 1;
      var cssPrefix = ctor.cssPrefix();
      var animationName = '__skate' + ctor.count;
      var keyframeRule = '@'
        + cssPrefix
        + 'keyframes '
        + animationName
        + ' { from { opacity: 0; } to { opacity: 1; } }';
      var animationRule = this.component.selector
        + '{'
        + cssPrefix
        + 'animation:'
        + animationName
        + ' .01s;}';

      ctor.keyframes.sheet.insertRule(keyframeRule, index);
      ctor.animations.sheet.insertRule(animationRule, index);
      ctor.events.forEach(function(e) {
        document.addEventListener(e, that.triggerInsert, false);
      });

      return this;
    },

    deafen: function() {
      var that = this;
      var key = this.selectors[this.selector];
      var listener = this.listeners[key] || [];
      var index = listener.indexOf(handler);

      if (index > -1) {
        var event = this.events[key];
        --event.count;

        if (!event.count) {
          styles.sheet.deleteRule(styles.sheet.cssRules.item(event.rule));
          keyframes.removeChild(event.keyframe);

          delete this.events[key];
          delete this.selectors[selector];
        }

        --this.listeners.count;
        listener.splice(index, 1);

        if (!this.listeners.count) {
          this.constructor.events.forEach(function(name) {
            document.removeEventListener(name, that.triggerInsert, false);
          });
        }
      }

      return this;
    }
  }

  function MutationEventAdapter(component) {
    abstractAdapter(this, component);
  }

  MutationEventAdapter.prototype = {
    listen: function() {
      var existing = document.querySelectorAll(this.component.selector);

      // IE doesn't handle existing events correctly.
      for (var a = 0; a < existing.length; a++) {
        this.component.trigger('insert', (existing[a]));
      }

      document.addEventListener('DOMNodeInserted', function(e) {
        if (e.target.msMatchesSelector(this.component.selector)) {
          this.component.trigger('insert', e.target);
        }
      }, false);

      return this;
    },

    deafen: function() {
      return this;
    }
  };

  function abstractAdapter(adapter, component) {
    adapter.component = component;

    adapter.triggerReady = function(e) {
      return component.trigger('ready', e.target);
    };

    adapter.triggerInsert = function(e) {
      return component.trigger('insert', e.target);
    };

    adapter.triggerRemove = function(e) {
      return component.trigger('remove', e.target);
    };
  }

  if (CssKeyframeAdapter.supported) {
    CssKeyframeAdapter.keyframes.type = CssKeyframeAdapter.animations.type = 'text/css';
    CssKeyframeAdapter.head.appendChild(CssKeyframeAdapter.keyframes);
    CssKeyframeAdapter.head.appendChild(CssKeyframeAdapter.animations);
  }

  if (typeof define === 'function' && define.amd) {
    define('skate', function() {
      return skate;
    });
  } else {
    window.skate = skate;
  }

})();
<commit_msg>Get keyframes working after refactor.<commit_after>/**
 * Heavily inspired by https://github.com/csuwildcat/SelectorListener.
 */
(function() {

  'use strict';

  var domPrefixes = [
    'khtml',
    'moz',
    'ms',
    'o',
    'webkit',
  ];

  function skate(selector) {
    return new Skate(selector);
  }

  function Skate(selector) {
    this.selector = selector;
    this.events = {
      ready: [],
      insert: [],
      remove: []
    };

    if (CssKeyframeAdapter.supported) {
      this.adapter = new CssKeyframeAdapter(this);
    } else {
      this.adapter = new MutationEventAdapter(this);
    }

    this.listen();
  }

  Skate.prototype = {
    on: function(evt, fn) {
      this.events[evt].push(fn);
      return this;
    },

    off: function(evt, fn) {
      if (fn) {
        this.events[evt].splice(this.events[evt].indexOf(fn), 1);
      } else {
        this.events[evt] = [];
      }

      return this;
    },

    listen: function() {
      this.adapter.listen();
      return this;
    },

    deafen: function() {
      this.adapter.deafen();
      return this;
    },

    trigger: function(evt, data) {
      this.events[evt].forEach(function(fn) {
        fn(data);
      });

      return this;
    }
  };

  function CssKeyframeAdapter(component) {
    this.component = component;
    this.events = {};
    this.listeners = {};
    this.selectors = {};
  }

  CssKeyframeAdapter.instances = [];
  CssKeyframeAdapter.id = '__skate';
  CssKeyframeAdapter.keyframes = document.createElement('style');
  CssKeyframeAdapter.animations = document.createElement('style');
  CssKeyframeAdapter.events = ['animationstart', 'oAnimationStart', 'MSAnimationStart', 'webkitAnimationStart'];

  CssKeyframeAdapter.prefix = function() {
    var css = document.documentElement.style;
    var prefix = false;

    if (typeof css.animation !== 'undefined') {
      return '';
    }

    domPrefixes.some(function(domPrefix) {
      if (typeof css[domPrefix + 'Animation'] !== 'undefined') {
        prefix = domPrefix;
        return true;
      }
    });

    return prefix;
  };

  CssKeyframeAdapter.cssPrefix = function() {
    var prefix = CssKeyframeAdapter.prefix();
    return prefix ? '-' + prefix + '-' : '';
  };

  CssKeyframeAdapter.supported = function() {
    return typeof CssKeyframeAdapter.prefix() === 'string';
  };

  CssKeyframeAdapter.setup = function() {
    var head = document.getElementsByTagName('head')[0];

    CssKeyframeAdapter.animations.type = CssKeyframeAdapter.keyframes.type = 'text/css';
    head.appendChild(CssKeyframeAdapter.keyframes);
    head.appendChild(CssKeyframeAdapter.animations);
    CssKeyframeAdapter.events.forEach(function(evt) {
      document.addEventListener(evt, CssKeyframeAdapter.handler, false);
    });
  };

  CssKeyframeAdapter.handler = function(e) {
    var index = e.animationName.replace(CssKeyframeAdapter.id, '');
    CssKeyframeAdapter.instances[index].component.trigger('insert', e.target);
  };

  CssKeyframeAdapter.prototype = {
    constructor: CssKeyframeAdapter,

    listen: function() {
      CssKeyframeAdapter.instances.push(this);

      var index = CssKeyframeAdapter.instances.indexOf(this);
      var name = this.constructor.id + index;
      var prefix = this.constructor.cssPrefix();

      this.constructor.keyframes.sheet.insertRule('@' + prefix + 'keyframes ' + name + '{from{opacity:0;}to{opacity:1;}}', index);
      this.constructor.animations.sheet.insertRule(this.component.selector + '{' + prefix + 'animation:' + name + ' .01s;}', index);

      return this;
    },

    deafen: function() {
      var index = CssKeyframeAdapter.instances.indexOf(this);

      CssKeyframeAdapter.splice(index, 1);
      this.constructor.keyframes.sheet.deleteRule(this.constructor.keyframes.sheet.cssRules.item(index));
      this.constructor.animations.sheet.deleteRule(this.constructor.animations.sheet.cssRules.item(index));

      return this;
    }
  }

  function MutationEventAdapter(component) {
    abstractAdapter(this, component);
  }

  MutationEventAdapter.prototype = {
    listen: function() {
      var existing = document.querySelectorAll(this.component.selector);

      // IE doesn't handle existing events correctly.
      for (var a = 0; a < existing.length; a++) {
        this.component.trigger('insert', (existing[a]));
      }

      document.addEventListener('DOMNodeInserted', function(e) {
        if (e.target.msMatchesSelector(this.component.selector)) {
          this.component.trigger('insert', e.target);
        }
      }, false);

      return this;
    },

    deafen: function() {
      return this;
    }
  };

  if (CssKeyframeAdapter.supported()) {
    CssKeyframeAdapter.setup();
  }

  if (typeof define === 'function' && define.amd) {
    define('skate', function() {
      return skate;
    });
  } else {
    window.skate = skate;
  }

})();
<|endoftext|>