Skip to content

Commit

Permalink
feat($templateFactory): refactor to a Provider to have a $http/$templ…
Browse files Browse the repository at this point in the history
…ateRequest switch

This creates a $TemplateFactoryProvider to be able to set a global config option
that forces $templateFactory to use $http (which bypasses the security checks,
hence the scary name). Added tests and doc for that too. This still defaults to
$http on older Angulars as expected.
  • Loading branch information
rjamet authored and christopherthielen committed Dec 15, 2016
1 parent ad1f093 commit 7f1dec0
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 5 deletions.
60 changes: 55 additions & 5 deletions src/templateFactory.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,54 @@

/**
* @ngdoc object
* @name ui.router.util.$templateFactoryProvider
*
* @description
* Provider for $templateFactory. Manages which template-loading mechanism to
* use, and will default to the most recent one ($templateRequest on Angular
* versions starting from 1.3, $http otherwise).
*/
function $TemplateFactoryProvider() {
var shouldUnsafelyUseHttp = angular.version.minor < 3;

/**
* @ngdoc function
* @name ui.router.util.$templateFactoryProvider#shouldUnsafelyUseHttp
* @methodOf ui.router.util.$templateFactoryProvider
*
* @description
* Forces $templateFactory to use $http instead of $templateRequest. This
* might cause XSS, as $http doesn't enforce the regular security checks for
* templates that have been introduced in Angular 1.3. Note that setting this
* to false on Angular older than 1.3.x will crash, as the $templateRequest
* service (and the security checks) are not implemented on these versions.
*
* See the $sce documentation, section
* <a href="https://docs.angularjs.org/api/ng/service/$sce#impact-on-loading-templates">
* Impact on loading templates</a> for more details about this mechanism.
*
* @param {boolean} value
*/
this.shouldUnsafelyUseHttp = function(value) {
shouldUnsafelyUseHttp = !!value;
};

/**
* @ngdoc object
* @name ui.router.util.$templateFactory
*
* @requires $http
* @requires $templateCache
* @requires $injector
*
* @description
* Service. Manages loading of templates.
*/
this.$get = ['$http', '$templateCache', '$injector', function($http, $templateCache, $injector){
return new $TemplateFactory($http, $templateCache, $injector, shouldUnsafelyUseHttp);}];
}


/**
* @ngdoc object
* @name ui.router.util.$templateFactory
Expand All @@ -9,8 +60,7 @@
* @description
* Service. Manages loading of templates.
*/
$TemplateFactory.$inject = ['$http', '$templateCache', '$injector'];
function $TemplateFactory( $http, $templateCache, $injector) {
function $TemplateFactory($http, $templateCache, $injector, shouldUnsafelyUseHttp) {

/**
* @ngdoc function
Expand Down Expand Up @@ -83,7 +133,7 @@ function $TemplateFactory( $http, $templateCache, $injector) {
if (isFunction(url)) url = url(params);
if (url == null) return null;
else {
if($injector.has && $injector.has('$templateRequest')) {
if(!shouldUnsafelyUseHttp) {
return $injector.get('$templateRequest')(url);
} else {
return $http
Expand Down Expand Up @@ -111,6 +161,6 @@ function $TemplateFactory( $http, $templateCache, $injector) {
this.fromProvider = function (provider, params, locals) {
return $injector.invoke(provider, null, locals || { params: params });
};
}
};

angular.module('ui.router.util').service('$templateFactory', $TemplateFactory);
angular.module('ui.router.util').provider('$templateFactory', $TemplateFactoryProvider);
23 changes: 23 additions & 0 deletions test/templateFactorySpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,26 @@ describe('templateFactory', function () {
}));
}
});

describe('templateFactory with $http use forced', function () {

beforeEach(function() {
angular
.module('forceHttpInTemplateFactory', [])
.config(function($templateFactoryProvider) {
$templateFactoryProvider.shouldUnsafelyUseHttp(true);
});
module('ui.router.util');
module('forceHttpInTemplateFactory');
});

it('does not restrict URL loading', inject(function($templateFactory, $httpBackend) {
$httpBackend.expectGET('http://evil.com/views/view.html').respond(200, 'template!');
$templateFactory.fromUrl('http://evil.com/views/view.html');
$httpBackend.flush();

$httpBackend.expectGET('data:text/html,foo').respond(200, 'template!');
$templateFactory.fromUrl('data:text/html,foo');
$httpBackend.flush();
}));
});

0 comments on commit 7f1dec0

Please sign in to comment.