Update Umbraco to 7.12.2

This commit is contained in:
2018-09-16 15:08:47 -04:00
parent 7ed7776432
commit 616ab81bad
764 changed files with 142787 additions and 66790 deletions
+17
View File
@@ -0,0 +1,17 @@
var app = angular.module('umbraco', [
'umbraco.filters',
'umbraco.directives',
'umbraco.resources',
'umbraco.services',
'umbraco.httpbackend',
'ngCookies',
'ngMobile',
'ngSanitize',
'tmh.dynamicLocale'
]);
/* For Angular 1.4: we need to load in Route, animate and touch seperately
'ngRoute',
'ngAnimate',
'ngTouch'
*/
+12 -3
View File
@@ -11,7 +11,7 @@ var app = angular.module('umbraco', [
'ngMobile',
'tmh.dynamicLocale',
'ngFileUpload',
'LocalStorageModule'
'LocalStorageModule'
]);
var packages = angular.module("umbraco.packages", []);
@@ -22,12 +22,21 @@ var packages = angular.module("umbraco.packages", []);
//module is initilized.
angular.module("umbraco.views", ["umbraco.viewcache"]);
angular.module("umbraco.viewcache", [])
.run(function($rootScope, $templateCache) {
.run(function ($rootScope, $templateCache, localStorageService) {
/** For debug mode, always clear template cache to cut down on
dev frustration and chrome cache on templates */
if (Umbraco.Sys.ServerVariables.isDebuggingEnabled) {
$templateCache.removeAll();
}
else {
var storedVersion = localStorageService.get("umbVersion");
if (!storedVersion || storedVersion !== Umbraco.Sys.ServerVariables.application.cacheBuster) {
//if the stored version doesn't match our cache bust version, clear the template cache
$templateCache.removeAll();
//store the current version
localStorageService.set("umbVersion", Umbraco.Sys.ServerVariables.application.cacheBuster);
}
}
})
.config([
//This ensures that all of our angular views are cache busted, if the path starts with views/ and ends with .html, then
@@ -39,7 +48,7 @@ angular.module("umbraco.viewcache", [])
$delegate.get = function (url, config) {
if (Umbraco.Sys.ServerVariables.application && url.startsWith("views/") && url.endsWith(".html")) {
var rnd = Umbraco.Sys.ServerVariables.application.version + "." + Umbraco.Sys.ServerVariables.application.cdf;
var rnd = Umbraco.Sys.ServerVariables.application.cacheBuster;
var _op = (url.indexOf("?") > 0) ? "&" : "?";
url += _op + "umb__rnd=" + rnd;
}
+2 -2
View File
@@ -11,8 +11,8 @@ LazyLoad.js([
'../js/umbraco.security.js',
'../ServerVariables',
'../lib/spectrum/spectrum.js',
'../js/canvasdesigner.panel.js',
'../js/umbraco.canvasdesigner.js',
'../js/canvasdesigner.panel.js'
], function () {
jQuery(document).ready(function () {
angular.bootstrap(document, ['Umbraco.canvasdesigner']);
+63 -10
View File
@@ -1,34 +1,86 @@
/** Executed when the application starts, binds to events and set global state */
app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', 'editorState', 'fileManager', 'assetsService', 'eventsService', '$cookies', '$templateCache',
function (userService, $log, $rootScope, $location, navigationService, appState, editorState, fileManager, assetsService, eventsService, $cookies, $templateCache) {
app.run(['userService', '$log', '$rootScope', '$location', 'queryStrings', 'navigationService', 'appState', 'editorState', 'fileManager', 'assetsService', 'eventsService', '$cookies', '$templateCache', 'localStorageService', 'tourService', 'dashboardResource',
function (userService, $log, $rootScope, $location, queryStrings, navigationService, appState, editorState, fileManager, assetsService, eventsService, $cookies, $templateCache, localStorageService, tourService, dashboardResource) {
//This sets the default jquery ajax headers to include our csrf token, we
// need to user the beforeSend method because our token changes per user/login so
// it cannot be static
$.ajaxSetup({
beforeSend: function (xhr) {
xhr.setRequestHeader("X-XSRF-TOKEN", $cookies["XSRF-TOKEN"]);
xhr.setRequestHeader("X-UMB-XSRF-TOKEN", $cookies["UMB-XSRF-TOKEN"]);
if (queryStrings.getParams().umbDebug === "true" || queryStrings.getParams().umbdebug === "true") {
xhr.setRequestHeader("X-UMB-DEBUG", "true");
}
}
});
/** Listens for authentication and checks if our required assets are loaded, if/once they are we'll broadcast a ready event */
eventsService.on("app.authenticated", function(evt, data) {
assetsService._loadInitAssets().then(function() {
appState.setGlobalState("isReady", true);
//send the ready event with the included returnToPath,returnToSearch data
eventsService.emit("app.ready", data);
returnToPath = null, returnToSearch = null;
// Loads the user's locale settings for Moment.
userService.loadMomentLocaleForCurrentUser().then(function() {
//Register all of the tours on the server
tourService.registerAllTours().then(function () {
appReady(data);
// Auto start intro tour
tourService.getTourByAlias("umbIntroIntroduction").then(function (introTour) {
// start intro tour if it hasn't been completed or disabled
if (introTour && introTour.disabled !== true && introTour.completed !== true) {
tourService.startTour(introTour);
}
});
}, function(){
appReady(data);
});
});
});
});
function appReady(data) {
appState.setGlobalState("isReady", true);
//send the ready event with the included returnToPath,returnToSearch data
eventsService.emit("app.ready", data);
returnToPath = null, returnToSearch = null;
}
/** execute code on each successful route */
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
if(current.params.section){
$rootScope.locationTitle = current.params.section + " - " + $location.$$host;
var deployConfig = Umbraco.Sys.ServerVariables.deploy;
var deployEnv, deployEnvTitle;
if (deployConfig) {
deployEnv = Umbraco.Sys.ServerVariables.deploy.CurrentWorkspace;
deployEnvTitle = "(" + deployEnv + ") ";
}
if(current.params.section) {
//Uppercase the current section, content, media, settings, developer, forms
var currentSection = current.params.section.charAt(0).toUpperCase() + current.params.section.slice(1);
var baseTitle = currentSection + " - " + $location.$$host;
//Check deploy for Global Umbraco.Sys obj workspace
if(deployEnv){
$rootScope.locationTitle = deployEnvTitle + baseTitle;
}
else {
$rootScope.locationTitle = baseTitle;
}
}
else {
if(deployEnv) {
$rootScope.locationTitle = deployEnvTitle + "Umbraco - " + $location.$$host;
}
$rootScope.locationTitle = "Umbraco - " + $location.$$host;
}
@@ -67,4 +119,5 @@ app.run(['userService', '$log', '$rootScope', '$location', 'navigationService',
//var touchDevice = ("ontouchstart" in window || window.touch || window.navigator.msMaxTouchPoints === 5 || window.DocumentTouch && document instanceof DocumentTouch);
var touchDevice = /android|webos|iphone|ipad|ipod|blackberry|iemobile|touch/i.test(navigator.userAgent.toLowerCase());
appState.setGlobalState("touchDevice", touchDevice);
}]);
+18 -16
View File
@@ -1,17 +1,19 @@
LazyLoad.js( [
'lib/jquery/jquery.min.js',
/* 1.1.5 */
'lib/angular/1.1.5/angular.min.js',
'lib/angular/1.1.5/angular-cookies.min.js',
'lib/angular/1.1.5/angular-mobile.min.js',
'lib/angular/1.1.5/angular-mocks.js',
'lib/angular/1.1.5/angular-sanitize.min.js',
'lib/underscore/underscore-min.js',
'js/umbraco.installer.js',
'js/umbraco.directives.js'
], function () {
jQuery(document).ready(function () {
angular.bootstrap(document, ['ngSanitize', 'umbraco.install', 'umbraco.directives.validation']);
});
}
LazyLoad.js([
'lib/jquery/jquery.min.js',
/* 1.1.5 */
'lib/angular/1.1.5/angular.min.js',
'lib/angular/1.1.5/angular-cookies.min.js',
'lib/angular/1.1.5/angular-mobile.min.js',
'lib/angular/1.1.5/angular-mocks.js',
'lib/angular/1.1.5/angular-sanitize.min.js',
'lib/underscore/underscore-min.js',
'lib/angular/angular-ui-sortable.js',
'js/installer.app.js',
'js/umbraco.directives.js',
'js/umbraco.installer.js'
], function () {
jQuery(document).ready(function () {
angular.bootstrap(document, ['umbraco']);
});
}
);
+7
View File
@@ -0,0 +1,7 @@
var app = angular.module('umbraco', [
'umbraco.directives',
'umbraco.install',
'ngCookies',
'ngMobile',
'ngSanitize'
]);
+49
View File
@@ -0,0 +1,49 @@
LazyLoad.js(
[
'lib/jquery/jquery.min.js',
'lib/jquery-ui/jquery-ui.min.js',
/* 1.1.5 */
'lib/angular/1.1.5/angular.min.js',
'lib/angular/1.1.5/angular-cookies.min.js',
'lib/angular/1.1.5/angular-sanitize.min.js',
'lib/angular/angular-ui-sortable.js',
'lib/angular/1.1.5/angular-mocks.js',
'lib/angular/1.1.5/angular-mobile.min.js',
'lib/underscore/underscore-min.js',
'lib/angular-dynamic-locale/tmhDynamicLocale.min.js',
'lib/bootstrap/js/bootstrap.2.3.2.min.js',
'lib/bootstrap-tabdrop/bootstrap-tabdrop.min.js',
'lib/umbraco/Extensions.js',
'lib/umbraco/NamespaceManager.js',
'lib/umbraco/LegacyUmbClientMgr.js',
'lib/umbraco/LegacySpeechBubble.js',
'js/umbraco.servervariables.js',
'js/app.dev.js',
'js/umbraco.httpbackend.js',
'js/umbraco.testing.js',
'js/umbraco.directives.js',
'js/umbraco.filters.js',
'js/umbraco.resources.js',
'js/umbraco.services.js',
'js/umbraco.security.js',
'js/umbraco.controllers.js',
'js/routes.js',
'js/init.js'
],
function () {
jQuery(document).ready(function () {
angular.bootstrap(document, ['umbraco']);
});
}
);
+53 -17
View File
@@ -31,6 +31,12 @@ app.config(function ($routeProvider) {
userService.getCurrentUser({ broadcastEvent: broadcast }).then(function (user) {
//is auth, check if we allow or reject
if (isRequired) {
//This checks the current section and will force a redirect to 'content' as the default
if ($route.current.params.section.toLowerCase() === "default" || $route.current.params.section.toLowerCase() === "umbraco" || $route.current.params.section === "") {
$route.current.params.section = "content";
}
// U4-5430, Benjamin Howarth
// We need to change the current route params if the user only has access to a single section
// To do this we need to grab the current user's allowed sections, then reject the promise with the correct path.
@@ -98,14 +104,29 @@ app.config(function ($routeProvider) {
resolve: doLogout()
})
.when('/:section', {
templateUrl: function (rp) {
if (rp.section.toLowerCase() === "default" || rp.section.toLowerCase() === "umbraco" || rp.section === "")
{
rp.section = "content";
}
rp.url = "dashboard.aspx?app=" + rp.section;
return 'views/common/dashboard.html';
//This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
template: "<div ng-include='templateUrl'></div>",
//This controller will execute for this route, then we can execute some code in order to set the template Url
controller: function ($scope, $route, $routeParams, $location, sectionService) {
//We are going to check the currently loaded sections for the user and if the section we are navigating
//to has a custom route path we'll use that
sectionService.getSectionsForUser().then(function(sections) {
//find the one we're requesting
var found = _.find(sections, function(s) {
return s.alias === $routeParams.section;
})
if (found && found.routePath) {
//there's a custom route path so redirect
$location.path(found.routePath);
}
else {
//there's no custom route path so continue as normal
$routeParams.url = "dashboard.aspx?app=" + $routeParams.section;
$scope.templateUrl = 'views/common/dashboard.html';
}
});
},
resolve: canRoute(true)
})
@@ -120,17 +141,32 @@ app.config(function ($routeProvider) {
resolve: canRoute(true)
})
.when('/:section/:tree/:method', {
templateUrl: function (rp) {
if (!rp.method)
return "views/common/dashboard.html";
//This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
template: "<div ng-include='templateUrl'></div>",
//This controller will execute for this route, then we replace the template dynamnically based on the current tree.
controller: function ($scope, $route, $routeParams, treeService) {
//NOTE: This current isn't utilized by anything but does open up some cool opportunities for
// us since we'll be able to have specialized views for individual sections which is something
// we've never had before. So could utilize this for a new dashboard model when we get native
// angular dashboards working. Perhaps a normal section dashboard would list out the registered
// dashboards (as tabs if we wanted) and each tab could actually be a route link to one of these views?
if (!$routeParams.method) {
$scope.templateUrl = "views/common/dashboard.html";
}
return ('views/' + rp.tree + '/' + rp.method + '.html');
// Here we need to figure out if this route is for a package tree and if so then we need
// to change it's convention view path to:
// /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html
// otherwise if it is a core tree we use the core paths:
// views/{treetype}/{method}.html
var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree);
if (packageTreeFolder) {
$scope.templateUrl = (Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath +
"/" + packageTreeFolder +
"/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html");
}
else {
$scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html');
}
},
resolve: canRoute(true)
})
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+116 -41
View File
@@ -1,53 +1,128 @@
/*! umbraco
* https://github.com/umbraco/umbraco-cms/
* Copyright (c) 2016 Umbraco HQ;
* Licensed
*/
(function() {
angular.module('umbraco.filters', []);
angular.module("umbraco.filters")
.filter('compareArrays', function() {
(function () {
angular.module('umbraco.filters', []);
angular.module('umbraco.filters').filter('compareArrays', function () {
return function inArray(array, compareArray, compareProperty) {
var result = [];
angular.forEach(array, function(arrayItem){
angular.forEach(array, function (arrayItem) {
var exists = false;
angular.forEach(compareArray, function(compareItem){
if( arrayItem[compareProperty] === compareItem[compareProperty]) {
angular.forEach(compareArray, function (compareItem) {
if (arrayItem[compareProperty] === compareItem[compareProperty]) {
exists = true;
}
});
if(!exists) {
if (!exists) {
result.push(arrayItem);
}
});
return result;
};
});
angular.module("umbraco.filters").filter('timespan', function() {
return function(input) {
var sec_num = parseInt(input, 10);
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
var seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
var time = hours+':'+minutes+':'+seconds;
return time;
});
// Filter to take a node id and grab it's name instead
// Usage: {{ pickerAlias | ncNodeName }}
// Cache for node names so we don't make a ton of requests
var ncNodeNameCache = {
id: '',
keys: {}
};
});
})();
angular.module('umbraco.filters').filter('ncNodeName', function (editorState, entityResource) {
function formatLabel(firstNodeName, totalNodes) {
return totalNodes <= 1 ? firstNodeName // If there is more than one item selected, append the additional number of items selected to hint that
: firstNodeName + ' (+' + (totalNodes - 1) + ')';
}
return function (input) {
// Check we have a value at all
if (input === '' || input.toString() === '0') {
return '';
}
var currentNode = editorState.getCurrent();
// Ensure a unique cache per editor instance
var key = 'ncNodeName_' + currentNode.key;
if (ncNodeNameCache.id !== key) {
ncNodeNameCache.id = key;
ncNodeNameCache.keys = {};
}
// MNTP values are comma separated IDs. We'll only fetch the first one for the NC header.
var ids = input.split(',');
var lookupId = ids[0];
// See if there is a value in the cache and use that
if (ncNodeNameCache.keys[lookupId]) {
return formatLabel(ncNodeNameCache.keys[lookupId], ids.length);
}
// No value, so go fetch one
// We'll put a temp value in the cache though so we don't
// make a load of requests while we wait for a response
ncNodeNameCache.keys[lookupId] = 'Loading...';
var type = lookupId.indexOf('umb://media/') === 0 ? 'Media' : lookupId.indexOf('umb://member/') === 0 ? 'Member' : 'Document';
entityResource.getById(lookupId, type).then(function (ent) {
ncNodeNameCache.keys[lookupId] = ent.name;
});
// Return the current value for now
return formatLabel(ncNodeNameCache.keys[lookupId], ids.length);
};
}).filter('ncRichText', function () {
return function (input) {
return $('<div/>').html(input).text();
};
});
/**
* @ngdoc filter
* @name umbraco.filters.preserveNewLineInHtml
* @description
* Used when rendering a string as HTML (i.e. with ng-bind-html) to convert line-breaks to <br /> tags
**/
angular.module('umbraco.filters').filter('preserveNewLineInHtml', function () {
return function (text) {
if (!text) {
return '';
}
return text.replace(/\n/g, '<br />');
};
});
angular.module('umbraco.filters').filter('timespan', function () {
return function (input) {
var sec_num = parseInt(input, 10);
var hours = Math.floor(sec_num / 3600);
var minutes = Math.floor((sec_num - hours * 3600) / 60);
var seconds = sec_num - hours * 3600 - minutes * 60;
if (hours < 10) {
hours = '0' + hours;
}
if (minutes < 10) {
minutes = '0' + minutes;
}
if (seconds < 10) {
seconds = '0' + seconds;
}
var time = hours + ':' + minutes + ':' + seconds;
return time;
};
});
/**
* @ngdoc filter
* @name umbraco.filters.filter:umbWordLimit
* @namespace umbWordLimitFilter
*
* @description
* Limits the number of words in a string to the passed in value
*/
(function () {
'use strict';
function umbWordLimitFilter() {
return function (collection, property) {
if (!angular.isString(collection)) {
return collection;
}
if (angular.isUndefined(property)) {
return collection;
}
var newString = '';
var array = [];
array = collection.split(' ', property);
array.length = property;
newString = array.join(' ');
return newString;
};
}
angular.module('umbraco.filters').filter('umbWordLimit', umbWordLimitFilter);
}());
}());
+398 -454
View File
@@ -1,468 +1,412 @@
/*! umbraco
* https://github.com/umbraco/umbraco-cms/
* Copyright (c) 2016 Umbraco HQ;
* Licensed
*/
(function() {
angular.module('umbraco.install', []);
angular.module("umbraco.install").controller("Umbraco.InstallerController",
function ($scope, installerService) {
//TODO: Decouple the service from the controller - the controller should be responsible
// for the model (state) and the service should be responsible for helping the controller,
// the controller should be passing the model into it's methods for manipulation and not hold
// state. We should not be assigning properties from a service to a controller's scope.
// see: https://github.com/umbraco/Umbraco-CMS/commit/b86ef0d7ac83f699aee35d807f7f7ebb6dd0ed2c#commitcomment-5721204
$scope.stepIndex = 0;
//comment this out if you just want to see tips
installerService.init();
//uncomment this to see tips
//installerService.switchToFeedback();
$scope.installer = installerService.status;
$scope.forward = function () {
installerService.forward();
};
$scope.backward = function () {
installerService.backward();
};
$scope.install = function () {
installerService.install();
};
$scope.gotoStep = function (step) {
installerService.gotoNamedStep(step);
};
$scope.restart = function () {
installerService.gotoStep(0);
};
});
//this ensure that we start with a clean slate on every install and upgrade
angular.module("umbraco.install").run(function ($templateCache) {
$templateCache.removeAll();
});
angular.module("umbraco.install").factory('installerService', function($rootScope, $q, $timeout, $http, $location, $log){
var _status = {
index: 0,
current: undefined,
steps: undefined,
loading: true,
progress: "100%"
};
var factTimer = undefined;
var _installerModel = {
installId: undefined,
instructions: {
}
};
//add to umbraco installer facts here
var facts = ['Umbraco helped millions of people watch a man jump from the edge of space',
'Over 370 000 websites are currently powered by Umbraco',
"At least 2 people have named their cat 'Umbraco'",
'On an average day, more than 1000 people download Umbraco',
'<a target="_blank" href="http://umbraco.tv">umbraco.tv</a> is the premier source of Umbraco video tutorials to get you started',
'You can find the world\'s friendliest CMS community at <a target="_blank" href="http://our.umbraco.org">our.umbraco.org</a>',
'You can become a certified Umbraco developer by attending one of the official courses',
'Umbraco works really well on tablets',
'You have 100% control over your markup and design when crafting a website in Umbraco',
'Umbraco is the best of both worlds: 100% free and open source, and backed by a professional and profitable company',
"There's a pretty big chance, you've visited a website powered by Umbraco today",
"'Umbraco-spotting' is the game of spotting big brands running Umbraco",
"At least 4 people have the Umbraco logo tattooed on them",
"'Umbraco' is the danish name for an allen key",
"Umbraco has been around since 2005, that's a looong time in IT",
"More than 400 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='http://codegarden15.com'>CodeGarden</a>",
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
"You can extend Umbraco without modifying the source code using either JavaScript or C#",
"Umbraco was installed in more than 165 countries in 2015"
];
/**
(function () {
angular.module('umbraco.install', ['umbraco.directives']);
angular.module('umbraco.install').controller('Umbraco.InstallerController', function ($scope, installerService) {
//TODO: Decouple the service from the controller - the controller should be responsible
// for the model (state) and the service should be responsible for helping the controller,
// the controller should be passing the model into it's methods for manipulation and not hold
// state. We should not be assigning properties from a service to a controller's scope.
// see: https://github.com/umbraco/Umbraco-CMS/commit/b86ef0d7ac83f699aee35d807f7f7ebb6dd0ed2c#commitcomment-5721204
$scope.stepIndex = 0;
//comment this out if you just want to see tips
installerService.init();
//uncomment this to see tips
//installerService.switchToFeedback();
$scope.installer = installerService.status;
$scope.forward = function () {
installerService.forward();
};
$scope.backward = function () {
installerService.backward();
};
$scope.install = function () {
installerService.install();
};
$scope.gotoStep = function (step) {
installerService.gotoNamedStep(step);
};
$scope.restart = function () {
installerService.gotoStep(0);
};
});
//this ensure that we start with a clean slate on every install and upgrade
angular.module('umbraco.install').run(function ($templateCache) {
$templateCache.removeAll();
});
angular.module('umbraco.install').factory('installerService', function ($rootScope, $q, $timeout, $http, $location, $log) {
var _status = {
index: 0,
current: undefined,
steps: undefined,
loading: true,
progress: '100%'
};
var factTimer = undefined;
var _installerModel = {
installId: undefined,
instructions: {}
};
//add to umbraco installer facts here
var facts = [
'Umbraco helped millions of people watch a man jump from the edge of space',
'Over 440 000 websites are currently powered by Umbraco',
'At least 2 people have named their cat \'Umbraco\'',
'On an average day, more than 1000 people download Umbraco',
'<a target="_blank" href="https://umbraco.tv">umbraco.tv</a> is the premier source of Umbraco video tutorials to get you started',
'You can find the world\'s friendliest CMS community at <a target="_blank" href="https://our.umbraco.com">our.umbraco.com</a>',
'You can become a certified Umbraco developer by attending one of the official courses',
'Umbraco works really well on tablets',
'You have 100% control over your markup and design when crafting a website in Umbraco',
'Umbraco is the best of both worlds: 100% free and open source, and backed by a professional and profitable company',
'There\'s a pretty big chance, you\'ve visited a website powered by Umbraco today',
'\'Umbraco-spotting\' is the game of spotting big brands running Umbraco',
'At least 4 people have the Umbraco logo tattooed on them',
'\'Umbraco\' is the Danish name for an allen key',
'Umbraco has been around since 2005, that\'s a looong time in IT',
'More than 600 people from all over the world meet each year in Denmark in May for our annual conference <a target=\'_blank\' href=\'https://umbra.co/codegarden\'>CodeGarden</a>',
'While you are installing Umbraco someone else on the other side of the planet is probably doing it too',
'You can extend Umbraco without modifying the source code using either JavaScript or C#',
'Umbraco has been installed in more than 198 countries'
];
/**
Returns the description for the step at a given index based on the order of the serverOrder of steps
Since they don't execute on the server in the order that they are displayed in the UI.
*/
function getDescriptionForStepAtIndex(steps, index) {
var sorted = _.sortBy(steps, "serverOrder");
if (sorted[index]) {
return sorted[index].description;
}
return null;
}
/* Returns the description for the given step name */
function getDescriptionForStepName(steps, name) {
var found = _.find(steps, function(i) {
return i.name == name;
});
return (found) ? found.description : null;
}
//calculates the offset of the progressbar on the installer
function calculateProgress(steps, next) {
var sorted = _.sortBy(steps, "serverOrder");
var pct = "100%";
for (var i = sorted.length - 1; i >= 0; i--) {
if(sorted[i].name == next){
pct = Math.floor((i+1) / steps.length * 100) + "%";
break;
}
}
return pct;
}
//helpful defaults for the view loading
function resolveView(view){
if(view.indexOf(".html") < 0){
view = view + ".html";
}
if(view.indexOf("/") < 0){
view = "views/install/" + view;
}
return view;
}
/** Have put this here because we are not referencing our other modules */
function safeApply (scope, fn) {
if (scope.$$phase || scope.$root.$$phase) {
if (angular.isFunction(fn)) {
fn();
}
}
else {
if (angular.isFunction(fn)) {
scope.$apply(fn);
}
else {
scope.$apply();
}
}
}
var service = {
status : _status,
//loads the needed steps and sets the intial state
init : function(){
service.status.loading = true;
if(!_status.all){
service.getSteps().then(function(response){
service.status.steps = response.data.steps;
service.status.index = 0;
_installerModel.installId = response.data.installId;
service.findNextStep();
$timeout(function(){
service.status.loading = false;
service.status.configuring = true;
}, 2000);
});
}
},
//loads available packages from our.umbraco.org
getPackages : function(){
return $http.get(Umbraco.Sys.ServerVariables.installApiBaseUrl + "GetPackages");
},
getSteps : function(){
return $http.get(Umbraco.Sys.ServerVariables.installApiBaseUrl + "GetSetup");
},
gotoStep : function(index){
var step = service.status.steps[index];
step.view = resolveView(step.view);
if(!step.model){
step.model = {};
}
service.status.index = index;
service.status.current = step;
service.retrieveCurrentStep();
},
gotoNamedStep : function(stepName){
var step = _.find(service.status.steps, function(s, index){
if (s.view && s.name === stepName) {
service.status.index = index;
return true;
}
return false;
});
step.view = resolveView(step.view);
if(!step.model){
step.model = {};
}
service.retrieveCurrentStep();
service.status.current = step;
},
/**
Finds the next step containing a view. If one is found it stores it as the current step
and retreives the step information and returns it, otherwise returns null .
*/
findNextStep : function(){
var step = _.find(service.status.steps, function(s, index){
if(s.view && index >= service.status.index){
service.status.index = index;
return true;
}
return false;
});
if (step) {
if (step.view.indexOf(".html") < 0) {
step.view = step.view + ".html";
function getDescriptionForStepAtIndex(steps, index) {
var sorted = _.sortBy(steps, 'serverOrder');
if (sorted[index]) {
return sorted[index].description;
}
return null;
}
/* Returns the description for the given step name */
function getDescriptionForStepName(steps, name) {
var found = _.find(steps, function (i) {
return i.name == name;
});
return found ? found.description : null;
}
//calculates the offset of the progressbar on the installer
function calculateProgress(steps, next) {
var sorted = _.sortBy(steps, 'serverOrder');
var pct = '100%';
for (var i = sorted.length - 1; i >= 0; i--) {
if (sorted[i].name == next) {
pct = Math.floor((i + 1) / steps.length * 100) + '%';
break;
}
if (step.view.indexOf("/") < 0) {
step.view = "views/install/" + step.view;
}
return pct;
}
//helpful defaults for the view loading
function resolveView(view) {
if (view.indexOf('.html') < 0) {
view = view + '.html';
}
if (view.indexOf('/') < 0) {
view = 'views/install/' + view;
}
return view;
}
/** Have put this here because we are not referencing our other modules */
function safeApply(scope, fn) {
if (scope.$$phase || scope.$root.$$phase) {
if (angular.isFunction(fn)) {
fn();
}
} else {
if (angular.isFunction(fn)) {
scope.$apply(fn);
} else {
scope.$apply();
}
}
}
var service = {
status: _status,
//loads the needed steps and sets the intial state
init: function () {
service.status.loading = true;
if (!_status.all) {
service.getSteps().then(function (response) {
service.status.steps = response.data.steps;
service.status.index = 0;
_installerModel.installId = response.data.installId;
service.findNextStep();
$timeout(function () {
service.status.loading = false;
service.status.configuring = true;
}, 2000);
});
}
},
//loads available packages from our.umbraco.com
getPackages: function () {
return $http.get(Umbraco.Sys.ServerVariables.installApiBaseUrl + 'GetPackages');
},
getSteps: function () {
return $http.get(Umbraco.Sys.ServerVariables.installApiBaseUrl + 'GetSetup');
},
gotoStep: function (index) {
var step = service.status.steps[index];
step.view = resolveView(step.view);
if (!step.model) {
step.model = {};
}
service.status.index = index;
service.status.current = step;
service.retrieveCurrentStep();
//returns the next found step
return step;
}
else {
//there are no more steps found containing a view so return null
return null;
}
},
storeCurrentStep : function(){
_installerModel.instructions[service.status.current.name] = service.status.current.model;
},
retrieveCurrentStep : function(){
if(_installerModel.instructions[service.status.current.name]){
service.status.current.model = _installerModel.instructions[service.status.current.name];
}
},
/** Moves the installer forward to the next view, if there are not more views than the installation will commence */
forward : function(){
service.storeCurrentStep();
service.status.index++;
var found = service.findNextStep();
if (!found) {
//no more steps were found so start the installation process
service.install();
}
},
backwards : function(){
service.storeCurrentStep();
service.gotoStep(service.status.index--);
},
install : function(){
service.storeCurrentStep();
service.switchToFeedback();
service.status.feedback = getDescriptionForStepAtIndex(service.status.steps, 0);
service.status.progress = 0;
function processInstallStep() {
$http.post(Umbraco.Sys.ServerVariables.installApiBaseUrl + "PostPerformInstall", _installerModel)
.success(function(data, status, headers, config) {
if (!data.complete) {
//progress feedback
service.status.progress = calculateProgress(service.status.steps, data.nextStep);
if (data.view) {
//set the current view and model to whatever the process returns, the view is responsible for retriggering install();
var v = resolveView(data.view);
service.status.current = { view: v, model: data.model };
//turn off loading bar and feedback
service.switchToConfiguration();
}
else {
var desc = getDescriptionForStepName(service.status.steps, data.nextStep);
if (desc) {
service.status.feedback = desc;
}
processInstallStep();
}
}
else {
service.complete();
}
}).error(function(data, status, headers, config) {
//need to handle 500's separately, this will happen if something goes wrong outside
// of the installer (like app startup events or something) and these will get returned as text/html
// not as json. If this happens we can't actually load in external views since they will YSOD as well!
},
gotoNamedStep: function (stepName) {
var step = _.find(service.status.steps, function (s, index) {
if (s.view && s.name === stepName) {
service.status.index = index;
return true;
}
return false;
});
step.view = resolveView(step.view);
if (!step.model) {
step.model = {};
}
service.retrieveCurrentStep();
service.status.current = step;
},
/**
Finds the next step containing a view. If one is found it stores it as the current step
and retreives the step information and returns it, otherwise returns null .
*/
findNextStep: function () {
var step = _.find(service.status.steps, function (s, index) {
if (s.view && index >= service.status.index) {
service.status.index = index;
return true;
}
return false;
});
if (step) {
if (step.view.indexOf('.html') < 0) {
step.view = step.view + '.html';
}
if (step.view.indexOf('/') < 0) {
step.view = 'views/install/' + step.view;
}
if (!step.model) {
step.model = {};
}
service.status.current = step;
service.retrieveCurrentStep();
//returns the next found step
return step;
} else {
//there are no more steps found containing a view so return null
return null;
}
},
storeCurrentStep: function () {
_installerModel.instructions[service.status.current.name] = service.status.current.model;
},
retrieveCurrentStep: function () {
if (_installerModel.instructions[service.status.current.name]) {
service.status.current.model = _installerModel.instructions[service.status.current.name];
}
},
/** Moves the installer forward to the next view, if there are not more views than the installation will commence */
forward: function () {
service.storeCurrentStep();
service.status.index++;
var found = service.findNextStep();
if (!found) {
//no more steps were found so start the installation process
service.install();
}
},
backwards: function () {
service.storeCurrentStep();
service.gotoStep(service.status.index--);
},
install: function () {
service.storeCurrentStep();
service.switchToFeedback();
service.status.feedback = getDescriptionForStepAtIndex(service.status.steps, 0);
service.status.progress = 0;
function processInstallStep() {
$http.post(Umbraco.Sys.ServerVariables.installApiBaseUrl + 'PostPerformInstall', _installerModel).success(function (data, status, headers, config) {
if (!data.complete) {
//progress feedback
service.status.progress = calculateProgress(service.status.steps, data.nextStep);
if (data.view) {
//set the current view and model to whatever the process returns, the view is responsible for retriggering install();
var v = resolveView(data.view);
service.status.current = {
view: v,
model: data.model
};
//turn off loading bar and feedback
service.switchToConfiguration();
} else {
var desc = getDescriptionForStepName(service.status.steps, data.nextStep);
if (desc) {
service.status.feedback = desc;
}
processInstallStep();
}
} else {
service.complete();
}
}).error(function (data, status, headers, config) {
//need to handle 500's separately, this will happen if something goes wrong outside
// of the installer (like app startup events or something) and these will get returned as text/html
// not as json. If this happens we can't actually load in external views since they will YSOD as well!
// so we need to display this in our own internal way
if (status >= 500 && status < 600) {
service.status.current = { view: "ysod", model: null };
var ysod = data;
if (status >= 500 && status < 600) {
service.status.current = {
view: 'ysod',
model: null
};
var ysod = data;
//we need to manually write the html to the iframe - the html contains full html markup
$timeout(function () {
document.getElementById('ysod').contentDocument.write(ysod);
}, 500);
}
else {
//this is where we handle installer error
var v = data.view ? resolveView(data.view) : resolveView("error");
var model = data.model ? data.model : data;
service.status.current = { view: v, model: model };
}
service.switchToConfiguration();
});
}
processInstallStep();
},
randomFact: function () {
safeApply($rootScope, function() {
service.status.fact = facts[_.random(facts.length - 1)];
});
},
switchToFeedback : function(){
service.status.current = undefined;
service.status.loading = true;
service.status.configuring = false;
//initial fact
service.randomFact();
//timed facts
factTimer = window.setInterval(function(){
service.randomFact();
},6000);
},
switchToConfiguration : function(){
service.status.loading = false;
service.status.configuring = true;
service.status.feedback = undefined;
service.status.fact = undefined;
if(factTimer){
clearInterval(factTimer);
}
},
complete : function(){
service.status.progress = "100%";
service.status.done = true;
service.status.feedback = "Redirecting you to Umbraco, please wait";
service.status.loading = false;
if(factTimer){
clearInterval(factTimer);
}
$timeout(function(){
window.location.href = Umbraco.Sys.ServerVariables.umbracoBaseUrl;
}, 1500);
}
};
return service;
});
angular.module("umbraco.install").controller("Umbraco.Installer.DataBaseController", function($scope, $http, installerService){
$scope.checking = false;
$scope.dbs = [
{name: 'Microsoft SQL Server Compact (SQL CE)', id: 0},
{name: 'Microsoft SQL Server', id: 1},
{ name: 'Microsoft SQL Azure', id: 3 },
{ name: 'MySQL', id: 2 },
{name: 'Custom connection string', id: -1}];
if(installerService.status.current.model.dbType === undefined){
installerService.status.current.model.dbType = 0;
}
$scope.validateAndForward = function(){
if(!$scope.checking && this.myForm.$valid){
$scope.checking = true;
var model = installerService.status.current.model;
$http.post(Umbraco.Sys.ServerVariables.installApiBaseUrl + "PostValidateDatabaseConnection",
model).then(function(response){
if(response.data === "true"){
installerService.forward();
}else{
$scope.invalidDbDns = true;
}
$scope.checking = false;
}, function(){
$scope.invalidDbDns = true;
$scope.checking = false;
});
}
};
});
angular.module("umbraco.install").controller("Umbraco.Installer.PackagesController", function ($scope, installerService) {
installerService.getPackages().then(function (response) {
$scope.packages = response.data;
$timeout(function () {
document.getElementById('ysod').contentDocument.write(ysod);
}, 500);
} else {
//this is where we handle installer error
var v = data.view ? resolveView(data.view) : resolveView('error');
var model = data.model ? data.model : data;
service.status.current = {
view: v,
model: model
};
}
service.switchToConfiguration();
});
}
processInstallStep();
},
randomFact: function () {
safeApply($rootScope, function () {
service.status.fact = facts[_.random(facts.length - 1)];
});
},
switchToFeedback: function () {
service.status.current = undefined;
service.status.loading = true;
service.status.configuring = false;
//initial fact
service.randomFact();
//timed facts
factTimer = window.setInterval(function () {
service.randomFact();
}, 6000);
},
switchToConfiguration: function () {
service.status.loading = false;
service.status.configuring = true;
service.status.feedback = undefined;
service.status.fact = undefined;
if (factTimer) {
clearInterval(factTimer);
}
},
complete: function () {
service.status.progress = '100%';
service.status.done = true;
service.status.feedback = 'Redirecting you to Umbraco, please wait';
service.status.loading = false;
if (factTimer) {
clearInterval(factTimer);
}
$timeout(function () {
window.location.href = Umbraco.Sys.ServerVariables.umbracoBaseUrl;
}, 1500);
}
};
return service;
});
$scope.setPackageAndContinue = function (pckId) {
installerService.status.current.model = pckId;
installerService.forward();
};
});
angular.module("umbraco.install").controller("Umbraco.Install.UserController", function($scope, installerService) {
$scope.passwordPattern = /.*/;
$scope.installer.current.model.subscribeToNewsLetter = true;
if ($scope.installer.current.model.minNonAlphaNumericLength > 0) {
var exp = "";
for (var i = 0; i < $scope.installer.current.model.minNonAlphaNumericLength; i++) {
exp += ".*[\\W].*";
angular.module('umbraco.install').controller('Umbraco.Installer.DataBaseController', function ($scope, $http, installerService) {
$scope.checking = false;
$scope.invalidDbDns = false;
$scope.dbs = [
{
name: 'Microsoft SQL Server Compact (SQL CE)',
id: 0
},
{
name: 'Microsoft SQL Server',
id: 1
},
{
name: 'Microsoft SQL Azure',
id: 3
},
{
name: 'MySQL',
id: 2
},
{
name: 'Custom connection string',
id: -1
}
];
if (installerService.status.current.model.dbType === undefined) {
installerService.status.current.model.dbType = 0;
}
//replace duplicates
exp = exp.replace(".*.*", ".*");
$scope.passwordPattern = new RegExp(exp);
}
$scope.validateAndInstall = function(){
installerService.install();
};
$scope.validateAndForward = function(){
if(this.myForm.$valid){
installerService.forward();
}
};
});
})();
$scope.validateAndForward = function () {
if (!$scope.checking && this.myForm.$valid) {
$scope.checking = true;
$scope.invalidDbDns = false;
var model = installerService.status.current.model;
$http.post(Umbraco.Sys.ServerVariables.installApiBaseUrl + 'PostValidateDatabaseConnection', model).then(function (response) {
if (response.data === 'true') {
installerService.forward();
} else {
$scope.invalidDbDns = true;
}
$scope.checking = false;
}, function () {
$scope.invalidDbDns = true;
$scope.checking = false;
});
}
};
});
angular.module('umbraco.install').controller('Umbraco.Installer.MachineKeyController', function ($scope, installerService) {
$scope.continue = function () {
installerService.status.current.model = true;
installerService.forward();
};
$scope.ignoreKey = function () {
installerService.status.current.model = false;
installerService.forward();
};
});
angular.module('umbraco.install').controller('Umbraco.Installer.PackagesController', function ($scope, installerService) {
installerService.getPackages().then(function (response) {
$scope.packages = response.data;
});
$scope.setPackageAndContinue = function (pckId) {
installerService.status.current.model = pckId;
installerService.forward();
};
});
angular.module('umbraco.install').controller('Umbraco.Install.UserController', function ($scope, installerService) {
$scope.passwordPattern = /.*/;
$scope.installer.current.model.subscribeToNewsLetter = false;
if ($scope.installer.current.model.minNonAlphaNumericLength > 0) {
var exp = '';
for (var i = 0; i < $scope.installer.current.model.minNonAlphaNumericLength; i++) {
exp += '.*[\\W].*';
}
//replace duplicates
exp = exp.replace('.*.*', '.*');
$scope.passwordPattern = new RegExp(exp);
}
$scope.validateAndInstall = function () {
installerService.install();
};
$scope.validateAndForward = function () {
if (this.myForm.$valid) {
installerService.forward();
}
};
});
}());
File diff suppressed because it is too large Load Diff
+160 -169
View File
@@ -1,206 +1,197 @@
/*! umbraco
* https://github.com/umbraco/umbraco-cms/
* Copyright (c) 2016 Umbraco HQ;
* Licensed
*/
(function() {
//TODO: This is silly and unecessary to have a separate module for this
angular.module('umbraco.security.retryQueue', []);
angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']);
angular.module('umbraco.security', ['umbraco.security.retryQueue', 'umbraco.security.interceptor']);
//TODO: This is silly and unecessary to have a separate module for this
angular.module('umbraco.security.retryQueue', [])
// This is a generic retry queue for security failures. Each item is expected to expose two functions: retry and cancel.
.factory('securityRetryQueue', ['$q', '$log', function ($q, $log) {
var retryQueue = [];
var retryUser = null;
var service = {
// The security service puts its own handler in here!
onItemAddedCallbacks: [],
hasMore: function() {
return retryQueue.length > 0;
},
push: function(retryItem) {
retryQueue.push(retryItem);
// Call all the onItemAdded callbacks
angular.forEach(service.onItemAddedCallbacks, function(cb) {
try {
cb(retryItem);
} catch(e) {
$log.error('securityRetryQueue.push(retryItem): callback threw an error' + e);
(function () {
angular.module('umbraco.security.retryQueue', []);
angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']);
angular.module('umbraco.security', [
'umbraco.security.retryQueue',
'umbraco.security.interceptor'
]);
//TODO: This is silly and unecessary to have a separate module for this
angular.module('umbraco.security.retryQueue', []) // This is a generic retry queue for security failures. Each item is expected to expose two functions: retry and cancel.
.factory('securityRetryQueue', [
'$q',
'$log',
function ($q, $log) {
var retryQueue = [];
var retryUser = null;
var service = {
// The security service puts its own handler in here!
onItemAddedCallbacks: [],
hasMore: function () {
return retryQueue.length > 0;
},
push: function (retryItem) {
retryQueue.push(retryItem);
// Call all the onItemAdded callbacks
angular.forEach(service.onItemAddedCallbacks, function (cb) {
try {
cb(retryItem);
} catch (e) {
$log.error('securityRetryQueue.push(retryItem): callback threw an error' + e);
}
});
},
pushRetryFn: function (reason, userName, retryFn) {
// The reason parameter is optional
if (arguments.length === 2) {
retryFn = userName;
userName = reason;
reason = undefined;
}
if (retryUser && retryUser !== userName || userName === null) {
throw new Error('invalid user');
}
retryUser = userName;
// The deferred object that will be resolved or rejected by calling retry or cancel
var deferred = $q.defer();
var retryItem = {
reason: reason,
retry: function () {
// Wrap the result of the retryFn into a promise if it is not already
$q.when(retryFn()).then(function (value) {
// If it was successful then resolve our deferred
deferred.resolve(value);
}, function (value) {
// Othewise reject it
deferred.reject(value);
});
},
cancel: function () {
// Give up on retrying and reject our deferred
deferred.reject();
}
};
service.push(retryItem);
return deferred.promise;
},
retryReason: function () {
return service.hasMore() && retryQueue[0].reason;
},
cancelAll: function () {
while (service.hasMore()) {
retryQueue.shift().cancel();
}
retryUser = null;
},
retryAll: function (userName) {
if (retryUser == null) {
return;
}
if (retryUser !== userName) {
service.cancelAll();
return;
}
while (service.hasMore()) {
retryQueue.shift().retry();
}
}
};
return service;
}
});
},
pushRetryFn: function(reason, userName, retryFn) {
// The reason parameter is optional
if ( arguments.length === 2) {
retryFn = userName;
userName = reason;
reason = undefined;
}
if ((retryUser && retryUser !== userName) || userName === null) {
throw new Error('invalid user');
}
retryUser = userName;
// The deferred object that will be resolved or rejected by calling retry or cancel
var deferred = $q.defer();
var retryItem = {
reason: reason,
retry: function() {
// Wrap the result of the retryFn into a promise if it is not already
$q.when(retryFn()).then(function(value) {
// If it was successful then resolve our deferred
deferred.resolve(value);
}, function(value) {
// Othewise reject it
deferred.reject(value);
});
},
cancel: function() {
// Give up on retrying and reject our deferred
deferred.reject();
}
};
service.push(retryItem);
return deferred.promise;
},
retryReason: function() {
return service.hasMore() && retryQueue[0].reason;
},
cancelAll: function() {
while(service.hasMore()) {
retryQueue.shift().cancel();
}
retryUser = null;
},
retryAll: function (userName) {
if (retryUser == null) {
return;
}
if (retryUser !== userName) {
service.cancelAll();
return;
}
while(service.hasMore()) {
retryQueue.shift().retry();
}
}
};
return service;
}]);
angular.module('umbraco.security.interceptor')
// This http interceptor listens for authentication successes and failures
.factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'requestInterceptorFilter', function ($injector, queue, notifications, requestInterceptorFilter) {
return function(promise) {
return promise.then(
function(originalResponse) {
]);
angular.module('umbraco.security.interceptor') // This http interceptor listens for authentication successes and failures
.factory('securityInterceptor', [
'$injector',
'securityRetryQueue',
'notificationsService',
'eventsService',
'requestInterceptorFilter',
function ($injector, queue, notifications, eventsService, requestInterceptorFilter) {
return function (promise) {
return promise.then(function (originalResponse) {
// Intercept successful requests
//Here we'll check if our custom header is in the response which indicates how many seconds the user's session has before it
//expires. Then we'll update the user in the user service accordingly.
var headers = originalResponse.headers();
if (headers["x-umb-user-seconds"]) {
if (headers['x-umb-user-seconds']) {
// We must use $injector to get the $http service to prevent circular dependency
var userService = $injector.get('userService');
userService.setUserTimeout(headers["x-umb-user-seconds"]);
userService.setUserTimeout(headers['x-umb-user-seconds']);
}
//this checks if the user's values have changed, in which case we need to update the user details throughout
//the back office similar to how we do when a user logs in
if (headers['x-umb-user-modified']) {
eventsService.emit('app.userRefresh');
}
return promise;
}, function(originalResponse) {
}, function (originalResponse) {
// Intercept failed requests
//Here we'll check if we should ignore the error, this will be based on an original header set
var headers = originalResponse.config ? originalResponse.config.headers : {};
if (headers["x-umb-ignore-error"] === "ignore") {
// Make sure we have the configuration of the request (don't we always?)
var config = originalResponse.config ? originalResponse.config : {};
// Make sure we have an object for the headers of the request
var headers = config.headers ? config.headers : {};
//Here we'll check if we should ignore the error (either based on the original header set or the request configuration)
if (headers['x-umb-ignore-error'] === 'ignore' || config.umbIgnoreErrors === true || angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(originalResponse.status) !== -1) {
//exit/ignore
return promise;
}
var filtered = _.find(requestInterceptorFilter(), function(val) {
return originalResponse.config.url.indexOf(val) > 0;
var filtered = _.find(requestInterceptorFilter(), function (val) {
return config.url.indexOf(val) > 0;
});
if (filtered) {
return promise;
}
//A 401 means that the user is not logged in
if (originalResponse.status === 401) {
var userService = $injector.get('userService'); // see above
//Associate the user name with the retry to ensure we retry for the right user
promise = userService.getCurrentUser()
.then(function (user) {
var userName = user ? user.name : null;
//The request bounced because it was not authorized - add a new request to the retry queue
return queue.pushRetryFn('unauthorized-server', userName, function retryRequest() {
// We must use $injector to get the $http service to prevent circular dependency
return $injector.get('$http')(originalResponse.config);
});
if (originalResponse.status === 401 && !originalResponse.config.url.endsWith('umbraco/backoffice/UmbracoApi/Authentication/GetCurrentUser')) {
var userService = $injector.get('userService');
// see above
//Associate the user name with the retry to ensure we retry for the right user
promise = userService.getCurrentUser().then(function (user) {
var userName = user ? user.name : null;
//The request bounced because it was not authorized - add a new request to the retry queue
return queue.pushRetryFn('unauthorized-server', userName, function retryRequest() {
// We must use $injector to get the $http service to prevent circular dependency
return $injector.get('$http')(originalResponse.config);
});
});
}
else if (originalResponse.status === 404) {
} else if (originalResponse.status === 404) {
//a 404 indicates that the request was not found - this could be due to a non existing url, or it could
//be due to accessing a url with a parameter that doesn't exist, either way we should notifiy the user about it
var errMsg = "The URL returned a 404 (not found): <br/><i>" + originalResponse.config.url.split('?')[0] + "</i>";
var errMsg = 'The URL returned a 404 (not found): <br/><i>' + originalResponse.config.url.split('?')[0] + '</i>';
if (originalResponse.data && originalResponse.data.ExceptionMessage) {
errMsg += "<br/> with error: <br/><i>" + originalResponse.data.ExceptionMessage + "</i>";
errMsg += '<br/> with error: <br/><i>' + originalResponse.data.ExceptionMessage + '</i>';
}
if (originalResponse.config.data) {
errMsg += "<br/> with data: <br/><i>" + angular.toJson(originalResponse.config.data) + "</i><br/>Contact your administrator for information.";
errMsg += '<br/> with data: <br/><i>' + angular.toJson(originalResponse.config.data) + '</i><br/>Contact your administrator for information.';
}
notifications.error(
"Request error",
errMsg);
}
else if (originalResponse.status === 403) {
notifications.error('Request error', errMsg);
} else if (originalResponse.status === 403) {
//if the status was a 403 it means the user didn't have permission to do what the request was trying to do.
//How do we deal with this now, need to tell the user somehow that they don't have permission to do the thing that was
//requested. We can either deal with this globally here, or we can deal with it globally for individual requests on the umbRequestHelper,
// or completely custom for services calling resources.
//http://issues.umbraco.org/issue/U4-2749
//It was decided to just put these messages into the normal status messages.
var msg = "Unauthorized access to URL: <br/><i>" + originalResponse.config.url.split('?')[0] + "</i>";
var msg = 'Unauthorized access to URL: <br/><i>' + originalResponse.config.url.split('?')[0] + '</i>';
if (originalResponse.config.data) {
msg += "<br/> with data: <br/><i>" + angular.toJson(originalResponse.config.data) + "</i><br/>Contact your administrator for information.";
msg += '<br/> with data: <br/><i>' + angular.toJson(originalResponse.config.data) + '</i><br/>Contact your administrator for information.';
}
notifications.error(
"Authorization error",
msg);
notifications.error('Authorization error', msg);
}
return promise;
});
};
}
]) //used to set headers on all requests where necessary
.factory('umbracoRequestInterceptor', function ($q, queryStrings) {
return {
//dealing with requests:
'request': function (config) {
if (queryStrings.getParams().umbDebug === 'true' || queryStrings.getParams().umbdebug === 'true') {
config.headers['X-UMB-DEBUG'] = 'true';
}
return config;
}
};
}])
.value('requestInterceptorFilter', function() {
return ["www.gravatar.com"];
})
// We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block.
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.responseInterceptors.push('securityInterceptor');
}]);
})();
}).value('requestInterceptorFilter', function () {
return ['www.gravatar.com'];
}) // We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block.
.config([
'$httpProvider',
function ($httpProvider) {
$httpProvider.defaults.xsrfHeaderName = 'X-UMB-XSRF-TOKEN';
$httpProvider.defaults.xsrfCookieName = 'UMB-XSRF-TOKEN';
$httpProvider.responseInterceptors.push('securityInterceptor');
$httpProvider.interceptors.push('umbracoRequestInterceptor');
}
]);
}());
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlCustom="private" cacheControlMode="UseMaxAge" cacheControlMaxAge="3.00:00:00" />
</staticContent>
</system.webServer>
</configuration>