<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';
var DebugLogtron = require('debug-logtron');
var TChannelJSON = require('../../as/json');
var HyperbahnClient = require('../../hyperbahn/index.js');
var series = require('run-series');

module.exports = runTests;

if (require.main === module) {
    runTests(require('../lib/hyperbahn-cluster.js'));
}

function send(opts, done) {
    var tchannelJSON = TChannelJSON({
        logger: opts.logger
    });
    tchannelJSON.send(opts.bob.clientChannel.request({
        timeout: 5000,
        serviceName: opts.steve.serviceName
    }), 'echo', null, 'hello', function onResponse(err, res) {
        if (err) {
            opts.assert.end(err);
        }

        done(err, res);
    });
}

function wait(done) {
    setTimeout(done, 500);
}

function runTests(HyperbahnCluster) {
    HyperbahnCluster.test('rps counter works', {
        size: 1,
        seedConfig: {
            'rateLimiting': {
                'enabled': true,
                'rateLimiterBuckets': 2,
                'exemptServices': [
                    'hyperbahn',
                    'ringpop'
                ]
            }
        }
    }, function t(cluster, assert) {
        var steve = cluster.remotes.steve;
        var bob = cluster.remotes.bob;

        var steveHyperbahnClient = new HyperbahnClient({
            serviceName: steve.serviceName,
            callerName: 'forward-test',
            hostPortList: cluster.hostPortList,
            tchannel: steve.channel,
            logger: DebugLogtron('hyperbahnClient')
        });
        steveHyperbahnClient.once('advertised', onAdvertised);
        steveHyperbahnClient.advertise();
        function onAdvertised() {
            var opts = {
                logger: cluster.logger,
                bob: bob,
                steve: steve,
                assert: assert
            };
            series([
                send.bind(null, opts),
                send.bind(null, opts),
                send.bind(null, opts),
                function check(done) {
                    cluster.apps.forEach(function (app) {
                        var relayChannel = app.clients.tchannel;
                        assert.equals(relayChannel.handler.rateLimiter.totalRequestCounter.rps, 6, 'total request');
                        assert.equals(relayChannel.handler.rateLimiter.counters.steve.rps, 3, 'request for steve');
                        assert.equals(relayChannel.handler.rateLimiter.counters.tcollector.rps, 3, 'request for tcollector');
                    });
                    done();
                }
            ], function done() {
                steveHyperbahnClient.destroy();
                assert.end();
            });
        }
    });

    HyperbahnCluster.test('rps counter works in 1.5 seconds', {
        size: 1,
        seedConfig: {
            'rateLimiting': {
                'enabled': true,
                'rateLimiterBuckets': 2,
                'exemptServices': [
                    'hyperbahn',
                    'ringpop'
                ]
            }
        }
    }, function t(cluster, assert) {
        var steve = cluster.remotes.steve;
        var bob = cluster.remotes.bob;

        var steveHyperbahnClient = new HyperbahnClient({
            serviceName: steve.serviceName,
            callerName: 'forward-test',
            hostPortList: cluster.hostPortList,
            tchannel: steve.channel,
            logger: DebugLogtron('hyperbahnClient')
        });
        steveHyperbahnClient.once('advertised', onAdvertised);
        steveHyperbahnClient.advertise();

        function onAdvertised() {
            var opts = {
                logger: cluster.logger,
                bob: bob,
                steve: steve,
                assert: assert
            };
            series([
                send.bind(null, opts),
                send.bind(null, opts),
                wait,
                send.bind(null, opts),
                function check1(done) {
                    cluster.apps.forEach(function (app) {
                        var relayChannel = app.clients.tchannel;
                        var rateLimiter = relayChannel.handler.rateLimiter;
                        assert.equals(rateLimiter.totalRequestCounter.rps, 6, 'check1: total request');
                        assert.equals(rateLimiter.counters.steve.rps, 3, 'check1: request for steve');
                        assert.equals(rateLimiter.counters.tcollector.rps, 3, 'check1: request for tcollector');
                    });
                    done();
                },
                wait,
                send.bind(null, opts),
                function check2(done) {
                    cluster.apps.forEach(function (app) {
                        var relayChannel = app.clients.tchannel;
                        var rateLimiter = relayChannel.handler.rateLimiter;
                        assert.equals(rateLimiter.totalRequestCounter.rps, 4, 'check2: total request');
                        assert.equals(rateLimiter.counters.steve.rps, 2, 'check2: request for steve');
                        assert.equals(rateLimiter.counters.tcollector.rps, 2, 'check2: request for tcollector');
                    });
                    done();
                }
            ], function done() {
                steveHyperbahnClient.destroy();
                assert.end();
            });
        }
    });

    HyperbahnCluster.test('service rate limiting works', {
        size: 1,
        kValue: 2,
        seedConfig: {
            'rateLimiting': {
                'enabled': true,
                'rateLimiterBuckets': 2,
                'exemptServices': [
                    'hyperbahn',
                    'ringpop'
                ],
                'rpsLimitForServiceName': {
                    'steve': 2
                }
            }
        }
    }, function t(cluster, assert) {
        var steve = cluster.remotes.steve;
        var bob = cluster.remotes.bob;

        var steveHyperbahnClient = new HyperbahnClient({
            serviceName: steve.serviceName,
            callerName: 'forward-test',
            hostPortList: cluster.hostPortList,
            tchannel: steve.channel,
            logger: DebugLogtron('hyperbahnClient')
        });
        steveHyperbahnClient.once('advertised', onAdvertised);
        steveHyperbahnClient.advertise();

        function onAdvertised() {
            var opts = {
                logger: cluster.logger,
                bob: bob,
                steve: steve,
                assert: assert
            };
            series([
                send.bind(null, opts),
                send.bind(null, opts),
                function sendError(done) {
                    var tchannelJSON = TChannelJSON({
                        logger: cluster.logger
                    });
                    tchannelJSON.send(bob.clientChannel.request({
                        timeout: 5000,
                        serviceName: steve.serviceName
                    }), 'echo', null, 'hello', function onResponse(err, res) {
                        assert.ok(err && err.type === 'tchannel.busy' &&
                            err.message === 'steve is rate-limited by the rps of 2',
                            'should be rate limited');
                        done();
                    });
                }
            ], function done() {
                steveHyperbahnClient.destroy();
                assert.end();
            });
        }
    });

    HyperbahnCluster.test('total rate limiting works', {
        size: 5,
        kValue: 1,
        seedConfig: {
            'rateLimiting': {
                'enabled': true,
                'rateLimiterBuckets': 2,
                'totalRpsLimit': 2,
                'exemptServices': [
                    'hyperbahn',
                    'ringpop',
                    'tcollector'
                ]
            }
        }
    }, function t(cluster, assert) {
        var steve = cluster.remotes.steve;
        var bob = cluster.remotes.bob;

        var steveHyperbahnClient = new HyperbahnClient({
            serviceName: steve.serviceName,
            callerName: 'forward-test',
            hostPortList: cluster.hostPortList,
            tchannel: steve.channel,
            logger: DebugLogtron('hyperbahnClient')
        });
        steveHyperbahnClient.once('advertised', onAdvertised);
        steveHyperbahnClient.advertise();

        function onAdvertised() {
            var opts = {
                logger: cluster.logger,
                bob: bob,
                steve: steve,
                assert: assert
            };
            series([
                send.bind(null, opts),
                send.bind(null, opts),
                wait,
                function sendError(done) {
                    var tchannelJSON = TChannelJSON({
                        logger: cluster.logger
                    });
                    tchannelJSON.send(bob.clientChannel.request({
                        timeout: 5000,
                        serviceName: steve.serviceName
                    }), 'echo', null, 'hello', function onResponse(err, res) {
                        assert.ok(err && err.type === 'tchannel.busy' &&
                            err.message === 'hyperbahn node is rate-limited by the total rps of 2',
                            'should be rate limited');
                        done();
                    });
                }
            ], function done() {
                steveHyperbahnClient.destroy();
                assert.end();
            });
        }
    });
}
<commit_msg>tests/hyperbahn/rate-limiter: explicate wait time<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

'use strict';
var DebugLogtron = require('debug-logtron');
var TChannelJSON = require('../../as/json');
var HyperbahnClient = require('../../hyperbahn/index.js');
var series = require('run-series');

module.exports = runTests;

if (require.main === module) {
    runTests(require('../lib/hyperbahn-cluster.js'));
}

function send(opts, done) {
    var tchannelJSON = TChannelJSON({
        logger: opts.logger
    });
    tchannelJSON.send(opts.bob.clientChannel.request({
        timeout: 5000,
        serviceName: opts.steve.serviceName
    }), 'echo', null, 'hello', function onResponse(err, res) {
        if (err) {
            opts.assert.end(err);
        }

        done(err, res);
    });
}

function waitFor(t) {
    return function wait(done) {
        setTimeout(done, 500);
    };
}

function runTests(HyperbahnCluster) {
    HyperbahnCluster.test('rps counter works', {
        size: 1,
        seedConfig: {
            'rateLimiting': {
                'enabled': true,
                'rateLimiterBuckets': 2,
                'exemptServices': [
                    'hyperbahn',
                    'ringpop'
                ]
            }
        }
    }, function t(cluster, assert) {
        var steve = cluster.remotes.steve;
        var bob = cluster.remotes.bob;

        var steveHyperbahnClient = new HyperbahnClient({
            serviceName: steve.serviceName,
            callerName: 'forward-test',
            hostPortList: cluster.hostPortList,
            tchannel: steve.channel,
            logger: DebugLogtron('hyperbahnClient')
        });
        steveHyperbahnClient.once('advertised', onAdvertised);
        steveHyperbahnClient.advertise();
        function onAdvertised() {
            var opts = {
                logger: cluster.logger,
                bob: bob,
                steve: steve,
                assert: assert
            };
            series([
                send.bind(null, opts),
                send.bind(null, opts),
                send.bind(null, opts),
                function check(done) {
                    cluster.apps.forEach(function (app) {
                        var relayChannel = app.clients.tchannel;
                        assert.equals(relayChannel.handler.rateLimiter.totalRequestCounter.rps, 6, 'total request');
                        assert.equals(relayChannel.handler.rateLimiter.counters.steve.rps, 3, 'request for steve');
                        assert.equals(relayChannel.handler.rateLimiter.counters.tcollector.rps, 3, 'request for tcollector');
                    });
                    done();
                }
            ], function done() {
                steveHyperbahnClient.destroy();
                assert.end();
            });
        }
    });

    HyperbahnCluster.test('rps counter works in 1.5 seconds', {
        size: 1,
        seedConfig: {
            'rateLimiting': {
                'enabled': true,
                'rateLimiterBuckets': 2,
                'exemptServices': [
                    'hyperbahn',
                    'ringpop'
                ]
            }
        }
    }, function t(cluster, assert) {
        var steve = cluster.remotes.steve;
        var bob = cluster.remotes.bob;

        var steveHyperbahnClient = new HyperbahnClient({
            serviceName: steve.serviceName,
            callerName: 'forward-test',
            hostPortList: cluster.hostPortList,
            tchannel: steve.channel,
            logger: DebugLogtron('hyperbahnClient')
        });
        steveHyperbahnClient.once('advertised', onAdvertised);
        steveHyperbahnClient.advertise();

        function onAdvertised() {
            var opts = {
                logger: cluster.logger,
                bob: bob,
                steve: steve,
                assert: assert
            };
            series([
                send.bind(null, opts),
                send.bind(null, opts),
                waitFor(500),
                send.bind(null, opts),
                function check1(done) {
                    cluster.apps.forEach(function (app) {
                        var relayChannel = app.clients.tchannel;
                        var rateLimiter = relayChannel.handler.rateLimiter;
                        assert.equals(rateLimiter.totalRequestCounter.rps, 6, 'check1: total request');
                        assert.equals(rateLimiter.counters.steve.rps, 3, 'check1: request for steve');
                        assert.equals(rateLimiter.counters.tcollector.rps, 3, 'check1: request for tcollector');
                    });
                    done();
                },

                waitFor(500),
                send.bind(null, opts),
                function check2(done) {
                    cluster.apps.forEach(function (app) {
                        var relayChannel = app.clients.tchannel;
                        var rateLimiter = relayChannel.handler.rateLimiter;
                        assert.equals(rateLimiter.totalRequestCounter.rps, 4, 'check2: total request');
                        assert.equals(rateLimiter.counters.steve.rps, 2, 'check2: request for steve');
                        assert.equals(rateLimiter.counters.tcollector.rps, 2, 'check2: request for tcollector');
                    });
                    done();
                }
            ], function done() {
                steveHyperbahnClient.destroy();
                assert.end();
            });
        }
    });

    HyperbahnCluster.test('service rate limiting works', {
        size: 1,
        kValue: 2,
        seedConfig: {
            'rateLimiting': {
                'enabled': true,
                'rateLimiterBuckets': 2,
                'exemptServices': [
                    'hyperbahn',
                    'ringpop'
                ],
                'rpsLimitForServiceName': {
                    'steve': 2
                }
            }
        }
    }, function t(cluster, assert) {
        var steve = cluster.remotes.steve;
        var bob = cluster.remotes.bob;

        var steveHyperbahnClient = new HyperbahnClient({
            serviceName: steve.serviceName,
            callerName: 'forward-test',
            hostPortList: cluster.hostPortList,
            tchannel: steve.channel,
            logger: DebugLogtron('hyperbahnClient')
        });
        steveHyperbahnClient.once('advertised', onAdvertised);
        steveHyperbahnClient.advertise();

        function onAdvertised() {
            var opts = {
                logger: cluster.logger,
                bob: bob,
                steve: steve,
                assert: assert
            };
            series([
                send.bind(null, opts),
                send.bind(null, opts),
                function sendError(done) {
                    var tchannelJSON = TChannelJSON({
                        logger: cluster.logger
                    });
                    tchannelJSON.send(bob.clientChannel.request({
                        timeout: 5000,
                        serviceName: steve.serviceName
                    }), 'echo', null, 'hello', function onResponse(err, res) {
                        assert.ok(err && err.type === 'tchannel.busy' &&
                            err.message === 'steve is rate-limited by the rps of 2',
                            'should be rate limited');
                        done();
                    });
                }
            ], function done() {
                steveHyperbahnClient.destroy();
                assert.end();
            });
        }
    });

    HyperbahnCluster.test('total rate limiting works', {
        size: 5,
        kValue: 1,
        seedConfig: {
            'rateLimiting': {
                'enabled': true,
                'rateLimiterBuckets': 2,
                'totalRpsLimit': 2,
                'exemptServices': [
                    'hyperbahn',
                    'ringpop',
                    'tcollector'
                ]
            }
        }
    }, function t(cluster, assert) {
        var steve = cluster.remotes.steve;
        var bob = cluster.remotes.bob;

        var steveHyperbahnClient = new HyperbahnClient({
            serviceName: steve.serviceName,
            callerName: 'forward-test',
            hostPortList: cluster.hostPortList,
            tchannel: steve.channel,
            logger: DebugLogtron('hyperbahnClient')
        });
        steveHyperbahnClient.once('advertised', onAdvertised);
        steveHyperbahnClient.advertise();

        function onAdvertised() {
            var opts = {
                logger: cluster.logger,
                bob: bob,
                steve: steve,
                assert: assert
            };
            series([
                send.bind(null, opts),
                send.bind(null, opts),
                waitFor(500),
                function sendError(done) {
                    var tchannelJSON = TChannelJSON({
                        logger: cluster.logger
                    });
                    tchannelJSON.send(bob.clientChannel.request({
                        timeout: 5000,
                        serviceName: steve.serviceName
                    }), 'echo', null, 'hello', function onResponse(err, res) {
                        assert.ok(err && err.type === 'tchannel.busy' &&
                            err.message === 'hyperbahn node is rate-limited by the total rps of 2',
                            'should be rate limited');
                        done();
                    });
                }
            ], function done() {
                steveHyperbahnClient.destroy();
                assert.end();
            });
        }
    });
}
<|endoftext|>


<commit_before>FileActions={
	actions:{},
	defaults:{},
	icons:{},
	currentFile:null,
	register:function(mime,name,icon,action){
		if(!FileActions.actions[mime]){
			FileActions.actions[mime]={};
		}
		FileActions.actions[mime][name]=action;
		FileActions.icons[name]=icon;
	},
	setDefault:function(mime,name){
		FileActions.defaults[mime]=name;
	},
	get:function(mime,type){
		var actions={};
		if(FileActions.actions.all){
			actions=$.extend( actions, FileActions.actions.all )
		}
		if(mime){
			if(FileActions.actions[mime]){
				actions=$.extend( actions, FileActions.actions[mime] )
			}
			var mimePart=mime.substr(0,mime.indexOf('/'));
			if(FileActions.actions[mimePart]){
				actions=$.extend( actions, FileActions.actions[mimePart] )
			}
		}
		if(type){//type is 'dir' or 'file'
			if(FileActions.actions[type]){
				actions=$.extend( actions, FileActions.actions[type] )
			}
		}
		return actions;
	},
	getDefault:function(mime,type){
		if(mime){
			var mimePart=mime.substr(0,mime.indexOf('/'));
		}
		var name=false;
		if(mime && FileActions.defaults[mime]){
			name=FileActions.defaults[mime];
		}else if(mime && FileActions.defaults[mimePart]){
			name=FileActions.defaults[mimePart];
		}else if(type && FileActions.defaults[type]){
			name=FileActions.defaults[type];
		}else{
			name=FileActions.defaults.all;
		}
		var actions=this.get(mime,type);
		return actions[name];
	},
	display:function(parent, filename, type){
		FileActions.currentFile=parent;
		$('#fileList span.fileactions, #fileList td.date a.action').remove();
		var actions=FileActions.get(FileActions.getCurrentMimeType(),FileActions.getCurrentType());
		var file=FileActions.getCurrentFile();
		if($('tr').filterAttr('data-file',file).data('renaming')){
			return;
		}
		parent.children('a.name').append('');
		var defaultAction=FileActions.getDefault(FileActions.getCurrentMimeType(),FileActions.getCurrentType());
		for(name in actions){
			// no rename and share action for the 'Shared' dir
			if((name=='Rename' || name =='Share') && type=='dir' && filename=='Shared') { continue; }
			if((name=='Download' || actions[name]!=defaultAction) && name!='Delete'){
				var img=FileActions.icons[name];
				if(img.call){
					img=img(file);
				}
				var html='';
				if(img) { html+=' '; }
				html += t('files', name) +'';
				var element=$(html);
				element.data('action',name);
				element.click(function(event){
					event.stopPropagation();
					event.preventDefault();
					var action=actions[$(this).data('action')];
					var currentFile=FileActions.getCurrentFile();
					FileActions.hide();
					action(currentFile);
				});
				element.hide();
				parent.find('a.name>span.fileactions').append(element);
			}
		}
		if(actions['Delete'] && (type!='dir' || filename != 'Shared')){ // no delete action for the 'Shared' dir
			var img=FileActions.icons['Delete'];
			if(img.call){
				img=img(file);
			}
			if ($('#dir').val().indexOf('Shared') != -1) {
				var html='';
			} else  {
				var html='';
			}
			var element=$(html);
			if(img){
				element.append($(''));
			}
			element.data('action','Delete');
			element.click(function(event){
				event.stopPropagation();
				event.preventDefault();
				var action=actions[$(this).data('action')];
				var currentFile=FileActions.getCurrentFile();
				FileActions.hide();
				action(currentFile);
			});
			element.hide();
			parent.parent().children().last().append(element);
		}
		$('#fileList .action').css('-o-transition-property','none');//temporarly disable
		$('#fileList .action').fadeIn(200,function(){
			$('#fileList .action').css('-o-transition-property','opacity');
		});
		return false;
	},
	hide:function(){
		$('#fileList span.fileactions, #fileList td.date a.action').fadeOut(200,function(){
			$(this).remove();
		});
	},
	getCurrentFile:function(){
		return FileActions.currentFile.parent().attr('data-file');
	},
	getCurrentMimeType:function(){
		return FileActions.currentFile.parent().attr('data-mime');
	},
	getCurrentType:function(){
		return FileActions.currentFile.parent().attr('data-type');
	}
}

$(document).ready(function(){
	if($('#allowZipDownload').val() == 1){
		var downloadScope = 'all';
	} else {
		var downloadScope = 'file';
	}
	FileActions.register(downloadScope,'Download',function(){return OC.imagePath('core','actions/download')},function(filename){
		window.location=OC.filePath('files', 'ajax', 'download.php') + encodeURIComponent('?files='+encodeURIComponent(filename)+'&dir='+encodeURIComponent($('#dir').val()));
	});
});

FileActions.register('all','Delete',function(){return OC.imagePath('core','actions/delete')},function(filename){
	if(Files.cancelUpload(filename)) {
		if(filename.substr){
			filename=[filename];
		}
		$.each(filename,function(index,file){
			var filename = $('tr').filterAttr('data-file',file);
			filename.hide();
			filename.find('input[type="checkbox"]').removeAttr('checked');
			filename.removeClass('selected');
		});
		procesSelection();
	}else{
		FileList.do_delete(filename);
	}
});

FileActions.register('all','Rename',function(){return OC.imagePath('core','actions/rename')},function(filename){
	FileList.rename(filename);
});

FileActions.register('dir','Open','',function(filename){
	window.location=OC.linkTo('files', 'index.php') + '&dir='+encodeURIComponent($('#dir').val()).replace(/%2F/g, '/')+'/'+encodeURIComponent(filename);
});

FileActions.setDefault('dir','Open');
<commit_msg>Remove delete tipsy if file is deleted, fixes bug oc-958<commit_after>FileActions={
	actions:{},
	defaults:{},
	icons:{},
	currentFile:null,
	register:function(mime,name,icon,action){
		if(!FileActions.actions[mime]){
			FileActions.actions[mime]={};
		}
		FileActions.actions[mime][name]=action;
		FileActions.icons[name]=icon;
	},
	setDefault:function(mime,name){
		FileActions.defaults[mime]=name;
	},
	get:function(mime,type){
		var actions={};
		if(FileActions.actions.all){
			actions=$.extend( actions, FileActions.actions.all )
		}
		if(mime){
			if(FileActions.actions[mime]){
				actions=$.extend( actions, FileActions.actions[mime] )
			}
			var mimePart=mime.substr(0,mime.indexOf('/'));
			if(FileActions.actions[mimePart]){
				actions=$.extend( actions, FileActions.actions[mimePart] )
			}
		}
		if(type){//type is 'dir' or 'file'
			if(FileActions.actions[type]){
				actions=$.extend( actions, FileActions.actions[type] )
			}
		}
		return actions;
	},
	getDefault:function(mime,type){
		if(mime){
			var mimePart=mime.substr(0,mime.indexOf('/'));
		}
		var name=false;
		if(mime && FileActions.defaults[mime]){
			name=FileActions.defaults[mime];
		}else if(mime && FileActions.defaults[mimePart]){
			name=FileActions.defaults[mimePart];
		}else if(type && FileActions.defaults[type]){
			name=FileActions.defaults[type];
		}else{
			name=FileActions.defaults.all;
		}
		var actions=this.get(mime,type);
		return actions[name];
	},
	display:function(parent, filename, type){
		FileActions.currentFile=parent;
		$('#fileList span.fileactions, #fileList td.date a.action').remove();
		var actions=FileActions.get(FileActions.getCurrentMimeType(),FileActions.getCurrentType());
		var file=FileActions.getCurrentFile();
		if($('tr').filterAttr('data-file',file).data('renaming')){
			return;
		}
		parent.children('a.name').append('');
		var defaultAction=FileActions.getDefault(FileActions.getCurrentMimeType(),FileActions.getCurrentType());
		for(name in actions){
			// no rename and share action for the 'Shared' dir
			if((name=='Rename' || name =='Share') && type=='dir' && filename=='Shared') { continue; }
			if((name=='Download' || actions[name]!=defaultAction) && name!='Delete'){
				var img=FileActions.icons[name];
				if(img.call){
					img=img(file);
				}
				var html='';
				if(img) { html+=' '; }
				html += t('files', name) +'';
				var element=$(html);
				element.data('action',name);
				element.click(function(event){
					event.stopPropagation();
					event.preventDefault();
					var action=actions[$(this).data('action')];
					var currentFile=FileActions.getCurrentFile();
					FileActions.hide();
					action(currentFile);
				});
				element.hide();
				parent.find('a.name>span.fileactions').append(element);
			}
		}
		if(actions['Delete'] && (type!='dir' || filename != 'Shared')){ // no delete action for the 'Shared' dir
			var img=FileActions.icons['Delete'];
			if(img.call){
				img=img(file);
			}
			if ($('#dir').val().indexOf('Shared') != -1) {
				var html='';
			} else  {
				var html='';
			}
			var element=$(html);
			if(img){
				element.append($(''));
			}
			element.data('action','Delete');
			element.click(function(event){
				event.stopPropagation();
				event.preventDefault();
				var action=actions[$(this).data('action')];
				var currentFile=FileActions.getCurrentFile();
				FileActions.hide();
				action(currentFile);
			});
			element.hide();
			parent.parent().children().last().append(element);
		}
		$('#fileList .action').css('-o-transition-property','none');//temporarly disable
		$('#fileList .action').fadeIn(200,function(){
			$('#fileList .action').css('-o-transition-property','opacity');
		});
		return false;
	},
	hide:function(){
		$('#fileList span.fileactions, #fileList td.date a.action').fadeOut(200,function(){
			$(this).remove();
		});
	},
	getCurrentFile:function(){
		return FileActions.currentFile.parent().attr('data-file');
	},
	getCurrentMimeType:function(){
		return FileActions.currentFile.parent().attr('data-mime');
	},
	getCurrentType:function(){
		return FileActions.currentFile.parent().attr('data-type');
	}
}

$(document).ready(function(){
	if($('#allowZipDownload').val() == 1){
		var downloadScope = 'all';
	} else {
		var downloadScope = 'file';
	}
	FileActions.register(downloadScope,'Download',function(){return OC.imagePath('core','actions/download')},function(filename){
		window.location=OC.filePath('files', 'ajax', 'download.php') + encodeURIComponent('?files='+encodeURIComponent(filename)+'&dir='+encodeURIComponent($('#dir').val()));
	});
});

FileActions.register('all','Delete',function(){return OC.imagePath('core','actions/delete')},function(filename){
	if(Files.cancelUpload(filename)) {
		if(filename.substr){
			filename=[filename];
		}
		$.each(filename,function(index,file){
			var filename = $('tr').filterAttr('data-file',file);
			filename.hide();
			filename.find('input[type="checkbox"]').removeAttr('checked');
			filename.removeClass('selected');
		});
		procesSelection();
	}else{
		FileList.do_delete(filename);
	}
	$('.tipsy').remove();
});

FileActions.register('all','Rename',function(){return OC.imagePath('core','actions/rename')},function(filename){
	FileList.rename(filename);
});

FileActions.register('dir','Open','',function(filename){
	window.location=OC.linkTo('files', 'index.php') + '&dir='+encodeURIComponent($('#dir').val()).replace(/%2F/g, '/')+'/'+encodeURIComponent(filename);
});

FileActions.setDefault('dir','Open');
<|endoftext|>


<commit_before>$(function(){

  $( document ).ready(function(){
    //code to call the github api and get the files from the "projects" folder

    path = "projects";

    projects_count = 0;
    projects_content = new Array();

    /* PERSONALIZE THIS CONTENT FOR YOUR FORKED COPY */
    // List of repositories in the format ["repository_user", "repository_name"]
    // EG:  ["gscardine", "Projects"] and ["OpenInnovationNetwork", "Projects"],
    // Example: in github.com/OpenInnovationNetwork/Projects/, it is "OpenInnovationNetwork"
    //     repository_user = "OpenInnovationNetwork"
    //     repository_name = "Projects"
    repository_list = [
      ["StandardLaw", "Projects"],
      ["CIVICS", "Projects"],
      ["LawasCode", "Projects"],
      ["natashanelson", "Projects"]

    ];

    // int i = 0;
    for (var i = 0; i < repository_list.length; i++) {
      repository_user = repository_list[i][0];
      repository_name = repository_list[i][1];

      // FIND ALL THE FILES INSIDE THE FOLDER
      $.ajax({
        url: "https://api.github.com/repos/"+repository_user+"/"+repository_name+"/contents/"+path,
        method: "get"
      })
      .success(function(allFiles){

        $.each(allFiles, function (index, value) {
          // GET CONTENT OF EACH JSON FILE
          if ((value.type == "file") && (value.name.split('.').pop() == "json")) {

            projects_count++;

            $.ajax({
              url: value.url,
              method: "get"
            })
            .success(function( fileResponse ) {
              // PARSE CONTENT
              base64decoded = atob(fileResponse.content);

              try {
                json_content = jQuery.parseJSON(base64decoded);

                // Add to list of contents
                if (json_content.project_name && json_content.project_blurb) {
                  projects_content.push(json_content);
                }
              } catch (e) {
                // invalid json
              }
            })
            .fail(function($xhr) {
                var data = $xhr.responseJSON;
                console.log(data);
            });
          }
        });
      });
    }

    // THE CONTENT OF ALL FILES WAS RETRIEVED
    $(document).ajaxStop(function() {
      console.log('All '+ projects_count +' projects retrieved');

      // Remove preloader image
      $('#projects-list').empty();

      // SHOW CONTENT AS CARDS
      $.each(projects_content, function (index, json_content) {
        template = new Array();
        if (index % 3 == 0) {
          $('#projects-list').append('
');
        }

        project_people = project_thumbnail = project_url = project_demo_url = "";

    		if ((json_content.project_people != undefined) && (json_content.project_people != "")) {
          project_people = '

People: '+json_content.project_people+'
';
        }

    		if ((json_content.project_demo_url) && (json_content.project_demo_url != undefined)) {
          project_demo_url = '

Demo: '+json_content.project_demo_url+'
';
        }

    		if ((json_content.project_thumbnail != undefined) && (json_content.project_thumbnail != "")) {
          project_thumbnail = '';
        }

        if ((json_content.project_url != undefined) && (json_content.project_url != "")) {
          project_url = '
Project: '+json_content.project_url+'
';
        }

        $('#projects-list').append(
            '
 '+
              '
 ' +
                '
 ' +
					        project_thumbnail+
                  '
'+json_content.project_name+'
 '+
                  '
'+json_content.project_blurb+'
'+
        				  '

' +
        					  project_people +
        					  project_url +
        					  project_demo_url +
        				  '
 '+
                '
 '+
              '
 '+
            '
'
        );

        if (index % 3 == 2) {
          $('#projects-list').append('
');
        }

      });
    });

  });
});
<commit_msg>Update projects_retrieval.js<commit_after>$(function(){

  $( document ).ready(function(){
    //code to call the github api and get the files from the "projects" folder

    path = "projects";

    projects_count = 0;
    projects_content = new Array();

    /* PERSONALIZE THIS CONTENT FOR YOUR FORKED COPY */
    // List of repositories in the format ["repository_user", "repository_name"]
    // EG:  ["gscardine", "Projects"] and ["OpenInnovationNetwork", "Projects"],
    // Example: in github.com/OpenInnovationNetwork/Projects/, it is "OpenInnovationNetwork"
    //     repository_user = "OpenInnovationNetwork"
    //     repository_name = "Projects"
    repository_list = [
      ["StandardLaw", "Projects"],
      ["CIVICS", "Projects"],
      ["LawAsCode", "Projects"],
      ["natashanelson", "Projects"]

    ];

    // int i = 0;
    for (var i = 0; i < repository_list.length; i++) {
      repository_user = repository_list[i][0];
      repository_name = repository_list[i][1];

      // FIND ALL THE FILES INSIDE THE FOLDER
      $.ajax({
        url: "https://api.github.com/repos/"+repository_user+"/"+repository_name+"/contents/"+path,
        method: "get"
      })
      .success(function(allFiles){

        $.each(allFiles, function (index, value) {
          // GET CONTENT OF EACH JSON FILE
          if ((value.type == "file") && (value.name.split('.').pop() == "json")) {

            projects_count++;

            $.ajax({
              url: value.url,
              method: "get"
            })
            .success(function( fileResponse ) {
              // PARSE CONTENT
              base64decoded = atob(fileResponse.content);

              try {
                json_content = jQuery.parseJSON(base64decoded);

                // Add to list of contents
                if (json_content.project_name && json_content.project_blurb) {
                  projects_content.push(json_content);
                }
              } catch (e) {
                // invalid json
              }
            })
            .fail(function($xhr) {
                var data = $xhr.responseJSON;
                console.log(data);
            });
          }
        });
      });
    }

    // THE CONTENT OF ALL FILES WAS RETRIEVED
    $(document).ajaxStop(function() {
      console.log('All '+ projects_count +' projects retrieved');

      // Remove preloader image
      $('#projects-list').empty();

      // SHOW CONTENT AS CARDS
      $.each(projects_content, function (index, json_content) {
        template = new Array();
        if (index % 3 == 0) {
          $('#projects-list').append('
');
        }

        project_people = project_thumbnail = project_url = project_demo_url = "";

    		if ((json_content.project_people != undefined) && (json_content.project_people != "")) {
          project_people = '

People: '+json_content.project_people+'
';
        }

    		if ((json_content.project_demo_url) && (json_content.project_demo_url != undefined)) {
          project_demo_url = '

Demo: '+json_content.project_demo_url+'
';
        }

    		if ((json_content.project_thumbnail != undefined) && (json_content.project_thumbnail != "")) {
          project_thumbnail = '';
        }

        if ((json_content.project_url != undefined) && (json_content.project_url != "")) {
          project_url = '
Project: '+json_content.project_url+'
';
        }

        $('#projects-list').append(
            '
 '+
              '
 ' +
                '
 ' +
					        project_thumbnail+
                  '
'+json_content.project_name+'
 '+
                  '
'+json_content.project_blurb+'
'+
        				  '

' +
        					  project_people +
        					  project_url +
        					  project_demo_url +
        				  '
 '+
                '
 '+
              '
 '+
            '
'
        );

        if (index % 3 == 2) {
          $('#projects-list').append('
');
        }

      });
    });

  });
});
<|endoftext|>


<commit_before>define(['jquery'], function ($) {
    var loadingbarId = '#personaBar-loadingbar';
    var loaded = false;
    var error = true;

    var defaultOptions = {
        slowOperationMessage: "It appears you have a slow connection... We are processing your content"
    };

    function loading(options) {
        if (window.dnn.loading) return;

        options = $.extend(defaultOptions, options);
        var loadingbar = $(loadingbarId);
        var progressbar = $(loadingbarId + ' > div');
        var width = loadingbar.width();
        var closeLoadingBar = $("#close-load-error");
        var loadingBarMessage = loadingbar.children('span');
        var slowConnectionTimeout = 4000;

        loadingbar.show();
        loadingBarMessage.html("");
        window.dnn.loading = true;
        closeLoadingBar.hide();

        function hideLoadingBar() {
            loadingbar.hide();
        }

        progressbar.removeClass().css({ width: 0, height: 5 }).stop(true, false).animate({ width: 0.75 * width }, 300, 'linear', function () {
            var pingDuration = 0;
            function checkloaded() {
                if (loaded) {
                    loaded = false;
                    window.dnn.loading = false;

                    clearTimeout(checkloaded);

                    checkloaded = null;
                    pingDuration = 0;

                    if (!error) {
                        progressbar.stop(true, false).animate({ width: "100%" }, 100, 'linear', hideLoadingBar);
                    } else {
                        loadingBarMessage.show().html("There was an error retrieving your content. Please check your internet connection.");
                        progressbar.stop(true, false).addClass("load-error").animate({ width: "100%" }, 100, 'linear').animate({ height: 25 }, 100, 'linear', function () {
                            closeLoadingBar.show().click(hideLoadingBar);
                        });
                    }
                }
                else {
                    pingDuration += 20;
                    if (pingDuration >= slowConnectionTimeout) {
                        var message = options.slowOperationMessage;
                        loadingBarMessage.show().html(message);
                        progressbar.animate({
                            height: 25
                        }, 'linear');
                    }
                    setTimeout(checkloaded, 20);
                }
            };
            checkloaded();
        });
    };

    return {
        startLoading: function (options) {
            loading(options);
        },
        stopLoading: function stopLoading(_error) {
            if (window.dnn.loading) {
                loaded = true;
                error = _error;
            }
        }
    }
});<commit_msg>Close #90: better message while processiong content<commit_after>define(['jquery'], function ($) {
    var loadingbarId = '#personaBar-loadingbar';
    var loaded = false;
    var error = true;

    var defaultOptions = {
        slowOperationMessage: "We are processing your content, please wait..."
    };

    function loading(options) {
        if (window.dnn.loading) return;

        options = $.extend(defaultOptions, options);
        var loadingbar = $(loadingbarId);
        var progressbar = $(loadingbarId + ' > div');
        var width = loadingbar.width();
        var closeLoadingBar = $("#close-load-error");
        var loadingBarMessage = loadingbar.children('span');
        var slowConnectionTimeout = 4000;

        loadingbar.show();
        loadingBarMessage.html("");
        window.dnn.loading = true;
        closeLoadingBar.hide();

        function hideLoadingBar() {
            loadingbar.hide();
        }

        progressbar.removeClass().css({ width: 0, height: 5 }).stop(true, false).animate({ width: 0.75 * width }, 300, 'linear', function () {
            var pingDuration = 0;
            function checkloaded() {
                if (loaded) {
                    loaded = false;
                    window.dnn.loading = false;

                    clearTimeout(checkloaded);

                    checkloaded = null;
                    pingDuration = 0;

                    if (!error) {
                        progressbar.stop(true, false).animate({ width: "100%" }, 100, 'linear', hideLoadingBar);
                    } else {
                        loadingBarMessage.show().html("There was an error retrieving your content. Please check your internet connection.");
                        progressbar.stop(true, false).addClass("load-error").animate({ width: "100%" }, 100, 'linear').animate({ height: 25 }, 100, 'linear', function () {
                            closeLoadingBar.show().click(hideLoadingBar);
                        });
                    }
                }
                else {
                    pingDuration += 20;
                    if (pingDuration >= slowConnectionTimeout) {
                        var message = options.slowOperationMessage;
                        loadingBarMessage.show().html(message);
                        progressbar.animate({
                            height: 25
                        }, 'linear');
                    }
                    setTimeout(checkloaded, 20);
                }
            };
            checkloaded();
        });
    };

    return {
        startLoading: function (options) {
            loading(options);
        },
        stopLoading: function stopLoading(_error) {
            if (window.dnn.loading) {
                loaded = true;
                error = _error;
            }
        }
    }
});<|endoftext|>


<commit_before>/*jslint browser: true, plusplus: true */
/*global jQuery, Handlebars, moment */
var CourseRoster = {};

CourseRoster.format_last_activity = function (date_str) {
    "use strict";
    return (date_str === null) ? "" : moment(date_str).format("MMM D [at] h:mma");
};

CourseRoster.format_total_activity = function (sec) {
    "use strict";
    return (sec === 0) ? "" : moment().startOf("day").seconds(sec).format("H:mm:ss");
};

Handlebars.registerHelper("format_last_activity", function (datetime) {
    "use strict";
    return CourseRoster.format_last_activity(datetime);
});
Handlebars.registerHelper("format_total_activity", function (sec) {
    "use strict";
    return CourseRoster.format_total_activity(sec);
});

(function ($) {
    "use strict";

    function loading_people(xhr) {
        var template = Handlebars.compile($("#loading-people-tmpl").html());
        $("#people-table tbody").html(template());
    }

    function load_dummy() {
        $(this).attr("src", window.course_roster.dummy_avatar);
    }

    function load_next_avatar() {
        var el = $("a.avatar:empty").first();
        if (el.length === 1) {
            $("<img/>").load(load_next_avatar).error(load_dummy)
                       .appendTo(el).attr("src", el.attr("data-avatar"));
        }
    }

    function create_filters() {
        var api = $("#people-table").dataTable().api();
        $("#role-filter").on("change", function () {
            var val = $(this).val(),
                col = 4;
            api.column(col).search(val).draw();
        }).appendTo("#people-table_filter").show();
    }

    function draw_people(data) {
        var template = Handlebars.compile($("#people-table-tmpl").html()),
            i,
            len,
            opt;

        $("#people-table tbody").html(template(data));

        for (i = 0, len = data.roles.length; i < len; i++) {
            opt = data.roles[i];
            $("<option>").attr("value", opt.role)
                         .text(opt.role + " (" + opt.count + ")")
                         .appendTo("#role-filter");
        }

        $("#people-table").dataTable({
            "aaSorting": [[ 0, "asc" ]],
            "bPaginate": true,
            "iDisplayLength": 25,
            "bScrollCollapse": true,
            "initComplete": create_filters,
            "order": [[ 1, "asc" ]],
            "columns": [{ "orderable": false, "searchable": false },
                null, null, null, null, null, null]
        }).on("draw.dt", load_next_avatar);

        load_next_avatar();
    }

    function load_people() {
        $.ajax({
            url: "/roster/api/v1/people",
            dataType: "json",
            beforeSend: loading_people,
            //error: ...
            success: draw_people
        });
    }

    $(document).ready(function () {
        load_people();
    });
}(jQuery));
<commit_msg>fix roster url<commit_after>/*jslint browser: true, plusplus: true */
/*global jQuery, Handlebars, moment */
var CourseRoster = {};

CourseRoster.format_last_activity = function (date_str) {
    "use strict";
    return (date_str === null) ? "" : moment(date_str).format("MMM D [at] h:mma");
};

CourseRoster.format_total_activity = function (sec) {
    "use strict";
    return (sec === 0) ? "" : moment().startOf("day").seconds(sec).format("H:mm:ss");
};

Handlebars.registerHelper("format_last_activity", function (datetime) {
    "use strict";
    return CourseRoster.format_last_activity(datetime);
});
Handlebars.registerHelper("format_total_activity", function (sec) {
    "use strict";
    return CourseRoster.format_total_activity(sec);
});

(function ($) {
    "use strict";

    function loading_people(xhr) {
        var template = Handlebars.compile($("#loading-people-tmpl").html());
        $("#people-table tbody").html(template());
    }

    function load_dummy() {
        $(this).attr("src", window.course_roster.dummy_avatar);
    }

    function load_next_avatar() {
        var el = $("a.avatar:empty").first();
        if (el.length === 1) {
            $("<img/>").load(load_next_avatar).error(load_dummy)
                       .appendTo(el).attr("src", el.attr("data-avatar"));
        }
    }

    function create_filters() {
        var api = $("#people-table").dataTable().api();
        $("#role-filter").on("change", function () {
            var val = $(this).val(),
                col = 4;
            api.column(col).search(val).draw();
        }).appendTo("#people-table_filter").show();
    }

    function draw_people(data) {
        var template = Handlebars.compile($("#people-table-tmpl").html()),
            i,
            len,
            opt;

        $("#people-table tbody").html(template(data));

        for (i = 0, len = data.roles.length; i < len; i++) {
            opt = data.roles[i];
            $("<option>").attr("value", opt.role)
                         .text(opt.role + " (" + opt.count + ")")
                         .appendTo("#role-filter");
        }

        $("#people-table").dataTable({
            "aaSorting": [[ 0, "asc" ]],
            "bPaginate": true,
            "iDisplayLength": 25,
            "bScrollCollapse": true,
            "initComplete": create_filters,
            "order": [[ 1, "asc" ]],
            "columns": [{ "orderable": false, "searchable": false },
                null, null, null, null, null, null]
        }).on("draw.dt", load_next_avatar);

        load_next_avatar();
    }

    function load_people() {
        $.ajax({
            url: "/roster/api/v1/roster",
            dataType: "json",
            beforeSend: loading_people,
            //error: ...
            success: draw_people
        });
    }

    $(document).ready(function () {
        load_people();
    });
}(jQuery));
<|endoftext|>


<commit_before>const overlay = document.createElement('div')
overlay.style.backgroundColor = 'rgba(104, 182, 255, 0.35)'
overlay.style.position = 'fixed'
overlay.style.zIndex = '99999'

/**
 * Highlight an instance.
 *
 * @param {Vue} instance
 */

export function highlight (instance) {
  if (!instance) return
  if (!instance._isFragment) {
    showOverlay(instance.$el.getBoundingClientRect())
  } else {
    highlightFragment(instance)
  }
}

/**
 * Remove highlight overlay.
 */

export function unHighlight () {
  if (overlay.parentNode) {
    document.body.removeChild(overlay)
  }
}

/**
 * Highlight a fragment instance.
 * Loop over its node range and determine its bounding box.
 *
 * @param {Vue} instance
 */

function highlightFragment ({ _fragmentStart, _fragmentEnd }) {
  const Vue = window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue
  let top, bottom, left, right
  Vue.util.mapNodeRange(_fragmentStart, _fragmentEnd, function (node) {
    let rect
    if (node.nodeType === 1 || node.getBoundingClientRect) {
      rect = node.getBoundingClientRect()
    } else if (node.nodeType === 3 && node.data.trim()) {
      rect = getTextRect(node)
    }
    if (rect) {
      if (!top || rect.top < top) {
        if (rect.top === 0) debugger
        top = rect.top
      }
      if (!bottom || rect.bottom > bottom) {
        bottom = rect.bottom
      }
      if (!left || rect.left < left) {
        left = rect.left
      }
      if (!right || rect.right > right) {
        right = rect.right
      }
    }
  })
  showOverlay({
    top,
    left,
    width: right - left,
    height: bottom - top
  })
}

/**
 * Get the bounding rect for a text node using a Range.
 *
 * @param {Text} node
 * @return {Rect}
 */

const range = document.createRange()
function getTextRect (node) {
  range.selectNode(node)
  return range.getBoundingClientRect()
}

/**
 * Display the overlay with given rect.
 *
 * @param {Rect}
 */

function showOverlay ({ width = 0, height = 0, top = 0, left = 0 }) {
  overlay.style.width = ~~width + 'px'
  overlay.style.height = ~~height + 'px'
  overlay.style.top = ~~top + 'px'
  overlay.style.left = ~~left + 'px'
  document.body.appendChild(overlay)
}
<commit_msg>scroll into view when highlighting<commit_after>const overlay = document.createElement('div')
overlay.style.backgroundColor = 'rgba(104, 182, 255, 0.35)'
overlay.style.position = 'fixed'
overlay.style.zIndex = '99999'

/**
 * Highlight an instance.
 *
 * @param {Vue} instance
 */

export function highlight (instance) {
  if (!instance) return
  scrollIntoView(instance.$el)
  if (!instance._isFragment) {
    showOverlay(instance.$el.getBoundingClientRect())
  } else {
    highlightFragment(instance)
  }
}

function scrollIntoView (node) {
  var top = node.offsetTop
  if (top == null) {
    scrollIntoView(node.previousSibling || node.parentNode)
  } else {
    window.scrollTo(0, top)
  }
}

/**
 * Remove highlight overlay.
 */

export function unHighlight () {
  if (overlay.parentNode) {
    document.body.removeChild(overlay)
  }
}

/**
 * Highlight a fragment instance.
 * Loop over its node range and determine its bounding box.
 *
 * @param {Vue} instance
 */

function highlightFragment ({ _fragmentStart, _fragmentEnd }) {
  const Vue = window.__VUE_DEVTOOLS_GLOBAL_HOOK__.Vue
  let top, bottom, left, right
  Vue.util.mapNodeRange(_fragmentStart, _fragmentEnd, function (node) {
    let rect
    if (node.nodeType === 1 || node.getBoundingClientRect) {
      rect = node.getBoundingClientRect()
    } else if (node.nodeType === 3 && node.data.trim()) {
      rect = getTextRect(node)
    }
    if (rect) {
      if (!top || rect.top < top) {
        if (rect.top === 0) debugger
        top = rect.top
      }
      if (!bottom || rect.bottom > bottom) {
        bottom = rect.bottom
      }
      if (!left || rect.left < left) {
        left = rect.left
      }
      if (!right || rect.right > right) {
        right = rect.right
      }
    }
  })
  showOverlay({
    top,
    left,
    width: right - left,
    height: bottom - top
  })
}

/**
 * Get the bounding rect for a text node using a Range.
 *
 * @param {Text} node
 * @return {Rect}
 */

const range = document.createRange()
function getTextRect (node) {
  range.selectNode(node)
  return range.getBoundingClientRect()
}

/**
 * Display the overlay with given rect.
 *
 * @param {Rect}
 */

function showOverlay ({ width = 0, height = 0, top = 0, left = 0 }) {
  overlay.style.width = ~~width + 'px'
  overlay.style.height = ~~height + 'px'
  overlay.style.top = ~~top + 'px'
  overlay.style.left = ~~left + 'px'
  document.body.appendChild(overlay)
}
<|endoftext|>


<commit_before>// TODO: Move all the styling into CSS classes
var Commands = function(hostline, user, group) {
    // Various dd parameters
    exponent = Math.floor((Math.random() * 4));
    hd_size = 64 << exponent;            // Random but within the specified range
    dd_duration = (hd_size >> 6) * 500;  // Make the base length stable
    dd_device = 'sda'                    // This probably won't gain 'coolness' from changing
    dd_block_size = 4                    // Assumed MB

    var formatSpaces = function (name, spaces) {
        emptyString = '';
        while (emptyString.length < spaces) emptyString += ' ';

        return (name + emptyString).slice(0, spaces);
    }

    var padNumber = function (value, spaces) {
        emptyString = '';
        while (emptyString.length < spaces) emptyString += '0';

        return (emptyString + value).slice(('' + value).length);
    }

    var softLink = function (user, group, source, target) {
        return 'lrwxrwxrwx   1 ' + formatSpaces(user, 5) + ' ' + formatSpaces(group, 5) + '    35 Mar 29  2013 ' +
               '
' + source + '
' +
               ' -> ' +
               '' + target + '';
    }

    var ddCopyOutput = function (device, size_gb, block_size, duration) {
        records = (size_gb << 10) / block_size;
        variance = Math.random();
        true_duration = duration/1000.0 + variance;
        throughput = size_gb / true_duration;

        // This is stupid but JS seems to roll over at a certain point for ints 2^32 < x < 2^64
        // so we do this digit-trim hack to display it correctly
        bytes_copied = (size_gb << 20) / 1000;
        bytes_copied <<= 10;

        return records + '+0 records in\n' +
               records + '+0 records out\n' +
               bytes_copied + '000 bytes (' + size_gb + ' GB) copied, ' +
                 true_duration.toFixed(5) + ' s, ' + throughput.toFixed(1) + ' GB/s';
    }

    return { 'poweroff':     { typedCommand: "poweroff",
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 0,
                               output: "\nBroadcast message from " + hostline + "\n\t\t(/dev/pts/0) at " +
                                       padNumber(new Date().getHours(), 2) + ":" +
                                       padNumber(new Date().getMinutes(), 2) + "...\n\n" +
                                       "The system is going down for halt NOW!"
                             },
             'get_users':    { typedCommand: 'cat /etc/passwd | grep \'/home/\' | grep \'^[^:]*:x:[0-9]\\{4\\}:\' | awk -F: \'{print $1}\'',
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 100,
                               output: user
                             },
             'ls_home':      { typedCommand: 'ls -la ~' + user,
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 100,
                               output: 'drwx------ 113 ' + formatSpaces(user, 5) + ' ' + formatSpaces(group, 5) + ' 36864 Jul 24 22:38 .\n' +
                                       'drwxr-xr-x   6 ' + formatSpaces('root', 5) + ' ' + formatSpaces('root', 5) + '  4096 Jan  6  2015 ..\n' +
                                       softLink(user, group, 'github', 'https://github.com/sgnn7') + '\n' +
                                       softLink(user, group, 'twitter', 'https://twitter.com/sgnn7') + '\n' +
                                       softLink(user, group, 'linkedin', 'https://linkedin.com/in/sgnn7')
                             },
             'dd_partition': { typedCommand: 'dd if=/dev/urandom of=/dev/' + dd_device + ' bs=' + dd_block_size + 'M',
                               startDelay: 1200,
                               hesitation: 3000,
                               duration: dd_duration,
                               output: ddCopyOutput(dd_device, hd_size, dd_block_size, dd_duration)
                             },
            };
};

var Scroller = function(target){
    hostline = "root@" + (window.location.hostname || 'localhost');
    bash_prompt = '
' + hostline + '

:

~

#
';

    commands = new Commands(hostline, 'sg', 'sg');

    textSpeed = 19;
    textSpeedJitter = 12;
    textStartSpeed = 800;
    newlineSpeed = 400;
    promptDelay = 1000;

    textPos = 0;

    commandList = ['get_users', 'ls_home', 'dd_partition', 'poweroff'];

    cursorSpeed = 500;
    cursorShowing = false;
    cursorStates = ['_', ' '];

    addTextInstant = function(text) {
        // console.log(target);

        var oldText = document.getElementById(target).innerHTML || "";
        document.getElementById(target).innerHTML = oldText + text;
    };

    removeCursor = function() {
        var oldText = document.getElementById(target).innerHTML || "";
        document.getElementById(target).innerHTML = oldText.substring(0, oldText.length - 1);
    };

    addPrompt = function() {
        addTextInstant(bash_prompt);
    };

    updateCursorState = function(text) {
        var oldText = document.getElementById(target).innerHTML || "";

        if (!text) {
            oldText += " ";
        }

        this.cursorShowing = !this.cursorShowing;

        newText = oldText.substring(0, oldText.length - 1) + this.cursorStates[ this.cursorShowing ? 0 : 1 ];
        document.getElementById(target).innerHTML = newText;
        setTimeout(function() {
                        this.updateCursorState(newText);
                   },
                   this.cursorSpeed);
    };

    addTypedText = function(typedText, commandIndex, originalText, textIndex) {
        // Could have assumed ECMA6 and done default params but this is more compatible
        if (!originalText)
            originalText = document.getElementById(target).innerHTML || "";

        if (!textIndex)
            textIndex = 0;

        this.addTextInstant(typedText.substring(textIndex, textIndex + 1));

        if (textIndex <= typedText.length) {
            textIndex++;
            if (typedText.substring(textIndex - 1, textIndex) == '\n') {
                this.addTextInstant('_');
                setTimeout(function() {
                               printCommandOutput(command, commandIndex);
                           },
                           command.hesitation);
            } else {
                randomJitter = this.textSpeedJitter * Math.random();
                jitteredTextSpeed = this.textSpeed + (randomJitter / 2);

                // console.log("Jitter:", jitteredTextSpeed);

                setTimeout(function() {
                               this.addTypedText(typedText, commandIndex, originalText, textIndex);
                           },
                           jitteredTextSpeed);
            }
        }
    };

    typeCommand = function(command, index) {
        addTypedText(command.typedCommand + '\n', index);
    };

    // Prints the prompt and executes a single command and displays it's output
    printCommandOutput = function(command, commandIndex) {
        removeCursor();
        addTextInstant(command.output);
        addTextInstant('\n\n');

        setTimeout(function() {
                       executeCommands(commandIndex + 1);
                   },
                   promptDelay);
    };

    // Prints the prompt, types the command, and then executes it
    executeCommand = function(commandIndex) {
        commandName = commandList[commandIndex];
        command = commands[commandName];
        console.log('Command: ' + commandName);

        addPrompt();

        setTimeout(function() {
                       typeCommand(command, commandIndex);
                   },
                   command.startDelay);
    };

    // Executes one command at a time from the commandList
    executeCommands = function(commandIndex) {
        if (!commandIndex)
            commandIndex = 0;

        if (commandIndex >= commandList.length)
            return;

        executeCommand(commandIndex);
    };

    executeCommands();
}
<commit_msg>Small formatting fix to prompt printing<commit_after>// TODO: Move all the styling into CSS classes
var Commands = function(hostline, user, group) {
    // Various dd parameters
    exponent = Math.floor((Math.random() * 4));
    hd_size = 64 << exponent;            // Random but within the specified range
    dd_duration = (hd_size >> 6) * 500;  // Make the base length stable
    dd_device = 'sda'                    // This probably won't gain 'coolness' from changing
    dd_block_size = 4                    // Assumed MB

    var formatSpaces = function (name, spaces) {
        emptyString = '';
        while (emptyString.length < spaces) emptyString += ' ';

        return (name + emptyString).slice(0, spaces);
    }

    var padNumber = function (value, spaces) {
        emptyString = '';
        while (emptyString.length < spaces) emptyString += '0';

        return (emptyString + value).slice(('' + value).length);
    }

    var softLink = function (user, group, source, target) {
        return 'lrwxrwxrwx   1 ' + formatSpaces(user, 5) + ' ' + formatSpaces(group, 5) + '    35 Mar 29  2013 ' +
               '
' + source + '
' +
               ' -> ' +
               '' + target + '';
    }

    var ddCopyOutput = function (device, size_gb, block_size, duration) {
        records = (size_gb << 10) / block_size;
        variance = Math.random();
        true_duration = duration/1000.0 + variance;
        throughput = size_gb / true_duration;

        // This is stupid but JS seems to roll over at a certain point for ints 2^32 < x < 2^64
        // so we do this digit-trim hack to display it correctly
        bytes_copied = (size_gb << 20) / 1000;
        bytes_copied <<= 10;

        return records + '+0 records in\n' +
               records + '+0 records out\n' +
               bytes_copied + '000 bytes (' + size_gb + ' GB) copied, ' +
                 true_duration.toFixed(5) + ' s, ' + throughput.toFixed(1) + ' GB/s';
    }

    return { 'poweroff':     { typedCommand: "poweroff",
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 0,
                               output: "\nBroadcast message from " + hostline + "\n\t\t(/dev/pts/0) at " +
                                       padNumber(new Date().getHours(), 2) + ":" +
                                       padNumber(new Date().getMinutes(), 2) + "...\n\n" +
                                       "The system is going down for halt NOW!"
                             },
             'get_users':    { typedCommand: 'cat /etc/passwd | grep \'/home/\' | grep \'^[^:]*:x:[0-9]\\{4\\}:\' | awk -F: \'{print $1}\'',
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 100,
                               output: user
                             },
             'ls_home':      { typedCommand: 'ls -la ~' + user,
                               startDelay: 1250,
                               hesitation: 200,
                               duration: 100,
                               output: 'drwx------ 113 ' + formatSpaces(user, 5) + ' ' + formatSpaces(group, 5) + ' 36864 Jul 24 22:38 .\n' +
                                       'drwxr-xr-x   6 ' + formatSpaces('root', 5) + ' ' + formatSpaces('root', 5) + '  4096 Jan  6  2015 ..\n' +
                                       softLink(user, group, 'github', 'https://github.com/sgnn7') + '\n' +
                                       softLink(user, group, 'twitter', 'https://twitter.com/sgnn7') + '\n' +
                                       softLink(user, group, 'linkedin', 'https://linkedin.com/in/sgnn7')
                             },
             'dd_partition': { typedCommand: 'dd if=/dev/urandom of=/dev/' + dd_device + ' bs=' + dd_block_size + 'M',
                               startDelay: 1200,
                               hesitation: 3000,
                               duration: dd_duration,
                               output: ddCopyOutput(dd_device, hd_size, dd_block_size, dd_duration)
                             },
            };
};

var Scroller = function(target){
    hostline = "root@" + (window.location.hostname || 'localhost');
    bash_prompt = '
' + hostline + '
' +
                  '
:
' +
                  '
~
' +
                  '
#
';

    commands = new Commands(hostline, 'sg', 'sg');

    textSpeed = 19;
    textSpeedJitter = 12;
    textStartSpeed = 800;
    newlineSpeed = 400;
    promptDelay = 1000;

    textPos = 0;

    commandList = ['get_users', 'ls_home', 'dd_partition', 'poweroff'];

    cursorSpeed = 500;
    cursorShowing = false;
    cursorStates = ['_', ' '];

    addTextInstant = function(text) {
        // console.log(target);

        var oldText = document.getElementById(target).innerHTML || "";
        document.getElementById(target).innerHTML = oldText + text;
    };

    removeCursor = function() {
        var oldText = document.getElementById(target).innerHTML || "";
        document.getElementById(target).innerHTML = oldText.substring(0, oldText.length - 1);
    };

    addPrompt = function() {
        addTextInstant(bash_prompt);
    };

    updateCursorState = function(text) {
        var oldText = document.getElementById(target).innerHTML || "";

        if (!text) {
            oldText += " ";
        }

        this.cursorShowing = !this.cursorShowing;

        newText = oldText.substring(0, oldText.length - 1) + this.cursorStates[ this.cursorShowing ? 0 : 1 ];
        document.getElementById(target).innerHTML = newText;
        setTimeout(function() {
                        this.updateCursorState(newText);
                   },
                   this.cursorSpeed);
    };

    addTypedText = function(typedText, commandIndex, originalText, textIndex) {
        // Could have assumed ECMA6 and done default params but this is more compatible
        if (!originalText)
            originalText = document.getElementById(target).innerHTML || "";

        if (!textIndex)
            textIndex = 0;

        this.addTextInstant(typedText.substring(textIndex, textIndex + 1));

        if (textIndex <= typedText.length) {
            textIndex++;
            if (typedText.substring(textIndex - 1, textIndex) == '\n') {
                this.addTextInstant('_');
                setTimeout(function() {
                               printCommandOutput(command, commandIndex);
                           },
                           command.hesitation);
            } else {
                randomJitter = this.textSpeedJitter * Math.random();
                jitteredTextSpeed = this.textSpeed + (randomJitter / 2);

                // console.log("Jitter:", jitteredTextSpeed);

                setTimeout(function() {
                               this.addTypedText(typedText, commandIndex, originalText, textIndex);
                           },
                           jitteredTextSpeed);
            }
        }
    };

    typeCommand = function(command, index) {
        addTypedText(command.typedCommand + '\n', index);
    };

    // Prints the prompt and executes a single command and displays it's output
    printCommandOutput = function(command, commandIndex) {
        removeCursor();
        addTextInstant(command.output);
        addTextInstant('\n\n');

        setTimeout(function() {
                       executeCommands(commandIndex + 1);
                   },
                   promptDelay);
    };

    // Prints the prompt, types the command, and then executes it
    executeCommand = function(commandIndex) {
        commandName = commandList[commandIndex];
        command = commands[commandName];
        console.log('Command: ' + commandName);

        addPrompt();

        setTimeout(function() {
                       typeCommand(command, commandIndex);
                   },
                   command.startDelay);
    };

    // Executes one command at a time from the commandList
    executeCommands = function(commandIndex) {
        if (!commandIndex)
            commandIndex = 0;

        if (commandIndex >= commandList.length)
            return;

        executeCommand(commandIndex);
    };

    executeCommands();
}
<|endoftext|>


<commit_before>'use strict';

const getDestinationPrompts = require('./prompts/get-destination-prompts');

module.exports = plop => {
  // Policy generator
  plop.setGenerator('policy', {
    description: 'Generate a policy for an API',
    prompts: [
      {
        type: 'input',
        name: 'id',
        message: 'Policy name',
      },
      ...getDestinationPrompts('policy', plop.getDestBasePath(), { rootFolder: true }),
    ],
    actions(answers) {
      let filePath;
      if (answers.destination === 'api') {
        filePath = `api/{{api}}`;
      } else if (answers.destination === 'plugin') {
        filePath = `plugins/{{plugin}}`;
      } else {
        filePath = `./`;
      }

      return [
        {
          type: 'add',
          path: `${filePath}/policies/{{id}}.js`,
          templateFile: 'templates/policy.js.hbs',
        },
      ];
    },
  });
};
<commit_msg>fixing file paths when generating policies inside plugins<commit_after>'use strict';

const getDestinationPrompts = require('./prompts/get-destination-prompts');

module.exports = plop => {
  // Policy generator
  plop.setGenerator('policy', {
    description: 'Generate a policy for an API',
    prompts: [
      {
        type: 'input',
        name: 'id',
        message: 'Policy name',
      },
      ...getDestinationPrompts('policy', plop.getDestBasePath(), { rootFolder: true }),
    ],
    actions(answers) {
      let filePath;
      if (answers.destination === 'api') {
        filePath = `api/{{api}}`;
      } else if (answers.destination === 'plugin') {
        filePath = `plugins/{{plugin}}/server`;
      } else {
        filePath = `./`;
      }

      return [
        {
          type: 'add',
          path: `${filePath}/policies/{{id}}.js`,
          templateFile: 'templates/policy.js.hbs',
        },
      ];
    },
  });
};
<|endoftext|>


<commit_before>/**
 * @license Apache-2.0
 * Copyright 2020 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @fileoverview
 * Crawl over all test/com/google/.../runtime_tests/*_test.html files and
 * execute them in a JSDOM context, fail the test if any do not succeed.
 */

const { JSDOM, VirtualConsole } = require('jsdom');
const { fail } = require('assert');
const chalk = require('chalk');
const fs = require('fs');
const FutureEvent = require('future-event');
const glob = require('glob');
const path = require('path');

const TEST_FILES = glob.sync(path.resolve(
  __dirname,
  '../../test/com/google/javascript/jscomp/runtime_tests/**/build/*_test.html'
));

describe('Runtime tests', () => {
  for (let testUrl of TEST_FILES) {
    const logs = [];
    const passed = /PASSED/i;
    const failed = /FAILED/i;

    const allLogs = () => logs.join('\n');
    const chalkMsg = (msg) => {
      const isPass = passed.test(msg);
      const isFail = failed.test(msg);

      if (isPass || isFail) {
        return msg.replace(
          passed, chalk.green('PASSED')
        ).replace(
          failed, chalk.red('FAILED')
        );
      }
      else return msg;
    }

    const testName = path.basename(testUrl);
    const TestIsFinished = new FutureEvent();
    const virtualConsole = new VirtualConsole()
      .on('log', (msg) => {
        logs.push(chalkMsg(msg));
        if (/Tests complete/i.test(msg)) TestIsFinished.ready(allLogs());
        else if (/Tests failed/i.test(msg)) TestIsFinished.cancel(allLogs());
      });

    const TEST_DOC = fs.readFileSync(
      path.resolve(
        __dirname,
        '../../',
        testUrl
      ),
      'utf-8'
    );

    it(`should pass test suite ${path.basename(testUrl)}`, async () => {
      const { window } = new JSDOM(TEST_DOC, {
        /**
         * This does not actually run a server of any kind, it only informs the
         * DOM what to put in `window.location.origin`. By default, this is
         * `null`, and any non-HTTPS URL field here will throw an error in the
         * test suite
         */
        url: 'https://localhost:42',
        /**
         * This flag will allow the execution of `<script>` tags that are added
         * to the DOM after the `onload` event, i.e., those that are added by
         * `goog.module` and `goog.require`.
         */
        runScripts: 'dangerously',
        /**
         * Pipe `console.log` to our virtual console.
         */
        virtualConsole
      });

      try {
        await TestIsFinished;
      } catch (e) {
        // Format the error a bit: first line red, rest unformatted.
        const errorLines = e.toString().split('\n');
        let formattedError;
        for (let i = 0; i < errorLines.length; i++) {
          formattedError += i === 0
            ? chalk.red(errorLines[i])
            : errorLines[i];
        }
        fail(`Failed test in suite ${testName}: \n${formattedError}\n`);
      }
      console.log(`Passed all tests in suite ${testName}`);
    });
  }
});<commit_msg>Removed test formatting, more trouble than it's worth<commit_after>/**
 * @license Apache-2.0
 * Copyright 2020 The Closure Compiler Authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @fileoverview
 * Crawl over all test/com/google/.../runtime_tests/*_test.html files and
 * execute them in a JSDOM context, fail the test if any do not succeed.
 */

const { JSDOM, VirtualConsole } = require('jsdom');
const { fail } = require('assert');
const chalk = require('chalk');
const fs = require('fs');
const FutureEvent = require('future-event');
const glob = require('glob');
const path = require('path');

const TEST_FILES = glob.sync(path.resolve(
    __dirname,
    '../../test/com/google/javascript/jscomp/runtime_tests/**/build/*_test.html',
));

describe('Runtime tests', () => {
  for (const testUrl of TEST_FILES) {
    const logs = [];
    const passed = /PASSED/i;
    const failed = /FAILED/i;

    const allLogs = () => logs.join('\n');
    const chalkMsg = (msg) => {
      const isPass = passed.test(msg);
      const isFail = failed.test(msg);

      if (isPass || isFail) {
        return msg.replace(
            passed, chalk.green('PASSED'),
        ).replace(
            failed, chalk.red('FAILED'),
        );
      } else return msg;
    };

    const testName = path.basename(testUrl);
    const TestIsFinished = new FutureEvent();
    const virtualConsole = new VirtualConsole()
        .on('log', (msg) => {
          logs.push(chalkMsg(msg));
          if (/Tests complete/i.test(msg)) TestIsFinished.ready(allLogs());
          else if (/Tests failed/i.test(msg)) TestIsFinished.cancel(allLogs());
        });

    const TEST_DOC = fs.readFileSync(
        path.resolve(
            __dirname,
            '../../',
            testUrl,
        ),
        'utf-8',
    );

    it(`should pass test suite ${path.basename(testUrl)}`, async () => {
      new JSDOM(TEST_DOC, {
        /**
         * This does not actually run a server of any kind, it only informs the
         * DOM what to put in `window.location.origin`. By default, this is
         * `null`, and any non-HTTPS URL field here will throw an error in the
         * test suite
         */
        url: 'https://localhost:42',
        /**
         * This flag will allow the execution of `<script>` tags that are added
         * to the DOM after the `onload` event, i.e., those that are added by
         * `goog.module` and `goog.require`.
         */
        runScripts: 'dangerously',
        /**
         * Pipe `console.log` to our virtual console.
         */
        virtualConsole,
      });

      try {
        await TestIsFinished;
      } catch (e) {
        fail(`Failed test in suite ${testName}: \n${e}\n`);
      }
      console.log(`Passed all tests in suite ${testName}`);
    });
  }
});
<|endoftext|>


<commit_before>exports = module.exports = function(authenticate) {

  return function verify(req, token, cb) {
    authenticate(token, function(err, tkn, ctx) {
      if (err) { return cb(err); }

      // TODO: Check confirmation methods, etc

      var info = {};
      if (tkn.client) {
        info.client = tkn.client;
      }
      if (tkn.scope) {
        info.scope = tkn.scope;
      }

      if (!tkn.subject) {
        return cb(null, false);
      }
      return cb(null, tkn.subject, info);
    });
  };
};

exports['@require'] = [
  'http://i.bixbyjs.org/security/authentication/token/authenticate'
];
<commit_msg>Switch from subject to user.<commit_after>exports = module.exports = function(authenticate) {

  return function verify(req, token, cb) {
    authenticate(token, function(err, tkn, ctx) {
      if (err) { return cb(err); }

      // TODO: Check confirmation methods, etc

      var info = {};
      if (tkn.client) {
        info.client = tkn.client;
      }
      if (tkn.scope) {
        info.scope = tkn.scope;
      }

      if (!tkn.user) {
        return cb(null, false);
      }
      return cb(null, tkn.user, info);
    });
  };
};

exports['@require'] = [
  'http://i.bixbyjs.org/security/authentication/token/authenticate'
];
<|endoftext|>